vbscript: Added Chr implementation.
[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 "dmusic_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
25
26 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
27 {
28     return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
29 }
30
31 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
32 {
33     return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
34 }
35
36 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
37 {
38     return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
39 }
40
41 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
42 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
43 {
44     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
45
46     TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
47
48     if (IsEqualIID (riid, &IID_IUnknown) ||
49         IsEqualGUID(riid, &IID_IDirectMusicPort) ||
50         IsEqualGUID(riid, &IID_IDirectMusicPort8)) {
51         *ret_iface = &This->IDirectMusicPort_iface;
52         IDirectMusicPort_AddRef((LPDIRECTMUSICPORT)*ret_iface);
53         return S_OK;
54     } else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload) ||
55                IsEqualGUID(riid, &IID_IDirectMusicPortDownload8)) {
56         *ret_iface = &This->IDirectMusicPortDownload_iface;
57         IDirectMusicPortDownload_AddRef((LPDIRECTMUSICPORTDOWNLOAD)*ret_iface);
58         return S_OK;
59     } else if (IsEqualGUID(riid, &IID_IDirectMusicThru) ||
60                IsEqualGUID(riid, &IID_IDirectMusicThru8)) {
61         *ret_iface = &This->IDirectMusicThru_iface;
62         IDirectMusicThru_AddRef((LPDIRECTMUSICTHRU)*ret_iface);
63         return S_OK;
64     }
65
66     WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
67
68     return E_NOINTERFACE;
69 }
70
71 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
72 {
73     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
74     ULONG ref = InterlockedIncrement(&This->ref);
75
76     TRACE("(%p)->(): new ref = %u\n", This, ref);
77
78     DMUSIC_LockModule();
79
80     return ref;
81 }
82
83 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
84 {
85     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
86     ULONG ref = InterlockedDecrement(&This->ref);
87
88     TRACE("(%p)->(): new ref = %u\n", This, ref);
89
90     if (!ref)
91     {
92         IDirectMusicSynth_Activate(This->synth, FALSE);
93         IDirectMusicSynth_Close(This->synth);
94         IDirectMusicSynth_Release(This->synth);
95         IDirectMusicSynthSink_Release(This->synth_sink);
96         IReferenceClock_Release(This->pLatencyClock);
97         HeapFree(GetProcessHeap(), 0, This);
98     }
99
100     DMUSIC_UnlockModule();
101
102     return ref;
103 }
104
105 /* SynthPortImpl IDirectMusicPort interface follows: */
106 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
107 {
108     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
109     HRESULT hr;
110     REFERENCE_TIME time;
111     LPBYTE data;
112     DWORD size;
113
114     TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
115
116     if (!buffer)
117         return E_POINTER;
118
119     hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
120
121     if (SUCCEEDED(hr))
122         hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
123
124     if (SUCCEEDED(hr))
125         hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
126
127     if (SUCCEEDED(hr))
128         hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
129
130     return hr;
131 }
132
133 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
134 {
135     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
136
137     FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
138
139     return S_OK;
140 }
141
142 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
143 {
144     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
145
146     FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
147
148     return S_OK;
149 }
150
151 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
152 {
153     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
154
155     FIXME("(%p/%p)->(%p, %p, %p, %d): stub\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
156
157     if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
158         return E_POINTER;
159
160     return DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(&IID_IDirectMusicDownloadedInstrument, (LPVOID*)downloaded_instrument, NULL);
161 }
162
163 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
164 {
165     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
166
167     FIXME("(%p/%p)->(%p): stub\n", iface, This, downloaded_instrument);
168
169     return S_OK;
170 }
171
172 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
173 {
174     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
175
176     TRACE("(%p/%p)->(%p)\n", iface, This, clock);
177
178     *clock = This->pLatencyClock;
179     IReferenceClock_AddRef(*clock);
180
181     return S_OK;
182 }
183
184 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
185 {
186     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
187
188     FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
189
190     return S_OK;
191 }
192
193 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
194 {
195     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
196
197     FIXME("(%p/%p)->(): stub\n", iface, This);
198
199     return S_OK;
200 }
201
202 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
203 {
204     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
205
206     TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
207
208     *port_caps = This->caps;
209
210     return S_OK;
211 }
212
213 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size,
214                                                            LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped)
215 {
216     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
217
218     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);
219
220     return S_OK;
221 }
222
223 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
224 {
225     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
226
227     FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
228
229     This->nrofgroups = channel_groups;
230
231     return S_OK;
232 }
233
234 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
235 {
236     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
237
238     TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
239
240     *channel_groups = This->nrofgroups;
241
242     return S_OK;
243 }
244
245 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Activate(LPDIRECTMUSICPORT iface, BOOL active)
246 {
247     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
248
249     TRACE("(%p/%p)->(%d)\n", iface, This, active);
250
251     This->fActive = active;
252
253     return S_OK;
254 }
255
256 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
257 {
258     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
259
260     FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
261
262     if (channel > 16)
263     {
264         WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
265         /*return E_INVALIDARG;*/
266     }
267
268     return S_OK;
269 }
270
271 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
272 {
273     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
274
275     TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
276
277     *priority = This->group[channel_group - 1].channel[channel].priority;
278
279     return S_OK;
280 }
281
282 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetDirectSound(LPDIRECTMUSICPORT iface, LPDIRECTSOUND direct_sound, LPDIRECTSOUNDBUFFER direct_sound_buffer)
283 {
284     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
285
286     FIXME("(%p/%p)->(%p, %p): stub\n", iface, This, direct_sound, direct_sound_buffer);
287
288     return S_OK;
289 }
290
291 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
292 {
293         SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
294         WAVEFORMATEX format;
295         FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
296
297         if (pWaveFormatEx == NULL)
298         {
299                 if (pdwWaveFormatExSize)
300                         *pdwWaveFormatExSize = sizeof(format);
301                 else
302                         return E_POINTER;
303         }
304         else
305         {
306                 if (pdwWaveFormatExSize == NULL)
307                         return E_POINTER;
308
309                 /* Just fill this in with something that will not crash Direct Sound for now. */
310                 /* It won't be used anyway until Performances are completed */
311                 format.wFormatTag = WAVE_FORMAT_PCM;
312                 format.nChannels = 2; /* This->params.dwAudioChannels; */
313                 format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */
314                 format.wBitsPerSample = 16;     /* FIXME: check this */
315                 format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8;
316                 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
317                 format.cbSize = 0;
318
319                 if (*pdwWaveFormatExSize >= sizeof(format))
320                 {
321                         CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
322                         *pdwWaveFormatExSize = sizeof(format);  /* FIXME check if this is set */
323                 }
324                 else
325                         return E_POINTER;       /* FIXME find right error */
326         }
327
328         if (pdwBufferSize)
329                 *pdwBufferSize = 44100 * 2 * 2;
330         else
331                 return E_POINTER;
332
333         return S_OK;
334 }
335
336 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = {
337     /**** IDirectMusicPort IUnknown part methods ***/
338     SynthPortImpl_IDirectMusicPort_QueryInterface,
339     SynthPortImpl_IDirectMusicPort_AddRef,
340     SynthPortImpl_IDirectMusicPort_Release,
341     /**** IDirectMusicPort methods ***/
342     SynthPortImpl_IDirectMusicPort_PlayBuffer,
343     SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle,
344     SynthPortImpl_IDirectMusicPort_Read,
345     SynthPortImpl_IDirectMusicPort_DownloadInstrument,
346     SynthPortImpl_IDirectMusicPort_UnloadInstrument,
347     SynthPortImpl_IDirectMusicPort_GetLatencyClock,
348     SynthPortImpl_IDirectMusicPort_GetRunningStats,
349     SynthPortImpl_IDirectMusicPort_Compact,
350     SynthPortImpl_IDirectMusicPort_GetCaps,
351     SynthPortImpl_IDirectMusicPort_DeviceIoControl,
352     SynthPortImpl_IDirectMusicPort_SetNumChannelGroups,
353     SynthPortImpl_IDirectMusicPort_GetNumChannelGroups,
354     SynthPortImpl_IDirectMusicPort_Activate,
355     SynthPortImpl_IDirectMusicPort_SetChannelPriority,
356     SynthPortImpl_IDirectMusicPort_GetChannelPriority,
357     SynthPortImpl_IDirectMusicPort_SetDirectSound,
358     SynthPortImpl_IDirectMusicPort_GetFormat
359 };
360
361 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
362 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
363 {
364     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
365
366     TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
367
368     return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
369 }
370
371 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
372 {
373     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
374
375     TRACE("(%p/%p)->()\n", iface, This);
376
377     return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
378 }
379
380 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
381 {
382     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
383
384     TRACE("(%p/%p)->()\n", iface, This);
385
386     return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
387 }
388
389 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
390 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
391 {
392     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
393
394     FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
395
396     if (!IDMDownload)
397         return E_POINTER;
398
399     return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
400 }
401
402 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
403 {
404     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
405
406     FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
407
408     return S_OK;
409 }
410
411 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
412 {
413     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
414
415     FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
416
417     return S_OK;
418 }
419
420 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
421 {
422     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
423
424     FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
425
426     return S_OK;
427 }
428
429 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
430 {
431     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
432
433     FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
434
435     return S_OK;
436 }
437
438 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
439 {
440     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
441
442     FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
443
444     return S_OK;
445 }
446
447 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = {
448     /*** IDirectMusicPortDownload IUnknown part methods ***/
449     SynthPortImpl_IDirectMusicPortDownload_QueryInterface,
450     SynthPortImpl_IDirectMusicPortDownload_AddRef,
451     SynthPortImpl_IDirectMusicPortDownload_Release,
452     /*** IDirectMusicPortDownload methods ***/
453     SynthPortImpl_IDirectMusicPortDownload_GetBuffer,
454     SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer,
455     SynthPortImpl_IDirectMusicPortDownload_GetDLId,
456     SynthPortImpl_IDirectMusicPortDownload_GetAppend,
457     SynthPortImpl_IDirectMusicPortDownload_Download,
458     SynthPortImpl_IDirectMusicPortDownload_Unload
459 };
460
461 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
462 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
463 {
464     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
465
466     TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
467
468     return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
469 }
470
471 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
472 {
473     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
474
475     TRACE("(%p/%p)->()\n", iface, This);
476
477     return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
478 }
479
480 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
481 {
482     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
483
484     TRACE("(%p/%p)->()\n", iface, This);
485
486     return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
487 }
488
489 /*  SynthPortImpl IDirectMusicThru Interface follows: */
490 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group,
491                                                        DWORD destination_channel, LPDIRECTMUSICPORT destination_port)
492 {
493     SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
494
495     FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
496
497     return S_OK;
498 }
499
500 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = {
501     /*** IDirectMusicThru IUnknown part methods */
502     SynthPortImpl_IDirectMusicThru_QueryInterface,
503     SynthPortImpl_IDirectMusicThru_AddRef,
504     SynthPortImpl_IDirectMusicThru_Release,
505     /*** IDirectMusicThru methods ***/
506     SynthPortImpl_IDirectMusicThru_ThruChannel
507 };
508
509 HRESULT DMUSIC_CreateSynthPortImpl(LPCGUID guid, LPVOID *object, LPUNKNOWN unkouter, LPDMUS_PORTPARAMS port_params, LPDMUS_PORTCAPS port_caps, DWORD device)
510 {
511     SynthPortImpl *obj;
512     HRESULT hr = E_FAIL;
513     UINT i;
514
515     TRACE("(%p,%p,%p,%p,%p%d)\n", guid, object, unkouter, port_params, port_caps, device);
516
517     *object = NULL;
518
519     obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
520     if (!obj)
521         return E_OUTOFMEMORY;
522
523     obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl;
524     obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl;
525     obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl;
526     obj->ref = 0;  /* Will be inited by QueryInterface */
527     obj->fActive = FALSE;
528     obj->params = *port_params;
529     obj->caps = *port_caps;
530
531     hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
532     if (hr != S_OK)
533     {
534         HeapFree(GetProcessHeap(), 0, obj);
535         return hr;
536     }
537
538     if (SUCCEEDED(hr))
539         hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
540
541     if (SUCCEEDED(hr))
542         hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
543
544     if (SUCCEEDED(hr))
545         hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
546
547     if (SUCCEEDED(hr))
548         hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
549
550     if (SUCCEEDED(hr))
551         hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
552
553     if (SUCCEEDED(hr))
554         hr = IDirectMusicSynth_Open(obj->synth, port_params);
555
556     if (0)
557     {
558         if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
559             obj->nrofgroups = port_params->dwChannelGroups;
560             /* Setting default priorities */
561             for (i = 0; i < obj->nrofgroups; i++) {
562                 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
563                 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
564                 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
565                 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
566                 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
567                 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
568                 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
569                 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
570                 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
571                 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
572                 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
573                 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
574                 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
575                 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
576                 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
577                 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
578                 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
579             }
580         }
581     }
582
583     if (SUCCEEDED(hr))
584         return IDirectMusicPort_QueryInterface((LPDIRECTMUSICPORT)obj, guid, object);
585
586     if (obj->synth)
587         IDirectMusicSynth_Release(obj->synth);
588     if (obj->synth_sink)
589         IDirectMusicSynthSink_Release(obj->synth_sink);
590     if (obj->pLatencyClock)
591         IReferenceClock_Release(obj->pLatencyClock);
592     HeapFree(GetProcessHeap(), 0, obj);
593
594     return hr;
595 }
596
597 HRESULT DMUSIC_CreateMidiOutPortImpl(LPCGUID guid, LPVOID *object, LPUNKNOWN unkouter, LPDMUS_PORTPARAMS port_params, LPDMUS_PORTCAPS port_caps, DWORD device)
598 {
599     TRACE("(%p,%p,%p,%p,%p,%d): stub\n", guid, object, unkouter, port_params, port_caps, device);
600
601     return E_NOTIMPL;
602 }
603
604 HRESULT DMUSIC_CreateMidiInPortImpl(LPCGUID guid, LPVOID *object, LPUNKNOWN unkouter, LPDMUS_PORTPARAMS port_params, LPDMUS_PORTCAPS port_caps, DWORD device)
605 {
606     TRACE("(%p,%p,%p,%p,%p,%d): stub\n", guid, object, unkouter, port_params, port_caps, device);
607
608     return E_NOTIMPL;
609 }