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 25 WINE_DEFAULT_DEBUG_CHANNEL(dmusic); 26 27 typedef struct SynthPortImpl { 28 IDirectMusicPort IDirectMusicPort_iface; 29 IDirectMusicPortDownload IDirectMusicPortDownload_iface; 30 IDirectMusicThru IDirectMusicThru_iface; 31 IKsControl IKsControl_iface; 32 LONG ref; 33 IDirectMusic8Impl *parent; 34 IDirectSound *dsound; 35 IDirectSoundBuffer *dsbuffer; 36 IReferenceClock *pLatencyClock; 37 IDirectMusicSynth *synth; 38 IDirectMusicSynthSink *synth_sink; 39 BOOL active; 40 DMUS_PORTCAPS caps; 41 DMUS_PORTPARAMS params; 42 int nrofgroups; 43 DMUSIC_PRIVATE_CHANNEL_GROUP group[1]; 44 } SynthPortImpl; 45 46 static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface) 47 { 48 return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface); 49 } 50 51 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPort(IDirectMusicPort *iface) 52 { 53 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPort_iface); 54 } 55 56 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicPortDownload(IDirectMusicPortDownload *iface) 57 { 58 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicPortDownload_iface); 59 } 60 61 static inline SynthPortImpl *impl_from_SynthPortImpl_IDirectMusicThru(IDirectMusicThru *iface) 62 { 63 return CONTAINING_RECORD(iface, SynthPortImpl, IDirectMusicThru_iface); 64 } 65 66 static inline SynthPortImpl *impl_from_IKsControl(IKsControl *iface) 67 { 68 return CONTAINING_RECORD(iface, SynthPortImpl, IKsControl_iface); 69 } 70 71 /* IDirectMusicDownloadedInstrument IUnknown part follows: */ 72 static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface) 73 { 74 TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface); 75 76 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument)) 77 { 78 IDirectMusicDownloadedInstrument_AddRef(iface); 79 *ret_iface = iface; 80 return S_OK; 81 } 82 83 WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface); 84 85 return E_NOINTERFACE; 86 } 87 88 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface) 89 { 90 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface); 91 ULONG ref = InterlockedIncrement(&This->ref); 92 93 TRACE("(%p)->(): new ref = %u\n", iface, ref); 94 95 return ref; 96 } 97 98 static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface) 99 { 100 IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface); 101 ULONG ref = InterlockedDecrement(&This->ref); 102 103 TRACE("(%p)->(): new ref = %u\n", iface, ref); 104 105 if (!ref) 106 { 107 HeapFree(GetProcessHeap(), 0, This->data); 108 HeapFree(GetProcessHeap(), 0, This); 109 DMUSIC_UnlockModule(); 110 } 111 112 return ref; 113 } 114 115 static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = { 116 IDirectMusicDownloadedInstrumentImpl_QueryInterface, 117 IDirectMusicDownloadedInstrumentImpl_AddRef, 118 IDirectMusicDownloadedInstrumentImpl_Release 119 }; 120 121 static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface) 122 { 123 if (!iface) 124 return NULL; 125 assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl); 126 127 return impl_from_IDirectMusicDownloadedInstrument(iface); 128 } 129 130 static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument) 131 { 132 IDirectMusicDownloadedInstrumentImpl *object; 133 134 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 135 if (!object) 136 { 137 *instrument = NULL; 138 return E_OUTOFMEMORY; 139 } 140 141 object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl; 142 object->ref = 1; 143 144 *instrument = &object->IDirectMusicDownloadedInstrument_iface; 145 DMUSIC_LockModule(); 146 147 return S_OK; 148 } 149 150 /* SynthPortImpl IDirectMusicPort IUnknown part follows: */ 151 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_QueryInterface(LPDIRECTMUSICPORT iface, REFIID riid, LPVOID *ret_iface) 152 { 153 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 154 155 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface); 156 157 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectMusicPort)) 158 *ret_iface = &This->IDirectMusicPort_iface; 159 else if (IsEqualGUID(riid, &IID_IDirectMusicPortDownload)) 160 *ret_iface = &This->IDirectMusicPortDownload_iface; 161 else if (IsEqualGUID(riid, &IID_IDirectMusicThru)) 162 *ret_iface = &This->IDirectMusicThru_iface; 163 else if (IsEqualGUID(riid, &IID_IKsControl)) 164 *ret_iface = &This->IKsControl_iface; 165 else { 166 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface); 167 *ret_iface = NULL; 168 return E_NOINTERFACE; 169 } 170 171 IUnknown_AddRef((IUnknown*)*ret_iface); 172 173 return S_OK; 174 } 175 176 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_AddRef(LPDIRECTMUSICPORT iface) 177 { 178 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 179 ULONG ref = InterlockedIncrement(&This->ref); 180 181 TRACE("(%p)->(): new ref = %u\n", This, ref); 182 183 DMUSIC_LockModule(); 184 185 return ref; 186 } 187 188 static ULONG WINAPI SynthPortImpl_IDirectMusicPort_Release(LPDIRECTMUSICPORT iface) 189 { 190 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 191 ULONG ref = InterlockedDecrement(&This->ref); 192 193 TRACE("(%p)->(): new ref = %u\n", This, ref); 194 195 if (!ref) 196 { 197 dmusic_remove_port(This->parent, iface); 198 IDirectMusicSynth_Activate(This->synth, FALSE); 199 IDirectMusicSynth_Close(This->synth); 200 IDirectMusicSynth_Release(This->synth); 201 IDirectMusicSynthSink_Release(This->synth_sink); 202 IReferenceClock_Release(This->pLatencyClock); 203 if (This->dsbuffer) 204 IDirectSoundBuffer_Release(This->dsbuffer); 205 if (This->dsound) 206 IDirectSound_Release(This->dsound); 207 HeapFree(GetProcessHeap(), 0, This); 208 } 209 210 DMUSIC_UnlockModule(); 211 212 return ref; 213 } 214 215 /* SynthPortImpl IDirectMusicPort interface follows: */ 216 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_PlayBuffer(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer) 217 { 218 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 219 HRESULT hr; 220 REFERENCE_TIME time; 221 LPBYTE data; 222 DWORD size; 223 224 TRACE("(%p/%p)->(%p)\n", iface, This, buffer); 225 226 if (!buffer) 227 return E_POINTER; 228 229 hr = IDirectMusicBuffer_GetStartTime(buffer, &time); 230 231 if (SUCCEEDED(hr)) 232 hr = IDirectMusicBuffer_GetRawBufferPtr(buffer, &data); 233 234 if (SUCCEEDED(hr)) 235 hr = IDirectMusicBuffer_GetUsedBytes(buffer, &size); 236 237 if (SUCCEEDED(hr)) 238 hr = IDirectMusicSynth_PlayBuffer(This->synth, time, data, size); 239 240 return hr; 241 } 242 243 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle(LPDIRECTMUSICPORT iface, HANDLE event) 244 { 245 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 246 247 FIXME("(%p/%p)->(%p): stub\n", iface, This, event); 248 249 return S_OK; 250 } 251 252 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT iface, LPDIRECTMUSICBUFFER buffer) 253 { 254 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 255 256 FIXME("(%p/%p)->(%p): stub\n", iface, This, buffer); 257 258 return S_OK; 259 } 260 261 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges) 262 { 263 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 264 IDirectMusicInstrumentImpl *instrument_object; 265 HRESULT ret; 266 BOOL free; 267 HANDLE download; 268 DMUS_DOWNLOADINFO *info; 269 DMUS_OFFSETTABLE *offset_table; 270 DMUS_INSTRUMENT *instrument_info; 271 BYTE *data; 272 ULONG offset; 273 ULONG nb_regions; 274 ULONG size; 275 ULONG i; 276 277 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges); 278 279 if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges)) 280 return E_POINTER; 281 282 instrument_object = impl_from_IDirectMusicInstrument(instrument); 283 284 nb_regions = instrument_object->header.cRegions; 285 size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions; 286 287 data = HeapAlloc(GetProcessHeap(), 0, size); 288 if (!data) 289 return E_OUTOFMEMORY; 290 291 info = (DMUS_DOWNLOADINFO*)data; 292 offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO)); 293 offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions); 294 295 info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2; 296 info->dwDLId = 0; 297 info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions; 298 info->cbSize = size; 299 300 offset_table->ulOffsetTable[0] = offset; 301 instrument_info = (DMUS_INSTRUMENT*)(data + offset); 302 offset += sizeof(DMUS_INSTRUMENT); 303 instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale); 304 instrument_info->ulFirstRegionIdx = 1; 305 instrument_info->ulGlobalArtIdx = 0; /* FIXME */ 306 instrument_info->ulFirstExtCkIdx = 0; /* FIXME */ 307 instrument_info->ulCopyrightIdx = 0; /* FIXME */ 308 instrument_info->ulFlags = 0; /* FIXME */ 309 310 for (i = 0; i < nb_regions; i++) 311 { 312 DMUS_REGION *region = (DMUS_REGION*)(data + offset); 313 314 offset_table->ulOffsetTable[1 + i] = offset; 315 offset += sizeof(DMUS_REGION); 316 region->RangeKey = instrument_object->regions[i].header.RangeKey; 317 region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity; 318 region->fusOptions = instrument_object->regions[i].header.fusOptions; 319 region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup; 320 region->ulRegionArtIdx = 0; /* FIXME */ 321 region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0; 322 region->ulFirstExtCkIdx = 0; /* FIXME */ 323 region->WaveLink = instrument_object->regions[i].wave_link; 324 region->WSMP = instrument_object->regions[i].wave_sample; 325 region->WLOOP[0] = instrument_object->regions[i].wave_loop; 326 } 327 328 ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free); 329 330 if (SUCCEEDED(ret)) 331 ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument); 332 333 if (SUCCEEDED(ret)) 334 { 335 IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument); 336 337 downloaded_object->data = data; 338 downloaded_object->downloaded = TRUE; 339 } 340 341 *downloaded_instrument = NULL; 342 HeapFree(GetProcessHeap(), 0, data); 343 344 return E_FAIL; 345 } 346 347 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument) 348 { 349 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 350 IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument); 351 352 TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument); 353 354 if (!downloaded_instrument) 355 return E_POINTER; 356 357 if (!downloaded_object->downloaded) 358 return DMUS_E_NOT_DOWNLOADED_TO_PORT; 359 360 HeapFree(GetProcessHeap(), 0, downloaded_object->data); 361 downloaded_object->data = NULL; 362 downloaded_object->downloaded = FALSE; 363 364 return S_OK; 365 } 366 367 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetLatencyClock(LPDIRECTMUSICPORT iface, IReferenceClock** clock) 368 { 369 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 370 371 TRACE("(%p/%p)->(%p)\n", iface, This, clock); 372 373 *clock = This->pLatencyClock; 374 IReferenceClock_AddRef(*clock); 375 376 return S_OK; 377 } 378 379 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetRunningStats(LPDIRECTMUSICPORT iface, LPDMUS_SYNTHSTATS stats) 380 { 381 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 382 383 FIXME("(%p/%p)->(%p): stub\n", iface, This, stats); 384 385 return S_OK; 386 } 387 388 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Compact(LPDIRECTMUSICPORT iface) 389 { 390 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 391 392 FIXME("(%p/%p)->(): stub\n", iface, This); 393 394 return S_OK; 395 } 396 397 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetCaps(LPDIRECTMUSICPORT iface, LPDMUS_PORTCAPS port_caps) 398 { 399 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 400 401 TRACE("(%p/%p)->(%p)\n", iface, This, port_caps); 402 403 *port_caps = This->caps; 404 405 return S_OK; 406 } 407 408 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DeviceIoControl(LPDIRECTMUSICPORT iface, DWORD io_control_code, LPVOID in_buffer, DWORD in_buffer_size, 409 LPVOID out_buffer, DWORD out_buffer_size, LPDWORD bytes_returned, LPOVERLAPPED overlapped) 410 { 411 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 412 413 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); 414 415 return S_OK; 416 } 417 418 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetNumChannelGroups(LPDIRECTMUSICPORT iface, DWORD channel_groups) 419 { 420 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 421 422 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, channel_groups); 423 424 This->nrofgroups = channel_groups; 425 426 return S_OK; 427 } 428 429 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetNumChannelGroups(LPDIRECTMUSICPORT iface, LPDWORD channel_groups) 430 { 431 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 432 433 TRACE("(%p/%p)->(%p)\n", iface, This, channel_groups); 434 435 *channel_groups = This->nrofgroups; 436 437 return S_OK; 438 } 439 440 static HRESULT WINAPI synth_dmport_Activate(IDirectMusicPort *iface, BOOL active) 441 { 442 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 443 444 FIXME("(%p/%p)->(%d): semi-stub\n", iface, This, active); 445 446 if (This->active == active) 447 return S_FALSE; 448 449 if (active) { 450 /* Acquire the dsound */ 451 if (!This->dsound) { 452 IDirectSound_AddRef(This->parent->dsound); 453 This->dsound = This->parent->dsound; 454 } 455 IDirectSound_AddRef(This->dsound); 456 } else { 457 /* Release the dsound */ 458 IDirectSound_Release(This->dsound); 459 IDirectSound_Release(This->parent->dsound); 460 if (This->dsound == This->parent->dsound) 461 This->dsound = NULL; 462 } 463 464 This->active = active; 465 466 return S_OK; 467 } 468 469 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_SetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, DWORD priority) 470 { 471 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 472 473 FIXME("(%p/%p)->(%d, %d, %d): semi-stub\n", iface, This, channel_group, channel, priority); 474 475 if (channel > 16) 476 { 477 WARN("isn't there supposed to be 16 channels (no. %d requested)?! (faking as it is ok)\n", channel); 478 /*return E_INVALIDARG;*/ 479 } 480 481 return S_OK; 482 } 483 484 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetChannelPriority(LPDIRECTMUSICPORT iface, DWORD channel_group, DWORD channel, LPDWORD priority) 485 { 486 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 487 488 TRACE("(%p/%p)->(%u, %u, %p)\n", iface, This, channel_group, channel, priority); 489 490 *priority = This->group[channel_group - 1].channel[channel].priority; 491 492 return S_OK; 493 } 494 495 static HRESULT WINAPI synth_dmport_SetDirectSound(IDirectMusicPort *iface, IDirectSound *dsound, 496 IDirectSoundBuffer *dsbuffer) 497 { 498 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 499 500 FIXME("(%p/%p)->(%p, %p): semi-stub\n", iface, This, dsound, dsbuffer); 501 502 if (This->active) 503 return DMUS_E_DSOUND_ALREADY_SET; 504 505 if (This->dsound) { 506 if (This->dsound != This->parent->dsound) 507 ERR("Not the same dsound in the port (%p) and parent dmusic (%p), expect trouble!\n", 508 This->dsound, This->parent->dsound); 509 if (!IDirectSound_Release(This->parent->dsound)) 510 This->parent->dsound = NULL; 511 } 512 if (This->dsbuffer) 513 IDirectSound_Release(This->dsbuffer); 514 515 This->dsound = dsound; 516 This->dsbuffer = dsbuffer; 517 518 if (This->dsound) 519 IDirectSound_AddRef(This->dsound); 520 if (This->dsbuffer) 521 IDirectSound_AddRef(This->dsbuffer); 522 523 return S_OK; 524 } 525 526 static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_GetFormat(LPDIRECTMUSICPORT iface, LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize) 527 { 528 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); 529 WAVEFORMATEX format; 530 FIXME("(%p, %p, %p, %p): stub\n", This, pWaveFormatEx, pdwWaveFormatExSize, pdwBufferSize); 531 532 if (pWaveFormatEx == NULL) 533 { 534 if (pdwWaveFormatExSize) 535 *pdwWaveFormatExSize = sizeof(format); 536 else 537 return E_POINTER; 538 } 539 else 540 { 541 if (pdwWaveFormatExSize == NULL) 542 return E_POINTER; 543 544 /* Just fill this in with something that will not crash Direct Sound for now. */ 545 /* It won't be used anyway until Performances are completed */ 546 format.wFormatTag = WAVE_FORMAT_PCM; 547 format.nChannels = 2; /* This->params.dwAudioChannels; */ 548 format.nSamplesPerSec = 44100; /* This->params.dwSampleRate; */ 549 format.wBitsPerSample = 16; /* FIXME: check this */ 550 format.nBlockAlign = (format.wBitsPerSample * format.nChannels) / 8; 551 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; 552 format.cbSize = 0; 553 554 if (*pdwWaveFormatExSize >= sizeof(format)) 555 { 556 CopyMemory(pWaveFormatEx, &format, min(sizeof(format), *pdwWaveFormatExSize)); 557 *pdwWaveFormatExSize = sizeof(format); /* FIXME check if this is set */ 558 } 559 else 560 return E_POINTER; /* FIXME find right error */ 561 } 562 563 if (pdwBufferSize) 564 *pdwBufferSize = 44100 * 2 * 2; 565 else 566 return E_POINTER; 567 568 return S_OK; 569 } 570 571 static const IDirectMusicPortVtbl SynthPortImpl_DirectMusicPort_Vtbl = { 572 /**** IDirectMusicPort IUnknown part methods ***/ 573 SynthPortImpl_IDirectMusicPort_QueryInterface, 574 SynthPortImpl_IDirectMusicPort_AddRef, 575 SynthPortImpl_IDirectMusicPort_Release, 576 /**** IDirectMusicPort methods ***/ 577 SynthPortImpl_IDirectMusicPort_PlayBuffer, 578 SynthPortImpl_IDirectMusicPort_SetReadNotificationHandle, 579 SynthPortImpl_IDirectMusicPort_Read, 580 SynthPortImpl_IDirectMusicPort_DownloadInstrument, 581 SynthPortImpl_IDirectMusicPort_UnloadInstrument, 582 SynthPortImpl_IDirectMusicPort_GetLatencyClock, 583 SynthPortImpl_IDirectMusicPort_GetRunningStats, 584 SynthPortImpl_IDirectMusicPort_Compact, 585 SynthPortImpl_IDirectMusicPort_GetCaps, 586 SynthPortImpl_IDirectMusicPort_DeviceIoControl, 587 SynthPortImpl_IDirectMusicPort_SetNumChannelGroups, 588 SynthPortImpl_IDirectMusicPort_GetNumChannelGroups, 589 synth_dmport_Activate, 590 SynthPortImpl_IDirectMusicPort_SetChannelPriority, 591 SynthPortImpl_IDirectMusicPort_GetChannelPriority, 592 synth_dmport_SetDirectSound, 593 SynthPortImpl_IDirectMusicPort_GetFormat 594 }; 595 596 /* SynthPortImpl IDirectMusicPortDownload IUnknown part follows: */ 597 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_QueryInterface(LPDIRECTMUSICPORTDOWNLOAD iface, REFIID riid, LPVOID *ret_iface) 598 { 599 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 600 601 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface); 602 603 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface); 604 } 605 606 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface) 607 { 608 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 609 610 TRACE("(%p/%p)->()\n", iface, This); 611 612 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface); 613 } 614 615 static ULONG WINAPI SynthPortImpl_IDirectMusicPortDownload_Release(LPDIRECTMUSICPORTDOWNLOAD iface) 616 { 617 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 618 619 TRACE("(%p/%p)->()\n", iface, This); 620 621 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface); 622 } 623 624 /* SynthPortImpl IDirectMusicPortDownload Interface follows: */ 625 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD DLId, IDirectMusicDownload** IDMDownload) 626 { 627 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 628 629 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, DLId, IDMDownload); 630 631 if (!IDMDownload) 632 return E_POINTER; 633 634 return DMUSIC_CreateDirectMusicDownloadImpl(&IID_IDirectMusicDownload, (LPVOID*)IDMDownload, NULL); 635 } 636 637 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD size, IDirectMusicDownload** IDMDownload) 638 { 639 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 640 641 FIXME("(%p/%p)->(%u, %p): stub\n", iface, This, size, IDMDownload); 642 643 return S_OK; 644 } 645 646 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetDLId(LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* start_DLId, DWORD count) 647 { 648 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 649 650 FIXME("(%p/%p)->(%p, %u): stub\n", iface, This, start_DLId, count); 651 652 return S_OK; 653 } 654 655 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_GetAppend (LPDIRECTMUSICPORTDOWNLOAD iface, DWORD* append) 656 { 657 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 658 659 FIXME("(%p/%p)->(%p): stub\n", iface, This, append); 660 661 return S_OK; 662 } 663 664 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Download(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload) 665 { 666 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 667 668 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload); 669 670 return S_OK; 671 } 672 673 static HRESULT WINAPI SynthPortImpl_IDirectMusicPortDownload_Unload(LPDIRECTMUSICPORTDOWNLOAD iface, IDirectMusicDownload* IDMDownload) 674 { 675 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPortDownload(iface); 676 677 FIXME("(%p/%p)->(%p): stub\n", iface, This, IDMDownload); 678 679 return S_OK; 680 } 681 682 static const IDirectMusicPortDownloadVtbl SynthPortImpl_DirectMusicPortDownload_Vtbl = { 683 /*** IDirectMusicPortDownload IUnknown part methods ***/ 684 SynthPortImpl_IDirectMusicPortDownload_QueryInterface, 685 SynthPortImpl_IDirectMusicPortDownload_AddRef, 686 SynthPortImpl_IDirectMusicPortDownload_Release, 687 /*** IDirectMusicPortDownload methods ***/ 688 SynthPortImpl_IDirectMusicPortDownload_GetBuffer, 689 SynthPortImpl_IDirectMusicPortDownload_AllocateBuffer, 690 SynthPortImpl_IDirectMusicPortDownload_GetDLId, 691 SynthPortImpl_IDirectMusicPortDownload_GetAppend, 692 SynthPortImpl_IDirectMusicPortDownload_Download, 693 SynthPortImpl_IDirectMusicPortDownload_Unload 694 }; 695 696 /* SynthPortImpl IDirectMusicThru IUnknown part follows: */ 697 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_QueryInterface(LPDIRECTMUSICTHRU iface, REFIID riid, LPVOID *ret_iface) 698 { 699 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface); 700 701 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface); 702 703 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface); 704 } 705 706 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_AddRef(LPDIRECTMUSICTHRU iface) 707 { 708 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface); 709 710 TRACE("(%p/%p)->()\n", iface, This); 711 712 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface); 713 } 714 715 static ULONG WINAPI SynthPortImpl_IDirectMusicThru_Release(LPDIRECTMUSICTHRU iface) 716 { 717 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface); 718 719 TRACE("(%p/%p)->()\n", iface, This); 720 721 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface); 722 } 723 724 /* SynthPortImpl IDirectMusicThru Interface follows: */ 725 static HRESULT WINAPI SynthPortImpl_IDirectMusicThru_ThruChannel(LPDIRECTMUSICTHRU iface, DWORD source_channel_group, DWORD source_channel, DWORD destination_channel_group, 726 DWORD destination_channel, LPDIRECTMUSICPORT destination_port) 727 { 728 SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicThru(iface); 729 730 FIXME("(%p/%p)->(%d, %d, %d, %d, %p): stub\n", iface, This, source_channel_group, source_channel, destination_channel_group, destination_channel, destination_port); 731 732 return S_OK; 733 } 734 735 static const IDirectMusicThruVtbl SynthPortImpl_DirectMusicThru_Vtbl = { 736 /*** IDirectMusicThru IUnknown part methods */ 737 SynthPortImpl_IDirectMusicThru_QueryInterface, 738 SynthPortImpl_IDirectMusicThru_AddRef, 739 SynthPortImpl_IDirectMusicThru_Release, 740 /*** IDirectMusicThru methods ***/ 741 SynthPortImpl_IDirectMusicThru_ThruChannel 742 }; 743 744 static HRESULT WINAPI IKsControlImpl_QueryInterface(IKsControl *iface, REFIID riid, 745 void **ret_iface) 746 { 747 SynthPortImpl *This = impl_from_IKsControl(iface); 748 749 return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface); 750 } 751 752 static ULONG WINAPI IKsControlImpl_AddRef(IKsControl *iface) 753 { 754 SynthPortImpl *This = impl_from_IKsControl(iface); 755 756 return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface); 757 } 758 759 static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface) 760 { 761 SynthPortImpl *This = impl_from_IKsControl(iface); 762 763 return IDirectMusicPort_Release(&This->IDirectMusicPort_iface); 764 } 765 766 static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop, 767 ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len) 768 { 769 TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, prop, prop_len, data, data_len, ret_len); 770 TRACE("prop = %s - %u - %u\n", debugstr_guid(&prop->u.s.Set), prop->u.s.Id, prop->u.s.Flags); 771 772 if (prop->u.s.Flags != KSPROPERTY_TYPE_GET) 773 { 774 FIXME("prop flags %u not yet supported\n", prop->u.s.Flags); 775 return S_FALSE; 776 } 777 778 if (data_len < sizeof(DWORD)) 779 return E_NOT_SUFFICIENT_BUFFER; 780 781 FIXME("Unknown property %s\n", debugstr_guid(&prop->u.s.Set)); 782 *(DWORD*)data = FALSE; 783 *ret_len = sizeof(DWORD); 784 785 return S_OK; 786 } 787 788 static HRESULT WINAPI IKsControlImpl_KsMethod(IKsControl *iface, KSMETHOD *method, 789 ULONG method_len, void *data, ULONG data_len, ULONG *ret_len) 790 { 791 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, method, method_len, data, data_len, ret_len); 792 793 return E_NOTIMPL; 794 } 795 796 static HRESULT WINAPI IKsControlImpl_KsEvent(IKsControl *iface, KSEVENT *event, ULONG event_len, 797 void *data, ULONG data_len, ULONG *ret_len) 798 { 799 FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, event, event_len, data, data_len, ret_len); 800 801 return E_NOTIMPL; 802 } 803 804 static const IKsControlVtbl ikscontrol_vtbl = { 805 IKsControlImpl_QueryInterface, 806 IKsControlImpl_AddRef, 807 IKsControlImpl_Release, 808 IKsControlImpl_KsProperty, 809 IKsControlImpl_KsMethod, 810 IKsControlImpl_KsEvent 811 }; 812 813 HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, 814 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) 815 { 816 SynthPortImpl *obj; 817 HRESULT hr = E_FAIL; 818 int i; 819 820 TRACE("(%p, %p, %p)\n", port_params, port_caps, port); 821 822 *port = NULL; 823 824 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SynthPortImpl)); 825 if (!obj) 826 return E_OUTOFMEMORY; 827 828 obj->IDirectMusicPort_iface.lpVtbl = &SynthPortImpl_DirectMusicPort_Vtbl; 829 obj->IDirectMusicPortDownload_iface.lpVtbl = &SynthPortImpl_DirectMusicPortDownload_Vtbl; 830 obj->IDirectMusicThru_iface.lpVtbl = &SynthPortImpl_DirectMusicThru_Vtbl; 831 obj->IKsControl_iface.lpVtbl = &ikscontrol_vtbl; 832 obj->ref = 1; 833 obj->parent = parent; 834 obj->active = FALSE; 835 obj->params = *port_params; 836 obj->caps = *port_caps; 837 838 hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (LPVOID*)&obj->pLatencyClock, NULL); 839 if (hr != S_OK) 840 { 841 HeapFree(GetProcessHeap(), 0, obj); 842 return hr; 843 } 844 845 if (SUCCEEDED(hr)) 846 hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void**)&obj->synth); 847 848 if (SUCCEEDED(hr)) 849 hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink); 850 851 if (SUCCEEDED(hr)) 852 hr = IDirectMusicSynth_SetMasterClock(obj->synth, obj->pLatencyClock); 853 854 if (SUCCEEDED(hr)) 855 hr = IDirectMusicSynthSink_SetMasterClock(obj->synth_sink, obj->pLatencyClock); 856 857 if (SUCCEEDED(hr)) 858 hr = IDirectMusicSynth_SetSynthSink(obj->synth, obj->synth_sink); 859 860 if (SUCCEEDED(hr)) 861 hr = IDirectMusicSynth_Open(obj->synth, port_params); 862 863 if (0) 864 { 865 if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) { 866 obj->nrofgroups = port_params->dwChannelGroups; 867 /* Setting default priorities */ 868 for (i = 0; i < obj->nrofgroups; i++) { 869 TRACE ("Setting default channel priorities on channel group %i\n", i + 1); 870 obj->group[i].channel[0].priority = DAUD_CHAN1_DEF_VOICE_PRIORITY; 871 obj->group[i].channel[1].priority = DAUD_CHAN2_DEF_VOICE_PRIORITY; 872 obj->group[i].channel[2].priority = DAUD_CHAN3_DEF_VOICE_PRIORITY; 873 obj->group[i].channel[3].priority = DAUD_CHAN4_DEF_VOICE_PRIORITY; 874 obj->group[i].channel[4].priority = DAUD_CHAN5_DEF_VOICE_PRIORITY; 875 obj->group[i].channel[5].priority = DAUD_CHAN6_DEF_VOICE_PRIORITY; 876 obj->group[i].channel[6].priority = DAUD_CHAN7_DEF_VOICE_PRIORITY; 877 obj->group[i].channel[7].priority = DAUD_CHAN8_DEF_VOICE_PRIORITY; 878 obj->group[i].channel[8].priority = DAUD_CHAN9_DEF_VOICE_PRIORITY; 879 obj->group[i].channel[9].priority = DAUD_CHAN10_DEF_VOICE_PRIORITY; 880 obj->group[i].channel[10].priority = DAUD_CHAN11_DEF_VOICE_PRIORITY; 881 obj->group[i].channel[11].priority = DAUD_CHAN12_DEF_VOICE_PRIORITY; 882 obj->group[i].channel[12].priority = DAUD_CHAN13_DEF_VOICE_PRIORITY; 883 obj->group[i].channel[13].priority = DAUD_CHAN14_DEF_VOICE_PRIORITY; 884 obj->group[i].channel[14].priority = DAUD_CHAN15_DEF_VOICE_PRIORITY; 885 obj->group[i].channel[15].priority = DAUD_CHAN16_DEF_VOICE_PRIORITY; 886 } 887 } 888 } 889 890 if (SUCCEEDED(hr)) { 891 *port = &obj->IDirectMusicPort_iface; 892 return S_OK; 893 } 894 895 if (obj->synth) 896 IDirectMusicSynth_Release(obj->synth); 897 if (obj->synth_sink) 898 IDirectMusicSynthSink_Release(obj->synth_sink); 899 if (obj->pLatencyClock) 900 IReferenceClock_Release(obj->pLatencyClock); 901 HeapFree(GetProcessHeap(), 0, obj); 902 903 return hr; 904 } 905 906 HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, 907 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) 908 { 909 FIXME("(%p, %p, %p): stub\n", port_params, port_caps, port); 910 911 return E_NOTIMPL; 912 } 913 914 HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, 915 DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) 916 { 917 FIXME("(%p, %p, %p): stub\n", port_params, port_caps, port); 918 919 return E_NOTIMPL; 920 } 921