libwine: Do not restrict base address of main thread on 64 bit mac os.
[wine.git] / dlls / dmusic / port.c
blob91913a716f2fac9d529b1697dd07656ee64b5a25
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 "wine/heap.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
28 typedef struct SynthPortImpl {
29 IDirectMusicPort IDirectMusicPort_iface;
30 IDirectMusicPortDownload IDirectMusicPortDownload_iface;
31 IDirectMusicThru IDirectMusicThru_iface;
32 IKsControl IKsControl_iface;
33 LONG ref;
34 IDirectMusic8Impl *parent;
35 IDirectSound *dsound;
36 IDirectSoundBuffer *dsbuffer;
37 IReferenceClock *pLatencyClock;
38 IDirectMusicSynth *synth;
39 IDirectMusicSynthSink *synth_sink;
40 BOOL active;
41 DMUS_PORTCAPS caps;
42 DMUS_PORTPARAMS params;
43 int nrofgroups;
44 DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
45 } SynthPortImpl;
47 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
49 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
52 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
54 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
57 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
59 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
62 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
64 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
67 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface)
69 return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface);
72 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
73 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
75 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
77 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
79 IDirectMusicDownloadedInstrument_AddRef(iface);
80 *ret_iface = iface;
81 return S_OK;
84 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
86 return E_NOINTERFACE;
89 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
91 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
92 ULONG ref = InterlockedIncrement(&This->ref);
94 TRACE("(%p)->(): new ref = %u\n", iface, ref);
96 return ref;
99 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
101 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
102 ULONG ref = InterlockedDecrement(&This->ref);
104 TRACE("(%p)->(): new ref = %u\n", iface, ref);
106 if (!ref)
108 HeapFree(GetProcessHeap(), 0, This->data);
109 HeapFree(GetProcessHeap(), 0, This);
110 DMUSIC_UnlockModule();
113 return ref;
116 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
117 IDirectMusicDownloadedInstrumentImpl_QueryInterface,
118 IDirectMusicDownloadedInstrumentImpl_AddRef,
119 IDirectMusicDownloadedInstrumentImpl_Release
122 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
124 if (!iface)
125 return NULL;
126 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
128 return impl_from_IDirectMusicDownloadedInstrument(iface);
131 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
133 IDirectMusicDownloadedInstrumentImpl *object;
135 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
136 if (!object)
138 *instrument = NULL;
139 return E_OUTOFMEMORY;
142 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
143 object->ref = 1;
145 *instrument = &object->IDirectMusicDownloadedInstrument_iface;
146 DMUSIC_LockModule();
148 return S_OK;
151 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
152 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
154 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
156 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
158 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
159 *ret_iface = &This->IDirectMusicPort_iface;
160 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
161 *ret_iface = &This->IDirectMusicPortDownload_iface;
162 else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
163 *ret_iface = &This->IDirectMusicThru_iface;
164 else if (IsEqualGUID(riid, &IID_IKsControl))
165 *ret_iface = &This->IKsControl_iface;
166 else {
167 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
168 *ret_iface = NULL;
169 return E_NOINTERFACE;
172 IUnknown_AddRef((IUnknown*)*ret_iface);
174 return S_OK;
177 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
179 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
180 ULONG ref = InterlockedIncrement(&This->ref);
182 TRACE("(%p)->(): new ref = %u\n", This, ref);
184 DMUSIC_LockModule();
186 return ref;
189 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
191 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
192 ULONG ref = InterlockedDecrement(&This->ref);
194 TRACE("(%p)->(): new ref = %u\n", This, ref);
196 if (!ref)
198 dmusic_remove_port(This->parent, iface);
199 IDirectMusicSynth_Activate(This->synth, FALSE);
200 IDirectMusicSynth_Close(This->synth);
201 IDirectMusicSynth_Release(This->synth);
202 IDirectMusicSynthSink_Release(This->synth_sink);
203 IReferenceClock_Release(This->pLatencyClock);
204 if (This->dsbuffer)
205 IDirectSoundBuffer_Release(This->dsbuffer);
206 if (This->dsound)
207 IDirectSound_Release(This->dsound);
208 HeapFree(GetProcessHeap(), 0, This);
211 DMUSIC_UnlockModule();
213 return ref;
216 /* SynthPortImpl IDirectMusicPort interface follows: */
217 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
219 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
220 HRESULT hr;
221 REFERENCE_TIME time;
222 LPBYTE data;
223 DWORD size;
225 TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
227 if (!buffer)
228 return E_POINTER;
230 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
232 if (SUCCEEDED(hr))
233 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
235 if (SUCCEEDED(hr))
236 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
238 if (SUCCEEDED(hr))
239 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
241 return hr;
244 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
246 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
248 FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
250 return S_OK;
253 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
255 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
257 FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
259 return S_OK;
262 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
264 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
265 IDirectMusicInstrumentImpl *instrument_object;
266 HRESULT ret;
267 BOOL free;
268 HANDLE download;
269 DMUS_DOWNLOADINFO *info;
270 DMUS_OFFSETTABLE *offset_table;
271 DMUS_INSTRUMENT *instrument_info;
272 BYTE *data;
273 ULONG offset;
274 ULONG nb_regions;
275 ULONG size;
276 ULONG i;
278 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
280 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
281 return E_POINTER;
283 instrument_object = impl_from_IDirectMusicInstrument(instrument);
285 nb_regions = instrument_object->header.cRegions;
286 size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions;
288 data = HeapAlloc(GetProcessHeap(), 0, size);
289 if (!data)
290 return E_OUTOFMEMORY;
292 info = (DMUS_DOWNLOADINFO*)data;
293 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
294 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
296 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
297 info->dwDLId = 0;
298 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
299 info->cbSize = size;
301 offset_table->ulOffsetTable[0] = offset;
302 instrument_info = (DMUS_INSTRUMENT*)(data + offset);
303 offset += sizeof(DMUS_INSTRUMENT);
304 instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale);
305 instrument_info->ulFirstRegionIdx = 1;
306 instrument_info->ulGlobalArtIdx = 0; /* FIXME */
307 instrument_info->ulFirstExtCkIdx = 0; /* FIXME */
308 instrument_info->ulCopyrightIdx = 0; /* FIXME */
309 instrument_info->ulFlags = 0; /* FIXME */
311 for (i = 0; i < nb_regions; i++)
313 DMUS_REGION *region = (DMUS_REGION*)(data + offset);
315 offset_table->ulOffsetTable[1 + i] = offset;
316 offset += sizeof(DMUS_REGION);
317 region->RangeKey = instrument_object->regions[i].header.RangeKey;
318 region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity;
319 region->fusOptions = instrument_object->regions[i].header.fusOptions;
320 region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup;
321 region->ulRegionArtIdx = 0; /* FIXME */
322 region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
323 region->ulFirstExtCkIdx = 0; /* FIXME */
324 region->WaveLink = instrument_object->regions[i].wave_link;
325 region->WSMP = instrument_object->regions[i].wave_sample;
326 region->WLOOP[0] = instrument_object->regions[i].wave_loop;
329 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
331 if (SUCCEEDED(ret))
332 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
334 if (SUCCEEDED(ret))
336 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
338 downloaded_object->data = data;
339 downloaded_object->downloaded = TRUE;
342 *downloaded_instrument = NULL;
343 HeapFree(GetProcessHeap(), 0, data);
345 return E_FAIL;
348 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
350 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
351 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
353 TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument);
355 if (!downloaded_instrument)
356 return E_POINTER;
358 if (!downloaded_object->downloaded)
359 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
361 HeapFree(GetProcessHeap(), 0, downloaded_object->data);
362 downloaded_object->data = NULL;
363 downloaded_object->downloaded = FALSE;
365 return S_OK;
368 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
370 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
372 TRACE("(%p/%p)->(%p)\n", iface, This, clock);
374 *clock = This->pLatencyClock;
375 IReferenceClock_AddRef(*clock);
377 return S_OK;
380 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
382 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
384 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
386 return S_OK;
389 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
391 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
393 FIXME("(%p/%p)->(): stub\n", iface, This);
395 return S_OK;
398 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
400 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
402 TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
404 *port_caps = This->caps;
406 return S_OK;
409 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size,
410 LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped)
412 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
414 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);
416 return S_OK;
419 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
421 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
423 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
425 This->nrofgroups = channel_groups;
427 return S_OK;
430 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
432 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
434 TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
436 *channel_groups = This->nrofgroups;
438 return S_OK;
441 static HRESULT WINAPI synth_dmport_Activate(IDirectMusicPort *iface, BOOL active)
443 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
445 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
447 if (This->active == active)
448 return S_FALSE;
450 if (active) {
451 /* Acquire the dsound */
452 if (!This->dsound) {
453 IDirectSound_AddRef(This->parent->dsound);
454 This->dsound = This->parent->dsound;
456 IDirectSound_AddRef(This->dsound);
457 } else {
458 /* Release the dsound */
459 IDirectSound_Release(This->dsound);
460 IDirectSound_Release(This->parent->dsound);
461 if (This->dsound == This->parent->dsound)
462 This->dsound = NULL;
465 This->active = active;
467 return S_OK;
470 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
472 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
474 FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
476 if (channel > 16)
478 WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
479 /*return E_INVALIDARG;*/
482 return S_OK;
485 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
487 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
489 TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
491 *priority = This->group[channel_group - 1].channel[channel].priority;
493 return S_OK;
496 static HRESULT WINAPI synth_dmport_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
497 IDirectSoundBuffer *dsbuffer)
499 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
501 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
503 if (This->active)
504 return DMUS_E_DSOUND_ALREADY_SET;
506 if (This->dsound) {
507 if (This->dsound != This->parent->dsound)
508 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
509 This->dsound, This->parent->dsound);
510 if (!IDirectSound_Release(This->parent->dsound))
511 This->parent->dsound = NULL;
513 if (This->dsbuffer)
514 IDirectSoundBuffer_Release(This->dsbuffer);
516 This->dsound = dsound;
517 This->dsbuffer = dsbuffer;
519 if (This->dsound)
520 IDirectSound_AddRef(This->dsound);
521 if (This->dsbuffer)
522 IDirectSoundBuffer_AddRef(This->dsbuffer);
524 return S_OK;
527 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
529 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
530 WAVEFORMATEX format;
531 FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
533 if (pWaveFormatEx == NULL)
535 if (pdwWaveFormatExSize)
536 *pdwWaveFormatExSize = sizeof(format);
537 else
538 return E_POINTER;
540 else
542 if (pdwWaveFormatExSize == NULL)
543 return E_POINTER;
545 /* Just fill this in with something that will not crash Direct Sound for now. */
546 /* It won't be used anyway until Performances are completed */
547 format.wFormatTag = WAVE_FORMAT_PCM;
548 format.nChannels = 2; /* This->params.dwAudioChannels; */
549 format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */
550 format.wBitsPerSample = 16; /* FIXME: check this */
551 format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8;
552 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
553 format.cbSize = 0;
555 if (*pdwWaveFormatExSize >= sizeof(format))
557 CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
558 *pdwWaveFormatExSize = sizeof(format); /* FIXME check if this is set */
560 else
561 return E_POINTER; /* FIXME find right error */
564 if (pdwBufferSize)
565 *pdwBufferSize = 44100 * 2 * 2;
566 else
567 return E_POINTER;
569 return S_OK;
572 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = {
573 /**** IDirectMusicPort IUnknown part methods ***/
574 SynthPortImpl_IDirectMusicPort_QueryInterface,
575 SynthPortImpl_IDirectMusicPort_AddRef,
576 SynthPortImpl_IDirectMusicPort_Release,
577 /**** IDirectMusicPort methods ***/
578 SynthPortImpl_IDirectMusicPort_PlayBuffer,
579 SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle,
580 SynthPortImpl_IDirectMusicPort_Read,
581 SynthPortImpl_IDirectMusicPort_DownloadInstrument,
582 SynthPortImpl_IDirectMusicPort_UnloadInstrument,
583 SynthPortImpl_IDirectMusicPort_GetLatencyClock,
584 SynthPortImpl_IDirectMusicPort_GetRunningStats,
585 SynthPortImpl_IDirectMusicPort_Compact,
586 SynthPortImpl_IDirectMusicPort_GetCaps,
587 SynthPortImpl_IDirectMusicPort_DeviceIoControl,
588 SynthPortImpl_IDirectMusicPort_SetNumChannelGroups,
589 SynthPortImpl_IDirectMusicPort_GetNumChannelGroups,
590 synth_dmport_Activate,
591 SynthPortImpl_IDirectMusicPort_SetChannelPriority,
592 SynthPortImpl_IDirectMusicPort_GetChannelPriority,
593 synth_dmport_SetDirectSound,
594 SynthPortImpl_IDirectMusicPort_GetFormat
597 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
598 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
600 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
602 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
604 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
607 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
609 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
611 TRACE("(%p/%p)->()\n", iface, This);
613 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
616 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
618 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
620 TRACE("(%p/%p)->()\n", iface, This);
622 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
625 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
626 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
628 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
630 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
632 if (!IDMDownload)
633 return E_POINTER;
635 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
638 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
640 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
642 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
644 return S_OK;
647 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
649 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
651 FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
653 return S_OK;
656 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
658 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
660 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
662 return S_OK;
665 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
667 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
669 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
671 return S_OK;
674 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
676 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
678 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
680 return S_OK;
683 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = {
684 /*** IDirectMusicPortDownload IUnknown part methods ***/
685 SynthPortImpl_IDirectMusicPortDownload_QueryInterface,
686 SynthPortImpl_IDirectMusicPortDownload_AddRef,
687 SynthPortImpl_IDirectMusicPortDownload_Release,
688 /*** IDirectMusicPortDownload methods ***/
689 SynthPortImpl_IDirectMusicPortDownload_GetBuffer,
690 SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer,
691 SynthPortImpl_IDirectMusicPortDownload_GetDLId,
692 SynthPortImpl_IDirectMusicPortDownload_GetAppend,
693 SynthPortImpl_IDirectMusicPortDownload_Download,
694 SynthPortImpl_IDirectMusicPortDownload_Unload
697 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
698 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
700 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
702 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
704 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
707 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
709 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
711 TRACE("(%p/%p)->()\n", iface, This);
713 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
716 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
718 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
720 TRACE("(%p/%p)->()\n", iface, This);
722 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
725 /* SynthPortImpl IDirectMusicThru Interface follows: */
726 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group,
727 DWORD destination_channel, LPDIRECTMUSICPORT destination_port)
729 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
731 FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
733 return S_OK;
736 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = {
737 /*** IDirectMusicThru IUnknown part methods */
738 SynthPortImpl_IDirectMusicThru_QueryInterface,
739 SynthPortImpl_IDirectMusicThru_AddRef,
740 SynthPortImpl_IDirectMusicThru_Release,
741 /*** IDirectMusicThru methods ***/
742 SynthPortImpl_IDirectMusicThru_ThruChannel
745 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
746 void **ret_iface)
748 SynthPortImpl *This = impl_from_IKsControl(iface);
750 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
753 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
755 SynthPortImpl *This = impl_from_IKsControl(iface);
757 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
760 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
762 SynthPortImpl *This = impl_from_IKsControl(iface);
764 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
767 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
768 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
770 TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
771 TRACE("prop = %s - %u - %u\n", debugstr_guid(&prop->u.s.Set), prop->u.s.Id, prop->u.s.Flags);
773 if (prop->u.s.Flags != KSPROPERTY_TYPE_GET)
775 FIXME("prop flags %u not yet supported\n", prop->u.s.Flags);
776 return S_FALSE;
779 if (data_len < sizeof(DWORD))
780 return E_NOT_SUFFICIENT_BUFFER;
782 FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set));
783 *(DWORD*)data = FALSE;
784 *ret_len = sizeof(DWORD);
786 return S_OK;
789 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
790 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
792 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
794 return E_NOTIMPL;
797 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
798 void *data, ULONG data_len, ULONG *ret_len)
800 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
802 return E_NOTIMPL;
805 static const IKsControlVtbl ikscontrol_vtbl = {
806 IKsControlImpl_QueryInterface,
807 IKsControlImpl_AddRef,
808 IKsControlImpl_Release,
809 IKsControlImpl_KsProperty,
810 IKsControlImpl_KsMethod,
811 IKsControlImpl_KsEvent
814 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
815 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
817 SynthPortImpl *obj;
818 HRESULT hr = E_FAIL;
819 int i;
821 TRACE("(%p, %p, %p)\n", port_params, port_caps, port);
823 *port = NULL;
825 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
826 if (!obj)
827 return E_OUTOFMEMORY;
829 obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl;
830 obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl;
831 obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl;
832 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
833 obj->ref = 1;
834 obj->parent = parent;
835 obj->active = FALSE;
836 obj->params = *port_params;
837 obj->caps = *port_caps;
839 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
840 if (hr != S_OK)
842 HeapFree(GetProcessHeap(), 0, obj);
843 return hr;
846 if (SUCCEEDED(hr))
847 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
849 if (SUCCEEDED(hr))
850 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
852 if (SUCCEEDED(hr))
853 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
855 if (SUCCEEDED(hr))
856 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
858 if (SUCCEEDED(hr))
859 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
861 if (SUCCEEDED(hr))
862 hr = IDirectMusicSynth_Open(obj->synth, port_params);
864 if (0)
866 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
867 obj->nrofgroups = port_params->dwChannelGroups;
868 /* Setting default priorities */
869 for (i = 0; i < obj->nrofgroups; i++) {
870 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
871 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
872 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
873 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
874 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
875 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
876 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
877 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
878 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
879 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
880 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
881 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
882 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
883 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
884 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
885 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
886 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
891 if (SUCCEEDED(hr)) {
892 *port = &obj->IDirectMusicPort_iface;
893 return S_OK;
896 if (obj->synth)
897 IDirectMusicSynth_Release(obj->synth);
898 if (obj->synth_sink)
899 IDirectMusicSynthSink_Release(obj->synth_sink);
900 if (obj->pLatencyClock)
901 IReferenceClock_Release(obj->pLatencyClock);
902 HeapFree(GetProcessHeap(), 0, obj);
904 return hr;
907 struct midi_port {
908 IDirectMusicPort IDirectMusicPort_iface;
909 IDirectMusicThru IDirectMusicThru_iface;
910 LONG ref;
911 IReferenceClock *clock;
914 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
916 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
919 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
920 void **ret_iface)
922 struct midi_port *This = impl_from_IDirectMusicPort(iface);
924 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
926 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
927 *ret_iface = iface;
928 else if (IsEqualIID(riid, &IID_IDirectMusicThru))
929 *ret_iface = &This->IDirectMusicThru_iface;
930 else {
931 WARN("no interface for %s\n", debugstr_dmguid(riid));
932 *ret_iface = NULL;
933 return E_NOINTERFACE;
936 IUnknown_AddRef((IUnknown *)*ret_iface);
938 return S_OK;
941 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
943 struct midi_port *This = impl_from_IDirectMusicPort(iface);
944 ULONG ref = InterlockedIncrement(&This->ref);
946 TRACE("(%p) ref = %u\n", iface, ref);
948 return ref;
951 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
953 struct midi_port *This = impl_from_IDirectMusicPort(iface);
954 ULONG ref = InterlockedDecrement(&This->ref);
956 TRACE("(%p) ref = %u\n", iface, ref);
958 if (!ref) {
959 if (This->clock)
960 IReferenceClock_Release(This->clock);
961 heap_free(This);
964 return ref;
967 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
968 IDirectMusicBuffer *buffer)
970 FIXME("(%p, %p) stub!\n", iface, buffer);
972 return E_NOTIMPL;
975 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
976 HANDLE event)
978 FIXME("(%p, %p) stub!\n", iface, event);
980 return S_OK;
983 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
984 IDirectMusicBuffer *buffer)
986 FIXME("(%p, %p) stub!\n", iface, buffer);
988 return E_NOTIMPL;
991 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
992 IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
993 DMUS_NOTERANGE *ranges, DWORD num_ranges)
995 FIXME("(%p, %p, %p, %p, %u) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
997 return E_NOTIMPL;
1000 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
1001 IDirectMusicDownloadedInstrument *downloaded)
1003 FIXME("(%p, %p) stub!\n", iface, downloaded);
1005 return E_NOTIMPL;
1008 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
1009 IReferenceClock **clock)
1011 struct midi_port *This = impl_from_IDirectMusicPort(iface);
1013 TRACE("(%p, %p)\n", iface, clock);
1015 if (!clock)
1016 return E_POINTER;
1018 *clock = This->clock;
1019 IReferenceClock_AddRef(*clock);
1021 return S_OK;
1024 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
1025 DMUS_SYNTHSTATS *stats)
1027 FIXME("(%p, %p) stub!\n", iface, stats);
1029 return E_NOTIMPL;
1032 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
1034 FIXME("(%p) stub!\n", iface);
1036 return E_NOTIMPL;
1039 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
1041 FIXME("(%p, %p) stub!\n", iface, caps);
1043 return E_NOTIMPL;
1046 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
1047 DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
1048 OVERLAPPED *overlapped)
1050 FIXME("(%p, %u, %p, %u, %p, %u, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
1051 , size_out, ret_len, overlapped);
1053 return E_NOTIMPL;
1056 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
1057 DWORD cgroups)
1059 FIXME("(%p, %u) stub!\n", iface, cgroups);
1061 return E_NOTIMPL;
1064 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
1065 DWORD *cgroups)
1067 FIXME("(%p, %p) stub!\n", iface, cgroups);
1069 return E_NOTIMPL;
1072 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
1074 FIXME("(%p, %u) stub!\n", iface, active);
1076 return S_OK;
1079 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
1080 DWORD channel_group, DWORD channel, DWORD priority)
1082 FIXME("(%p, %u, %u, %u) stub!\n", iface, channel_group, channel, priority);
1084 return E_NOTIMPL;
1087 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
1088 DWORD channel_group, DWORD channel, DWORD *priority)
1090 FIXME("(%p, %u, %u, %p) stub!\n", iface, channel_group, channel, priority);
1092 return E_NOTIMPL;
1095 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
1096 IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
1098 FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
1100 return E_NOTIMPL;
1103 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
1104 DWORD *format_size, DWORD *buffer_size)
1106 FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
1108 return E_NOTIMPL;
1111 static const IDirectMusicPortVtbl midi_port_vtbl = {
1112 midi_IDirectMusicPort_QueryInterface,
1113 midi_IDirectMusicPort_AddRef,
1114 midi_IDirectMusicPort_Release,
1115 midi_IDirectMusicPort_PlayBuffer,
1116 midi_IDirectMusicPort_SetReadNotificationHandle,
1117 midi_IDirectMusicPort_Read,
1118 midi_IDirectMusicPort_DownloadInstrument,
1119 midi_IDirectMusicPort_UnloadInstrument,
1120 midi_IDirectMusicPort_GetLatencyClock,
1121 midi_IDirectMusicPort_GetRunningStats,
1122 midi_IDirectMusicPort_Compact,
1123 midi_IDirectMusicPort_GetCaps,
1124 midi_IDirectMusicPort_DeviceIoControl,
1125 midi_IDirectMusicPort_SetNumChannelGroups,
1126 midi_IDirectMusicPort_GetNumChannelGroups,
1127 midi_IDirectMusicPort_Activate,
1128 midi_IDirectMusicPort_SetChannelPriority,
1129 midi_IDirectMusicPort_GetChannelPriority,
1130 midi_IDirectMusicPort_SetDirectSound,
1131 midi_IDirectMusicPort_GetFormat,
1134 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
1136 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
1139 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
1140 void **ret_iface)
1142 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1144 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1147 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1149 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1151 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1154 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1156 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1158 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1161 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1162 DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1164 FIXME("(%p, %u, %u, %u, %u, %p) stub!\n", iface, src_group, src_channel, dest_group,
1165 dest_channel, dest_port);
1167 return S_OK;
1170 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1171 midi_IDirectMusicThru_QueryInterface,
1172 midi_IDirectMusicThru_AddRef,
1173 midi_IDirectMusicThru_Release,
1174 midi_IDirectMusicThru_ThruChannel,
1177 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1178 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1180 struct midi_port *obj;
1181 HRESULT hr;
1183 if (!(obj = heap_alloc_zero(sizeof(*obj))))
1184 return E_OUTOFMEMORY;
1186 obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1187 obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1188 obj->ref = 1;
1190 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1191 if (hr != S_OK) {
1192 HeapFree(GetProcessHeap(), 0, obj);
1193 return hr;
1196 *port = &obj->IDirectMusicPort_iface;
1198 return S_OK;
1201 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1202 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1204 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1206 return midi_port_create(parent, params, caps, port);
1209 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1210 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1212 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1214 return midi_port_create(parent, params, caps, port);