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