[DMUSIC] Sync with Wine Staging 1.9.23. CORE-12409
[reactos.git] / reactos / dll / directx / wine / dmusic / port.c
1 /*
2 * IDirectMusicPort Implementation
3 *
4 * Copyright (C) 2003-2004 Rok Mandeljc
5 * Copyright (C) 2012 Christian Costa
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "dmusic_private.h"
23
24 #include <assert.h>
25
26 typedef struct SynthPortImpl {
27 IDirectMusicPort IDirectMusicPort_iface;
28 IDirectMusicPortDownload IDirectMusicPortDownload_iface;
29 IDirectMusicThru IDirectMusicThru_iface;
30 IKsControl IKsControl_iface;
31 LONG ref;
32 IDirectSound *pDirectSound;
33 IReferenceClock *pLatencyClock;
34 IDirectMusicSynth *synth;
35 IDirectMusicSynthSink *synth_sink;
36 BOOL fActive;
37 DMUS_PORTCAPS caps;
38 DMUS_PORTPARAMS params;
39 int nrofgroups;
40 DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
41 } SynthPortImpl;
42
43 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
44 {
45 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
46 }
47
48 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
49 {
50 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
51 }
52
53 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
54 {
55 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
56 }
57
58 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
59 {
60 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
61 }
62
63 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface)
64 {
65 return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface);
66 }
67
68 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
69 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
70 {
71 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
72
73 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
74 {
75 IDirectMusicDownloadedInstrument_AddRef(iface);
76 *ret_iface = iface;
77 return S_OK;
78 }
79
80 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
81
82 return E_NOINTERFACE;
83 }
84
85 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
86 {
87 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
88 ULONG ref = InterlockedIncrement(&This->ref);
89
90 TRACE("(%p)->(): new ref = %u\n", iface, ref);
91
92 return ref;
93 }
94
95 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
96 {
97 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
98 ULONG ref = InterlockedDecrement(&This->ref);
99
100 TRACE("(%p)->(): new ref = %u\n", iface, ref);
101
102 if (!ref)
103 {
104 HeapFree(GetProcessHeap(), 0, This->data);
105 HeapFree(GetProcessHeap(), 0, This);
106 DMUSIC_UnlockModule();
107 }
108
109 return ref;
110 }
111
112 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
113 IDirectMusicDownloadedInstrumentImpl_QueryInterface,
114 IDirectMusicDownloadedInstrumentImpl_AddRef,
115 IDirectMusicDownloadedInstrumentImpl_Release
116 };
117
118 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
119 {
120 if (!iface)
121 return NULL;
122 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
123
124 return impl_from_IDirectMusicDownloadedInstrument(iface);
125 }
126
127 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
128 {
129 IDirectMusicDownloadedInstrumentImpl *object;
130
131 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
132 if (!object)
133 {
134 *instrument = NULL;
135 return E_OUTOFMEMORY;
136 }
137
138 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
139 object->ref = 1;
140
141 *instrument = &object->IDirectMusicDownloadedInstrument_iface;
142 DMUSIC_LockModule();
143
144 return S_OK;
145 }
146
147 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
148 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
149 {
150 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
151
152 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
153
154 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
155 *ret_iface = &This->IDirectMusicPort_iface;
156 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
157 *ret_iface = &This->IDirectMusicPortDownload_iface;
158 else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
159 *ret_iface = &This->IDirectMusicThru_iface;
160 else if (IsEqualGUID(riid, &IID_IKsControl))
161 *ret_iface = &This->IKsControl_iface;
162 else {
163 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
164 *ret_iface = NULL;
165 return E_NOINTERFACE;
166 }
167
168 IUnknown_AddRef((IUnknown*)*ret_iface);
169
170 return S_OK;
171 }
172
173 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
174 {
175 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
176 ULONG ref = InterlockedIncrement(&This->ref);
177
178 TRACE("(%p)->(): new ref = %u\n", This, ref);
179
180 DMUSIC_LockModule();
181
182 return ref;
183 }
184
185 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
186 {
187 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
188 ULONG ref = InterlockedDecrement(&This->ref);
189
190 TRACE("(%p)->(): new ref = %u\n", This, ref);
191
192 if (!ref)
193 {
194 IDirectMusicSynth_Activate(This->synth, FALSE);
195 IDirectMusicSynth_Close(This->synth);
196 IDirectMusicSynth_Release(This->synth);
197 IDirectMusicSynthSink_Release(This->synth_sink);
198 IReferenceClock_Release(This->pLatencyClock);
199 HeapFree(GetProcessHeap(), 0, This);
200 }
201
202 DMUSIC_UnlockModule();
203
204 return ref;
205 }
206
207 /* SynthPortImpl IDirectMusicPort interface follows: */
208 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
209 {
210 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
211 HRESULT hr;
212 REFERENCE_TIME time;
213 LPBYTE data;
214 DWORD size;
215
216 TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
217
218 if (!buffer)
219 return E_POINTER;
220
221 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
222
223 if (SUCCEEDED(hr))
224 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
225
226 if (SUCCEEDED(hr))
227 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
228
229 if (SUCCEEDED(hr))
230 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
231
232 return hr;
233 }
234
235 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
236 {
237 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
238
239 FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
240
241 return S_OK;
242 }
243
244 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
245 {
246 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
247
248 FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
249
250 return S_OK;
251 }
252
253 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
254 {
255 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
256 IDirectMusicInstrumentImpl *instrument_object;
257 HRESULT ret;
258 BOOL free;
259 HANDLE download;
260 DMUS_DOWNLOADINFO *info;
261 DMUS_OFFSETTABLE *offset_table;
262 DMUS_INSTRUMENT *instrument_info;
263 BYTE *data;
264 ULONG offset;
265 ULONG nb_regions;
266 ULONG size;
267 ULONG i;
268
269 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
270
271 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
272 return E_POINTER;
273
274 instrument_object = impl_from_IDirectMusicInstrument(instrument);
275
276 nb_regions = instrument_object->header.cRegions;
277 size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions;
278
279 data = HeapAlloc(GetProcessHeap(), 0, size);
280 if (!data)
281 return E_OUTOFMEMORY;
282
283 info = (DMUS_DOWNLOADINFO*)data;
284 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
285 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
286
287 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
288 info->dwDLId = 0;
289 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
290 info->cbSize = size;
291
292 offset_table->ulOffsetTable[0] = offset;
293 instrument_info = (DMUS_INSTRUMENT*)(data + offset);
294 offset += sizeof(DMUS_INSTRUMENT);
295 instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale);
296 instrument_info->ulFirstRegionIdx = 1;
297 instrument_info->ulGlobalArtIdx = 0; /* FIXME */
298 instrument_info->ulFirstExtCkIdx = 0; /* FIXME */
299 instrument_info->ulCopyrightIdx = 0; /* FIXME */
300 instrument_info->ulFlags = 0; /* FIXME */
301
302 for (i = 0; i < nb_regions; i++)
303 {
304 DMUS_REGION *region = (DMUS_REGION*)(data + offset);
305
306 offset_table->ulOffsetTable[1 + i] = offset;
307 offset += sizeof(DMUS_REGION);
308 region->RangeKey = instrument_object->regions[i].header.RangeKey;
309 region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity;
310 region->fusOptions = instrument_object->regions[i].header.fusOptions;
311 region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup;
312 region->ulRegionArtIdx = 0; /* FIXME */
313 region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
314 region->ulFirstExtCkIdx = 0; /* FIXME */
315 region->WaveLink = instrument_object->regions[i].wave_link;
316 region->WSMP = instrument_object->regions[i].wave_sample;
317 region->WLOOP[0] = instrument_object->regions[i].wave_loop;
318 }
319
320 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
321
322 if (SUCCEEDED(ret))
323 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
324
325 if (SUCCEEDED(ret))
326 {
327 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
328
329 downloaded_object->data = data;
330 downloaded_object->downloaded = TRUE;
331 }
332
333 *downloaded_instrument = NULL;
334 HeapFree(GetProcessHeap(), 0, data);
335
336 return E_FAIL;
337 }
338
339 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
340 {
341 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
342 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
343
344 TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument);
345
346 if (!downloaded_instrument)
347 return E_POINTER;
348
349 if (!downloaded_object->downloaded)
350 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
351
352 HeapFree(GetProcessHeap(), 0, downloaded_object->data);
353 downloaded_object->data = NULL;
354 downloaded_object->downloaded = FALSE;
355
356 return S_OK;
357 }
358
359 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
360 {
361 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
362
363 TRACE("(%p/%p)->(%p)\n", iface, This, clock);
364
365 *clock = This->pLatencyClock;
366 IReferenceClock_AddRef(*clock);
367
368 return S_OK;
369 }
370
371 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
372 {
373 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
374
375 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
376
377 return S_OK;
378 }
379
380 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
381 {
382 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
383
384 FIXME("(%p/%p)->(): stub\n", iface, This);
385
386 return S_OK;
387 }
388
389 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
390 {
391 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
392
393 TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
394
395 *port_caps = This->caps;
396
397 return S_OK;
398 }
399
400 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size,
401 LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped)
402 {
403 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
404
405 FIXME("(%p/%p)->(%d, %p, %d, %p, %d, %p, %p): stub\n", iface, This, io_control_code, in_buffer, in_buffer_size, out_buffer, out_buffer_size, bytes_returned, overlapped);
406
407 return S_OK;
408 }
409
410 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
411 {
412 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
413
414 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
415
416 This->nrofgroups = channel_groups;
417
418 return S_OK;
419 }
420
421 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
422 {
423 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
424
425 TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
426
427 *channel_groups = This->nrofgroups;
428
429 return S_OK;
430 }
431
432 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Activate(LPDIRECTMUSICPORT iface, BOOL active)
433 {
434 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
435
436 TRACE("(%p/%p)->(%d)\n", iface, This, active);
437
438 This->fActive = active;
439
440 return S_OK;
441 }
442
443 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
444 {
445 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
446
447 FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
448
449 if (channel > 16)
450 {
451 WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
452 /*return E_INVALIDARG;*/
453 }
454
455 return S_OK;
456 }
457
458 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
459 {
460 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
461
462 TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
463
464 *priority = This->group[channel_group - 1].channel[channel].priority;
465
466 return S_OK;
467 }
468
469 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetDirectSound(LPDIRECTMUSICPORT iface, LPDIRECTSOUND direct_sound, LPDIRECTSOUNDBUFFER direct_sound_buffer)
470 {
471 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
472
473 FIXME("(%p/%p)->(%p, %p): stub\n", iface, This, direct_sound, direct_sound_buffer);
474
475 return S_OK;
476 }
477
478 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
479 {
480 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
481 WAVEFORMATEX format;
482 FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
483
484 if (pWaveFormatEx == NULL)
485 {
486 if (pdwWaveFormatExSize)
487 *pdwWaveFormatExSize = sizeof(format);
488 else
489 return E_POINTER;
490 }
491 else
492 {
493 if (pdwWaveFormatExSize == NULL)
494 return E_POINTER;
495
496 /* Just fill this in with something that will not crash Direct Sound for now. */
497 /* It won't be used anyway until Performances are completed */
498 format.wFormatTag = WAVE_FORMAT_PCM;
499 format.nChannels = 2; /* This->params.dwAudioChannels; */
500 format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */
501 format.wBitsPerSample = 16; /* FIXME: check this */
502 format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8;
503 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
504 format.cbSize = 0;
505
506 if (*pdwWaveFormatExSize >= sizeof(format))
507 {
508 CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
509 *pdwWaveFormatExSize = sizeof(format); /* FIXME check if this is set */
510 }
511 else
512 return E_POINTER; /* FIXME find right error */
513 }
514
515 if (pdwBufferSize)
516 *pdwBufferSize = 44100 * 2 * 2;
517 else
518 return E_POINTER;
519
520 return S_OK;
521 }
522
523 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = {
524 /**** IDirectMusicPort IUnknown part methods ***/
525 SynthPortImpl_IDirectMusicPort_QueryInterface,
526 SynthPortImpl_IDirectMusicPort_AddRef,
527 SynthPortImpl_IDirectMusicPort_Release,
528 /**** IDirectMusicPort methods ***/
529 SynthPortImpl_IDirectMusicPort_PlayBuffer,
530 SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle,
531 SynthPortImpl_IDirectMusicPort_Read,
532 SynthPortImpl_IDirectMusicPort_DownloadInstrument,
533 SynthPortImpl_IDirectMusicPort_UnloadInstrument,
534 SynthPortImpl_IDirectMusicPort_GetLatencyClock,
535 SynthPortImpl_IDirectMusicPort_GetRunningStats,
536 SynthPortImpl_IDirectMusicPort_Compact,
537 SynthPortImpl_IDirectMusicPort_GetCaps,
538 SynthPortImpl_IDirectMusicPort_DeviceIoControl,
539 SynthPortImpl_IDirectMusicPort_SetNumChannelGroups,
540 SynthPortImpl_IDirectMusicPort_GetNumChannelGroups,
541 SynthPortImpl_IDirectMusicPort_Activate,
542 SynthPortImpl_IDirectMusicPort_SetChannelPriority,
543 SynthPortImpl_IDirectMusicPort_GetChannelPriority,
544 SynthPortImpl_IDirectMusicPort_SetDirectSound,
545 SynthPortImpl_IDirectMusicPort_GetFormat
546 };
547
548 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
549 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
550 {
551 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
552
553 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
554
555 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
556 }
557
558 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
559 {
560 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
561
562 TRACE("(%p/%p)->()\n", iface, This);
563
564 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
565 }
566
567 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
568 {
569 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
570
571 TRACE("(%p/%p)->()\n", iface, This);
572
573 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
574 }
575
576 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
577 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
578 {
579 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
580
581 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
582
583 if (!IDMDownload)
584 return E_POINTER;
585
586 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
587 }
588
589 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
590 {
591 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
592
593 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
594
595 return S_OK;
596 }
597
598 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
599 {
600 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
601
602 FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
603
604 return S_OK;
605 }
606
607 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
608 {
609 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
610
611 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
612
613 return S_OK;
614 }
615
616 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
617 {
618 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
619
620 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
621
622 return S_OK;
623 }
624
625 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
626 {
627 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
628
629 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
630
631 return S_OK;
632 }
633
634 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = {
635 /*** IDirectMusicPortDownload IUnknown part methods ***/
636 SynthPortImpl_IDirectMusicPortDownload_QueryInterface,
637 SynthPortImpl_IDirectMusicPortDownload_AddRef,
638 SynthPortImpl_IDirectMusicPortDownload_Release,
639 /*** IDirectMusicPortDownload methods ***/
640 SynthPortImpl_IDirectMusicPortDownload_GetBuffer,
641 SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer,
642 SynthPortImpl_IDirectMusicPortDownload_GetDLId,
643 SynthPortImpl_IDirectMusicPortDownload_GetAppend,
644 SynthPortImpl_IDirectMusicPortDownload_Download,
645 SynthPortImpl_IDirectMusicPortDownload_Unload
646 };
647
648 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
649 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
650 {
651 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
652
653 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
654
655 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
656 }
657
658 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
659 {
660 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
661
662 TRACE("(%p/%p)->()\n", iface, This);
663
664 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
665 }
666
667 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
668 {
669 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
670
671 TRACE("(%p/%p)->()\n", iface, This);
672
673 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
674 }
675
676 /* SynthPortImpl IDirectMusicThru Interface follows: */
677 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group,
678 DWORD destination_channel, LPDIRECTMUSICPORT destination_port)
679 {
680 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
681
682 FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
683
684 return S_OK;
685 }
686
687 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = {
688 /*** IDirectMusicThru IUnknown part methods */
689 SynthPortImpl_IDirectMusicThru_QueryInterface,
690 SynthPortImpl_IDirectMusicThru_AddRef,
691 SynthPortImpl_IDirectMusicThru_Release,
692 /*** IDirectMusicThru methods ***/
693 SynthPortImpl_IDirectMusicThru_ThruChannel
694 };
695
696 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
697 void **ret_iface)
698 {
699 SynthPortImpl *This = impl_from_IKsControl(iface);
700
701 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
702 }
703
704 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
705 {
706 SynthPortImpl *This = impl_from_IKsControl(iface);
707
708 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
709 }
710
711 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
712 {
713 SynthPortImpl *This = impl_from_IKsControl(iface);
714
715 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
716 }
717
718 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
719 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
720 {
721 TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
722 TRACE("prop = %s - %u - %u\n", debugstr_guid(&prop->Set), prop->Id, prop->Flags);
723
724 if (prop->Flags != KSPROPERTY_TYPE_GET)
725 {
726 FIXME("prop flags %u not yet supported\n", prop->Flags);
727 return S_FALSE;
728 }
729
730 if (data_len < sizeof(DWORD))
731 return E_NOT_SUFFICIENT_BUFFER;
732
733 FIXME("Unknown property %s\n", debugstr_guid(&prop->Set));
734 *(DWORD*)data = FALSE;
735 *ret_len = sizeof(DWORD);
736
737 return S_OK;
738 }
739
740 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
741 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
742 {
743 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
744
745 return E_NOTIMPL;
746 }
747
748 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
749 void *data, ULONG data_len, ULONG *ret_len)
750 {
751 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
752
753 return E_NOTIMPL;
754 }
755
756 static const IKsControlVtbl ikscontrol_vtbl = {
757 IKsControlImpl_QueryInterface,
758 IKsControlImpl_AddRef,
759 IKsControlImpl_Release,
760 IKsControlImpl_KsProperty,
761 IKsControlImpl_KsMethod,
762 IKsControlImpl_KsEvent
763 };
764
765 HRESULT DMUSIC_CreateSynthPortImpl(LPCGUID guid, LPVOID *object, LPUNKNOWN unkouter, LPDMUS_PORTPARAMS port_params, LPDMUS_PORTCAPS port_caps, DWORD device)
766 {
767 SynthPortImpl *obj;
768 HRESULT hr = E_FAIL;
769 int i;
770
771 TRACE("(%s, %p, %p, %p, %p, %d)\n", debugstr_guid(guid), object, unkouter, port_params,
772 port_caps, device);
773
774 *object = NULL;
775
776 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
777 if (!obj)
778 return E_OUTOFMEMORY;
779
780 obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl;
781 obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl;
782 obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl;
783 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
784 obj->ref = 0; /* Will be inited by QueryInterface */
785 obj->fActive = FALSE;
786 obj->params = *port_params;
787 obj->caps = *port_caps;
788
789 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
790 if (hr != S_OK)
791 {
792 HeapFree(GetProcessHeap(), 0, obj);
793 return hr;
794 }
795
796 if (SUCCEEDED(hr))
797 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
798
799 if (SUCCEEDED(hr))
800 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
801
802 if (SUCCEEDED(hr))
803 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
804
805 if (SUCCEEDED(hr))
806 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
807
808 if (SUCCEEDED(hr))
809 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
810
811 if (SUCCEEDED(hr))
812 hr = IDirectMusicSynth_Open(obj->synth, port_params);
813
814 if (0)
815 {
816 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
817 obj->nrofgroups = port_params->dwChannelGroups;
818 /* Setting default priorities */
819 for (i = 0; i < obj->nrofgroups; i++) {
820 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
821 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
822 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
823 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
824 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
825 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
826 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
827 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
828 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
829 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
830 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
831 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
832 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
833 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
834 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
835 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
836 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
837 }
838 }
839 }
840
841 if (SUCCEEDED(hr))
842 return IDirectMusicPort_QueryInterface((LPDIRECTMUSICPORT)obj, guid, object);
843
844 if (obj->synth)
845 IDirectMusicSynth_Release(obj->synth);
846 if (obj->synth_sink)
847 IDirectMusicSynthSink_Release(obj->synth_sink);
848 if (obj->pLatencyClock)
849 IReferenceClock_Release(obj->pLatencyClock);
850 HeapFree(GetProcessHeap(), 0, obj);
851
852 return hr;
853 }
854
855 HRESULT DMUSIC_CreateMidiOutPortImpl(LPCGUID guid, LPVOID *object, LPUNKNOWN unkouter, LPDMUS_PORTPARAMS port_params, LPDMUS_PORTCAPS port_caps, DWORD device)
856 {
857 TRACE("(%s, %p, %p, %p, %p, %d): stub\n", debugstr_guid(guid), object, unkouter, port_params,
858 port_caps, device);
859
860 return E_NOTIMPL;
861 }
862
863 HRESULT DMUSIC_CreateMidiInPortImpl(LPCGUID guid, LPVOID *object, LPUNKNOWN unkouter, LPDMUS_PORTPARAMS port_params, LPDMUS_PORTCAPS port_caps, DWORD device)
864 {
865 TRACE("(%s, %p, %p, %p, %p, %d): stub\n", debugstr_guid(guid), object, unkouter, port_params,
866 port_caps, device);
867
868 return E_NOTIMPL;
869 }