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 47 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface) 48 { 49 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface); 50 } 51 52 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface) 53 { 54 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface); 55 } 56 57 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface) 58 { 59 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface); 60 } 61 62 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface) 63 { 64 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface); 65 } 66 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: */ 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 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 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 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 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: */ 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 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 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: */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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: */ 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 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 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: */ 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 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 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 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 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 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: */ 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 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 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: */ 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 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 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 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 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 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 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 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 914 static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface) 915 { 916 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface); 917 } 918 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 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 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 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 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 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 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 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 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 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 1032 static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface) 1033 { 1034 FIXME("(%p) stub!\n", iface); 1035 1036 return E_NOTIMPL; 1037 } 1038 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 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 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 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 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 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 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 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 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 1134 static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface) 1135 { 1136 return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface); 1137 } 1138 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 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 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 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 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 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 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