kernel32/nls: Added LOCALE_SNAN entries.
[wine.git] / dlls / dmusic / port.c
blob50646153a7075b3ece2d1fc5c5a0390b6ae50f33
1 /*
2 * IDirectMusicPort Implementation
4 * Copyright (C) 2003-2004 Rok Mandeljc
5 * Copyright (C) 2012 Christian Costa
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.
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.
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
22 #include <assert.h>
23 #include "dmusic_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
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;
46 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
48 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
51 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
53 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
56 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
58 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
61 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
63 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
66 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface)
68 return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface);
71 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
72 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
74 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
76 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
78 IDirectMusicDownloadedInstrument_AddRef(iface);
79 *ret_iface = iface;
80 return S_OK;
83 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
85 return E_NOINTERFACE;
88 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
90 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
91 ULONG ref = InterlockedIncrement(&This->ref);
93 TRACE("(%p)->(): new ref = %u\n", iface, ref);
95 return ref;
98 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
100 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
101 ULONG ref = InterlockedDecrement(&This->ref);
103 TRACE("(%p)->(): new ref = %u\n", iface, ref);
105 if (!ref)
107 HeapFree(GetProcessHeap(), 0, This->data);
108 HeapFree(GetProcessHeap(), 0, This);
109 DMUSIC_UnlockModule();
112 return ref;
115 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
116 IDirectMusicDownloadedInstrumentImpl_QueryInterface,
117 IDirectMusicDownloadedInstrumentImpl_AddRef,
118 IDirectMusicDownloadedInstrumentImpl_Release
121 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
123 if (!iface)
124 return NULL;
125 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
127 return impl_from_IDirectMusicDownloadedInstrument(iface);
130 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
132 IDirectMusicDownloadedInstrumentImpl *object;
134 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
135 if (!object)
137 *instrument = NULL;
138 return E_OUTOFMEMORY;
141 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
142 object->ref = 1;
144 *instrument = &object->IDirectMusicDownloadedInstrument_iface;
145 DMUSIC_LockModule();
147 return S_OK;
150 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
151 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
153 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
155 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
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;
171 IUnknown_AddRef((IUnknown*)*ret_iface);
173 return S_OK;
176 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
178 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
179 ULONG ref = InterlockedIncrement(&This->ref);
181 TRACE("(%p)->(): new ref = %u\n", This, ref);
183 DMUSIC_LockModule();
185 return ref;
188 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
190 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
191 ULONG ref = InterlockedDecrement(&This->ref);
193 TRACE("(%p)->(): new ref = %u\n", This, ref);
195 if (!ref)
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);
210 DMUSIC_UnlockModule();
212 return ref;
215 /* SynthPortImpl IDirectMusicPort interface follows: */
216 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
218 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
219 HRESULT hr;
220 REFERENCE_TIME time;
221 LPBYTE data;
222 DWORD size;
224 TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
226 if (!buffer)
227 return E_POINTER;
229 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
231 if (SUCCEEDED(hr))
232 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
234 if (SUCCEEDED(hr))
235 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
237 if (SUCCEEDED(hr))
238 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
240 return hr;
243 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
245 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
247 FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
249 return S_OK;
252 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
254 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
256 FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
258 return S_OK;
261 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
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;
277 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
279 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
280 return E_POINTER;
282 instrument_object = impl_from_IDirectMusicInstrument(instrument);
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;
287 data = HeapAlloc(GetProcessHeap(), 0, size);
288 if (!data)
289 return E_OUTOFMEMORY;
291 info = (DMUS_DOWNLOADINFO*)data;
292 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
293 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
295 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
296 info->dwDLId = 0;
297 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
298 info->cbSize = size;
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 */
310 for (i = 0; i < nb_regions; i++)
312 DMUS_REGION *region = (DMUS_REGION*)(data + offset);
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;
328 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
330 if (SUCCEEDED(ret))
331 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
333 if (SUCCEEDED(ret))
335 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
337 downloaded_object->data = data;
338 downloaded_object->downloaded = TRUE;
341 *downloaded_instrument = NULL;
342 HeapFree(GetProcessHeap(), 0, data);
344 return E_FAIL;
347 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
349 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
350 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
352 TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument);
354 if (!downloaded_instrument)
355 return E_POINTER;
357 if (!downloaded_object->downloaded)
358 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
360 HeapFree(GetProcessHeap(), 0, downloaded_object->data);
361 downloaded_object->data = NULL;
362 downloaded_object->downloaded = FALSE;
364 return S_OK;
367 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
369 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
371 TRACE("(%p/%p)->(%p)\n", iface, This, clock);
373 *clock = This->pLatencyClock;
374 IReferenceClock_AddRef(*clock);
376 return S_OK;
379 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
381 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
383 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
385 return S_OK;
388 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
390 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
392 FIXME("(%p/%p)->(): stub\n", iface, This);
394 return S_OK;
397 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
399 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
401 TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
403 *port_caps = This->caps;
405 return S_OK;
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)
411 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
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);
415 return S_OK;
418 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
420 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
422 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
424 This->nrofgroups = channel_groups;
426 return S_OK;
429 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
431 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
433 TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
435 *channel_groups = This->nrofgroups;
437 return S_OK;
440 static HRESULT WINAPI synth_dmport_Activate(IDirectMusicPort *iface, BOOL active)
442 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
444 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
446 if (This->active == active)
447 return S_FALSE;
449 if (active) {
450 /* Acquire the dsound */
451 if (!This->dsound) {
452 IDirectSound_AddRef(This->parent->dsound);
453 This->dsound = This->parent->dsound;
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;
464 This->active = active;
466 return S_OK;
469 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
471 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
473 FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
475 if (channel > 16)
477 WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
478 /*return E_INVALIDARG;*/
481 return S_OK;
484 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
486 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
488 TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
490 *priority = This->group[channel_group - 1].channel[channel].priority;
492 return S_OK;
495 static HRESULT WINAPI synth_dmport_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
496 IDirectSoundBuffer *dsbuffer)
498 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
500 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
502 if (This->active)
503 return DMUS_E_DSOUND_ALREADY_SET;
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;
512 if (This->dsbuffer)
513 IDirectSound_Release(This->dsbuffer);
515 This->dsound = dsound;
516 This->dsbuffer = dsbuffer;
518 if (This->dsound)
519 IDirectSound_AddRef(This->dsound);
520 if (This->dsbuffer)
521 IDirectSound_AddRef(This->dsbuffer);
523 return S_OK;
526 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
528 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
529 WAVEFORMATEX format;
530 FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
532 if (pWaveFormatEx == NULL)
534 if (pdwWaveFormatExSize)
535 *pdwWaveFormatExSize = sizeof(format);
536 else
537 return E_POINTER;
539 else
541 if (pdwWaveFormatExSize == NULL)
542 return E_POINTER;
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;
554 if (*pdwWaveFormatExSize >= sizeof(format))
556 CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
557 *pdwWaveFormatExSize = sizeof(format); /* FIXME check if this is set */
559 else
560 return E_POINTER; /* FIXME find right error */
563 if (pdwBufferSize)
564 *pdwBufferSize = 44100 * 2 * 2;
565 else
566 return E_POINTER;
568 return S_OK;
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
596 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
597 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
599 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
601 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
603 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
606 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
608 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
610 TRACE("(%p/%p)->()\n", iface, This);
612 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
615 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
617 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
619 TRACE("(%p/%p)->()\n", iface, This);
621 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
624 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
625 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
627 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
629 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
631 if (!IDMDownload)
632 return E_POINTER;
634 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
637 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
639 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
641 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
643 return S_OK;
646 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
648 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
650 FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
652 return S_OK;
655 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
657 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
659 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
661 return S_OK;
664 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
666 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
668 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
670 return S_OK;
673 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
675 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
677 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
679 return S_OK;
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
696 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
697 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
699 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
701 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
703 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
706 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
708 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
710 TRACE("(%p/%p)->()\n", iface, This);
712 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
715 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
717 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
719 TRACE("(%p/%p)->()\n", iface, This);
721 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
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)
728 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
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);
732 return S_OK;
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
744 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
745 void **ret_iface)
747 SynthPortImpl *This = impl_from_IKsControl(iface);
749 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
752 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
754 SynthPortImpl *This = impl_from_IKsControl(iface);
756 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
759 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
761 SynthPortImpl *This = impl_from_IKsControl(iface);
763 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
766 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
767 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
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);
772 if (prop->u.s.Flags != KSPROPERTY_TYPE_GET)
774 FIXME("prop flags %u not yet supported\n", prop->u.s.Flags);
775 return S_FALSE;
778 if (data_len < sizeof(DWORD))
779 return E_NOT_SUFFICIENT_BUFFER;
781 FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set));
782 *(DWORD*)data = FALSE;
783 *ret_len = sizeof(DWORD);
785 return S_OK;
788 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
789 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
791 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
793 return E_NOTIMPL;
796 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
797 void *data, ULONG data_len, ULONG *ret_len)
799 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
801 return E_NOTIMPL;
804 static const IKsControlVtbl ikscontrol_vtbl = {
805 IKsControlImpl_QueryInterface,
806 IKsControlImpl_AddRef,
807 IKsControlImpl_Release,
808 IKsControlImpl_KsProperty,
809 IKsControlImpl_KsMethod,
810 IKsControlImpl_KsEvent
813 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
814 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
816 SynthPortImpl *obj;
817 HRESULT hr = E_FAIL;
818 int i;
820 TRACE("(%p, %p, %p)\n", port_params, port_caps, port);
822 *port = NULL;
824 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
825 if (!obj)
826 return E_OUTOFMEMORY;
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;
838 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
839 if (hr != S_OK)
841 HeapFree(GetProcessHeap(), 0, obj);
842 return hr;
845 if (SUCCEEDED(hr))
846 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
848 if (SUCCEEDED(hr))
849 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
851 if (SUCCEEDED(hr))
852 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
854 if (SUCCEEDED(hr))
855 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
857 if (SUCCEEDED(hr))
858 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
860 if (SUCCEEDED(hr))
861 hr = IDirectMusicSynth_Open(obj->synth, port_params);
863 if (0)
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;
890 if (SUCCEEDED(hr)) {
891 *port = &obj->IDirectMusicPort_iface;
892 return S_OK;
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);
903 return hr;
906 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
907 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
909 FIXME("(%p, %p, %p): stub\n", port_params, port_caps, port);
911 return E_NOTIMPL;
914 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
915 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
917 FIXME("(%p, %p, %p): stub\n", port_params, port_caps, port);
919 return E_NOTIMPL;