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