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