ntdll: Make wine_build a hidden symbol.
[wine.git] / dlls / dmusic / port.c
blob7bd2afdb9a37fd1d8a319897aa24513374b469e6
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"
24 #include "dmobject.h"
25 #include "wine/heap.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
29 typedef struct SynthPortImpl {
30 IDirectMusicPort IDirectMusicPort_iface;
31 IDirectMusicPortDownload IDirectMusicPortDownload_iface;
32 IDirectMusicThru IDirectMusicThru_iface;
33 IKsControl IKsControl_iface;
34 LONG ref;
35 IDirectMusic8Impl *parent;
36 IDirectSound *dsound;
37 IDirectSoundBuffer *dsbuffer;
38 IReferenceClock *pLatencyClock;
39 IDirectMusicSynth *synth;
40 IDirectMusicSynthSink *synth_sink;
41 BOOL active;
42 DMUS_PORTCAPS caps;
43 DMUS_PORTPARAMS params;
44 int nrofgroups;
45 DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
46 } SynthPortImpl;
48 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
50 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
53 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
55 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
58 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
60 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
63 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
65 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
68 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface)
70 return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface);
73 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
74 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
76 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
78 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
80 IDirectMusicDownloadedInstrument_AddRef(iface);
81 *ret_iface = iface;
82 return S_OK;
85 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
87 return E_NOINTERFACE;
90 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
92 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
93 ULONG ref = InterlockedIncrement(&This->ref);
95 TRACE("(%p)->(): new ref = %u\n", iface, ref);
97 return ref;
100 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
102 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
103 ULONG ref = InterlockedDecrement(&This->ref);
105 TRACE("(%p)->(): new ref = %u\n", iface, ref);
107 if (!ref)
109 HeapFree(GetProcessHeap(), 0, This->data);
110 HeapFree(GetProcessHeap(), 0, This);
111 DMUSIC_UnlockModule();
114 return ref;
117 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
118 IDirectMusicDownloadedInstrumentImpl_QueryInterface,
119 IDirectMusicDownloadedInstrumentImpl_AddRef,
120 IDirectMusicDownloadedInstrumentImpl_Release
123 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
125 if (!iface)
126 return NULL;
127 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
129 return impl_from_IDirectMusicDownloadedInstrument(iface);
132 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
134 IDirectMusicDownloadedInstrumentImpl *object;
136 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
137 if (!object)
139 *instrument = NULL;
140 return E_OUTOFMEMORY;
143 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
144 object->ref = 1;
146 *instrument = &object->IDirectMusicDownloadedInstrument_iface;
147 DMUSIC_LockModule();
149 return S_OK;
152 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
153 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
155 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
157 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
159 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
160 *ret_iface = &This->IDirectMusicPort_iface;
161 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
162 *ret_iface = &This->IDirectMusicPortDownload_iface;
163 else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
164 *ret_iface = &This->IDirectMusicThru_iface;
165 else if (IsEqualGUID(riid, &IID_IKsControl))
166 *ret_iface = &This->IKsControl_iface;
167 else {
168 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
169 *ret_iface = NULL;
170 return E_NOINTERFACE;
173 IUnknown_AddRef((IUnknown*)*ret_iface);
175 return S_OK;
178 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
180 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
181 ULONG ref = InterlockedIncrement(&This->ref);
183 TRACE("(%p)->(): new ref = %u\n", This, ref);
185 DMUSIC_LockModule();
187 return ref;
190 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
192 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
193 ULONG ref = InterlockedDecrement(&This->ref);
195 TRACE("(%p)->(): new ref = %u\n", This, ref);
197 if (!ref)
199 dmusic_remove_port(This->parent, iface);
200 IDirectMusicSynth_Activate(This->synth, FALSE);
201 IDirectMusicSynth_Close(This->synth);
202 IDirectMusicSynth_Release(This->synth);
203 IDirectMusicSynthSink_Release(This->synth_sink);
204 IReferenceClock_Release(This->pLatencyClock);
205 if (This->dsbuffer)
206 IDirectSoundBuffer_Release(This->dsbuffer);
207 if (This->dsound)
208 IDirectSound_Release(This->dsound);
209 HeapFree(GetProcessHeap(), 0, This);
212 DMUSIC_UnlockModule();
214 return ref;
217 /* SynthPortImpl IDirectMusicPort interface follows: */
218 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
220 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
221 HRESULT hr;
222 REFERENCE_TIME time;
223 LPBYTE data;
224 DWORD size;
226 TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
228 if (!buffer)
229 return E_POINTER;
231 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
233 if (SUCCEEDED(hr))
234 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
236 if (SUCCEEDED(hr))
237 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
239 if (SUCCEEDED(hr))
240 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
242 return hr;
245 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
247 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
249 FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
251 return S_OK;
254 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
256 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
258 FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
260 return S_OK;
263 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
265 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
266 IDirectMusicInstrumentImpl *instrument_object;
267 HRESULT ret;
268 BOOL free;
269 HANDLE download;
270 DMUS_DOWNLOADINFO *info;
271 DMUS_OFFSETTABLE *offset_table;
272 DMUS_INSTRUMENT *instrument_info;
273 BYTE *data;
274 ULONG offset;
275 ULONG nb_regions;
276 ULONG size;
277 ULONG i;
279 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
281 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
282 return E_POINTER;
284 instrument_object = impl_from_IDirectMusicInstrument(instrument);
286 nb_regions = instrument_object->header.cRegions;
287 size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions;
289 data = HeapAlloc(GetProcessHeap(), 0, size);
290 if (!data)
291 return E_OUTOFMEMORY;
293 info = (DMUS_DOWNLOADINFO*)data;
294 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
295 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
297 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
298 info->dwDLId = 0;
299 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
300 info->cbSize = size;
302 offset_table->ulOffsetTable[0] = offset;
303 instrument_info = (DMUS_INSTRUMENT*)(data + offset);
304 offset += sizeof(DMUS_INSTRUMENT);
305 instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale);
306 instrument_info->ulFirstRegionIdx = 1;
307 instrument_info->ulGlobalArtIdx = 0; /* FIXME */
308 instrument_info->ulFirstExtCkIdx = 0; /* FIXME */
309 instrument_info->ulCopyrightIdx = 0; /* FIXME */
310 instrument_info->ulFlags = 0; /* FIXME */
312 for (i = 0; i < nb_regions; i++)
314 DMUS_REGION *region = (DMUS_REGION*)(data + offset);
316 offset_table->ulOffsetTable[1 + i] = offset;
317 offset += sizeof(DMUS_REGION);
318 region->RangeKey = instrument_object->regions[i].header.RangeKey;
319 region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity;
320 region->fusOptions = instrument_object->regions[i].header.fusOptions;
321 region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup;
322 region->ulRegionArtIdx = 0; /* FIXME */
323 region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
324 region->ulFirstExtCkIdx = 0; /* FIXME */
325 region->WaveLink = instrument_object->regions[i].wave_link;
326 region->WSMP = instrument_object->regions[i].wave_sample;
327 region->WLOOP[0] = instrument_object->regions[i].wave_loop;
330 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
332 if (SUCCEEDED(ret))
333 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
335 if (SUCCEEDED(ret))
337 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
339 downloaded_object->data = data;
340 downloaded_object->downloaded = TRUE;
343 *downloaded_instrument = NULL;
344 HeapFree(GetProcessHeap(), 0, data);
346 return E_FAIL;
349 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
351 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
352 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
354 TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument);
356 if (!downloaded_instrument)
357 return E_POINTER;
359 if (!downloaded_object->downloaded)
360 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
362 HeapFree(GetProcessHeap(), 0, downloaded_object->data);
363 downloaded_object->data = NULL;
364 downloaded_object->downloaded = FALSE;
366 return S_OK;
369 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
371 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
373 TRACE("(%p/%p)->(%p)\n", iface, This, clock);
375 *clock = This->pLatencyClock;
376 IReferenceClock_AddRef(*clock);
378 return S_OK;
381 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
383 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
385 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
387 return S_OK;
390 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
392 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
394 FIXME("(%p/%p)->(): stub\n", iface, This);
396 return S_OK;
399 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
401 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
403 TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
405 *port_caps = This->caps;
407 return S_OK;
410 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size,
411 LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped)
413 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
415 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);
417 return S_OK;
420 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
422 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
424 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
426 This->nrofgroups = channel_groups;
428 return S_OK;
431 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
433 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
435 TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
437 *channel_groups = This->nrofgroups;
439 return S_OK;
442 static HRESULT WINAPI synth_dmport_Activate(IDirectMusicPort *iface, BOOL active)
444 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
446 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
448 if (This->active == active)
449 return S_FALSE;
451 if (active) {
452 /* Acquire the dsound */
453 if (!This->dsound) {
454 IDirectSound_AddRef(This->parent->dsound);
455 This->dsound = This->parent->dsound;
457 IDirectSound_AddRef(This->dsound);
458 } else {
459 /* Release the dsound */
460 IDirectSound_Release(This->dsound);
461 IDirectSound_Release(This->parent->dsound);
462 if (This->dsound == This->parent->dsound)
463 This->dsound = NULL;
466 This->active = active;
468 return S_OK;
471 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
473 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
475 FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
477 if (channel > 16)
479 WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
480 /*return E_INVALIDARG;*/
483 return S_OK;
486 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
488 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
490 TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
492 *priority = This->group[channel_group - 1].channel[channel].priority;
494 return S_OK;
497 static HRESULT WINAPI synth_dmport_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
498 IDirectSoundBuffer *dsbuffer)
500 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
502 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
504 if (This->active)
505 return DMUS_E_DSOUND_ALREADY_SET;
507 if (This->dsound) {
508 if (This->dsound != This->parent->dsound)
509 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
510 This->dsound, This->parent->dsound);
511 if (!IDirectSound_Release(This->parent->dsound))
512 This->parent->dsound = NULL;
514 if (This->dsbuffer)
515 IDirectSoundBuffer_Release(This->dsbuffer);
517 This->dsound = dsound;
518 This->dsbuffer = dsbuffer;
520 if (This->dsound)
521 IDirectSound_AddRef(This->dsound);
522 if (This->dsbuffer)
523 IDirectSoundBuffer_AddRef(This->dsbuffer);
525 return S_OK;
528 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
530 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
531 WAVEFORMATEX format;
532 FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
534 if (pWaveFormatEx == NULL)
536 if (pdwWaveFormatExSize)
537 *pdwWaveFormatExSize = sizeof(format);
538 else
539 return E_POINTER;
541 else
543 if (pdwWaveFormatExSize == NULL)
544 return E_POINTER;
546 /* Just fill this in with something that will not crash Direct Sound for now. */
547 /* It won't be used anyway until Performances are completed */
548 format.wFormatTag = WAVE_FORMAT_PCM;
549 format.nChannels = 2; /* This->params.dwAudioChannels; */
550 format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */
551 format.wBitsPerSample = 16; /* FIXME: check this */
552 format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8;
553 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
554 format.cbSize = 0;
556 if (*pdwWaveFormatExSize >= sizeof(format))
558 CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
559 *pdwWaveFormatExSize = sizeof(format); /* FIXME check if this is set */
561 else
562 return E_POINTER; /* FIXME find right error */
565 if (pdwBufferSize)
566 *pdwBufferSize = 44100 * 2 * 2;
567 else
568 return E_POINTER;
570 return S_OK;
573 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = {
574 /**** IDirectMusicPort IUnknown part methods ***/
575 SynthPortImpl_IDirectMusicPort_QueryInterface,
576 SynthPortImpl_IDirectMusicPort_AddRef,
577 SynthPortImpl_IDirectMusicPort_Release,
578 /**** IDirectMusicPort methods ***/
579 SynthPortImpl_IDirectMusicPort_PlayBuffer,
580 SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle,
581 SynthPortImpl_IDirectMusicPort_Read,
582 SynthPortImpl_IDirectMusicPort_DownloadInstrument,
583 SynthPortImpl_IDirectMusicPort_UnloadInstrument,
584 SynthPortImpl_IDirectMusicPort_GetLatencyClock,
585 SynthPortImpl_IDirectMusicPort_GetRunningStats,
586 SynthPortImpl_IDirectMusicPort_Compact,
587 SynthPortImpl_IDirectMusicPort_GetCaps,
588 SynthPortImpl_IDirectMusicPort_DeviceIoControl,
589 SynthPortImpl_IDirectMusicPort_SetNumChannelGroups,
590 SynthPortImpl_IDirectMusicPort_GetNumChannelGroups,
591 synth_dmport_Activate,
592 SynthPortImpl_IDirectMusicPort_SetChannelPriority,
593 SynthPortImpl_IDirectMusicPort_GetChannelPriority,
594 synth_dmport_SetDirectSound,
595 SynthPortImpl_IDirectMusicPort_GetFormat
598 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
599 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
601 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
603 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
605 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
608 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
610 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
612 TRACE("(%p/%p)->()\n", iface, This);
614 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
617 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
619 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
621 TRACE("(%p/%p)->()\n", iface, This);
623 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
626 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
627 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
629 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
631 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
633 if (!IDMDownload)
634 return E_POINTER;
636 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
639 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
641 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
643 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
645 return S_OK;
648 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
650 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
652 FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
654 return S_OK;
657 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
659 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
661 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
663 return S_OK;
666 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
668 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
670 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
672 return S_OK;
675 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
677 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
679 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
681 return S_OK;
684 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = {
685 /*** IDirectMusicPortDownload IUnknown part methods ***/
686 SynthPortImpl_IDirectMusicPortDownload_QueryInterface,
687 SynthPortImpl_IDirectMusicPortDownload_AddRef,
688 SynthPortImpl_IDirectMusicPortDownload_Release,
689 /*** IDirectMusicPortDownload methods ***/
690 SynthPortImpl_IDirectMusicPortDownload_GetBuffer,
691 SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer,
692 SynthPortImpl_IDirectMusicPortDownload_GetDLId,
693 SynthPortImpl_IDirectMusicPortDownload_GetAppend,
694 SynthPortImpl_IDirectMusicPortDownload_Download,
695 SynthPortImpl_IDirectMusicPortDownload_Unload
698 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
699 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
701 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
703 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
705 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
708 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
710 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
712 TRACE("(%p/%p)->()\n", iface, This);
714 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
717 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
719 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
721 TRACE("(%p/%p)->()\n", iface, This);
723 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
726 /* SynthPortImpl IDirectMusicThru Interface follows: */
727 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group,
728 DWORD destination_channel, LPDIRECTMUSICPORT destination_port)
730 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
732 FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
734 return S_OK;
737 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = {
738 /*** IDirectMusicThru IUnknown part methods */
739 SynthPortImpl_IDirectMusicThru_QueryInterface,
740 SynthPortImpl_IDirectMusicThru_AddRef,
741 SynthPortImpl_IDirectMusicThru_Release,
742 /*** IDirectMusicThru methods ***/
743 SynthPortImpl_IDirectMusicThru_ThruChannel
746 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
747 void **ret_iface)
749 SynthPortImpl *This = impl_from_IKsControl(iface);
751 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
754 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
756 SynthPortImpl *This = impl_from_IKsControl(iface);
758 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
761 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
763 SynthPortImpl *This = impl_from_IKsControl(iface);
765 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
768 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
769 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
771 TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
772 TRACE("prop = %s - %u - %u\n", debugstr_guid(&prop->u.s.Set), prop->u.s.Id, prop->u.s.Flags);
774 if (prop->u.s.Flags != KSPROPERTY_TYPE_GET)
776 FIXME("prop flags %u not yet supported\n", prop->u.s.Flags);
777 return S_FALSE;
780 if (data_len < sizeof(DWORD))
781 return E_NOT_SUFFICIENT_BUFFER;
783 FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set));
784 *(DWORD*)data = FALSE;
785 *ret_len = sizeof(DWORD);
787 return S_OK;
790 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
791 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
793 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
795 return E_NOTIMPL;
798 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
799 void *data, ULONG data_len, ULONG *ret_len)
801 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
803 return E_NOTIMPL;
806 static const IKsControlVtbl ikscontrol_vtbl = {
807 IKsControlImpl_QueryInterface,
808 IKsControlImpl_AddRef,
809 IKsControlImpl_Release,
810 IKsControlImpl_KsProperty,
811 IKsControlImpl_KsMethod,
812 IKsControlImpl_KsEvent
815 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
816 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
818 SynthPortImpl *obj;
819 HRESULT hr = E_FAIL;
820 int i;
822 TRACE("(%p, %p, %p)\n", port_params, port_caps, port);
824 *port = NULL;
826 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
827 if (!obj)
828 return E_OUTOFMEMORY;
830 obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl;
831 obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl;
832 obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl;
833 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
834 obj->ref = 1;
835 obj->parent = parent;
836 obj->active = FALSE;
837 obj->params = *port_params;
838 obj->caps = *port_caps;
840 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
841 if (hr != S_OK)
843 HeapFree(GetProcessHeap(), 0, obj);
844 return hr;
847 if (SUCCEEDED(hr))
848 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
850 if (SUCCEEDED(hr))
851 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
853 if (SUCCEEDED(hr))
854 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
856 if (SUCCEEDED(hr))
857 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
859 if (SUCCEEDED(hr))
860 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
862 if (SUCCEEDED(hr))
863 hr = IDirectMusicSynth_Open(obj->synth, port_params);
865 if (0)
867 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
868 obj->nrofgroups = port_params->dwChannelGroups;
869 /* Setting default priorities */
870 for (i = 0; i < obj->nrofgroups; i++) {
871 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
872 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
873 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
874 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
875 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
876 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
877 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
878 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
879 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
880 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
881 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
882 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
883 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
884 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
885 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
886 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
887 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
892 if (SUCCEEDED(hr)) {
893 *port = &obj->IDirectMusicPort_iface;
894 return S_OK;
897 if (obj->synth)
898 IDirectMusicSynth_Release(obj->synth);
899 if (obj->synth_sink)
900 IDirectMusicSynthSink_Release(obj->synth_sink);
901 if (obj->pLatencyClock)
902 IReferenceClock_Release(obj->pLatencyClock);
903 HeapFree(GetProcessHeap(), 0, obj);
905 return hr;
908 struct midi_port {
909 IDirectMusicPort IDirectMusicPort_iface;
910 IDirectMusicThru IDirectMusicThru_iface;
911 LONG ref;
912 IReferenceClock *clock;
915 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
917 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
920 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
921 void **ret_iface)
923 struct midi_port *This = impl_from_IDirectMusicPort(iface);
925 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
927 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
928 *ret_iface = iface;
929 else if (IsEqualIID(riid, &IID_IDirectMusicThru))
930 *ret_iface = &This->IDirectMusicThru_iface;
931 else {
932 WARN("no interface for %s\n", debugstr_dmguid(riid));
933 *ret_iface = NULL;
934 return E_NOINTERFACE;
937 IUnknown_AddRef((IUnknown *)*ret_iface);
939 return S_OK;
942 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
944 struct midi_port *This = impl_from_IDirectMusicPort(iface);
945 ULONG ref = InterlockedIncrement(&This->ref);
947 TRACE("(%p) ref = %u\n", iface, ref);
949 return ref;
952 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
954 struct midi_port *This = impl_from_IDirectMusicPort(iface);
955 ULONG ref = InterlockedDecrement(&This->ref);
957 TRACE("(%p) ref = %u\n", iface, ref);
959 if (!ref) {
960 if (This->clock)
961 IReferenceClock_Release(This->clock);
962 heap_free(This);
965 return ref;
968 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
969 IDirectMusicBuffer *buffer)
971 FIXME("(%p, %p) stub!\n", iface, buffer);
973 return E_NOTIMPL;
976 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
977 HANDLE event)
979 FIXME("(%p, %p) stub!\n", iface, event);
981 return S_OK;
984 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
985 IDirectMusicBuffer *buffer)
987 FIXME("(%p, %p) stub!\n", iface, buffer);
989 return E_NOTIMPL;
992 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
993 IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
994 DMUS_NOTERANGE *ranges, DWORD num_ranges)
996 FIXME("(%p, %p, %p, %p, %u) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
998 return E_NOTIMPL;
1001 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
1002 IDirectMusicDownloadedInstrument *downloaded)
1004 FIXME("(%p, %p) stub!\n", iface, downloaded);
1006 return E_NOTIMPL;
1009 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
1010 IReferenceClock **clock)
1012 struct midi_port *This = impl_from_IDirectMusicPort(iface);
1014 TRACE("(%p, %p)\n", iface, clock);
1016 if (!clock)
1017 return E_POINTER;
1019 *clock = This->clock;
1020 IReferenceClock_AddRef(*clock);
1022 return S_OK;
1025 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
1026 DMUS_SYNTHSTATS *stats)
1028 FIXME("(%p, %p) stub!\n", iface, stats);
1030 return E_NOTIMPL;
1033 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
1035 FIXME("(%p) stub!\n", iface);
1037 return E_NOTIMPL;
1040 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
1042 FIXME("(%p, %p) stub!\n", iface, caps);
1044 return E_NOTIMPL;
1047 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
1048 DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
1049 OVERLAPPED *overlapped)
1051 FIXME("(%p, %u, %p, %u, %p, %u, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
1052 , size_out, ret_len, overlapped);
1054 return E_NOTIMPL;
1057 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
1058 DWORD cgroups)
1060 FIXME("(%p, %u) stub!\n", iface, cgroups);
1062 return E_NOTIMPL;
1065 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
1066 DWORD *cgroups)
1068 FIXME("(%p, %p) stub!\n", iface, cgroups);
1070 return E_NOTIMPL;
1073 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
1075 FIXME("(%p, %u) stub!\n", iface, active);
1077 return S_OK;
1080 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
1081 DWORD channel_group, DWORD channel, DWORD priority)
1083 FIXME("(%p, %u, %u, %u) stub!\n", iface, channel_group, channel, priority);
1085 return E_NOTIMPL;
1088 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
1089 DWORD channel_group, DWORD channel, DWORD *priority)
1091 FIXME("(%p, %u, %u, %p) stub!\n", iface, channel_group, channel, priority);
1093 return E_NOTIMPL;
1096 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
1097 IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
1099 FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
1101 return E_NOTIMPL;
1104 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
1105 DWORD *format_size, DWORD *buffer_size)
1107 FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
1109 return E_NOTIMPL;
1112 static const IDirectMusicPortVtbl midi_port_vtbl = {
1113 midi_IDirectMusicPort_QueryInterface,
1114 midi_IDirectMusicPort_AddRef,
1115 midi_IDirectMusicPort_Release,
1116 midi_IDirectMusicPort_PlayBuffer,
1117 midi_IDirectMusicPort_SetReadNotificationHandle,
1118 midi_IDirectMusicPort_Read,
1119 midi_IDirectMusicPort_DownloadInstrument,
1120 midi_IDirectMusicPort_UnloadInstrument,
1121 midi_IDirectMusicPort_GetLatencyClock,
1122 midi_IDirectMusicPort_GetRunningStats,
1123 midi_IDirectMusicPort_Compact,
1124 midi_IDirectMusicPort_GetCaps,
1125 midi_IDirectMusicPort_DeviceIoControl,
1126 midi_IDirectMusicPort_SetNumChannelGroups,
1127 midi_IDirectMusicPort_GetNumChannelGroups,
1128 midi_IDirectMusicPort_Activate,
1129 midi_IDirectMusicPort_SetChannelPriority,
1130 midi_IDirectMusicPort_GetChannelPriority,
1131 midi_IDirectMusicPort_SetDirectSound,
1132 midi_IDirectMusicPort_GetFormat,
1135 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
1137 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
1140 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
1141 void **ret_iface)
1143 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1145 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1148 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1150 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1152 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1155 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1157 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1159 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1162 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1163 DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1165 FIXME("(%p, %u, %u, %u, %u, %p) stub!\n", iface, src_group, src_channel, dest_group,
1166 dest_channel, dest_port);
1168 return S_OK;
1171 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1172 midi_IDirectMusicThru_QueryInterface,
1173 midi_IDirectMusicThru_AddRef,
1174 midi_IDirectMusicThru_Release,
1175 midi_IDirectMusicThru_ThruChannel,
1178 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1179 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1181 struct midi_port *obj;
1182 HRESULT hr;
1184 if (!(obj = heap_alloc_zero(sizeof(*obj))))
1185 return E_OUTOFMEMORY;
1187 obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1188 obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1189 obj->ref = 1;
1191 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1192 if (hr != S_OK) {
1193 HeapFree(GetProcessHeap(), 0, obj);
1194 return hr;
1197 *port = &obj->IDirectMusicPort_iface;
1199 return S_OK;
1202 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1203 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1205 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1207 return midi_port_create(parent, params, caps, port);
1210 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1211 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1213 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1215 return midi_port_create(parent, params, caps, port);