cfgmgr32: Add stub for CM_Get_Device_Interface_PropertyW.
[wine.git] / dlls / dmusic / port.c
blobb23a3f5d4dddddc9f4fc620353b1355b7c19b463
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 struct download_entry
29 struct list entry;
30 IDirectMusicDownload *download;
31 HANDLE handle;
32 DWORD id;
35 struct synth_port {
36 IDirectMusicPort IDirectMusicPort_iface;
37 IDirectMusicPortDownload IDirectMusicPortDownload_iface;
38 IDirectMusicThru IDirectMusicThru_iface;
39 IKsControl IKsControl_iface;
40 LONG ref;
41 IDirectMusic8Impl *parent;
42 IDirectSound *dsound;
43 IDirectSoundBuffer *dsbuffer;
44 IDirectMusicSynth *synth;
45 IDirectMusicSynthSink *synth_sink;
46 BOOL active;
47 DMUS_PORTPARAMS params;
48 int nrofgroups;
49 DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
51 struct list downloads;
52 DWORD next_dlid;
55 static inline struct synth_port *synth_from_IDirectMusicPort(IDirectMusicPort *iface)
57 return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicPort_iface);
60 static inline struct synth_port *synth_from_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
62 return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicPortDownload_iface);
65 static inline struct synth_port *synth_from_IDirectMusicThru(IDirectMusicThru *iface)
67 return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicThru_iface);
70 static inline struct synth_port *synth_from_IKsControl(IKsControl *iface)
72 return CONTAINING_RECORD(iface, struct synth_port, IKsControl_iface);
75 static HRESULT WINAPI synth_port_QueryInterface(IDirectMusicPort *iface, REFIID riid, void **ret_iface)
77 struct synth_port *This = synth_from_IDirectMusicPort(iface);
79 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
81 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
82 *ret_iface = &This->IDirectMusicPort_iface;
83 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
84 *ret_iface = &This->IDirectMusicPortDownload_iface;
85 else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
86 *ret_iface = &This->IDirectMusicThru_iface;
87 else if (IsEqualGUID(riid, &IID_IKsControl))
88 *ret_iface = &This->IKsControl_iface;
89 else {
90 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
91 *ret_iface = NULL;
92 return E_NOINTERFACE;
95 IUnknown_AddRef((IUnknown*)*ret_iface);
97 return S_OK;
100 static ULONG WINAPI synth_port_AddRef(IDirectMusicPort *iface)
102 struct synth_port *This = synth_from_IDirectMusicPort(iface);
103 ULONG ref = InterlockedIncrement(&This->ref);
105 TRACE("(%p): new ref = %lu\n", This, ref);
107 return ref;
110 static ULONG WINAPI synth_port_Release(IDirectMusicPort *iface)
112 struct synth_port *This = synth_from_IDirectMusicPort(iface);
113 ULONG ref = InterlockedDecrement(&This->ref);
115 TRACE("(%p): new ref = %lu\n", This, ref);
117 if (!ref)
119 struct download_entry *entry, *next;
121 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->downloads, struct download_entry, entry)
123 list_remove(&entry->entry);
124 IDirectMusicDownload_Release(entry->download);
125 free(entry);
128 dmusic_remove_port(This->parent, iface);
129 IDirectMusicSynthSink_Release(This->synth_sink);
130 IDirectMusicSynth_Activate(This->synth, FALSE);
131 IDirectMusicSynth_Close(This->synth);
132 IDirectMusicSynth_Release(This->synth);
133 if (This->dsbuffer)
134 IDirectSoundBuffer_Release(This->dsbuffer);
135 if (This->dsound)
136 IDirectSound_Release(This->dsound);
137 free(This);
140 return ref;
143 static HRESULT WINAPI synth_port_PlayBuffer(IDirectMusicPort *iface, IDirectMusicBuffer *buffer)
145 struct synth_port *This = synth_from_IDirectMusicPort(iface);
146 HRESULT hr;
147 REFERENCE_TIME time;
148 LPBYTE data;
149 DWORD size;
151 TRACE("(%p, %p)\n", iface, buffer);
153 if (!buffer)
154 return E_POINTER;
156 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
158 if (SUCCEEDED(hr))
159 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
161 if (SUCCEEDED(hr))
162 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
164 if (SUCCEEDED(hr))
165 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
167 return hr;
170 static HRESULT WINAPI synth_port_SetReadNotificationHandle(IDirectMusicPort *iface, HANDLE event)
172 TRACE("(%p, %p): method not implemented\n", iface, event);
173 return E_NOTIMPL;
176 static HRESULT WINAPI synth_port_Read(IDirectMusicPort *iface, IDirectMusicBuffer *buffer)
178 TRACE("(%p, %p): method not implemented\n", iface, buffer);
179 return E_NOTIMPL;
182 static HRESULT WINAPI synth_port_DownloadInstrument(IDirectMusicPort *iface, IDirectMusicInstrument *instrument,
183 IDirectMusicDownloadedInstrument **downloaded_instrument, DMUS_NOTERANGE *note_ranges, DWORD num_note_ranges)
185 struct synth_port *This = synth_from_IDirectMusicPort(iface);
187 TRACE("(%p, %p, %p, %p, %ld)\n", iface, instrument, downloaded_instrument, note_ranges, num_note_ranges);
189 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
190 return E_POINTER;
192 return instrument_download_to_port(instrument, &This->IDirectMusicPortDownload_iface, downloaded_instrument);
195 static HRESULT WINAPI synth_port_UnloadInstrument(IDirectMusicPort *iface,
196 IDirectMusicDownloadedInstrument *downloaded_instrument)
198 struct synth_port *This = synth_from_IDirectMusicPort(iface);
200 TRACE("(%p, %p)\n", iface, downloaded_instrument);
202 if (!downloaded_instrument)
203 return E_POINTER;
205 return instrument_unload_from_port(downloaded_instrument, &This->IDirectMusicPortDownload_iface);
208 static HRESULT WINAPI synth_port_GetLatencyClock(IDirectMusicPort *iface, IReferenceClock **clock)
210 struct synth_port *This = synth_from_IDirectMusicPort(iface);
212 TRACE("(%p, %p)\n", iface, clock);
214 return IDirectMusicSynth8_GetLatencyClock(This->synth, clock);
217 static HRESULT WINAPI synth_port_GetRunningStats(IDirectMusicPort *iface, DMUS_SYNTHSTATS *stats)
219 struct synth_port *This = synth_from_IDirectMusicPort(iface);
221 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
223 return S_OK;
226 static HRESULT WINAPI synth_port_Compact(IDirectMusicPort *iface)
228 TRACE("(%p): method not implemented\n", iface);
229 return E_NOTIMPL;
232 static HRESULT WINAPI synth_port_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *port_caps)
234 struct synth_port *This = synth_from_IDirectMusicPort(iface);
236 TRACE("(%p, %p)\n", iface, port_caps);
238 return IDirectMusicSynth_GetPortCaps(This->synth, port_caps);
241 static HRESULT WINAPI synth_port_DeviceIoControl(IDirectMusicPort *iface, DWORD io_control_code,
242 void *in_buffer, DWORD in_buffer_size, void *out_buffer, DWORD out_buffer_size,
243 DWORD *bytes_returned, OVERLAPPED *overlapped)
245 struct synth_port *This = synth_from_IDirectMusicPort(iface);
247 FIXME("(%p/%p, %ld, %p, %ld, %p, %ld, %p, %p): stub\n", iface, This, io_control_code, in_buffer, in_buffer_size, out_buffer, out_buffer_size, bytes_returned, overlapped);
249 return S_OK;
252 static HRESULT WINAPI synth_port_SetNumChannelGroups(IDirectMusicPort *iface, DWORD channel_groups)
254 struct synth_port *This = synth_from_IDirectMusicPort(iface);
256 FIXME("(%p, %ld): semi-stub\n", iface, channel_groups);
258 This->nrofgroups = channel_groups;
260 return S_OK;
263 static HRESULT WINAPI synth_port_GetNumChannelGroups(IDirectMusicPort *iface, DWORD *channel_groups)
265 struct synth_port *This = synth_from_IDirectMusicPort(iface);
267 TRACE("(%p, %p)\n", iface, channel_groups);
269 *channel_groups = This->nrofgroups;
271 return S_OK;
274 static HRESULT WINAPI synth_port_Activate(IDirectMusicPort *iface, BOOL active)
276 struct synth_port *This = synth_from_IDirectMusicPort(iface);
278 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
280 if (This->active == active)
281 return S_FALSE;
283 if (active) {
284 /* Acquire the dsound */
285 if (!This->dsound) {
286 IDirectSound_AddRef(This->parent->dsound);
287 This->dsound = This->parent->dsound;
289 IDirectSound_AddRef(This->dsound);
290 } else {
291 /* Release the dsound */
292 IDirectSound_Release(This->dsound);
293 IDirectSound_Release(This->parent->dsound);
294 if (This->dsound == This->parent->dsound)
295 This->dsound = NULL;
298 This->active = active;
300 return S_OK;
303 static HRESULT WINAPI synth_port_SetChannelPriority(IDirectMusicPort *iface, DWORD channel_group,
304 DWORD channel, DWORD priority)
306 struct synth_port *This = synth_from_IDirectMusicPort(iface);
308 FIXME("(%p/%p, %ld, %ld, %ld): semi-stub\n", iface, This, channel_group, channel, priority);
310 if (channel > 16)
312 WARN("isn't there supposed to be 16 channels (no. %ld requested)?! (faking as it is ok)\n", channel);
313 /*return E_INVALIDARG;*/
316 return S_OK;
319 static HRESULT WINAPI synth_port_GetChannelPriority(IDirectMusicPort *iface, DWORD channel_group,
320 DWORD channel, DWORD *priority)
322 struct synth_port *This = synth_from_IDirectMusicPort(iface);
324 TRACE("(%p, %lu, %lu, %p)\n", iface, channel_group, channel, priority);
326 *priority = This->group[channel_group - 1].channel[channel].priority;
328 return S_OK;
331 static HRESULT WINAPI synth_port_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
332 IDirectSoundBuffer *dsbuffer)
334 struct synth_port *This = synth_from_IDirectMusicPort(iface);
336 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
338 if (This->active)
339 return DMUS_E_DSOUND_ALREADY_SET;
341 if (This->dsound) {
342 if (This->dsound != This->parent->dsound)
343 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
344 This->dsound, This->parent->dsound);
345 if (!IDirectSound_Release(This->parent->dsound))
346 This->parent->dsound = NULL;
348 if (This->dsbuffer)
349 IDirectSoundBuffer_Release(This->dsbuffer);
351 This->dsound = dsound;
352 This->dsbuffer = dsbuffer;
354 if (This->dsound)
355 IDirectSound_AddRef(This->dsound);
356 if (This->dsbuffer)
357 IDirectSoundBuffer_AddRef(This->dsbuffer);
359 return S_OK;
362 static HRESULT WINAPI synth_port_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
363 DWORD *fmtsize, DWORD *bufsize)
365 struct synth_port *This = synth_from_IDirectMusicPort(iface);
366 HRESULT hr;
368 TRACE("(%p, %p, %p, %p)\n", This, format, fmtsize, bufsize);
370 if (FAILED(hr = IDirectMusicSynth_GetFormat(This->synth, format, fmtsize)))
371 return hr;
373 if (bufsize)
374 hr = IDirectMusicSynthSink_GetDesiredBufferSize(This->synth_sink, bufsize);
376 return hr;
379 static const IDirectMusicPortVtbl synth_port_vtbl = {
380 /**** IDirectMusicPort IUnknown part methods ***/
381 synth_port_QueryInterface,
382 synth_port_AddRef,
383 synth_port_Release,
384 /**** IDirectMusicPort methods ***/
385 synth_port_PlayBuffer,
386 synth_port_SetReadNotificationHandle,
387 synth_port_Read,
388 synth_port_DownloadInstrument,
389 synth_port_UnloadInstrument,
390 synth_port_GetLatencyClock,
391 synth_port_GetRunningStats,
392 synth_port_Compact,
393 synth_port_GetCaps,
394 synth_port_DeviceIoControl,
395 synth_port_SetNumChannelGroups,
396 synth_port_GetNumChannelGroups,
397 synth_port_Activate,
398 synth_port_SetChannelPriority,
399 synth_port_GetChannelPriority,
400 synth_port_SetDirectSound,
401 synth_port_GetFormat
404 static HRESULT WINAPI synth_port_download_QueryInterface(IDirectMusicPortDownload *iface, REFIID riid, void **ret_iface)
406 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
408 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
410 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
413 static ULONG WINAPI synth_port_download_AddRef(IDirectMusicPortDownload *iface)
415 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
417 TRACE("(%p)\n", iface);
419 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
422 static ULONG WINAPI synth_port_download_Release(IDirectMusicPortDownload *iface)
424 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
426 TRACE("(%p)\n", iface);
428 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
431 static HRESULT WINAPI synth_port_download_GetBuffer(IDirectMusicPortDownload *iface, DWORD id,
432 IDirectMusicDownload **download)
434 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
435 struct download_entry *entry;
437 TRACE("(%p/%p, %lu, %p)\n", iface, This, id, download);
439 if (!download) return E_POINTER;
440 if (id >= This->next_dlid) return DMUS_E_INVALID_DOWNLOADID;
442 LIST_FOR_EACH_ENTRY(entry, &This->downloads, struct download_entry, entry)
444 if (entry->id == id)
446 *download = entry->download;
447 IDirectMusicDownload_AddRef(entry->download);
448 return S_OK;
452 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
455 static HRESULT WINAPI synth_port_download_AllocateBuffer(IDirectMusicPortDownload *iface, DWORD size,
456 IDirectMusicDownload **download)
458 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
460 TRACE("(%p/%p, %lu, %p)\n", iface, This, size, download);
462 if (!download) return E_POINTER;
463 if (!size) return E_INVALIDARG;
465 return download_create(size, download);
468 static HRESULT WINAPI synth_port_download_GetDLId(IDirectMusicPortDownload *iface, DWORD *first, DWORD count)
470 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
472 TRACE("(%p/%p, %p, %lu)\n", iface, This, first, count);
474 if (!first) return E_POINTER;
475 if (!count) return E_INVALIDARG;
477 *first = This->next_dlid;
478 This->next_dlid += count;
480 return S_OK;
483 static HRESULT WINAPI synth_port_download_GetAppend(IDirectMusicPortDownload *iface, DWORD *append)
485 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
487 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
489 return S_OK;
492 static HRESULT WINAPI synth_port_download_Download(IDirectMusicPortDownload *iface, IDirectMusicDownload *download)
494 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
495 struct download_entry *entry;
496 DMUS_DOWNLOADINFO *info;
497 HANDLE handle;
498 BOOL can_free;
499 DWORD size;
500 HRESULT hr;
502 TRACE("(%p/%p)->(%p)\n", iface, This, download);
504 if (!download) return E_POINTER;
506 LIST_FOR_EACH_ENTRY(entry, &This->downloads, struct download_entry, entry)
507 if (entry->download == download) return DMUS_E_ALREADY_DOWNLOADED;
509 if (!(entry = malloc(sizeof(*entry)))) return E_OUTOFMEMORY;
510 if (SUCCEEDED(hr = IDirectMusicDownload_GetBuffer(download, (void **)&info, &size))
511 && SUCCEEDED(hr = IDirectMusicSynth_Download(This->synth, &handle, info, &can_free)))
513 entry->download = download;
514 IDirectMusicDownload_AddRef(download);
515 entry->id = info->dwDLId;
516 entry->handle = handle;
517 list_add_tail(&This->downloads, &entry->entry);
520 if (FAILED(hr)) free(entry);
521 return hr;
524 static HRESULT WINAPI synth_port_download_Unload(IDirectMusicPortDownload *iface, IDirectMusicDownload *download)
526 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
527 struct download_entry *entry;
528 HANDLE handle = 0;
530 TRACE("(%p/%p)->(%p)\n", iface, This, download);
532 if (!download) return E_POINTER;
534 LIST_FOR_EACH_ENTRY(entry, &This->downloads, struct download_entry, entry)
536 if (entry->download == download)
538 list_remove(&entry->entry);
539 IDirectMusicDownload_Release(entry->download);
540 handle = entry->handle;
541 free(entry);
542 break;
546 if (!handle) return S_OK;
547 return IDirectMusicSynth_Unload(This->synth, handle, NULL, NULL);
550 static const IDirectMusicPortDownloadVtbl synth_port_download_vtbl = {
551 /*** IDirectMusicPortDownload IUnknown part methods ***/
552 synth_port_download_QueryInterface,
553 synth_port_download_AddRef,
554 synth_port_download_Release,
555 /*** IDirectMusicPortDownload methods ***/
556 synth_port_download_GetBuffer,
557 synth_port_download_AllocateBuffer,
558 synth_port_download_GetDLId,
559 synth_port_download_GetAppend,
560 synth_port_download_Download,
561 synth_port_download_Unload
564 static HRESULT WINAPI synth_port_thru_QueryInterface(IDirectMusicThru *iface, REFIID riid, void **ret_iface)
566 struct synth_port *This = synth_from_IDirectMusicThru(iface);
568 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
570 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
573 static ULONG WINAPI synth_port_thru_AddRef(IDirectMusicThru *iface)
575 struct synth_port *This = synth_from_IDirectMusicThru(iface);
577 TRACE("(%p)\n", iface);
579 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
582 static ULONG WINAPI synth_port_thru_Release(IDirectMusicThru *iface)
584 struct synth_port *This = synth_from_IDirectMusicThru(iface);
586 TRACE("(%p)\n", iface);
588 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
591 static HRESULT WINAPI synth_port_thru_ThruChannel(IDirectMusicThru *iface, DWORD source_channel_group,
592 DWORD source_channel, DWORD destination_channel_group, DWORD destination_channel,
593 IDirectMusicPort *destination_port)
595 struct synth_port *This = synth_from_IDirectMusicThru(iface);
597 FIXME("(%p/%p, %ld, %ld, %ld, %ld, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
599 return S_OK;
602 static const IDirectMusicThruVtbl synth_port_thru_vtbl = {
603 /*** IDirectMusicThru IUnknown part methods */
604 synth_port_thru_QueryInterface,
605 synth_port_thru_AddRef,
606 synth_port_thru_Release,
607 /*** IDirectMusicThru methods ***/
608 synth_port_thru_ThruChannel
611 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
612 void **ret_iface)
614 struct synth_port *This = synth_from_IKsControl(iface);
616 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
619 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
621 struct synth_port *This = synth_from_IKsControl(iface);
623 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
626 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
628 struct synth_port *This = synth_from_IKsControl(iface);
630 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
633 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
634 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
636 TRACE("(%p, %p, %lu, %p, %lu, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
637 TRACE("prop = %s - %lu - %lu\n", debugstr_guid(&prop->Set), prop->Id, prop->Flags);
639 if (prop->Flags != KSPROPERTY_TYPE_GET)
641 FIXME("prop flags %lu not yet supported\n", prop->Flags);
642 return S_FALSE;
645 if (data_len < sizeof(DWORD))
646 return E_NOT_SUFFICIENT_BUFFER;
648 FIXME("Unknown property %s\n", debugstr_guid(&prop->Set));
649 *(DWORD*)data = FALSE;
650 *ret_len = sizeof(DWORD);
652 return S_OK;
655 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
656 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
658 FIXME("(%p, %p, %lu, %p, %lu, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
660 return E_NOTIMPL;
663 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
664 void *data, ULONG data_len, ULONG *ret_len)
666 FIXME("(%p, %p, %lu, %p, %lu, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
668 return E_NOTIMPL;
671 static const IKsControlVtbl ikscontrol_vtbl = {
672 IKsControlImpl_QueryInterface,
673 IKsControlImpl_AddRef,
674 IKsControlImpl_Release,
675 IKsControlImpl_KsProperty,
676 IKsControlImpl_KsMethod,
677 IKsControlImpl_KsEvent
680 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
681 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
683 struct synth_port *obj;
684 HRESULT hr = E_FAIL;
685 int i;
687 TRACE("(%p, %p)\n", port_params, port);
689 *port = NULL;
691 obj = calloc(1, sizeof(*obj));
692 if (!obj)
693 return E_OUTOFMEMORY;
695 obj->IDirectMusicPort_iface.lpVtbl = &synth_port_vtbl;
696 obj->IDirectMusicPortDownload_iface.lpVtbl = &synth_port_download_vtbl;
697 obj->IDirectMusicThru_iface.lpVtbl = &synth_port_thru_vtbl;
698 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
699 obj->ref = 1;
700 obj->parent = parent;
701 obj->active = FALSE;
702 obj->params = *port_params;
703 list_init(&obj->downloads);
705 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth,
706 (void **)&obj->synth);
708 if (SUCCEEDED(hr))
709 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
711 if (SUCCEEDED(hr))
712 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
714 if (SUCCEEDED(hr))
715 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->parent->master_clock);
717 if (SUCCEEDED(hr))
718 hr = IDirectMusicSynth_Open(obj->synth, port_params);
720 if (0)
722 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
723 obj->nrofgroups = port_params->dwChannelGroups;
724 /* Setting default priorities */
725 for (i = 0; i < obj->nrofgroups; i++) {
726 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
727 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
728 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
729 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
730 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
731 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
732 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
733 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
734 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
735 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
736 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
737 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
738 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
739 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
740 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
741 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
742 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
747 if (SUCCEEDED(hr)) {
748 *port = &obj->IDirectMusicPort_iface;
749 return S_OK;
752 if (obj->synth)
753 IDirectMusicSynth_Release(obj->synth);
754 if (obj->synth_sink)
755 IDirectMusicSynthSink_Release(obj->synth_sink);
756 free(obj);
758 return hr;
761 struct midi_port {
762 IDirectMusicPort IDirectMusicPort_iface;
763 IDirectMusicThru IDirectMusicThru_iface;
764 LONG ref;
765 IReferenceClock *clock;
768 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
770 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
773 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
774 void **ret_iface)
776 struct midi_port *This = impl_from_IDirectMusicPort(iface);
778 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
780 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
781 *ret_iface = iface;
782 else if (IsEqualIID(riid, &IID_IDirectMusicThru))
783 *ret_iface = &This->IDirectMusicThru_iface;
784 else {
785 WARN("no interface for %s\n", debugstr_dmguid(riid));
786 *ret_iface = NULL;
787 return E_NOINTERFACE;
790 IUnknown_AddRef((IUnknown *)*ret_iface);
792 return S_OK;
795 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
797 struct midi_port *This = impl_from_IDirectMusicPort(iface);
798 ULONG ref = InterlockedIncrement(&This->ref);
800 TRACE("(%p) ref = %lu\n", iface, ref);
802 return ref;
805 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
807 struct midi_port *This = impl_from_IDirectMusicPort(iface);
808 ULONG ref = InterlockedDecrement(&This->ref);
810 TRACE("(%p) ref = %lu\n", iface, ref);
812 if (!ref) {
813 if (This->clock)
814 IReferenceClock_Release(This->clock);
815 free(This);
818 return ref;
821 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
822 IDirectMusicBuffer *buffer)
824 FIXME("(%p, %p) stub!\n", iface, buffer);
826 return E_NOTIMPL;
829 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
830 HANDLE event)
832 FIXME("(%p, %p) stub!\n", iface, event);
834 return S_OK;
837 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
838 IDirectMusicBuffer *buffer)
840 FIXME("(%p, %p) stub!\n", iface, buffer);
842 return E_NOTIMPL;
845 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
846 IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
847 DMUS_NOTERANGE *ranges, DWORD num_ranges)
849 FIXME("(%p, %p, %p, %p, %lu) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
851 return E_NOTIMPL;
854 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
855 IDirectMusicDownloadedInstrument *downloaded)
857 FIXME("(%p, %p) stub!\n", iface, downloaded);
859 return E_NOTIMPL;
862 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
863 IReferenceClock **clock)
865 struct midi_port *This = impl_from_IDirectMusicPort(iface);
867 TRACE("(%p, %p)\n", iface, clock);
869 if (!clock)
870 return E_POINTER;
872 *clock = This->clock;
873 IReferenceClock_AddRef(*clock);
875 return S_OK;
878 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
879 DMUS_SYNTHSTATS *stats)
881 FIXME("(%p, %p) stub!\n", iface, stats);
883 return E_NOTIMPL;
886 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
888 FIXME("(%p) stub!\n", iface);
890 return E_NOTIMPL;
893 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
895 FIXME("(%p, %p) stub!\n", iface, caps);
897 return E_NOTIMPL;
900 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
901 DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
902 OVERLAPPED *overlapped)
904 FIXME("(%p, %lu, %p, %lu, %p, %lu, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
905 , size_out, ret_len, overlapped);
907 return E_NOTIMPL;
910 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
911 DWORD cgroups)
913 FIXME("(%p, %lu) stub!\n", iface, cgroups);
915 return E_NOTIMPL;
918 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
919 DWORD *cgroups)
921 FIXME("(%p, %p) stub!\n", iface, cgroups);
923 return E_NOTIMPL;
926 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
928 FIXME("(%p, %u) stub!\n", iface, active);
930 return S_OK;
933 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
934 DWORD channel_group, DWORD channel, DWORD priority)
936 FIXME("(%p, %lu, %lu, %lu) stub!\n", iface, channel_group, channel, priority);
938 return E_NOTIMPL;
941 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
942 DWORD channel_group, DWORD channel, DWORD *priority)
944 FIXME("(%p, %lu, %lu, %p) stub!\n", iface, channel_group, channel, priority);
946 return E_NOTIMPL;
949 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
950 IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
952 FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
954 return E_NOTIMPL;
957 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
958 DWORD *format_size, DWORD *buffer_size)
960 FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
962 return E_NOTIMPL;
965 static const IDirectMusicPortVtbl midi_port_vtbl = {
966 midi_IDirectMusicPort_QueryInterface,
967 midi_IDirectMusicPort_AddRef,
968 midi_IDirectMusicPort_Release,
969 midi_IDirectMusicPort_PlayBuffer,
970 midi_IDirectMusicPort_SetReadNotificationHandle,
971 midi_IDirectMusicPort_Read,
972 midi_IDirectMusicPort_DownloadInstrument,
973 midi_IDirectMusicPort_UnloadInstrument,
974 midi_IDirectMusicPort_GetLatencyClock,
975 midi_IDirectMusicPort_GetRunningStats,
976 midi_IDirectMusicPort_Compact,
977 midi_IDirectMusicPort_GetCaps,
978 midi_IDirectMusicPort_DeviceIoControl,
979 midi_IDirectMusicPort_SetNumChannelGroups,
980 midi_IDirectMusicPort_GetNumChannelGroups,
981 midi_IDirectMusicPort_Activate,
982 midi_IDirectMusicPort_SetChannelPriority,
983 midi_IDirectMusicPort_GetChannelPriority,
984 midi_IDirectMusicPort_SetDirectSound,
985 midi_IDirectMusicPort_GetFormat,
988 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
990 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
993 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
994 void **ret_iface)
996 struct midi_port *This = impl_from_IDirectMusicThru(iface);
998 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1001 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1003 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1005 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1008 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1010 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1012 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1015 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1016 DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1018 FIXME("(%p, %lu, %lu, %lu, %lu, %p) stub!\n", iface, src_group, src_channel, dest_group,
1019 dest_channel, dest_port);
1021 return S_OK;
1024 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1025 midi_IDirectMusicThru_QueryInterface,
1026 midi_IDirectMusicThru_AddRef,
1027 midi_IDirectMusicThru_Release,
1028 midi_IDirectMusicThru_ThruChannel,
1031 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1032 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1034 struct midi_port *obj;
1035 HRESULT hr;
1037 if (!(obj = calloc(1, sizeof(*obj))))
1038 return E_OUTOFMEMORY;
1040 obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1041 obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1042 obj->ref = 1;
1044 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1045 if (hr != S_OK) {
1046 free(obj);
1047 return hr;
1050 *port = &obj->IDirectMusicPort_iface;
1052 return S_OK;
1055 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1056 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1058 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1060 return midi_port_create(parent, params, caps, port);
1063 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1064 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1066 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1068 return midi_port_create(parent, params, caps, port);