xref: /reactos/dll/directx/wine/dmusic/port.c (revision a16afc25)
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 <assert.h>
23 #include "dmusic_private.h"
24 #include "wine/heap.h"
25 
26 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
27 
28 typedef struct SynthPortImpl {
29     IDirectMusicPort IDirectMusicPort_iface;
30     IDirectMusicPortDownload IDirectMusicPortDownload_iface;
31     IDirectMusicThru IDirectMusicThru_iface;
32     IKsControl IKsControl_iface;
33     LONG ref;
34     IDirectMusic8Impl *parent;
35     IDirectSound *dsound;
36     IDirectSoundBuffer *dsbuffer;
37     IReferenceClock *pLatencyClock;
38     IDirectMusicSynth *synth;
39     IDirectMusicSynthSink *synth_sink;
40     BOOL active;
41     DMUS_PORTCAPS caps;
42     DMUS_PORTPARAMS params;
43     int nrofgroups;
44     DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
45 } SynthPortImpl;
46 
impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument * iface)47 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
48 {
49     return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
50 }
51 
impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort * iface)52 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
53 {
54     return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
55 }
56 
impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload * iface)57 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
58 {
59     return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
60 }
61 
impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru * iface)62 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
63 {
64     return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
65 }
66 
impl_from_IKsControl(IKsControl * iface)67 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface)
68 {
69     return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface);
70 }
71 
72 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument * iface,REFIID riid,VOID ** ret_iface)73 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
74 {
75     TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
76 
77     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
78     {
79         IDirectMusicDownloadedInstrument_AddRef(iface);
80         *ret_iface = iface;
81         return S_OK;
82     }
83 
84     WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
85 
86     return E_NOINTERFACE;
87 }
88 
IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)89 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
90 {
91     IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
92     ULONG ref = InterlockedIncrement(&This->ref);
93 
94     TRACE("(%p)->(): new ref = %u\n", iface, ref);
95 
96     return ref;
97 }
98 
IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)99 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
100 {
101     IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
102     ULONG ref = InterlockedDecrement(&This->ref);
103 
104     TRACE("(%p)->(): new ref = %u\n", iface, ref);
105 
106     if (!ref)
107     {
108         HeapFree(GetProcessHeap(), 0, This->data);
109         HeapFree(GetProcessHeap(), 0, This);
110         DMUSIC_UnlockModule();
111     }
112 
113     return ref;
114 }
115 
116 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
117     IDirectMusicDownloadedInstrumentImpl_QueryInterface,
118     IDirectMusicDownloadedInstrumentImpl_AddRef,
119     IDirectMusicDownloadedInstrumentImpl_Release
120 };
121 
unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument * iface)122 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
123 {
124     if (!iface)
125         return NULL;
126     assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
127 
128     return impl_from_IDirectMusicDownloadedInstrument(iface);
129 }
130 
DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument ** instrument)131 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
132 {
133     IDirectMusicDownloadedInstrumentImpl *object;
134 
135     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
136     if (!object)
137     {
138         *instrument = NULL;
139         return E_OUTOFMEMORY;
140     }
141 
142     object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
143     object->ref = 1;
144 
145     *instrument = &object->IDirectMusicDownloadedInstrument_iface;
146     DMUSIC_LockModule();
147 
148     return S_OK;
149 }
150 
151 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface,REFIID riid,LPVOID * ret_iface)152 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
153 {
154     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
155 
156     TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
157 
158     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
159         *ret_iface = &This->IDirectMusicPort_iface;
160     else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
161         *ret_iface = &This->IDirectMusicPortDownload_iface;
162     else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
163         *ret_iface = &This->IDirectMusicThru_iface;
164     else if (IsEqualGUID(riid, &IID_IKsControl))
165         *ret_iface = &This->IKsControl_iface;
166     else {
167         WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
168         *ret_iface = NULL;
169         return E_NOINTERFACE;
170     }
171 
172     IUnknown_AddRef((IUnknown*)*ret_iface);
173 
174     return S_OK;
175 }
176 
SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)177 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
178 {
179     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
180     ULONG ref = InterlockedIncrement(&This->ref);
181 
182     TRACE("(%p)->(): new ref = %u\n", This, ref);
183 
184     DMUSIC_LockModule();
185 
186     return ref;
187 }
188 
SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)189 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
190 {
191     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
192     ULONG ref = InterlockedDecrement(&This->ref);
193 
194     TRACE("(%p)->(): new ref = %u\n", This, ref);
195 
196     if (!ref)
197     {
198         dmusic_remove_port(This->parent, iface);
199         IDirectMusicSynth_Activate(This->synth, FALSE);
200         IDirectMusicSynth_Close(This->synth);
201         IDirectMusicSynth_Release(This->synth);
202         IDirectMusicSynthSink_Release(This->synth_sink);
203         IReferenceClock_Release(This->pLatencyClock);
204         if (This->dsbuffer)
205            IDirectSoundBuffer_Release(This->dsbuffer);
206         if (This->dsound)
207            IDirectSound_Release(This->dsound);
208         HeapFree(GetProcessHeap(), 0, This);
209     }
210 
211     DMUSIC_UnlockModule();
212 
213     return ref;
214 }
215 
216 /* SynthPortImpl IDirectMusicPort interface follows: */
SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface,LPDIRECTMUSICBUFFER buffer)217 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
218 {
219     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
220     HRESULT hr;
221     REFERENCE_TIME time;
222     LPBYTE data;
223     DWORD size;
224 
225     TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
226 
227     if (!buffer)
228         return E_POINTER;
229 
230     hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
231 
232     if (SUCCEEDED(hr))
233         hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
234 
235     if (SUCCEEDED(hr))
236         hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
237 
238     if (SUCCEEDED(hr))
239         hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
240 
241     return hr;
242 }
243 
SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface,HANDLE event)244 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
245 {
246     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
247 
248     FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
249 
250     return S_OK;
251 }
252 
SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface,LPDIRECTMUSICBUFFER buffer)253 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
254 {
255     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
256 
257     FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
258 
259     return S_OK;
260 }
261 
SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface,IDirectMusicInstrument * instrument,IDirectMusicDownloadedInstrument ** downloaded_instrument,DMUS_NOTERANGE * note_ranges,DWORD num_note_ranges)262 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
263 {
264     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
265     IDirectMusicInstrumentImpl *instrument_object;
266     HRESULT ret;
267     BOOL free;
268     HANDLE download;
269     DMUS_DOWNLOADINFO *info;
270     DMUS_OFFSETTABLE *offset_table;
271     DMUS_INSTRUMENT *instrument_info;
272     BYTE *data;
273     ULONG offset;
274     ULONG nb_regions;
275     ULONG size;
276     ULONG i;
277 
278     TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
279 
280     if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
281         return E_POINTER;
282 
283     instrument_object = impl_from_IDirectMusicInstrument(instrument);
284 
285     nb_regions = instrument_object->header.cRegions;
286     size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions;
287 
288     data = HeapAlloc(GetProcessHeap(), 0, size);
289     if (!data)
290         return E_OUTOFMEMORY;
291 
292     info = (DMUS_DOWNLOADINFO*)data;
293     offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
294     offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
295 
296     info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
297     info->dwDLId = 0;
298     info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
299     info->cbSize = size;
300 
301     offset_table->ulOffsetTable[0] = offset;
302     instrument_info = (DMUS_INSTRUMENT*)(data + offset);
303     offset += sizeof(DMUS_INSTRUMENT);
304     instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale);
305     instrument_info->ulFirstRegionIdx = 1;
306     instrument_info->ulGlobalArtIdx = 0; /* FIXME */
307     instrument_info->ulFirstExtCkIdx = 0; /* FIXME */
308     instrument_info->ulCopyrightIdx = 0; /* FIXME */
309     instrument_info->ulFlags = 0; /* FIXME */
310 
311     for (i = 0;  i < nb_regions; i++)
312     {
313         DMUS_REGION *region = (DMUS_REGION*)(data + offset);
314 
315         offset_table->ulOffsetTable[1 + i] = offset;
316         offset += sizeof(DMUS_REGION);
317         region->RangeKey = instrument_object->regions[i].header.RangeKey;
318         region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity;
319         region->fusOptions = instrument_object->regions[i].header.fusOptions;
320         region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup;
321         region->ulRegionArtIdx = 0; /* FIXME */
322         region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
323         region->ulFirstExtCkIdx = 0; /* FIXME */
324         region->WaveLink = instrument_object->regions[i].wave_link;
325         region->WSMP = instrument_object->regions[i].wave_sample;
326         region->WLOOP[0] = instrument_object->regions[i].wave_loop;
327     }
328 
329     ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
330 
331     if (SUCCEEDED(ret))
332         ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
333 
334     if (SUCCEEDED(ret))
335     {
336         IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
337 
338         downloaded_object->data = data;
339         downloaded_object->downloaded = TRUE;
340     }
341 
342     *downloaded_instrument = NULL;
343     HeapFree(GetProcessHeap(), 0, data);
344 
345     return E_FAIL;
346 }
347 
SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface,IDirectMusicDownloadedInstrument * downloaded_instrument)348 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
349 {
350     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
351     IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
352 
353     TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument);
354 
355     if (!downloaded_instrument)
356         return E_POINTER;
357 
358     if (!downloaded_object->downloaded)
359         return DMUS_E_NOT_DOWNLOADED_TO_PORT;
360 
361     HeapFree(GetProcessHeap(), 0, downloaded_object->data);
362     downloaded_object->data = NULL;
363     downloaded_object->downloaded = FALSE;
364 
365     return S_OK;
366 }
367 
SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface,IReferenceClock ** clock)368 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
369 {
370     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
371 
372     TRACE("(%p/%p)->(%p)\n", iface, This, clock);
373 
374     *clock = This->pLatencyClock;
375     IReferenceClock_AddRef(*clock);
376 
377     return S_OK;
378 }
379 
SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface,LPDMUS_SYNTHSTATS stats)380 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
381 {
382     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
383 
384     FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
385 
386     return S_OK;
387 }
388 
SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)389 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
390 {
391     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
392 
393     FIXME("(%p/%p)->(): stub\n", iface, This);
394 
395     return S_OK;
396 }
397 
SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface,LPDMUS_PORTCAPS port_caps)398 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
399 {
400     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
401 
402     TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
403 
404     *port_caps = This->caps;
405 
406     return S_OK;
407 }
408 
SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface,DWORD io_control_code,LPVOID in_buffer,DWORD in_buffer_size,LPVOID out_buffer,DWORD out_buffer_size,LPDWORD bytes_returned,LPOVERLAPPED overlapped)409 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size,
410                                                            LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped)
411 {
412     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
413 
414     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);
415 
416     return S_OK;
417 }
418 
SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface,DWORD channel_groups)419 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
420 {
421     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
422 
423     FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
424 
425     This->nrofgroups = channel_groups;
426 
427     return S_OK;
428 }
429 
SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface,LPDWORD channel_groups)430 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
431 {
432     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
433 
434     TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
435 
436     *channel_groups = This->nrofgroups;
437 
438     return S_OK;
439 }
440 
synth_dmport_Activate(IDirectMusicPort * iface,BOOL active)441 static HRESULT WINAPI synth_dmport_Activate(IDirectMusicPort *iface, BOOL active)
442 {
443     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
444 
445     FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
446 
447     if (This->active == active)
448         return S_FALSE;
449 
450     if (active) {
451         /* Acquire the dsound */
452         if (!This->dsound) {
453             IDirectSound_AddRef(This->parent->dsound);
454             This->dsound = This->parent->dsound;
455         }
456         IDirectSound_AddRef(This->dsound);
457     } else {
458         /* Release the dsound */
459         IDirectSound_Release(This->dsound);
460         IDirectSound_Release(This->parent->dsound);
461         if (This->dsound == This->parent->dsound)
462             This->dsound = NULL;
463     }
464 
465     This->active = active;
466 
467     return S_OK;
468 }
469 
SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface,DWORD channel_group,DWORD channel,DWORD priority)470 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
471 {
472     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
473 
474     FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
475 
476     if (channel > 16)
477     {
478         WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
479         /*return E_INVALIDARG;*/
480     }
481 
482     return S_OK;
483 }
484 
SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface,DWORD channel_group,DWORD channel,LPDWORD priority)485 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
486 {
487     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
488 
489     TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
490 
491     *priority = This->group[channel_group - 1].channel[channel].priority;
492 
493     return S_OK;
494 }
495 
synth_dmport_SetDirectSound(IDirectMusicPort * iface,IDirectSound * dsound,IDirectSoundBuffer * dsbuffer)496 static HRESULT WINAPI synth_dmport_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
497         IDirectSoundBuffer *dsbuffer)
498 {
499     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
500 
501     FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
502 
503     if (This->active)
504         return DMUS_E_DSOUND_ALREADY_SET;
505 
506     if (This->dsound) {
507         if (This->dsound != This->parent->dsound)
508             ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
509                     This->dsound, This->parent->dsound);
510         if (!IDirectSound_Release(This->parent->dsound))
511             This->parent->dsound = NULL;
512     }
513     if (This->dsbuffer)
514         IDirectSoundBuffer_Release(This->dsbuffer);
515 
516     This->dsound = dsound;
517     This->dsbuffer = dsbuffer;
518 
519     if (This->dsound)
520         IDirectSound_AddRef(This->dsound);
521     if (This->dsbuffer)
522         IDirectSoundBuffer_AddRef(This->dsbuffer);
523 
524     return S_OK;
525 }
526 
SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface,LPWAVEFORMATEX pWaveFormatEx,LPDWORD pdwWaveFormatExSize,LPDWORD pdwBufferSize)527 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
528 {
529 	SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
530 	WAVEFORMATEX format;
531 	FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
532 
533 	if (pWaveFormatEx == NULL)
534 	{
535 		if (pdwWaveFormatExSize)
536 			*pdwWaveFormatExSize = sizeof(format);
537 		else
538 			return E_POINTER;
539 	}
540 	else
541 	{
542 		if (pdwWaveFormatExSize == NULL)
543 			return E_POINTER;
544 
545 		/* Just fill this in with something that will not crash Direct Sound for now. */
546 		/* It won't be used anyway until Performances are completed */
547 		format.wFormatTag = WAVE_FORMAT_PCM;
548 		format.nChannels = 2; /* This->params.dwAudioChannels; */
549 		format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */
550 		format.wBitsPerSample = 16;	/* FIXME: check this */
551 		format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8;
552 		format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
553 		format.cbSize = 0;
554 
555 		if (*pdwWaveFormatExSize >= sizeof(format))
556 		{
557 			CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
558 			*pdwWaveFormatExSize = sizeof(format);	/* FIXME check if this is set */
559 		}
560 		else
561 			return E_POINTER;	/* FIXME find right error */
562 	}
563 
564 	if (pdwBufferSize)
565 		*pdwBufferSize = 44100 * 2 * 2;
566 	else
567 		return E_POINTER;
568 
569 	return S_OK;
570 }
571 
572 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = {
573     /**** IDirectMusicPort IUnknown part methods ***/
574     SynthPortImpl_IDirectMusicPort_QueryInterface,
575     SynthPortImpl_IDirectMusicPort_AddRef,
576     SynthPortImpl_IDirectMusicPort_Release,
577     /**** IDirectMusicPort methods ***/
578     SynthPortImpl_IDirectMusicPort_PlayBuffer,
579     SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle,
580     SynthPortImpl_IDirectMusicPort_Read,
581     SynthPortImpl_IDirectMusicPort_DownloadInstrument,
582     SynthPortImpl_IDirectMusicPort_UnloadInstrument,
583     SynthPortImpl_IDirectMusicPort_GetLatencyClock,
584     SynthPortImpl_IDirectMusicPort_GetRunningStats,
585     SynthPortImpl_IDirectMusicPort_Compact,
586     SynthPortImpl_IDirectMusicPort_GetCaps,
587     SynthPortImpl_IDirectMusicPort_DeviceIoControl,
588     SynthPortImpl_IDirectMusicPort_SetNumChannelGroups,
589     SynthPortImpl_IDirectMusicPort_GetNumChannelGroups,
590     synth_dmport_Activate,
591     SynthPortImpl_IDirectMusicPort_SetChannelPriority,
592     SynthPortImpl_IDirectMusicPort_GetChannelPriority,
593     synth_dmport_SetDirectSound,
594     SynthPortImpl_IDirectMusicPort_GetFormat
595 };
596 
597 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface,REFIID riid,LPVOID * ret_iface)598 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
599 {
600     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
601 
602     TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
603 
604     return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
605 }
606 
SynthPortImpl_IDirectMusicPortDownload_AddRef(LPDIRECTMUSICPORTDOWNLOAD iface)607 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
608 {
609     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
610 
611     TRACE("(%p/%p)->()\n", iface, This);
612 
613     return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
614 }
615 
SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)616 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
617 {
618     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
619 
620     TRACE("(%p/%p)->()\n", iface, This);
621 
622     return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
623 }
624 
625 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD DLId,IDirectMusicDownload ** IDMDownload)626 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
627 {
628     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
629 
630     FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
631 
632     if (!IDMDownload)
633         return E_POINTER;
634 
635     return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
636 }
637 
SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD size,IDirectMusicDownload ** IDMDownload)638 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
639 {
640     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
641 
642     FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
643 
644     return S_OK;
645 }
646 
SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD * start_DLId,DWORD count)647 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
648 {
649     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
650 
651     FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
652 
653     return S_OK;
654 }
655 
SynthPortImpl_IDirectMusicPortDownload_GetAppend(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD * append)656 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
657 {
658     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
659 
660     FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
661 
662     return S_OK;
663 }
664 
SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface,IDirectMusicDownload * IDMDownload)665 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
666 {
667     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
668 
669     FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
670 
671     return S_OK;
672 }
673 
SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface,IDirectMusicDownload * IDMDownload)674 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
675 {
676     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
677 
678     FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
679 
680     return S_OK;
681 }
682 
683 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = {
684     /*** IDirectMusicPortDownload IUnknown part methods ***/
685     SynthPortImpl_IDirectMusicPortDownload_QueryInterface,
686     SynthPortImpl_IDirectMusicPortDownload_AddRef,
687     SynthPortImpl_IDirectMusicPortDownload_Release,
688     /*** IDirectMusicPortDownload methods ***/
689     SynthPortImpl_IDirectMusicPortDownload_GetBuffer,
690     SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer,
691     SynthPortImpl_IDirectMusicPortDownload_GetDLId,
692     SynthPortImpl_IDirectMusicPortDownload_GetAppend,
693     SynthPortImpl_IDirectMusicPortDownload_Download,
694     SynthPortImpl_IDirectMusicPortDownload_Unload
695 };
696 
697 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface,REFIID riid,LPVOID * ret_iface)698 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
699 {
700     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
701 
702     TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
703 
704     return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
705 }
706 
SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)707 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
708 {
709     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
710 
711     TRACE("(%p/%p)->()\n", iface, This);
712 
713     return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
714 }
715 
SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)716 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
717 {
718     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
719 
720     TRACE("(%p/%p)->()\n", iface, This);
721 
722     return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
723 }
724 
725 /*  SynthPortImpl IDirectMusicThru Interface follows: */
SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface,DWORD source_channel_group,DWORD source_channel,DWORD destination_channel_group,DWORD destination_channel,LPDIRECTMUSICPORT destination_port)726 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group,
727                                                        DWORD destination_channel, LPDIRECTMUSICPORT destination_port)
728 {
729     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
730 
731     FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
732 
733     return S_OK;
734 }
735 
736 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = {
737     /*** IDirectMusicThru IUnknown part methods */
738     SynthPortImpl_IDirectMusicThru_QueryInterface,
739     SynthPortImpl_IDirectMusicThru_AddRef,
740     SynthPortImpl_IDirectMusicThru_Release,
741     /*** IDirectMusicThru methods ***/
742     SynthPortImpl_IDirectMusicThru_ThruChannel
743 };
744 
IKsControlImpl_QueryInterface(IKsControl * iface,REFIID riid,void ** ret_iface)745 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
746         void **ret_iface)
747 {
748     SynthPortImpl *This = impl_from_IKsControl(iface);
749 
750     return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
751 }
752 
IKsControlImpl_AddRef(IKsControl * iface)753 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
754 {
755     SynthPortImpl *This = impl_from_IKsControl(iface);
756 
757     return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
758 }
759 
IKsControlImpl_Release(IKsControl * iface)760 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
761 {
762     SynthPortImpl *This = impl_from_IKsControl(iface);
763 
764     return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
765 }
766 
IKsControlImpl_KsProperty(IKsControl * iface,KSPROPERTY * prop,ULONG prop_len,void * data,ULONG data_len,ULONG * ret_len)767 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
768         ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
769 {
770     TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
771     TRACE("prop = %s - %u - %u\n", debugstr_guid(&prop->u.s.Set), prop->u.s.Id, prop->u.s.Flags);
772 
773     if (prop->u.s.Flags != KSPROPERTY_TYPE_GET)
774     {
775         FIXME("prop flags %u not yet supported\n", prop->u.s.Flags);
776         return S_FALSE;
777     }
778 
779     if (data_len <  sizeof(DWORD))
780         return E_NOT_SUFFICIENT_BUFFER;
781 
782     FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set));
783     *(DWORD*)data = FALSE;
784     *ret_len = sizeof(DWORD);
785 
786     return S_OK;
787 }
788 
IKsControlImpl_KsMethod(IKsControl * iface,KSMETHOD * method,ULONG method_len,void * data,ULONG data_len,ULONG * ret_len)789 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
790         ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
791 {
792     FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
793 
794     return E_NOTIMPL;
795 }
796 
IKsControlImpl_KsEvent(IKsControl * iface,KSEVENT * event,ULONG event_len,void * data,ULONG data_len,ULONG * ret_len)797 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
798         void *data, ULONG data_len, ULONG *ret_len)
799 {
800     FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
801 
802     return E_NOTIMPL;
803 }
804 
805 static const IKsControlVtbl ikscontrol_vtbl = {
806     IKsControlImpl_QueryInterface,
807     IKsControlImpl_AddRef,
808     IKsControlImpl_Release,
809     IKsControlImpl_KsProperty,
810     IKsControlImpl_KsMethod,
811     IKsControlImpl_KsEvent
812 };
813 
synth_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * port_params,DMUS_PORTCAPS * port_caps,IDirectMusicPort ** port)814 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
815         DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
816 {
817     SynthPortImpl *obj;
818     HRESULT hr = E_FAIL;
819     int i;
820 
821     TRACE("(%p, %p, %p)\n", port_params, port_caps, port);
822 
823     *port = NULL;
824 
825     obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
826     if (!obj)
827         return E_OUTOFMEMORY;
828 
829     obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl;
830     obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl;
831     obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl;
832     obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
833     obj->ref = 1;
834     obj->parent = parent;
835     obj->active = FALSE;
836     obj->params = *port_params;
837     obj->caps = *port_caps;
838 
839     hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
840     if (hr != S_OK)
841     {
842         HeapFree(GetProcessHeap(), 0, obj);
843         return hr;
844     }
845 
846     if (SUCCEEDED(hr))
847         hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
848 
849     if (SUCCEEDED(hr))
850         hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
851 
852     if (SUCCEEDED(hr))
853         hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
854 
855     if (SUCCEEDED(hr))
856         hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
857 
858     if (SUCCEEDED(hr))
859         hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
860 
861     if (SUCCEEDED(hr))
862         hr = IDirectMusicSynth_Open(obj->synth, port_params);
863 
864     if (0)
865     {
866         if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
867             obj->nrofgroups = port_params->dwChannelGroups;
868             /* Setting default priorities */
869             for (i = 0; i < obj->nrofgroups; i++) {
870                 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
871                 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
872                 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
873                 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
874                 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
875                 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
876                 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
877                 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
878                 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
879                 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
880                 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
881                 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
882                 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
883                 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
884                 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
885                 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
886                 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
887             }
888         }
889     }
890 
891     if (SUCCEEDED(hr)) {
892         *port = &obj->IDirectMusicPort_iface;
893         return S_OK;
894     }
895 
896     if (obj->synth)
897         IDirectMusicSynth_Release(obj->synth);
898     if (obj->synth_sink)
899         IDirectMusicSynthSink_Release(obj->synth_sink);
900     if (obj->pLatencyClock)
901         IReferenceClock_Release(obj->pLatencyClock);
902     HeapFree(GetProcessHeap(), 0, obj);
903 
904     return hr;
905 }
906 
907 struct midi_port {
908     IDirectMusicPort IDirectMusicPort_iface;
909     IDirectMusicThru IDirectMusicThru_iface;
910     LONG ref;
911     IReferenceClock *clock;
912 };
913 
impl_from_IDirectMusicPort(IDirectMusicPort * iface)914 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
915 {
916     return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
917 }
918 
midi_IDirectMusicPort_QueryInterface(IDirectMusicPort * iface,REFIID riid,void ** ret_iface)919 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
920         void **ret_iface)
921 {
922     struct midi_port *This = impl_from_IDirectMusicPort(iface);
923 
924     TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
925 
926     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
927         *ret_iface = iface;
928     else if (IsEqualIID(riid, &IID_IDirectMusicThru))
929         *ret_iface = &This->IDirectMusicThru_iface;
930     else {
931         WARN("no interface for %s\n", debugstr_dmguid(riid));
932         *ret_iface = NULL;
933         return E_NOINTERFACE;
934     }
935 
936     IUnknown_AddRef((IUnknown *)*ret_iface);
937 
938     return S_OK;
939 }
940 
midi_IDirectMusicPort_AddRef(IDirectMusicPort * iface)941 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
942 {
943     struct midi_port *This = impl_from_IDirectMusicPort(iface);
944     ULONG ref = InterlockedIncrement(&This->ref);
945 
946     TRACE("(%p) ref = %u\n", iface, ref);
947 
948     return ref;
949 }
950 
midi_IDirectMusicPort_Release(IDirectMusicPort * iface)951 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
952 {
953     struct midi_port *This = impl_from_IDirectMusicPort(iface);
954     ULONG ref = InterlockedDecrement(&This->ref);
955 
956     TRACE("(%p) ref = %u\n", iface, ref);
957 
958     if (!ref) {
959         if (This->clock)
960             IReferenceClock_Release(This->clock);
961         heap_free(This);
962     }
963 
964     return ref;
965 }
966 
midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort * iface,IDirectMusicBuffer * buffer)967 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
968         IDirectMusicBuffer *buffer)
969 {
970     FIXME("(%p, %p) stub!\n", iface, buffer);
971 
972     return E_NOTIMPL;
973 }
974 
midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort * iface,HANDLE event)975 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
976         HANDLE event)
977 {
978     FIXME("(%p, %p) stub!\n", iface, event);
979 
980     return S_OK;
981 }
982 
midi_IDirectMusicPort_Read(IDirectMusicPort * iface,IDirectMusicBuffer * buffer)983 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
984         IDirectMusicBuffer *buffer)
985 {
986     FIXME("(%p, %p) stub!\n", iface, buffer);
987 
988     return E_NOTIMPL;
989 }
990 
midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort * iface,IDirectMusicInstrument * instrument,IDirectMusicDownloadedInstrument ** downloaded,DMUS_NOTERANGE * ranges,DWORD num_ranges)991 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
992         IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
993         DMUS_NOTERANGE *ranges, DWORD num_ranges)
994 {
995     FIXME("(%p, %p, %p, %p, %u) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
996 
997     return E_NOTIMPL;
998 }
999 
midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort * iface,IDirectMusicDownloadedInstrument * downloaded)1000 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
1001         IDirectMusicDownloadedInstrument *downloaded)
1002 {
1003     FIXME("(%p, %p) stub!\n", iface, downloaded);
1004 
1005     return E_NOTIMPL;
1006 }
1007 
midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort * iface,IReferenceClock ** clock)1008 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
1009         IReferenceClock **clock)
1010 {
1011     struct midi_port *This = impl_from_IDirectMusicPort(iface);
1012 
1013     TRACE("(%p, %p)\n", iface, clock);
1014 
1015     if (!clock)
1016         return E_POINTER;
1017 
1018     *clock = This->clock;
1019     IReferenceClock_AddRef(*clock);
1020 
1021     return S_OK;
1022 }
1023 
midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort * iface,DMUS_SYNTHSTATS * stats)1024 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
1025         DMUS_SYNTHSTATS *stats)
1026 {
1027     FIXME("(%p, %p) stub!\n", iface, stats);
1028 
1029     return E_NOTIMPL;
1030 }
1031 
midi_IDirectMusicPort_Compact(IDirectMusicPort * iface)1032 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
1033 {
1034     FIXME("(%p) stub!\n", iface);
1035 
1036     return E_NOTIMPL;
1037 }
1038 
midi_IDirectMusicPort_GetCaps(IDirectMusicPort * iface,DMUS_PORTCAPS * caps)1039 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
1040 {
1041     FIXME("(%p, %p) stub!\n", iface, caps);
1042 
1043     return E_NOTIMPL;
1044 }
1045 
midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort * iface,DWORD io_control_code,void * in,DWORD size_in,void * out,DWORD size_out,DWORD * ret_len,OVERLAPPED * overlapped)1046 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
1047         DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
1048         OVERLAPPED *overlapped)
1049 {
1050     FIXME("(%p, %u, %p, %u, %p, %u, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
1051             , size_out, ret_len, overlapped);
1052 
1053     return E_NOTIMPL;
1054 }
1055 
midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort * iface,DWORD cgroups)1056 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
1057         DWORD cgroups)
1058 {
1059     FIXME("(%p, %u) stub!\n", iface, cgroups);
1060 
1061     return E_NOTIMPL;
1062 }
1063 
midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort * iface,DWORD * cgroups)1064 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
1065         DWORD *cgroups)
1066 {
1067     FIXME("(%p, %p) stub!\n", iface, cgroups);
1068 
1069     return E_NOTIMPL;
1070 }
1071 
midi_IDirectMusicPort_Activate(IDirectMusicPort * iface,BOOL active)1072 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
1073 {
1074     FIXME("(%p, %u) stub!\n", iface, active);
1075 
1076     return S_OK;
1077 }
1078 
midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort * iface,DWORD channel_group,DWORD channel,DWORD priority)1079 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
1080         DWORD channel_group, DWORD channel, DWORD priority)
1081 {
1082     FIXME("(%p, %u, %u, %u) stub!\n", iface, channel_group, channel, priority);
1083 
1084     return E_NOTIMPL;
1085 }
1086 
midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort * iface,DWORD channel_group,DWORD channel,DWORD * priority)1087 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
1088         DWORD channel_group, DWORD channel, DWORD *priority)
1089 {
1090     FIXME("(%p, %u, %u, %p) stub!\n", iface, channel_group, channel, priority);
1091 
1092     return E_NOTIMPL;
1093 }
1094 
midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort * iface,IDirectSound * dsound,IDirectSoundBuffer * dsbuffer)1095 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
1096         IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
1097 {
1098     FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
1099 
1100     return E_NOTIMPL;
1101 }
1102 
midi_IDirectMusicPort_GetFormat(IDirectMusicPort * iface,WAVEFORMATEX * format,DWORD * format_size,DWORD * buffer_size)1103 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
1104         DWORD *format_size, DWORD *buffer_size)
1105 {
1106     FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
1107 
1108     return E_NOTIMPL;
1109 }
1110 
1111 static const IDirectMusicPortVtbl midi_port_vtbl = {
1112     midi_IDirectMusicPort_QueryInterface,
1113     midi_IDirectMusicPort_AddRef,
1114     midi_IDirectMusicPort_Release,
1115     midi_IDirectMusicPort_PlayBuffer,
1116     midi_IDirectMusicPort_SetReadNotificationHandle,
1117     midi_IDirectMusicPort_Read,
1118     midi_IDirectMusicPort_DownloadInstrument,
1119     midi_IDirectMusicPort_UnloadInstrument,
1120     midi_IDirectMusicPort_GetLatencyClock,
1121     midi_IDirectMusicPort_GetRunningStats,
1122     midi_IDirectMusicPort_Compact,
1123     midi_IDirectMusicPort_GetCaps,
1124     midi_IDirectMusicPort_DeviceIoControl,
1125     midi_IDirectMusicPort_SetNumChannelGroups,
1126     midi_IDirectMusicPort_GetNumChannelGroups,
1127     midi_IDirectMusicPort_Activate,
1128     midi_IDirectMusicPort_SetChannelPriority,
1129     midi_IDirectMusicPort_GetChannelPriority,
1130     midi_IDirectMusicPort_SetDirectSound,
1131     midi_IDirectMusicPort_GetFormat,
1132 };
1133 
impl_from_IDirectMusicThru(IDirectMusicThru * iface)1134 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
1135 {
1136     return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
1137 }
1138 
midi_IDirectMusicThru_QueryInterface(IDirectMusicThru * iface,REFIID riid,void ** ret_iface)1139 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
1140         void **ret_iface)
1141 {
1142     struct midi_port *This = impl_from_IDirectMusicThru(iface);
1143 
1144     return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1145 }
1146 
midi_IDirectMusicThru_AddRef(IDirectMusicThru * iface)1147 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1148 {
1149     struct midi_port *This = impl_from_IDirectMusicThru(iface);
1150 
1151     return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1152 }
1153 
midi_IDirectMusicThru_Release(IDirectMusicThru * iface)1154 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1155 {
1156     struct midi_port *This = impl_from_IDirectMusicThru(iface);
1157 
1158     return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1159 }
1160 
midi_IDirectMusicThru_ThruChannel(IDirectMusicThru * iface,DWORD src_group,DWORD src_channel,DWORD dest_group,DWORD dest_channel,IDirectMusicPort * dest_port)1161 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1162         DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1163 {
1164     FIXME("(%p, %u, %u, %u, %u, %p) stub!\n", iface, src_group, src_channel, dest_group,
1165             dest_channel, dest_port);
1166 
1167     return S_OK;
1168 }
1169 
1170 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1171     midi_IDirectMusicThru_QueryInterface,
1172     midi_IDirectMusicThru_AddRef,
1173     midi_IDirectMusicThru_Release,
1174     midi_IDirectMusicThru_ThruChannel,
1175 };
1176 
midi_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * params,DMUS_PORTCAPS * caps,IDirectMusicPort ** port)1177 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1178         DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1179 {
1180     struct midi_port *obj;
1181     HRESULT hr;
1182 
1183     if (!(obj = heap_alloc_zero(sizeof(*obj))))
1184         return E_OUTOFMEMORY;
1185 
1186     obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1187     obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1188     obj->ref = 1;
1189 
1190     hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1191     if (hr != S_OK) {
1192         HeapFree(GetProcessHeap(), 0, obj);
1193         return hr;
1194     }
1195 
1196     *port = &obj->IDirectMusicPort_iface;
1197 
1198     return S_OK;
1199 }
1200 
midi_out_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * params,DMUS_PORTCAPS * caps,IDirectMusicPort ** port)1201 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1202         DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1203 {
1204     TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1205 
1206     return midi_port_create(parent, params, caps, port);
1207 }
1208 
midi_in_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * params,DMUS_PORTCAPS * caps,IDirectMusicPort ** port)1209 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1210         DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1211 {
1212     TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1213 
1214     return midi_port_create(parent, params, caps, port);
1215 }
1216