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