dmime/tests: Check more notification / dirty messages fields.
[wine.git] / dlls / dmusic / port.c
blobf98d73f444463ec9d1d4f3332d80f45ea68d69a7
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);
277 HRESULT hr;
279 TRACE("(%p/%p)->(%d)\n", iface, This, active);
281 if (This->active == active) return S_FALSE;
283 if (active)
285 if (!This->dsound && FAILED(hr = IDirectMusicPort_SetDirectSound(iface,
286 This->parent->dsound, NULL)))
287 return hr;
288 if (FAILED(hr = IDirectMusicSynthSink_SetDirectSound(This->synth_sink,
289 This->dsound, This->dsbuffer)))
290 return hr;
292 if (FAILED(hr = IDirectMusicSynth_Activate(This->synth, active)))
293 return hr;
294 This->active = TRUE;
296 else
298 if (FAILED(hr = IDirectMusicSynth_Activate(This->synth, FALSE))) return hr;
299 This->active = FALSE;
301 if (FAILED(hr = IDirectMusicSynthSink_SetDirectSound(This->synth_sink, NULL, NULL)))
302 return hr;
303 hr = IDirectMusicPort_SetDirectSound(iface, NULL, NULL);
306 return hr;
309 static HRESULT WINAPI synth_port_SetChannelPriority(IDirectMusicPort *iface, DWORD channel_group,
310 DWORD channel, DWORD priority)
312 struct synth_port *This = synth_from_IDirectMusicPort(iface);
314 FIXME("(%p/%p, %ld, %ld, %ld): semi-stub\n", iface, This, channel_group, channel, priority);
316 if (channel > 16)
318 WARN("isn't there supposed to be 16 channels (no. %ld requested)?! (faking as it is ok)\n", channel);
319 /*return E_INVALIDARG;*/
322 return S_OK;
325 static HRESULT WINAPI synth_port_GetChannelPriority(IDirectMusicPort *iface, DWORD channel_group,
326 DWORD channel, DWORD *priority)
328 struct synth_port *This = synth_from_IDirectMusicPort(iface);
330 TRACE("(%p, %lu, %lu, %p)\n", iface, channel_group, channel, priority);
332 *priority = This->group[channel_group - 1].channel[channel].priority;
334 return S_OK;
337 static HRESULT WINAPI synth_port_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
338 IDirectSoundBuffer *dsbuffer)
340 struct synth_port *This = synth_from_IDirectMusicPort(iface);
342 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
344 if (This->active)
345 return DMUS_E_DSOUND_ALREADY_SET;
347 if (This->dsound) {
348 if (This->dsound != This->parent->dsound)
349 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
350 This->dsound, This->parent->dsound);
351 if (!IDirectSound_Release(This->parent->dsound))
352 This->parent->dsound = NULL;
354 if (This->dsbuffer)
355 IDirectSoundBuffer_Release(This->dsbuffer);
357 This->dsound = dsound;
358 This->dsbuffer = dsbuffer;
360 if (This->dsound)
361 IDirectSound_AddRef(This->dsound);
362 if (This->dsbuffer)
363 IDirectSoundBuffer_AddRef(This->dsbuffer);
365 return S_OK;
368 static HRESULT WINAPI synth_port_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
369 DWORD *fmtsize, DWORD *bufsize)
371 struct synth_port *This = synth_from_IDirectMusicPort(iface);
372 HRESULT hr;
374 TRACE("(%p, %p, %p, %p)\n", This, format, fmtsize, bufsize);
376 if (FAILED(hr = IDirectMusicSynth_GetFormat(This->synth, format, fmtsize)))
377 return hr;
379 if (bufsize)
380 hr = IDirectMusicSynthSink_GetDesiredBufferSize(This->synth_sink, bufsize);
382 return hr;
385 static const IDirectMusicPortVtbl synth_port_vtbl = {
386 /**** IDirectMusicPort IUnknown part methods ***/
387 synth_port_QueryInterface,
388 synth_port_AddRef,
389 synth_port_Release,
390 /**** IDirectMusicPort methods ***/
391 synth_port_PlayBuffer,
392 synth_port_SetReadNotificationHandle,
393 synth_port_Read,
394 synth_port_DownloadInstrument,
395 synth_port_UnloadInstrument,
396 synth_port_GetLatencyClock,
397 synth_port_GetRunningStats,
398 synth_port_Compact,
399 synth_port_GetCaps,
400 synth_port_DeviceIoControl,
401 synth_port_SetNumChannelGroups,
402 synth_port_GetNumChannelGroups,
403 synth_port_Activate,
404 synth_port_SetChannelPriority,
405 synth_port_GetChannelPriority,
406 synth_port_SetDirectSound,
407 synth_port_GetFormat
410 static HRESULT WINAPI synth_port_download_QueryInterface(IDirectMusicPortDownload *iface, REFIID riid, void **ret_iface)
412 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
414 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
416 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
419 static ULONG WINAPI synth_port_download_AddRef(IDirectMusicPortDownload *iface)
421 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
423 TRACE("(%p)\n", iface);
425 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
428 static ULONG WINAPI synth_port_download_Release(IDirectMusicPortDownload *iface)
430 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
432 TRACE("(%p)\n", iface);
434 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
437 static HRESULT WINAPI synth_port_download_GetBuffer(IDirectMusicPortDownload *iface, DWORD id,
438 IDirectMusicDownload **download)
440 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
441 struct download_entry *entry;
443 TRACE("(%p/%p, %lu, %p)\n", iface, This, id, download);
445 if (!download) return E_POINTER;
446 if (id >= This->next_dlid) return DMUS_E_INVALID_DOWNLOADID;
448 LIST_FOR_EACH_ENTRY(entry, &This->downloads, struct download_entry, entry)
450 if (entry->id == id)
452 *download = entry->download;
453 IDirectMusicDownload_AddRef(entry->download);
454 return S_OK;
458 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
461 static HRESULT WINAPI synth_port_download_AllocateBuffer(IDirectMusicPortDownload *iface, DWORD size,
462 IDirectMusicDownload **download)
464 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
466 TRACE("(%p/%p, %lu, %p)\n", iface, This, size, download);
468 if (!download) return E_POINTER;
469 if (!size) return E_INVALIDARG;
471 return download_create(size, download);
474 static HRESULT WINAPI synth_port_download_GetDLId(IDirectMusicPortDownload *iface, DWORD *first, DWORD count)
476 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
478 TRACE("(%p/%p, %p, %lu)\n", iface, This, first, count);
480 if (!first) return E_POINTER;
481 if (!count) return E_INVALIDARG;
483 *first = This->next_dlid;
484 This->next_dlid += count;
486 return S_OK;
489 static HRESULT WINAPI synth_port_download_GetAppend(IDirectMusicPortDownload *iface, DWORD *append)
491 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
493 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
495 return S_OK;
498 static HRESULT WINAPI synth_port_download_Download(IDirectMusicPortDownload *iface, IDirectMusicDownload *download)
500 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
501 struct download_entry *entry;
502 DMUS_DOWNLOADINFO *info;
503 HANDLE handle;
504 BOOL can_free;
505 DWORD size;
506 HRESULT hr;
508 TRACE("(%p/%p)->(%p)\n", iface, This, download);
510 if (!download) return E_POINTER;
512 LIST_FOR_EACH_ENTRY(entry, &This->downloads, struct download_entry, entry)
513 if (entry->download == download) return DMUS_E_ALREADY_DOWNLOADED;
515 if (!(entry = malloc(sizeof(*entry)))) return E_OUTOFMEMORY;
516 if (SUCCEEDED(hr = IDirectMusicDownload_GetBuffer(download, (void **)&info, &size))
517 && SUCCEEDED(hr = IDirectMusicSynth_Download(This->synth, &handle, info, &can_free)))
519 entry->download = download;
520 IDirectMusicDownload_AddRef(download);
521 entry->id = info->dwDLId;
522 entry->handle = handle;
523 list_add_tail(&This->downloads, &entry->entry);
526 if (FAILED(hr)) free(entry);
527 return hr;
530 static HRESULT WINAPI synth_port_download_Unload(IDirectMusicPortDownload *iface, IDirectMusicDownload *download)
532 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
533 struct download_entry *entry;
534 HANDLE handle = 0;
536 TRACE("(%p/%p)->(%p)\n", iface, This, download);
538 if (!download) return E_POINTER;
540 LIST_FOR_EACH_ENTRY(entry, &This->downloads, struct download_entry, entry)
542 if (entry->download == download)
544 list_remove(&entry->entry);
545 IDirectMusicDownload_Release(entry->download);
546 handle = entry->handle;
547 free(entry);
548 break;
552 if (!handle) return S_OK;
553 return IDirectMusicSynth_Unload(This->synth, handle, NULL, NULL);
556 static const IDirectMusicPortDownloadVtbl synth_port_download_vtbl = {
557 /*** IDirectMusicPortDownload IUnknown part methods ***/
558 synth_port_download_QueryInterface,
559 synth_port_download_AddRef,
560 synth_port_download_Release,
561 /*** IDirectMusicPortDownload methods ***/
562 synth_port_download_GetBuffer,
563 synth_port_download_AllocateBuffer,
564 synth_port_download_GetDLId,
565 synth_port_download_GetAppend,
566 synth_port_download_Download,
567 synth_port_download_Unload
570 static HRESULT WINAPI synth_port_thru_QueryInterface(IDirectMusicThru *iface, REFIID riid, void **ret_iface)
572 struct synth_port *This = synth_from_IDirectMusicThru(iface);
574 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
576 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
579 static ULONG WINAPI synth_port_thru_AddRef(IDirectMusicThru *iface)
581 struct synth_port *This = synth_from_IDirectMusicThru(iface);
583 TRACE("(%p)\n", iface);
585 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
588 static ULONG WINAPI synth_port_thru_Release(IDirectMusicThru *iface)
590 struct synth_port *This = synth_from_IDirectMusicThru(iface);
592 TRACE("(%p)\n", iface);
594 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
597 static HRESULT WINAPI synth_port_thru_ThruChannel(IDirectMusicThru *iface, DWORD source_channel_group,
598 DWORD source_channel, DWORD destination_channel_group, DWORD destination_channel,
599 IDirectMusicPort *destination_port)
601 struct synth_port *This = synth_from_IDirectMusicThru(iface);
603 FIXME("(%p/%p, %ld, %ld, %ld, %ld, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
605 return S_OK;
608 static const IDirectMusicThruVtbl synth_port_thru_vtbl = {
609 /*** IDirectMusicThru IUnknown part methods */
610 synth_port_thru_QueryInterface,
611 synth_port_thru_AddRef,
612 synth_port_thru_Release,
613 /*** IDirectMusicThru methods ***/
614 synth_port_thru_ThruChannel
617 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
618 void **ret_iface)
620 struct synth_port *This = synth_from_IKsControl(iface);
622 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
625 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
627 struct synth_port *This = synth_from_IKsControl(iface);
629 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
632 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
634 struct synth_port *This = synth_from_IKsControl(iface);
636 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
639 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
640 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
642 TRACE("(%p, %p, %lu, %p, %lu, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
643 TRACE("prop = %s - %lu - %lu\n", debugstr_guid(&prop->Set), prop->Id, prop->Flags);
645 if (prop->Flags != KSPROPERTY_TYPE_GET)
647 FIXME("prop flags %lu not yet supported\n", prop->Flags);
648 return S_FALSE;
651 if (data_len < sizeof(DWORD))
652 return E_NOT_SUFFICIENT_BUFFER;
654 FIXME("Unknown property %s\n", debugstr_guid(&prop->Set));
655 *(DWORD*)data = FALSE;
656 *ret_len = sizeof(DWORD);
658 return S_OK;
661 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
662 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
664 FIXME("(%p, %p, %lu, %p, %lu, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
666 return E_NOTIMPL;
669 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
670 void *data, ULONG data_len, ULONG *ret_len)
672 FIXME("(%p, %p, %lu, %p, %lu, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
674 return E_NOTIMPL;
677 static const IKsControlVtbl ikscontrol_vtbl = {
678 IKsControlImpl_QueryInterface,
679 IKsControlImpl_AddRef,
680 IKsControlImpl_Release,
681 IKsControlImpl_KsProperty,
682 IKsControlImpl_KsMethod,
683 IKsControlImpl_KsEvent
686 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
687 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
689 struct synth_port *obj;
690 HRESULT hr = E_FAIL;
691 int i;
693 TRACE("(%p, %p)\n", port_params, port);
695 *port = NULL;
697 obj = calloc(1, sizeof(*obj));
698 if (!obj)
699 return E_OUTOFMEMORY;
701 obj->IDirectMusicPort_iface.lpVtbl = &synth_port_vtbl;
702 obj->IDirectMusicPortDownload_iface.lpVtbl = &synth_port_download_vtbl;
703 obj->IDirectMusicThru_iface.lpVtbl = &synth_port_thru_vtbl;
704 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
705 obj->ref = 1;
706 obj->parent = parent;
707 obj->active = FALSE;
708 obj->params = *port_params;
709 list_init(&obj->downloads);
711 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth,
712 (void **)&obj->synth);
714 if (SUCCEEDED(hr))
715 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
717 if (SUCCEEDED(hr))
718 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
720 if (SUCCEEDED(hr))
721 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->parent->master_clock);
723 if (SUCCEEDED(hr))
724 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->parent->master_clock);
726 if (SUCCEEDED(hr))
727 hr = IDirectMusicSynth_Open(obj->synth, port_params);
729 if (0)
731 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
732 obj->nrofgroups = port_params->dwChannelGroups;
733 /* Setting default priorities */
734 for (i = 0; i < obj->nrofgroups; i++) {
735 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
736 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
737 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
738 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
739 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
740 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
741 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
742 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
743 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
744 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
745 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
746 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
747 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
748 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
749 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
750 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
751 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
756 if (SUCCEEDED(hr)) {
757 *port = &obj->IDirectMusicPort_iface;
758 return S_OK;
761 if (obj->synth)
762 IDirectMusicSynth_Release(obj->synth);
763 if (obj->synth_sink)
764 IDirectMusicSynthSink_Release(obj->synth_sink);
765 free(obj);
767 return hr;
770 struct midi_port {
771 IDirectMusicPort IDirectMusicPort_iface;
772 IDirectMusicThru IDirectMusicThru_iface;
773 LONG ref;
774 IReferenceClock *clock;
777 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
779 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
782 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
783 void **ret_iface)
785 struct midi_port *This = impl_from_IDirectMusicPort(iface);
787 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
789 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
790 *ret_iface = iface;
791 else if (IsEqualIID(riid, &IID_IDirectMusicThru))
792 *ret_iface = &This->IDirectMusicThru_iface;
793 else {
794 WARN("no interface for %s\n", debugstr_dmguid(riid));
795 *ret_iface = NULL;
796 return E_NOINTERFACE;
799 IUnknown_AddRef((IUnknown *)*ret_iface);
801 return S_OK;
804 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
806 struct midi_port *This = impl_from_IDirectMusicPort(iface);
807 ULONG ref = InterlockedIncrement(&This->ref);
809 TRACE("(%p) ref = %lu\n", iface, ref);
811 return ref;
814 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
816 struct midi_port *This = impl_from_IDirectMusicPort(iface);
817 ULONG ref = InterlockedDecrement(&This->ref);
819 TRACE("(%p) ref = %lu\n", iface, ref);
821 if (!ref) {
822 if (This->clock)
823 IReferenceClock_Release(This->clock);
824 free(This);
827 return ref;
830 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
831 IDirectMusicBuffer *buffer)
833 FIXME("(%p, %p) stub!\n", iface, buffer);
835 return E_NOTIMPL;
838 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
839 HANDLE event)
841 FIXME("(%p, %p) stub!\n", iface, event);
843 return S_OK;
846 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
847 IDirectMusicBuffer *buffer)
849 FIXME("(%p, %p) stub!\n", iface, buffer);
851 return E_NOTIMPL;
854 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
855 IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
856 DMUS_NOTERANGE *ranges, DWORD num_ranges)
858 FIXME("(%p, %p, %p, %p, %lu) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
860 return E_NOTIMPL;
863 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
864 IDirectMusicDownloadedInstrument *downloaded)
866 FIXME("(%p, %p) stub!\n", iface, downloaded);
868 return E_NOTIMPL;
871 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
872 IReferenceClock **clock)
874 struct midi_port *This = impl_from_IDirectMusicPort(iface);
876 TRACE("(%p, %p)\n", iface, clock);
878 if (!clock)
879 return E_POINTER;
881 *clock = This->clock;
882 IReferenceClock_AddRef(*clock);
884 return S_OK;
887 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
888 DMUS_SYNTHSTATS *stats)
890 FIXME("(%p, %p) stub!\n", iface, stats);
892 return E_NOTIMPL;
895 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
897 FIXME("(%p) stub!\n", iface);
899 return E_NOTIMPL;
902 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
904 FIXME("(%p, %p) stub!\n", iface, caps);
906 return E_NOTIMPL;
909 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
910 DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
911 OVERLAPPED *overlapped)
913 FIXME("(%p, %lu, %p, %lu, %p, %lu, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
914 , size_out, ret_len, overlapped);
916 return E_NOTIMPL;
919 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
920 DWORD cgroups)
922 FIXME("(%p, %lu) stub!\n", iface, cgroups);
924 return E_NOTIMPL;
927 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
928 DWORD *cgroups)
930 FIXME("(%p, %p) stub!\n", iface, cgroups);
932 return E_NOTIMPL;
935 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
937 FIXME("(%p, %u) stub!\n", iface, active);
939 return S_OK;
942 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
943 DWORD channel_group, DWORD channel, DWORD priority)
945 FIXME("(%p, %lu, %lu, %lu) stub!\n", iface, channel_group, channel, priority);
947 return E_NOTIMPL;
950 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
951 DWORD channel_group, DWORD channel, DWORD *priority)
953 FIXME("(%p, %lu, %lu, %p) stub!\n", iface, channel_group, channel, priority);
955 return E_NOTIMPL;
958 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
959 IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
961 FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
963 return E_NOTIMPL;
966 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
967 DWORD *format_size, DWORD *buffer_size)
969 FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
971 return E_NOTIMPL;
974 static const IDirectMusicPortVtbl midi_port_vtbl = {
975 midi_IDirectMusicPort_QueryInterface,
976 midi_IDirectMusicPort_AddRef,
977 midi_IDirectMusicPort_Release,
978 midi_IDirectMusicPort_PlayBuffer,
979 midi_IDirectMusicPort_SetReadNotificationHandle,
980 midi_IDirectMusicPort_Read,
981 midi_IDirectMusicPort_DownloadInstrument,
982 midi_IDirectMusicPort_UnloadInstrument,
983 midi_IDirectMusicPort_GetLatencyClock,
984 midi_IDirectMusicPort_GetRunningStats,
985 midi_IDirectMusicPort_Compact,
986 midi_IDirectMusicPort_GetCaps,
987 midi_IDirectMusicPort_DeviceIoControl,
988 midi_IDirectMusicPort_SetNumChannelGroups,
989 midi_IDirectMusicPort_GetNumChannelGroups,
990 midi_IDirectMusicPort_Activate,
991 midi_IDirectMusicPort_SetChannelPriority,
992 midi_IDirectMusicPort_GetChannelPriority,
993 midi_IDirectMusicPort_SetDirectSound,
994 midi_IDirectMusicPort_GetFormat,
997 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
999 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
1002 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
1003 void **ret_iface)
1005 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1007 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1010 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1012 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1014 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1017 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1019 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1021 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1024 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1025 DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1027 FIXME("(%p, %lu, %lu, %lu, %lu, %p) stub!\n", iface, src_group, src_channel, dest_group,
1028 dest_channel, dest_port);
1030 return S_OK;
1033 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1034 midi_IDirectMusicThru_QueryInterface,
1035 midi_IDirectMusicThru_AddRef,
1036 midi_IDirectMusicThru_Release,
1037 midi_IDirectMusicThru_ThruChannel,
1040 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1041 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1043 struct midi_port *obj;
1044 HRESULT hr;
1046 if (!(obj = calloc(1, sizeof(*obj))))
1047 return E_OUTOFMEMORY;
1049 obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1050 obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1051 obj->ref = 1;
1053 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1054 if (hr != S_OK) {
1055 free(obj);
1056 return hr;
1059 *port = &obj->IDirectMusicPort_iface;
1061 return S_OK;
1064 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1065 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1067 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1069 return midi_port_create(parent, params, caps, port);
1072 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1073 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1075 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1077 return midi_port_create(parent, params, caps, port);