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