1 /*
2 * IDirectMusicPort Implementation
3 *
4 * Copyright (C) 2003-2004 Rok Mandeljc
5 * Copyright (C) 2012 Christian Costa
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <assert.h>
23 #include "dmusic_private.h"
24 #include "wine/heap.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
27
28 typedef struct SynthPortImpl {
29 IDirectMusicPort IDirectMusicPort_iface;
30 IDirectMusicPortDownload IDirectMusicPortDownload_iface;
31 IDirectMusicThru IDirectMusicThru_iface;
32 IKsControl IKsControl_iface;
33 LONG ref;
34 IDirectMusic8Impl *parent;
35 IDirectSound *dsound;
36 IDirectSoundBuffer *dsbuffer;
37 IReferenceClock *pLatencyClock;
38 IDirectMusicSynth *synth;
39 IDirectMusicSynthSink *synth_sink;
40 BOOL active;
41 DMUS_PORTCAPS caps;
42 DMUS_PORTPARAMS params;
43 int nrofgroups;
44 DMUSIC_PRIVATE_CHANNEL_GROUP group[1];
45 } SynthPortImpl;
46
impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument * iface)47 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
48 {
49 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
50 }
51
impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort * iface)52 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface)
53 {
54 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface);
55 }
56
impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload * iface)57 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface)
58 {
59 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface);
60 }
61
impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru * iface)62 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface)
63 {
64 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface);
65 }
66
impl_from_IKsControl(IKsControl * iface)67 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface)
68 {
69 return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface);
70 }
71
72 /* IDirectMusicDownloadedInstrument IUnknown part follows: */
IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument * iface,REFIID riid,VOID ** ret_iface)73 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
74 {
75 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
76
77 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
78 {
79 IDirectMusicDownloadedInstrument_AddRef(iface);
80 *ret_iface = iface;
81 return S_OK;
82 }
83
84 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
85
86 return E_NOINTERFACE;
87 }
88
IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)89 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
90 {
91 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
92 ULONG ref = InterlockedIncrement(&This->ref);
93
94 TRACE("(%p)->(): new ref = %u\n", iface, ref);
95
96 return ref;
97 }
98
IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)99 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
100 {
101 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
102 ULONG ref = InterlockedDecrement(&This->ref);
103
104 TRACE("(%p)->(): new ref = %u\n", iface, ref);
105
106 if (!ref)
107 {
108 HeapFree(GetProcessHeap(), 0, This->data);
109 HeapFree(GetProcessHeap(), 0, This);
110 DMUSIC_UnlockModule();
111 }
112
113 return ref;
114 }
115
116 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
117 IDirectMusicDownloadedInstrumentImpl_QueryInterface,
118 IDirectMusicDownloadedInstrumentImpl_AddRef,
119 IDirectMusicDownloadedInstrumentImpl_Release
120 };
121
unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument * iface)122 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
123 {
124 if (!iface)
125 return NULL;
126 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl);
127
128 return impl_from_IDirectMusicDownloadedInstrument(iface);
129 }
130
DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument ** instrument)131 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
132 {
133 IDirectMusicDownloadedInstrumentImpl *object;
134
135 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
136 if (!object)
137 {
138 *instrument = NULL;
139 return E_OUTOFMEMORY;
140 }
141
142 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
143 object->ref = 1;
144
145 *instrument = &object->IDirectMusicDownloadedInstrument_iface;
146 DMUSIC_LockModule();
147
148 return S_OK;
149 }
150
151 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */
SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface,REFIID riid,LPVOID * ret_iface)152 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface)
153 {
154 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
155
156 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
157
158 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort))
159 *ret_iface = &This->IDirectMusicPort_iface;
160 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload))
161 *ret_iface = &This->IDirectMusicPortDownload_iface;
162 else if (IsEqualGUID(riid, &IID_IDirectMusicThru))
163 *ret_iface = &This->IDirectMusicThru_iface;
164 else if (IsEqualGUID(riid, &IID_IKsControl))
165 *ret_iface = &This->IKsControl_iface;
166 else {
167 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
168 *ret_iface = NULL;
169 return E_NOINTERFACE;
170 }
171
172 IUnknown_AddRef((IUnknown*)*ret_iface);
173
174 return S_OK;
175 }
176
SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)177 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface)
178 {
179 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
180 ULONG ref = InterlockedIncrement(&This->ref);
181
182 TRACE("(%p)->(): new ref = %u\n", This, ref);
183
184 DMUSIC_LockModule();
185
186 return ref;
187 }
188
SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)189 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface)
190 {
191 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
192 ULONG ref = InterlockedDecrement(&This->ref);
193
194 TRACE("(%p)->(): new ref = %u\n", This, ref);
195
196 if (!ref)
197 {
198 dmusic_remove_port(This->parent, iface);
199 IDirectMusicSynth_Activate(This->synth, FALSE);
200 IDirectMusicSynth_Close(This->synth);
201 IDirectMusicSynth_Release(This->synth);
202 IDirectMusicSynthSink_Release(This->synth_sink);
203 IReferenceClock_Release(This->pLatencyClock);
204 if (This->dsbuffer)
205 IDirectSoundBuffer_Release(This->dsbuffer);
206 if (This->dsound)
207 IDirectSound_Release(This->dsound);
208 HeapFree(GetProcessHeap(), 0, This);
209 }
210
211 DMUSIC_UnlockModule();
212
213 return ref;
214 }
215
216 /* SynthPortImpl IDirectMusicPort interface follows: */
SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface,LPDIRECTMUSICBUFFER buffer)217 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
218 {
219 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
220 HRESULT hr;
221 REFERENCE_TIME time;
222 LPBYTE data;
223 DWORD size;
224
225 TRACE("(%p/%p)->(%p)\n", iface, This, buffer);
226
227 if (!buffer)
228 return E_POINTER;
229
230 hr = IDirectMusicBuffer_GetStartTime(buffer, &time);
231
232 if (SUCCEEDED(hr))
233 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data);
234
235 if (SUCCEEDED(hr))
236 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size);
237
238 if (SUCCEEDED(hr))
239 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size);
240
241 return hr;
242 }
243
SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface,HANDLE event)244 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event)
245 {
246 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
247
248 FIXME("(%p/%p)->(%p): stub\n", iface, This, event);
249
250 return S_OK;
251 }
252
SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface,LPDIRECTMUSICBUFFER buffer)253 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer)
254 {
255 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
256
257 FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer);
258
259 return S_OK;
260 }
261
SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface,IDirectMusicInstrument * instrument,IDirectMusicDownloadedInstrument ** downloaded_instrument,DMUS_NOTERANGE * note_ranges,DWORD num_note_ranges)262 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges)
263 {
264 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
265 IDirectMusicInstrumentImpl *instrument_object;
266 HRESULT ret;
267 BOOL free;
268 HANDLE download;
269 DMUS_DOWNLOADINFO *info;
270 DMUS_OFFSETTABLE *offset_table;
271 DMUS_INSTRUMENT *instrument_info;
272 BYTE *data;
273 ULONG offset;
274 ULONG nb_regions;
275 ULONG size;
276 ULONG i;
277
278 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges);
279
280 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
281 return E_POINTER;
282
283 instrument_object = impl_from_IDirectMusicInstrument(instrument);
284
285 nb_regions = instrument_object->header.cRegions;
286 size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions;
287
288 data = HeapAlloc(GetProcessHeap(), 0, size);
289 if (!data)
290 return E_OUTOFMEMORY;
291
292 info = (DMUS_DOWNLOADINFO*)data;
293 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO));
294 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions);
295
296 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
297 info->dwDLId = 0;
298 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions;
299 info->cbSize = size;
300
301 offset_table->ulOffsetTable[0] = offset;
302 instrument_info = (DMUS_INSTRUMENT*)(data + offset);
303 offset += sizeof(DMUS_INSTRUMENT);
304 instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale);
305 instrument_info->ulFirstRegionIdx = 1;
306 instrument_info->ulGlobalArtIdx = 0; /* FIXME */
307 instrument_info->ulFirstExtCkIdx = 0; /* FIXME */
308 instrument_info->ulCopyrightIdx = 0; /* FIXME */
309 instrument_info->ulFlags = 0; /* FIXME */
310
311 for (i = 0; i < nb_regions; i++)
312 {
313 DMUS_REGION *region = (DMUS_REGION*)(data + offset);
314
315 offset_table->ulOffsetTable[1 + i] = offset;
316 offset += sizeof(DMUS_REGION);
317 region->RangeKey = instrument_object->regions[i].header.RangeKey;
318 region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity;
319 region->fusOptions = instrument_object->regions[i].header.fusOptions;
320 region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup;
321 region->ulRegionArtIdx = 0; /* FIXME */
322 region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
323 region->ulFirstExtCkIdx = 0; /* FIXME */
324 region->WaveLink = instrument_object->regions[i].wave_link;
325 region->WSMP = instrument_object->regions[i].wave_sample;
326 region->WLOOP[0] = instrument_object->regions[i].wave_loop;
327 }
328
329 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free);
330
331 if (SUCCEEDED(ret))
332 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument);
333
334 if (SUCCEEDED(ret))
335 {
336 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument);
337
338 downloaded_object->data = data;
339 downloaded_object->downloaded = TRUE;
340 }
341
342 *downloaded_instrument = NULL;
343 HeapFree(GetProcessHeap(), 0, data);
344
345 return E_FAIL;
346 }
347
SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface,IDirectMusicDownloadedInstrument * downloaded_instrument)348 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument)
349 {
350 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
351 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
352
353 TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument);
354
355 if (!downloaded_instrument)
356 return E_POINTER;
357
358 if (!downloaded_object->downloaded)
359 return DMUS_E_NOT_DOWNLOADED_TO_PORT;
360
361 HeapFree(GetProcessHeap(), 0, downloaded_object->data);
362 downloaded_object->data = NULL;
363 downloaded_object->downloaded = FALSE;
364
365 return S_OK;
366 }
367
SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface,IReferenceClock ** clock)368 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock)
369 {
370 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
371
372 TRACE("(%p/%p)->(%p)\n", iface, This, clock);
373
374 *clock = This->pLatencyClock;
375 IReferenceClock_AddRef(*clock);
376
377 return S_OK;
378 }
379
SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface,LPDMUS_SYNTHSTATS stats)380 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats)
381 {
382 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
383
384 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats);
385
386 return S_OK;
387 }
388
SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)389 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface)
390 {
391 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
392
393 FIXME("(%p/%p)->(): stub\n", iface, This);
394
395 return S_OK;
396 }
397
SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface,LPDMUS_PORTCAPS port_caps)398 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps)
399 {
400 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
401
402 TRACE("(%p/%p)->(%p)\n", iface, This, port_caps);
403
404 *port_caps = This->caps;
405
406 return S_OK;
407 }
408
SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface,DWORD io_control_code,LPVOID in_buffer,DWORD in_buffer_size,LPVOID out_buffer,DWORD out_buffer_size,LPDWORD bytes_returned,LPOVERLAPPED overlapped)409 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size,
410 LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped)
411 {
412 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
413
414 FIXME("(%p/%p)->(%d, %p, %d, %p, %d, %p, %p): stub\n", iface, This, io_control_code, in_buffer, in_buffer_size, out_buffer, out_buffer_size, bytes_returned, overlapped);
415
416 return S_OK;
417 }
418
SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface,DWORD channel_groups)419 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups)
420 {
421 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
422
423 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups);
424
425 This->nrofgroups = channel_groups;
426
427 return S_OK;
428 }
429
SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface,LPDWORD channel_groups)430 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups)
431 {
432 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
433
434 TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups);
435
436 *channel_groups = This->nrofgroups;
437
438 return S_OK;
439 }
440
synth_dmport_Activate(IDirectMusicPort * iface,BOOL active)441 static HRESULT WINAPI synth_dmport_Activate(IDirectMusicPort *iface, BOOL active)
442 {
443 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
444
445 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active);
446
447 if (This->active == active)
448 return S_FALSE;
449
450 if (active) {
451 /* Acquire the dsound */
452 if (!This->dsound) {
453 IDirectSound_AddRef(This->parent->dsound);
454 This->dsound = This->parent->dsound;
455 }
456 IDirectSound_AddRef(This->dsound);
457 } else {
458 /* Release the dsound */
459 IDirectSound_Release(This->dsound);
460 IDirectSound_Release(This->parent->dsound);
461 if (This->dsound == This->parent->dsound)
462 This->dsound = NULL;
463 }
464
465 This->active = active;
466
467 return S_OK;
468 }
469
SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface,DWORD channel_group,DWORD channel,DWORD priority)470 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority)
471 {
472 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
473
474 FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority);
475
476 if (channel > 16)
477 {
478 WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel);
479 /*return E_INVALIDARG;*/
480 }
481
482 return S_OK;
483 }
484
SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface,DWORD channel_group,DWORD channel,LPDWORD priority)485 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority)
486 {
487 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
488
489 TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority);
490
491 *priority = This->group[channel_group - 1].channel[channel].priority;
492
493 return S_OK;
494 }
495
synth_dmport_SetDirectSound(IDirectMusicPort * iface,IDirectSound * dsound,IDirectSoundBuffer * dsbuffer)496 static HRESULT WINAPI synth_dmport_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound,
497 IDirectSoundBuffer *dsbuffer)
498 {
499 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
500
501 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer);
502
503 if (This->active)
504 return DMUS_E_DSOUND_ALREADY_SET;
505
506 if (This->dsound) {
507 if (This->dsound != This->parent->dsound)
508 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n",
509 This->dsound, This->parent->dsound);
510 if (!IDirectSound_Release(This->parent->dsound))
511 This->parent->dsound = NULL;
512 }
513 if (This->dsbuffer)
514 IDirectSoundBuffer_Release(This->dsbuffer);
515
516 This->dsound = dsound;
517 This->dsbuffer = dsbuffer;
518
519 if (This->dsound)
520 IDirectSound_AddRef(This->dsound);
521 if (This->dsbuffer)
522 IDirectSoundBuffer_AddRef(This->dsbuffer);
523
524 return S_OK;
525 }
526
SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface,LPWAVEFORMATEX pWaveFormatEx,LPDWORD pdwWaveFormatExSize,LPDWORD pdwBufferSize)527 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize)
528 {
529 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface);
530 WAVEFORMATEX format;
531 FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize);
532
533 if (pWaveFormatEx == NULL)
534 {
535 if (pdwWaveFormatExSize)
536 *pdwWaveFormatExSize = sizeof(format);
537 else
538 return E_POINTER;
539 }
540 else
541 {
542 if (pdwWaveFormatExSize == NULL)
543 return E_POINTER;
544
545 /* Just fill this in with something that will not crash Direct Sound for now. */
546 /* It won't be used anyway until Performances are completed */
547 format.wFormatTag = WAVE_FORMAT_PCM;
548 format.nChannels = 2; /* This->params.dwAudioChannels; */
549 format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */
550 format.wBitsPerSample = 16; /* FIXME: check this */
551 format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8;
552 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
553 format.cbSize = 0;
554
555 if (*pdwWaveFormatExSize >= sizeof(format))
556 {
557 CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize));
558 *pdwWaveFormatExSize = sizeof(format); /* FIXME check if this is set */
559 }
560 else
561 return E_POINTER; /* FIXME find right error */
562 }
563
564 if (pdwBufferSize)
565 *pdwBufferSize = 44100 * 2 * 2;
566 else
567 return E_POINTER;
568
569 return S_OK;
570 }
571
572 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = {
573 /**** IDirectMusicPort IUnknown part methods ***/
574 SynthPortImpl_IDirectMusicPort_QueryInterface,
575 SynthPortImpl_IDirectMusicPort_AddRef,
576 SynthPortImpl_IDirectMusicPort_Release,
577 /**** IDirectMusicPort methods ***/
578 SynthPortImpl_IDirectMusicPort_PlayBuffer,
579 SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle,
580 SynthPortImpl_IDirectMusicPort_Read,
581 SynthPortImpl_IDirectMusicPort_DownloadInstrument,
582 SynthPortImpl_IDirectMusicPort_UnloadInstrument,
583 SynthPortImpl_IDirectMusicPort_GetLatencyClock,
584 SynthPortImpl_IDirectMusicPort_GetRunningStats,
585 SynthPortImpl_IDirectMusicPort_Compact,
586 SynthPortImpl_IDirectMusicPort_GetCaps,
587 SynthPortImpl_IDirectMusicPort_DeviceIoControl,
588 SynthPortImpl_IDirectMusicPort_SetNumChannelGroups,
589 SynthPortImpl_IDirectMusicPort_GetNumChannelGroups,
590 synth_dmport_Activate,
591 SynthPortImpl_IDirectMusicPort_SetChannelPriority,
592 SynthPortImpl_IDirectMusicPort_GetChannelPriority,
593 synth_dmport_SetDirectSound,
594 SynthPortImpl_IDirectMusicPort_GetFormat
595 };
596
597 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */
SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface,REFIID riid,LPVOID * ret_iface)598 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface)
599 {
600 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
601
602 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
603
604 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
605 }
606
SynthPortImpl_IDirectMusicPortDownload_AddRef(LPDIRECTMUSICPORTDOWNLOAD iface)607 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface)
608 {
609 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
610
611 TRACE("(%p/%p)->()\n", iface, This);
612
613 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
614 }
615
SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)616 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface)
617 {
618 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
619
620 TRACE("(%p/%p)->()\n", iface, This);
621
622 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
623 }
624
625 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */
SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD DLId,IDirectMusicDownload ** IDMDownload)626 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload)
627 {
628 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
629
630 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload);
631
632 if (!IDMDownload)
633 return E_POINTER;
634
635 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL);
636 }
637
SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD size,IDirectMusicDownload ** IDMDownload)638 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload)
639 {
640 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
641
642 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload);
643
644 return S_OK;
645 }
646
SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD * start_DLId,DWORD count)647 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count)
648 {
649 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
650
651 FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count);
652
653 return S_OK;
654 }
655
SynthPortImpl_IDirectMusicPortDownload_GetAppend(LPDIRECTMUSICPORTDOWNLOAD iface,DWORD * append)656 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append)
657 {
658 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
659
660 FIXME("(%p/%p)->(%p): stub\n", iface, This, append);
661
662 return S_OK;
663 }
664
SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface,IDirectMusicDownload * IDMDownload)665 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
666 {
667 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
668
669 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
670
671 return S_OK;
672 }
673
SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface,IDirectMusicDownload * IDMDownload)674 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload)
675 {
676 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface);
677
678 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload);
679
680 return S_OK;
681 }
682
683 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = {
684 /*** IDirectMusicPortDownload IUnknown part methods ***/
685 SynthPortImpl_IDirectMusicPortDownload_QueryInterface,
686 SynthPortImpl_IDirectMusicPortDownload_AddRef,
687 SynthPortImpl_IDirectMusicPortDownload_Release,
688 /*** IDirectMusicPortDownload methods ***/
689 SynthPortImpl_IDirectMusicPortDownload_GetBuffer,
690 SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer,
691 SynthPortImpl_IDirectMusicPortDownload_GetDLId,
692 SynthPortImpl_IDirectMusicPortDownload_GetAppend,
693 SynthPortImpl_IDirectMusicPortDownload_Download,
694 SynthPortImpl_IDirectMusicPortDownload_Unload
695 };
696
697 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */
SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface,REFIID riid,LPVOID * ret_iface)698 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface)
699 {
700 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
701
702 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
703
704 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
705 }
706
SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)707 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface)
708 {
709 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
710
711 TRACE("(%p/%p)->()\n", iface, This);
712
713 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
714 }
715
SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)716 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface)
717 {
718 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
719
720 TRACE("(%p/%p)->()\n", iface, This);
721
722 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
723 }
724
725 /* SynthPortImpl IDirectMusicThru Interface follows: */
SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface,DWORD source_channel_group,DWORD source_channel,DWORD destination_channel_group,DWORD destination_channel,LPDIRECTMUSICPORT destination_port)726 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group,
727 DWORD destination_channel, LPDIRECTMUSICPORT destination_port)
728 {
729 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface);
730
731 FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port);
732
733 return S_OK;
734 }
735
736 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = {
737 /*** IDirectMusicThru IUnknown part methods */
738 SynthPortImpl_IDirectMusicThru_QueryInterface,
739 SynthPortImpl_IDirectMusicThru_AddRef,
740 SynthPortImpl_IDirectMusicThru_Release,
741 /*** IDirectMusicThru methods ***/
742 SynthPortImpl_IDirectMusicThru_ThruChannel
743 };
744
IKsControlImpl_QueryInterface(IKsControl * iface,REFIID riid,void ** ret_iface)745 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid,
746 void **ret_iface)
747 {
748 SynthPortImpl *This = impl_from_IKsControl(iface);
749
750 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
751 }
752
IKsControlImpl_AddRef(IKsControl * iface)753 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface)
754 {
755 SynthPortImpl *This = impl_from_IKsControl(iface);
756
757 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
758 }
759
IKsControlImpl_Release(IKsControl * iface)760 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface)
761 {
762 SynthPortImpl *This = impl_from_IKsControl(iface);
763
764 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
765 }
766
IKsControlImpl_KsProperty(IKsControl * iface,KSPROPERTY * prop,ULONG prop_len,void * data,ULONG data_len,ULONG * ret_len)767 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop,
768 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len)
769 {
770 TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, prop, prop_len, data, data_len, ret_len);
771 TRACE("prop = %s - %u - %u\n", debugstr_guid(&prop->u.s.Set), prop->u.s.Id, prop->u.s.Flags);
772
773 if (prop->u.s.Flags != KSPROPERTY_TYPE_GET)
774 {
775 FIXME("prop flags %u not yet supported\n", prop->u.s.Flags);
776 return S_FALSE;
777 }
778
779 if (data_len < sizeof(DWORD))
780 return E_NOT_SUFFICIENT_BUFFER;
781
782 FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set));
783 *(DWORD*)data = FALSE;
784 *ret_len = sizeof(DWORD);
785
786 return S_OK;
787 }
788
IKsControlImpl_KsMethod(IKsControl * iface,KSMETHOD * method,ULONG method_len,void * data,ULONG data_len,ULONG * ret_len)789 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method,
790 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len)
791 {
792 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len);
793
794 return E_NOTIMPL;
795 }
796
IKsControlImpl_KsEvent(IKsControl * iface,KSEVENT * event,ULONG event_len,void * data,ULONG data_len,ULONG * ret_len)797 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len,
798 void *data, ULONG data_len, ULONG *ret_len)
799 {
800 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len);
801
802 return E_NOTIMPL;
803 }
804
805 static const IKsControlVtbl ikscontrol_vtbl = {
806 IKsControlImpl_QueryInterface,
807 IKsControlImpl_AddRef,
808 IKsControlImpl_Release,
809 IKsControlImpl_KsProperty,
810 IKsControlImpl_KsMethod,
811 IKsControlImpl_KsEvent
812 };
813
synth_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * port_params,DMUS_PORTCAPS * port_caps,IDirectMusicPort ** port)814 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
815 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port)
816 {
817 SynthPortImpl *obj;
818 HRESULT hr = E_FAIL;
819 int i;
820
821 TRACE("(%p, %p, %p)\n", port_params, port_caps, port);
822
823 *port = NULL;
824
825 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl));
826 if (!obj)
827 return E_OUTOFMEMORY;
828
829 obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl;
830 obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl;
831 obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl;
832 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl;
833 obj->ref = 1;
834 obj->parent = parent;
835 obj->active = FALSE;
836 obj->params = *port_params;
837 obj->caps = *port_caps;
838
839 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL);
840 if (hr != S_OK)
841 {
842 HeapFree(GetProcessHeap(), 0, obj);
843 return hr;
844 }
845
846 if (SUCCEEDED(hr))
847 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth);
848
849 if (SUCCEEDED(hr))
850 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
851
852 if (SUCCEEDED(hr))
853 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock);
854
855 if (SUCCEEDED(hr))
856 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock);
857
858 if (SUCCEEDED(hr))
859 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink);
860
861 if (SUCCEEDED(hr))
862 hr = IDirectMusicSynth_Open(obj->synth, port_params);
863
864 if (0)
865 {
866 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) {
867 obj->nrofgroups = port_params->dwChannelGroups;
868 /* Setting default priorities */
869 for (i = 0; i < obj->nrofgroups; i++) {
870 TRACE ("Setting default channel priorities on channel group %i\n", i + 1);
871 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY;
872 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY;
873 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY;
874 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY;
875 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY;
876 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY;
877 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY;
878 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY;
879 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY;
880 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY;
881 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY;
882 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY;
883 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY;
884 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY;
885 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY;
886 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY;
887 }
888 }
889 }
890
891 if (SUCCEEDED(hr)) {
892 *port = &obj->IDirectMusicPort_iface;
893 return S_OK;
894 }
895
896 if (obj->synth)
897 IDirectMusicSynth_Release(obj->synth);
898 if (obj->synth_sink)
899 IDirectMusicSynthSink_Release(obj->synth_sink);
900 if (obj->pLatencyClock)
901 IReferenceClock_Release(obj->pLatencyClock);
902 HeapFree(GetProcessHeap(), 0, obj);
903
904 return hr;
905 }
906
907 struct midi_port {
908 IDirectMusicPort IDirectMusicPort_iface;
909 IDirectMusicThru IDirectMusicThru_iface;
910 LONG ref;
911 IReferenceClock *clock;
912 };
913
impl_from_IDirectMusicPort(IDirectMusicPort * iface)914 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface)
915 {
916 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface);
917 }
918
midi_IDirectMusicPort_QueryInterface(IDirectMusicPort * iface,REFIID riid,void ** ret_iface)919 static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid,
920 void **ret_iface)
921 {
922 struct midi_port *This = impl_from_IDirectMusicPort(iface);
923
924 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
925
926 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort))
927 *ret_iface = iface;
928 else if (IsEqualIID(riid, &IID_IDirectMusicThru))
929 *ret_iface = &This->IDirectMusicThru_iface;
930 else {
931 WARN("no interface for %s\n", debugstr_dmguid(riid));
932 *ret_iface = NULL;
933 return E_NOINTERFACE;
934 }
935
936 IUnknown_AddRef((IUnknown *)*ret_iface);
937
938 return S_OK;
939 }
940
midi_IDirectMusicPort_AddRef(IDirectMusicPort * iface)941 static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface)
942 {
943 struct midi_port *This = impl_from_IDirectMusicPort(iface);
944 ULONG ref = InterlockedIncrement(&This->ref);
945
946 TRACE("(%p) ref = %u\n", iface, ref);
947
948 return ref;
949 }
950
midi_IDirectMusicPort_Release(IDirectMusicPort * iface)951 static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface)
952 {
953 struct midi_port *This = impl_from_IDirectMusicPort(iface);
954 ULONG ref = InterlockedDecrement(&This->ref);
955
956 TRACE("(%p) ref = %u\n", iface, ref);
957
958 if (!ref) {
959 if (This->clock)
960 IReferenceClock_Release(This->clock);
961 heap_free(This);
962 }
963
964 return ref;
965 }
966
midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort * iface,IDirectMusicBuffer * buffer)967 static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface,
968 IDirectMusicBuffer *buffer)
969 {
970 FIXME("(%p, %p) stub!\n", iface, buffer);
971
972 return E_NOTIMPL;
973 }
974
midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort * iface,HANDLE event)975 static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface,
976 HANDLE event)
977 {
978 FIXME("(%p, %p) stub!\n", iface, event);
979
980 return S_OK;
981 }
982
midi_IDirectMusicPort_Read(IDirectMusicPort * iface,IDirectMusicBuffer * buffer)983 static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface,
984 IDirectMusicBuffer *buffer)
985 {
986 FIXME("(%p, %p) stub!\n", iface, buffer);
987
988 return E_NOTIMPL;
989 }
990
midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort * iface,IDirectMusicInstrument * instrument,IDirectMusicDownloadedInstrument ** downloaded,DMUS_NOTERANGE * ranges,DWORD num_ranges)991 static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface,
992 IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded,
993 DMUS_NOTERANGE *ranges, DWORD num_ranges)
994 {
995 FIXME("(%p, %p, %p, %p, %u) stub!\n", iface, instrument, downloaded, ranges, num_ranges);
996
997 return E_NOTIMPL;
998 }
999
midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort * iface,IDirectMusicDownloadedInstrument * downloaded)1000 static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface,
1001 IDirectMusicDownloadedInstrument *downloaded)
1002 {
1003 FIXME("(%p, %p) stub!\n", iface, downloaded);
1004
1005 return E_NOTIMPL;
1006 }
1007
midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort * iface,IReferenceClock ** clock)1008 static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface,
1009 IReferenceClock **clock)
1010 {
1011 struct midi_port *This = impl_from_IDirectMusicPort(iface);
1012
1013 TRACE("(%p, %p)\n", iface, clock);
1014
1015 if (!clock)
1016 return E_POINTER;
1017
1018 *clock = This->clock;
1019 IReferenceClock_AddRef(*clock);
1020
1021 return S_OK;
1022 }
1023
midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort * iface,DMUS_SYNTHSTATS * stats)1024 static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface,
1025 DMUS_SYNTHSTATS *stats)
1026 {
1027 FIXME("(%p, %p) stub!\n", iface, stats);
1028
1029 return E_NOTIMPL;
1030 }
1031
midi_IDirectMusicPort_Compact(IDirectMusicPort * iface)1032 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface)
1033 {
1034 FIXME("(%p) stub!\n", iface);
1035
1036 return E_NOTIMPL;
1037 }
1038
midi_IDirectMusicPort_GetCaps(IDirectMusicPort * iface,DMUS_PORTCAPS * caps)1039 static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps)
1040 {
1041 FIXME("(%p, %p) stub!\n", iface, caps);
1042
1043 return E_NOTIMPL;
1044 }
1045
midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort * iface,DWORD io_control_code,void * in,DWORD size_in,void * out,DWORD size_out,DWORD * ret_len,OVERLAPPED * overlapped)1046 static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface,
1047 DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len,
1048 OVERLAPPED *overlapped)
1049 {
1050 FIXME("(%p, %u, %p, %u, %p, %u, %p, %p) stub!\n", iface, io_control_code, in, size_in, out
1051 , size_out, ret_len, overlapped);
1052
1053 return E_NOTIMPL;
1054 }
1055
midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort * iface,DWORD cgroups)1056 static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface,
1057 DWORD cgroups)
1058 {
1059 FIXME("(%p, %u) stub!\n", iface, cgroups);
1060
1061 return E_NOTIMPL;
1062 }
1063
midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort * iface,DWORD * cgroups)1064 static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface,
1065 DWORD *cgroups)
1066 {
1067 FIXME("(%p, %p) stub!\n", iface, cgroups);
1068
1069 return E_NOTIMPL;
1070 }
1071
midi_IDirectMusicPort_Activate(IDirectMusicPort * iface,BOOL active)1072 static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active)
1073 {
1074 FIXME("(%p, %u) stub!\n", iface, active);
1075
1076 return S_OK;
1077 }
1078
midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort * iface,DWORD channel_group,DWORD channel,DWORD priority)1079 static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface,
1080 DWORD channel_group, DWORD channel, DWORD priority)
1081 {
1082 FIXME("(%p, %u, %u, %u) stub!\n", iface, channel_group, channel, priority);
1083
1084 return E_NOTIMPL;
1085 }
1086
midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort * iface,DWORD channel_group,DWORD channel,DWORD * priority)1087 static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface,
1088 DWORD channel_group, DWORD channel, DWORD *priority)
1089 {
1090 FIXME("(%p, %u, %u, %p) stub!\n", iface, channel_group, channel, priority);
1091
1092 return E_NOTIMPL;
1093 }
1094
midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort * iface,IDirectSound * dsound,IDirectSoundBuffer * dsbuffer)1095 static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface,
1096 IDirectSound *dsound, IDirectSoundBuffer *dsbuffer)
1097 {
1098 FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer);
1099
1100 return E_NOTIMPL;
1101 }
1102
midi_IDirectMusicPort_GetFormat(IDirectMusicPort * iface,WAVEFORMATEX * format,DWORD * format_size,DWORD * buffer_size)1103 static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format,
1104 DWORD *format_size, DWORD *buffer_size)
1105 {
1106 FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size);
1107
1108 return E_NOTIMPL;
1109 }
1110
1111 static const IDirectMusicPortVtbl midi_port_vtbl = {
1112 midi_IDirectMusicPort_QueryInterface,
1113 midi_IDirectMusicPort_AddRef,
1114 midi_IDirectMusicPort_Release,
1115 midi_IDirectMusicPort_PlayBuffer,
1116 midi_IDirectMusicPort_SetReadNotificationHandle,
1117 midi_IDirectMusicPort_Read,
1118 midi_IDirectMusicPort_DownloadInstrument,
1119 midi_IDirectMusicPort_UnloadInstrument,
1120 midi_IDirectMusicPort_GetLatencyClock,
1121 midi_IDirectMusicPort_GetRunningStats,
1122 midi_IDirectMusicPort_Compact,
1123 midi_IDirectMusicPort_GetCaps,
1124 midi_IDirectMusicPort_DeviceIoControl,
1125 midi_IDirectMusicPort_SetNumChannelGroups,
1126 midi_IDirectMusicPort_GetNumChannelGroups,
1127 midi_IDirectMusicPort_Activate,
1128 midi_IDirectMusicPort_SetChannelPriority,
1129 midi_IDirectMusicPort_GetChannelPriority,
1130 midi_IDirectMusicPort_SetDirectSound,
1131 midi_IDirectMusicPort_GetFormat,
1132 };
1133
impl_from_IDirectMusicThru(IDirectMusicThru * iface)1134 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface)
1135 {
1136 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface);
1137 }
1138
midi_IDirectMusicThru_QueryInterface(IDirectMusicThru * iface,REFIID riid,void ** ret_iface)1139 static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid,
1140 void **ret_iface)
1141 {
1142 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1143
1144 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface);
1145 }
1146
midi_IDirectMusicThru_AddRef(IDirectMusicThru * iface)1147 static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface)
1148 {
1149 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1150
1151 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface);
1152 }
1153
midi_IDirectMusicThru_Release(IDirectMusicThru * iface)1154 static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface)
1155 {
1156 struct midi_port *This = impl_from_IDirectMusicThru(iface);
1157
1158 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface);
1159 }
1160
midi_IDirectMusicThru_ThruChannel(IDirectMusicThru * iface,DWORD src_group,DWORD src_channel,DWORD dest_group,DWORD dest_channel,IDirectMusicPort * dest_port)1161 static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group,
1162 DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port)
1163 {
1164 FIXME("(%p, %u, %u, %u, %u, %p) stub!\n", iface, src_group, src_channel, dest_group,
1165 dest_channel, dest_port);
1166
1167 return S_OK;
1168 }
1169
1170 static const IDirectMusicThruVtbl midi_thru_vtbl = {
1171 midi_IDirectMusicThru_QueryInterface,
1172 midi_IDirectMusicThru_AddRef,
1173 midi_IDirectMusicThru_Release,
1174 midi_IDirectMusicThru_ThruChannel,
1175 };
1176
midi_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * params,DMUS_PORTCAPS * caps,IDirectMusicPort ** port)1177 static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1178 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1179 {
1180 struct midi_port *obj;
1181 HRESULT hr;
1182
1183 if (!(obj = heap_alloc_zero(sizeof(*obj))))
1184 return E_OUTOFMEMORY;
1185
1186 obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl;
1187 obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl;
1188 obj->ref = 1;
1189
1190 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL);
1191 if (hr != S_OK) {
1192 HeapFree(GetProcessHeap(), 0, obj);
1193 return hr;
1194 }
1195
1196 *port = &obj->IDirectMusicPort_iface;
1197
1198 return S_OK;
1199 }
1200
midi_out_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * params,DMUS_PORTCAPS * caps,IDirectMusicPort ** port)1201 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1202 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1203 {
1204 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1205
1206 return midi_port_create(parent, params, caps, port);
1207 }
1208
midi_in_port_create(IDirectMusic8Impl * parent,DMUS_PORTPARAMS * params,DMUS_PORTCAPS * caps,IDirectMusicPort ** port)1209 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params,
1210 DMUS_PORTCAPS *caps, IDirectMusicPort **port)
1211 {
1212 TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port);
1213
1214 return midi_port_create(parent, params, caps, port);
1215 }
1216