winspool.drv: Implement OpenPrinter2.
[wine.git] / dlls / dmusic / port.c
blob8549c62c4b1e3b7a7f949ac1c23dcd57b29ef274
1 /*
2 * IDirectMusicPort Implementation
4 * Copyright (C) 2003-2004 Rok Mandeljc
5 * Copyright (C) 2012 Christian Costa
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <assert.h>
23 #include "dmusic_private.h"
24 #include "dmobject.h"
25 #include "wine/heap.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
29 struct synth_port {
30 IDirectMusicPort IDirectMusicPort_iface;
31 IDirectMusicPortDownload IDirectMusicPortDownload_iface;
32 IDirectMusicThru IDirectMusicThru_iface;
33 IKsControl IKsControl_iface;
34 LONG ref;
35 IDirectMusic8Impl *parent;
36 IDirectSound *dsound;
37 IDirectSoundBuffer *dsbuffer;
38 IDirectMusicSynth *synth;
39 IDirectMusicSynthSink *synth_sink;
40 BOOL active;
41 DMUS_PORTPARAMS params;
42 int nrofgroups;
43 DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
46 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
48 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
51 static inline struct synth_port *synth_from_IDirectMusicPort(IDirectMusicPort *iface)
53 return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicPort_iface);
56 static inline struct synth_port *synth_from_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
58 return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicPortDownload_iface);
61 static inline struct synth_port *synth_from_IDirectMusicThru(IDirectMusicThru *iface)
63 return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicThru_iface);
66 static inline struct synth_port *synth_from_IKsControl(IKsControl *iface)
68 return CONTAINING_RECORD(iface, struct synth_port, IKsControl_iface);
71 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
72 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
74 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
76 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
78 IDirectMusicDownloadedInstrument_AddRef(iface);
79 *ret_iface = iface;
80 return S_OK;
83 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
85 return E_NOINTERFACE;
88 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
90 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
91 ULONG ref = InterlockedIncrement(&This->ref);
93 TRACE("(%p): new ref = %lu\n", iface, ref);
95 return ref;
98 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
100 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
101 ULONG ref = InterlockedDecrement(&This->ref);
103 TRACE("(%p): new ref = %lu\n", iface, ref);
105 if (!ref)
107 HeapFree(GetProcessHeap(), 0, This->data);
108 HeapFree(GetProcessHeap(), 0, This);
109 DMUSIC_UnlockModule();
112 return ref;
115 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
116 IDirectMusicDownloadedInstrumentImpl_QueryInterface,
117 IDirectMusicDownloadedInstrumentImpl_AddRef,
118 IDirectMusicDownloadedInstrumentImpl_Release
121 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
123 if (!iface)
124 return NULL;
125 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
127 return impl_from_IDirectMusicDownloadedInstrument(iface);
130 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
132 IDirectMusicDownloadedInstrumentImpl *object;
134 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
135 if (!object)
137 *instrument = NULL;
138 return E_OUTOFMEMORY;
141 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
142 object->ref = 1;
144 *instrument = &object->IDirectMusicDownloadedInstrument_iface;
145 DMUSIC_LockModule();
147 return S_OK;
150 static HRESULT WINAPI synth_port_QueryInterface(IDirectMusicPort *iface, REFIID riid, void **ret_iface)
152 struct synth_port *This = synth_from_IDirectMusicPort(iface);
154 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
156 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
157 *ret_iface = &This->IDirectMusicPort_iface;
158 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
159 *ret_iface = &This->IDirectMusicPortDownload_iface;
160 else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
161 *ret_iface = &This->IDirectMusicThru_iface;
162 else if (IsEqualGUID(riid, &IID_IKsControl))
163 *ret_iface = &This->IKsControl_iface;
164 else {
165 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
166 *ret_iface = NULL;
167 return E_NOINTERFACE;
170 IUnknown_AddRef((IUnknown*)*ret_iface);
172 return S_OK;
175 static ULONG WINAPI synth_port_AddRef(IDirectMusicPort *iface)
177 struct synth_port *This = synth_from_IDirectMusicPort(iface);
178 ULONG ref = InterlockedIncrement(&This->ref);
180 TRACE("(%p): new ref = %lu\n", This, ref);
182 DMUSIC_LockModule();
184 return ref;
187 static ULONG WINAPI synth_port_Release(IDirectMusicPort *iface)
189 struct synth_port *This = synth_from_IDirectMusicPort(iface);
190 ULONG ref = InterlockedDecrement(&This->ref);
192 TRACE("(%p): new ref = %lu\n", This, ref);
194 if (!ref)
196 dmusic_remove_port(This->parent, iface);
197 IDirectMusicSynthSink_Release(This->synth_sink);
198 IDirectMusicSynth_Activate(This->synth, FALSE);
199 IDirectMusicSynth_Close(This->synth);
200 IDirectMusicSynth_Release(This->synth);
201 if (This->dsbuffer)
202 IDirectSoundBuffer_Release(This->dsbuffer);
203 if (This->dsound)
204 IDirectSound_Release(This->dsound);
205 HeapFree(GetProcessHeap(), 0, This);
208 DMUSIC_UnlockModule();
210 return ref;
213 static HRESULT WINAPI synth_port_PlayBuffer(IDirectMusicPort *iface, IDirectMusicBuffer *buffer)
215 struct synth_port *This = synth_from_IDirectMusicPort(iface);
216 HRESULT hr;
217 REFERENCE_TIME time;
218 LPBYTE data;
219 DWORD size;
221 TRACE("(%p, %p)\n", iface, buffer);
223 if (!buffer)
224 return E_POINTER;
226 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
228 if (SUCCEEDED(hr))
229 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
231 if (SUCCEEDED(hr))
232 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
234 if (SUCCEEDED(hr))
235 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
237 return hr;
240 static HRESULT WINAPI synth_port_SetReadNotificationHandle(IDirectMusicPort *iface, HANDLE event)
242 TRACE("(%p, %p): method not implemented\n", iface, event);
243 return E_NOTIMPL;
246 static HRESULT WINAPI synth_port_Read(IDirectMusicPort *iface, IDirectMusicBuffer *buffer)
248 TRACE("(%p, %p): method not implemented\n", iface, buffer);
249 return E_NOTIMPL;
252 static HRESULT WINAPI synth_port_DownloadInstrument(IDirectMusicPort *iface, IDirectMusicInstrument *instrument,
253 IDirectMusicDownloadedInstrument **downloaded_instrument, DMUS_NOTERANGE *note_ranges, DWORD num_note_ranges)
255 struct synth_port *This = synth_from_IDirectMusicPort(iface);
256 IDirectMusicInstrumentImpl *instrument_object;
257 HRESULT ret;
258 BOOL free;
259 HANDLE download;
260 DMUS_DOWNLOADINFO *info;
261 DMUS_OFFSETTABLE *offset_table;
262 DMUS_INSTRUMENT *instrument_info;
263 BYTE *data;
264 ULONG offset;
265 ULONG nb_regions;
266 ULONG size;
267 ULONG i;
269 TRACE("(%p, %p, %p, %p, %ld)\n", iface, instrument, downloaded_instrument, note_ranges, num_note_ranges);
271 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
272 return E_POINTER;
274 instrument_object = impl_from_IDirectMusicInstrument(instrument);
276 nb_regions = instrument_object->header.cRegions;
277 size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions;
279 data = HeapAlloc(GetProcessHeap(), 0, size);
280 if (!data)
281 return E_OUTOFMEMORY;
283 info = (DMUS_DOWNLOADINFO*)data;
284 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
285 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
287 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
288 info->dwDLId = 0;
289 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
290 info->cbSize = size;
292 offset_table->ulOffsetTable[0] = offset;
293 instrument_info = (DMUS_INSTRUMENT*)(data + offset);
294 offset += sizeof(DMUS_INSTRUMENT);
295 instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale);
296 instrument_info->ulFirstRegionIdx = 1;
297 instrument_info->ulGlobalArtIdx = 0; /* FIXME */
298 instrument_info->ulFirstExtCkIdx = 0; /* FIXME */
299 instrument_info->ulCopyrightIdx = 0; /* FIXME */
300 instrument_info->ulFlags = 0; /* FIXME */
302 for (i = 0; i < nb_regions; i++)
304 DMUS_REGION *region = (DMUS_REGION*)(data + offset);
306 offset_table->ulOffsetTable[1 + i] = offset;
307 offset += sizeof(DMUS_REGION);
308 region->RangeKey = instrument_object->regions[i].header.RangeKey;
309 region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity;
310 region->fusOptions = instrument_object->regions[i].header.fusOptions;
311 region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup;
312 region->ulRegionArtIdx = 0; /* FIXME */
313 region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
314 region->ulFirstExtCkIdx = 0; /* FIXME */
315 region->WaveLink = instrument_object->regions[i].wave_link;
316 region->WSMP = instrument_object->regions[i].wave_sample;
317 region->WLOOP[0] = instrument_object->regions[i].wave_loop;
320 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
322 if (SUCCEEDED(ret))
323 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
325 if (SUCCEEDED(ret))
327 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
329 downloaded_object->data = data;
330 downloaded_object->downloaded = TRUE;
333 *downloaded_instrument = NULL;
334 HeapFree(GetProcessHeap(), 0, data);
336 return E_FAIL;
339 static HRESULT WINAPI synth_port_UnloadInstrument(IDirectMusicPort *iface,
340 IDirectMusicDownloadedInstrument *downloaded_instrument)
342 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
344 TRACE("(%p, %p)\n", iface, downloaded_instrument);
346 if (!downloaded_instrument)
347 return E_POINTER;
349 if (!downloaded_object->downloaded)
350 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
352 HeapFree(GetProcessHeap(), 0, downloaded_object->data);
353 downloaded_object->data = NULL;
354 downloaded_object->downloaded = FALSE;
356 return S_OK;
359 static HRESULT WINAPI synth_port_GetLatencyClock(IDirectMusicPort *iface, IReferenceClock **clock)
361 struct synth_port *This = synth_from_IDirectMusicPort(iface);
363 TRACE("(%p, %p)\n", iface, clock);
365 return IDirectMusicSynth8_GetLatencyClock(This->synth, clock);
368 static HRESULT WINAPI synth_port_GetRunningStats(IDirectMusicPort *iface, DMUS_SYNTHSTATS *stats)
370 struct synth_port *This = synth_from_IDirectMusicPort(iface);
372 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
374 return S_OK;
377 static HRESULT WINAPI synth_port_Compact(IDirectMusicPort *iface)
379 TRACE("(%p): method not implemented\n", iface);
380 return E_NOTIMPL;
383 static HRESULT WINAPI synth_port_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *port_caps)
385 struct synth_port *This = synth_from_IDirectMusicPort(iface);
387 TRACE("(%p, %p)\n", iface, port_caps);
389 return IDirectMusicSynth_GetPortCaps(This->synth, port_caps);
392 static HRESULT WINAPI synth_port_DeviceIoControl(IDirectMusicPort *iface, DWORD io_control_code,
393 void *in_buffer, DWORD in_buffer_size, void *out_buffer, DWORD out_buffer_size,
394 DWORD *bytes_returned, OVERLAPPED *overlapped)
396 struct synth_port *This = synth_from_IDirectMusicPort(iface);
398 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);
400 return S_OK;
403 static HRESULT WINAPI synth_port_SetNumChannelGroups(IDirectMusicPort *iface, DWORD channel_groups)
405 struct synth_port *This = synth_from_IDirectMusicPort(iface);
407 FIXME("(%p, %ld): semi-stub\n", iface, channel_groups);
409 This->nrofgroups = channel_groups;
411 return S_OK;
414 static HRESULT WINAPI synth_port_GetNumChannelGroups(IDirectMusicPort *iface, DWORD *channel_groups)
416 struct synth_port *This = synth_from_IDirectMusicPort(iface);
418 TRACE("(%p, %p)\n", iface, channel_groups);
420 *channel_groups = This->nrofgroups;
422 return S_OK;
425 static HRESULT WINAPI synth_port_Activate(IDirectMusicPort *iface, BOOL active)
427 struct synth_port *This = synth_from_IDirectMusicPort(iface);
429 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
431 if (This->active == active)
432 return S_FALSE;
434 if (active) {
435 /* Acquire the dsound */
436 if (!This->dsound) {
437 IDirectSound_AddRef(This->parent->dsound);
438 This->dsound = This->parent->dsound;
440 IDirectSound_AddRef(This->dsound);
441 } else {
442 /* Release the dsound */
443 IDirectSound_Release(This->dsound);
444 IDirectSound_Release(This->parent->dsound);
445 if (This->dsound == This->parent->dsound)
446 This->dsound = NULL;
449 This->active = active;
451 return S_OK;
454 static HRESULT WINAPI synth_port_SetChannelPriority(IDirectMusicPort *iface, DWORD channel_group,
455 DWORD channel, DWORD priority)
457 struct synth_port *This = synth_from_IDirectMusicPort(iface);
459 FIXME("(%p/%p, %ld, %ld, %ld): semi-stub\n", iface, This, channel_group, channel, priority);
461 if (channel > 16)
463 WARN("isn't there supposed to be 16 channels (no. %ld requested)?! (faking as it is ok)\n", channel);
464 /*return E_INVALIDARG;*/
467 return S_OK;
470 static HRESULT WINAPI synth_port_GetChannelPriority(IDirectMusicPort *iface, DWORD channel_group,
471 DWORD channel, DWORD *priority)
473 struct synth_port *This = synth_from_IDirectMusicPort(iface);
475 TRACE("(%p, %lu, %lu, %p)\n", iface, channel_group, channel, priority);
477 *priority = This->group[channel_group - 1].channel[channel].priority;
479 return S_OK;
482 static HRESULT WINAPI synth_port_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
483 IDirectSoundBuffer *dsbuffer)
485 struct synth_port *This = synth_from_IDirectMusicPort(iface);
487 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
489 if (This->active)
490 return DMUS_E_DSOUND_ALREADY_SET;
492 if (This->dsound) {
493 if (This->dsound != This->parent->dsound)
494 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
495 This->dsound, This->parent->dsound);
496 if (!IDirectSound_Release(This->parent->dsound))
497 This->parent->dsound = NULL;
499 if (This->dsbuffer)
500 IDirectSoundBuffer_Release(This->dsbuffer);
502 This->dsound = dsound;
503 This->dsbuffer = dsbuffer;
505 if (This->dsound)
506 IDirectSound_AddRef(This->dsound);
507 if (This->dsbuffer)
508 IDirectSoundBuffer_AddRef(This->dsbuffer);
510 return S_OK;
513 static HRESULT WINAPI synth_port_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
514 DWORD *fmtsize, DWORD *bufsize)
516 struct synth_port *This = synth_from_IDirectMusicPort(iface);
517 HRESULT hr;
519 TRACE("(%p, %p, %p, %p)\n", This, format, fmtsize, bufsize);
521 if (FAILED(hr = IDirectMusicSynth_GetFormat(This->synth, format, fmtsize)))
522 return hr;
524 if (bufsize)
525 hr = IDirectMusicSynthSink_GetDesiredBufferSize(This->synth_sink, bufsize);
527 return hr;
530 static const IDirectMusicPortVtbl synth_port_vtbl = {
531 /**** IDirectMusicPort IUnknown part methods ***/
532 synth_port_QueryInterface,
533 synth_port_AddRef,
534 synth_port_Release,
535 /**** IDirectMusicPort methods ***/
536 synth_port_PlayBuffer,
537 synth_port_SetReadNotificationHandle,
538 synth_port_Read,
539 synth_port_DownloadInstrument,
540 synth_port_UnloadInstrument,
541 synth_port_GetLatencyClock,
542 synth_port_GetRunningStats,
543 synth_port_Compact,
544 synth_port_GetCaps,
545 synth_port_DeviceIoControl,
546 synth_port_SetNumChannelGroups,
547 synth_port_GetNumChannelGroups,
548 synth_port_Activate,
549 synth_port_SetChannelPriority,
550 synth_port_GetChannelPriority,
551 synth_port_SetDirectSound,
552 synth_port_GetFormat
555 static HRESULT WINAPI synth_port_download_QueryInterface(IDirectMusicPortDownload *iface, REFIID riid, void **ret_iface)
557 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
559 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
561 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
564 static ULONG WINAPI synth_port_download_AddRef(IDirectMusicPortDownload *iface)
566 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
568 TRACE("(%p)\n", iface);
570 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
573 static ULONG WINAPI synth_port_download_Release(IDirectMusicPortDownload *iface)
575 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
577 TRACE("(%p)\n", iface);
579 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
582 static HRESULT WINAPI synth_port_download_GetBuffer(IDirectMusicPortDownload *iface, DWORD DLId,
583 IDirectMusicDownload **IDMDownload)
585 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
587 FIXME("(%p/%p, %lu, %p): stub\n", iface, This, DLId, IDMDownload);
589 if (!IDMDownload)
590 return E_POINTER;
592 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
595 static HRESULT WINAPI synth_port_download_AllocateBuffer(IDirectMusicPortDownload *iface, DWORD size,
596 IDirectMusicDownload **IDMDownload)
598 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
600 FIXME("(%p/%p, %lu, %p): stub\n", iface, This, size, IDMDownload);
602 return S_OK;
605 static HRESULT WINAPI synth_port_download_GetDLId(IDirectMusicPortDownload *iface, DWORD *start_DLId, DWORD count)
607 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
609 FIXME("(%p/%p, %p, %lu): stub\n", iface, This, start_DLId, count);
611 return S_OK;
614 static HRESULT WINAPI synth_port_download_GetAppend(IDirectMusicPortDownload *iface, DWORD *append)
616 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
618 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
620 return S_OK;
623 static HRESULT WINAPI synth_port_download_Download(IDirectMusicPortDownload *iface, IDirectMusicDownload *IDMDownload)
625 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
627 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
629 return S_OK;
632 static HRESULT WINAPI synth_port_download_Unload(IDirectMusicPortDownload *iface, IDirectMusicDownload *IDMDownload)
634 struct synth_port *This = synth_from_IDirectMusicPortDownload(iface);
636 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
638 return S_OK;
641 static const IDirectMusicPortDownloadVtbl synth_port_download_vtbl = {
642 /*** IDirectMusicPortDownload IUnknown part methods ***/
643 synth_port_download_QueryInterface,
644 synth_port_download_AddRef,
645 synth_port_download_Release,
646 /*** IDirectMusicPortDownload methods ***/
647 synth_port_download_GetBuffer,
648 synth_port_download_AllocateBuffer,
649 synth_port_download_GetDLId,
650 synth_port_download_GetAppend,
651 synth_port_download_Download,
652 synth_port_download_Unload
655 static HRESULT WINAPI synth_port_thru_QueryInterface(IDirectMusicThru *iface, REFIID riid, void **ret_iface)
657 struct synth_port *This = synth_from_IDirectMusicThru(iface);
659 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
661 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
664 static ULONG WINAPI synth_port_thru_AddRef(IDirectMusicThru *iface)
666 struct synth_port *This = synth_from_IDirectMusicThru(iface);
668 TRACE("(%p)\n", iface);
670 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
673 static ULONG WINAPI synth_port_thru_Release(IDirectMusicThru *iface)
675 struct synth_port *This = synth_from_IDirectMusicThru(iface);
677 TRACE("(%p)\n", iface);
679 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
682 static HRESULT WINAPI synth_port_thru_ThruChannel(IDirectMusicThru *iface, DWORD source_channel_group,
683 DWORD source_channel, DWORD destination_channel_group, DWORD destination_channel,
684 IDirectMusicPort *destination_port)
686 struct synth_port *This = synth_from_IDirectMusicThru(iface);
688 FIXME("(%p/%p, %ld, %ld, %ld, %ld, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
690 return S_OK;
693 static const IDirectMusicThruVtbl synth_port_thru_vtbl = {
694 /*** IDirectMusicThru IUnknown part methods */
695 synth_port_thru_QueryInterface,
696 synth_port_thru_AddRef,
697 synth_port_thru_Release,
698 /*** IDirectMusicThru methods ***/
699 synth_port_thru_ThruChannel
702 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
703 void **ret_iface)
705 struct synth_port *This = synth_from_IKsControl(iface);
707 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
710 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
712 struct synth_port *This = synth_from_IKsControl(iface);
714 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
717 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
719 struct synth_port *This = synth_from_IKsControl(iface);
721 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
724 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
725 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
727 TRACE("(%p, %p, %lu, %p, %lu, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
728 TRACE("prop = %s - %lu - %lu\n", debugstr_guid(&prop->u.s.Set), prop->u.s.Id, prop->u.s.Flags);
730 if (prop->u.s.Flags != KSPROPERTY_TYPE_GET)
732 FIXME("prop flags %lu not yet supported\n", prop->u.s.Flags);
733 return S_FALSE;
736 if (data_len < sizeof(DWORD))
737 return E_NOT_SUFFICIENT_BUFFER;
739 FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set));
740 *(DWORD*)data = FALSE;
741 *ret_len = sizeof(DWORD);
743 return S_OK;
746 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
747 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
749 FIXME("(%p, %p, %lu, %p, %lu, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
751 return E_NOTIMPL;
754 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
755 void *data, ULONG data_len, ULONG *ret_len)
757 FIXME("(%p, %p, %lu, %p, %lu, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
759 return E_NOTIMPL;
762 static const IKsControlVtbl ikscontrol_vtbl = {
763 IKsControlImpl_QueryInterface,
764 IKsControlImpl_AddRef,
765 IKsControlImpl_Release,
766 IKsControlImpl_KsProperty,
767 IKsControlImpl_KsMethod,
768 IKsControlImpl_KsEvent
771 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
772 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
774 struct synth_port *obj;
775 HRESULT hr = E_FAIL;
776 int i;
778 TRACE("(%p, %p)\n", port_params, port);
780 *port = NULL;
782 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
783 if (!obj)
784 return E_OUTOFMEMORY;
786 obj->IDirectMusicPort_iface.lpVtbl = &synth_port_vtbl;
787 obj->IDirectMusicPortDownload_iface.lpVtbl = &synth_port_download_vtbl;
788 obj->IDirectMusicThru_iface.lpVtbl = &synth_port_thru_vtbl;
789 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
790 obj->ref = 1;
791 obj->parent = parent;
792 obj->active = FALSE;
793 obj->params = *port_params;
795 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth,
796 (void **)&obj->synth);
798 if (SUCCEEDED(hr))
799 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
801 if (SUCCEEDED(hr))
802 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
804 if (SUCCEEDED(hr))
805 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->parent->master_clock);
807 if (SUCCEEDED(hr))
808 hr = IDirectMusicSynth_Open(obj->synth, port_params);
810 if (0)
812 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
813 obj->nrofgroups = port_params->dwChannelGroups;
814 /* Setting default priorities */
815 for (i = 0; i < obj->nrofgroups; i++) {
816 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
817 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
818 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
819 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
820 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
821 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
822 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
823 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
824 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
825 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
826 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
827 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
828 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
829 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
830 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
831 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
832 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
837 if (SUCCEEDED(hr)) {
838 *port = &obj->IDirectMusicPort_iface;
839 return S_OK;
842 if (obj->synth)
843 IDirectMusicSynth_Release(obj->synth);
844 if (obj->synth_sink)
845 IDirectMusicSynthSink_Release(obj->synth_sink);
846 HeapFree(GetProcessHeap(), 0, obj);
848 return hr;
851 struct midi_port {
852 IDirectMusicPort IDirectMusicPort_iface;
853 IDirectMusicThru IDirectMusicThru_iface;
854 LONG ref;
855 IReferenceClock *clock;
858 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
860 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
863 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
864 void **ret_iface)
866 struct midi_port *This = impl_from_IDirectMusicPort(iface);
868 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
870 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
871 *ret_iface = iface;
872 else if (IsEqualIID(riid, &IID_IDirectMusicThru))
873 *ret_iface = &This->IDirectMusicThru_iface;
874 else {
875 WARN("no interface for %s\n", debugstr_dmguid(riid));
876 *ret_iface = NULL;
877 return E_NOINTERFACE;
880 IUnknown_AddRef((IUnknown *)*ret_iface);
882 return S_OK;
885 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
887 struct midi_port *This = impl_from_IDirectMusicPort(iface);
888 ULONG ref = InterlockedIncrement(&This->ref);
890 TRACE("(%p) ref = %lu\n", iface, ref);
892 return ref;
895 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
897 struct midi_port *This = impl_from_IDirectMusicPort(iface);
898 ULONG ref = InterlockedDecrement(&This->ref);
900 TRACE("(%p) ref = %lu\n", iface, ref);
902 if (!ref) {
903 if (This->clock)
904 IReferenceClock_Release(This->clock);
905 heap_free(This);
908 return ref;
911 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
912 IDirectMusicBuffer *buffer)
914 FIXME("(%p, %p) stub!\n", iface, buffer);
916 return E_NOTIMPL;
919 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
920 HANDLE event)
922 FIXME("(%p, %p) stub!\n", iface, event);
924 return S_OK;
927 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
928 IDirectMusicBuffer *buffer)
930 FIXME("(%p, %p) stub!\n", iface, buffer);
932 return E_NOTIMPL;
935 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
936 IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
937 DMUS_NOTERANGE *ranges, DWORD num_ranges)
939 FIXME("(%p, %p, %p, %p, %lu) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
941 return E_NOTIMPL;
944 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
945 IDirectMusicDownloadedInstrument *downloaded)
947 FIXME("(%p, %p) stub!\n", iface, downloaded);
949 return E_NOTIMPL;
952 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
953 IReferenceClock **clock)
955 struct midi_port *This = impl_from_IDirectMusicPort(iface);
957 TRACE("(%p, %p)\n", iface, clock);
959 if (!clock)
960 return E_POINTER;
962 *clock = This->clock;
963 IReferenceClock_AddRef(*clock);
965 return S_OK;
968 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
969 DMUS_SYNTHSTATS *stats)
971 FIXME("(%p, %p) stub!\n", iface, stats);
973 return E_NOTIMPL;
976 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
978 FIXME("(%p) stub!\n", iface);
980 return E_NOTIMPL;
983 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
985 FIXME("(%p, %p) stub!\n", iface, caps);
987 return E_NOTIMPL;
990 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
991 DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
992 OVERLAPPED *overlapped)
994 FIXME("(%p, %lu, %p, %lu, %p, %lu, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
995 , size_out, ret_len, overlapped);
997 return E_NOTIMPL;
1000 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
1001 DWORD cgroups)
1003 FIXME("(%p, %lu) stub!\n", iface, cgroups);
1005 return E_NOTIMPL;
1008 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
1009 DWORD *cgroups)
1011 FIXME("(%p, %p) stub!\n", iface, cgroups);
1013 return E_NOTIMPL;
1016 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
1018 FIXME("(%p, %u) stub!\n", iface, active);
1020 return S_OK;
1023 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
1024 DWORD channel_group, DWORD channel, DWORD priority)
1026 FIXME("(%p, %lu, %lu, %lu) stub!\n", iface, channel_group, channel, priority);
1028 return E_NOTIMPL;
1031 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
1032 DWORD channel_group, DWORD channel, DWORD *priority)
1034 FIXME("(%p, %lu, %lu, %p) stub!\n", iface, channel_group, channel, priority);
1036 return E_NOTIMPL;
1039 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
1040 IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
1042 FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
1044 return E_NOTIMPL;
1047 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
1048 DWORD *format_size, DWORD *buffer_size)
1050 FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
1052 return E_NOTIMPL;
1055 static const IDirectMusicPortVtbl midi_port_vtbl = {
1056 midi_IDirectMusicPort_QueryInterface,
1057 midi_IDirectMusicPort_AddRef,
1058 midi_IDirectMusicPort_Release,
1059 midi_IDirectMusicPort_PlayBuffer,
1060 midi_IDirectMusicPort_SetReadNotificationHandle,
1061 midi_IDirectMusicPort_Read,
1062 midi_IDirectMusicPort_DownloadInstrument,
1063 midi_IDirectMusicPort_UnloadInstrument,
1064 midi_IDirectMusicPort_GetLatencyClock,
1065 midi_IDirectMusicPort_GetRunningStats,
1066 midi_IDirectMusicPort_Compact,
1067 midi_IDirectMusicPort_GetCaps,
1068 midi_IDirectMusicPort_DeviceIoControl,
1069 midi_IDirectMusicPort_SetNumChannelGroups,
1070 midi_IDirectMusicPort_GetNumChannelGroups,
1071 midi_IDirectMusicPort_Activate,
1072 midi_IDirectMusicPort_SetChannelPriority,
1073 midi_IDirectMusicPort_GetChannelPriority,
1074 midi_IDirectMusicPort_SetDirectSound,
1075 midi_IDirectMusicPort_GetFormat,
1078 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
1080 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
1083 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
1084 void **ret_iface)
1086 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1088 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1091 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1093 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1095 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1098 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1100 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1102 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1105 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1106 DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1108 FIXME("(%p, %lu, %lu, %lu, %lu, %p) stub!\n", iface, src_group, src_channel, dest_group,
1109 dest_channel, dest_port);
1111 return S_OK;
1114 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1115 midi_IDirectMusicThru_QueryInterface,
1116 midi_IDirectMusicThru_AddRef,
1117 midi_IDirectMusicThru_Release,
1118 midi_IDirectMusicThru_ThruChannel,
1121 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1122 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1124 struct midi_port *obj;
1125 HRESULT hr;
1127 if (!(obj = heap_alloc_zero(sizeof(*obj))))
1128 return E_OUTOFMEMORY;
1130 obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1131 obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1132 obj->ref = 1;
1134 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1135 if (hr != S_OK) {
1136 HeapFree(GetProcessHeap(), 0, obj);
1137 return hr;
1140 *port = &obj->IDirectMusicPort_iface;
1142 return S_OK;
1145 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1146 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1148 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1150 return midi_port_create(parent, params, caps, port);
1153 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1154 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1156 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1158 return midi_port_create(parent, params, caps, port);