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