1 /* DirectMusic Main 2 * 3 * Copyright (C) 2003-2004 Rok Mandeljc 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "config.h" 21 #include "wine/port.h" 22 23 #include <stdio.h> 24 #include <stdarg.h> 25 26 #define COBJMACROS 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "winnt.h" 31 #include "wingdi.h" 32 #include "winuser.h" 33 #include "winreg.h" 34 #include "objbase.h" 35 #include "rpcproxy.h" 36 #include "initguid.h" 37 #include "dmusici.h" 38 39 #include "dmusic_private.h" 40 41 WINE_DEFAULT_DEBUG_CHANNEL(dmusic); 42 43 static HINSTANCE instance; 44 LONG DMUSIC_refCount = 0; 45 46 typedef struct { 47 IClassFactory IClassFactory_iface; 48 HRESULT (WINAPI *fnCreateInstance)(REFIID riid, void **ppv, IUnknown *pUnkOuter); 49 } IClassFactoryImpl; 50 51 /****************************************************************** 52 * IClassFactory implementation 53 */ 54 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 55 { 56 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); 57 } 58 59 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) 60 { 61 if (ppv == NULL) 62 return E_POINTER; 63 64 if (IsEqualGUID(&IID_IUnknown, riid)) 65 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 66 else if (IsEqualGUID(&IID_IClassFactory, riid)) 67 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 68 else { 69 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); 70 *ppv = NULL; 71 return E_NOINTERFACE; 72 } 73 74 *ppv = iface; 75 IUnknown_AddRef((IUnknown*)*ppv); 76 return S_OK; 77 } 78 79 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 80 { 81 DMUSIC_LockModule(); 82 83 return 2; /* non-heap based object */ 84 } 85 86 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 87 { 88 DMUSIC_UnlockModule(); 89 90 return 1; /* non-heap based object */ 91 } 92 93 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, 94 REFIID riid, void **ppv) 95 { 96 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 97 98 TRACE ("(%p, %s, %p)\n", pUnkOuter, debugstr_dmguid(riid), ppv); 99 100 return This->fnCreateInstance(riid, ppv, pUnkOuter); 101 } 102 103 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock) 104 { 105 TRACE("(%d)\n", dolock); 106 107 if (dolock) 108 DMUSIC_LockModule(); 109 else 110 DMUSIC_UnlockModule(); 111 112 return S_OK; 113 } 114 115 static const IClassFactoryVtbl classfactory_vtbl = { 116 ClassFactory_QueryInterface, 117 ClassFactory_AddRef, 118 ClassFactory_Release, 119 ClassFactory_CreateInstance, 120 ClassFactory_LockServer 121 }; 122 123 static IClassFactoryImpl DirectMusic_CF = {{&classfactory_vtbl}, DMUSIC_CreateDirectMusicImpl}; 124 static IClassFactoryImpl Collection_CF = {{&classfactory_vtbl}, 125 DMUSIC_CreateDirectMusicCollectionImpl}; 126 127 /****************************************************************** 128 * DllMain 129 * 130 * 131 */ 132 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 133 if (fdwReason == DLL_PROCESS_ATTACH) { 134 instance = hinstDLL; 135 DisableThreadLibraryCalls(hinstDLL); 136 } 137 138 return TRUE; 139 } 140 141 142 /****************************************************************** 143 * DllCanUnloadNow (DMUSIC.@) 144 * 145 * 146 */ 147 HRESULT WINAPI DllCanUnloadNow(void) 148 { 149 return DMUSIC_refCount != 0 ? S_FALSE : S_OK; 150 } 151 152 153 /****************************************************************** 154 * DllGetClassObject (DMUSIC.@) 155 * 156 * 157 */ 158 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 159 { 160 TRACE("(%s, %s, %p)\n", debugstr_dmguid(rclsid), debugstr_dmguid(riid), ppv); 161 if (IsEqualCLSID (rclsid, &CLSID_DirectMusic) && IsEqualIID (riid, &IID_IClassFactory)) { 162 *ppv = &DirectMusic_CF; 163 IClassFactory_AddRef((IClassFactory*)*ppv); 164 return S_OK; 165 } else if (IsEqualCLSID (rclsid, &CLSID_DirectMusicCollection) && IsEqualIID (riid, &IID_IClassFactory)) { 166 *ppv = &Collection_CF; 167 IClassFactory_AddRef((IClassFactory*)*ppv); 168 return S_OK; 169 } 170 171 WARN("(%s, %s, %p): no interface found.\n", debugstr_dmguid(rclsid), debugstr_dmguid(riid), ppv); 172 return CLASS_E_CLASSNOTAVAILABLE; 173 } 174 175 /*********************************************************************** 176 * DllRegisterServer (DMUSIC.@) 177 */ 178 HRESULT WINAPI DllRegisterServer(void) 179 { 180 return __wine_register_resources( instance ); 181 } 182 183 /*********************************************************************** 184 * DllUnregisterServer (DMUSIC.@) 185 */ 186 HRESULT WINAPI DllUnregisterServer(void) 187 { 188 return __wine_unregister_resources( instance ); 189 } 190 191 /****************************************************************** 192 * Helper functions 193 * 194 * 195 */ 196 /* dwPatch from MIDILOCALE */ 197 DWORD MIDILOCALE2Patch (const MIDILOCALE *pLocale) { 198 DWORD dwPatch = 0; 199 if (!pLocale) return 0; 200 dwPatch |= (pLocale->ulBank & F_INSTRUMENT_DRUMS); /* set drum bit */ 201 dwPatch |= ((pLocale->ulBank & 0x00007F7F) << 8); /* set MIDI bank location */ 202 dwPatch |= (pLocale->ulInstrument & 0x0000007F); /* set PC value */ 203 return dwPatch; 204 } 205 206 /* MIDILOCALE from dwPatch */ 207 void Patch2MIDILOCALE (DWORD dwPatch, LPMIDILOCALE pLocale) { 208 memset (pLocale, 0, sizeof(MIDILOCALE)); 209 210 pLocale->ulInstrument = (dwPatch & 0x7F); /* get PC value */ 211 pLocale->ulBank = ((dwPatch & 0x007F7F00) >> 8); /* get MIDI bank location */ 212 pLocale->ulBank |= (dwPatch & F_INSTRUMENT_DRUMS); /* get drum bit */ 213 } 214 215 /* check whether the given DWORD is even (return 0) or odd (return 1) */ 216 int even_or_odd (DWORD number) { 217 return (number & 0x1); /* basically, check if bit 0 is set ;) */ 218 } 219 220 /* FOURCC to string conversion for debug messages */ 221 const char *debugstr_fourcc (DWORD fourcc) { 222 if (!fourcc) return "'null'"; 223 return wine_dbg_sprintf ("\'%c%c%c%c\'", 224 (char)(fourcc), (char)(fourcc >> 8), 225 (char)(fourcc >> 16), (char)(fourcc >> 24)); 226 } 227 228 /* DMUS_VERSION struct to string conversion for debug messages */ 229 static const char *debugstr_dmversion (const DMUS_VERSION *version) { 230 if (!version) return "'null'"; 231 return wine_dbg_sprintf ("\'%i,%i,%i,%i\'", 232 (int)((version->dwVersionMS & 0xFFFF0000) >> 8), (int)(version->dwVersionMS & 0x0000FFFF), 233 (int)((version->dwVersionLS & 0xFFFF0000) >> 8), (int)(version->dwVersionLS & 0x0000FFFF)); 234 } 235 236 /* returns name of given GUID */ 237 const char *debugstr_dmguid (const GUID *id) { 238 static const guid_info guids[] = { 239 /* CLSIDs */ 240 GE(CLSID_AudioVBScript), 241 GE(CLSID_DirectMusic), 242 GE(CLSID_DirectMusicAudioPathConfig), 243 GE(CLSID_DirectMusicAuditionTrack), 244 GE(CLSID_DirectMusicBand), 245 GE(CLSID_DirectMusicBandTrack), 246 GE(CLSID_DirectMusicChordMapTrack), 247 GE(CLSID_DirectMusicChordMap), 248 GE(CLSID_DirectMusicChordTrack), 249 GE(CLSID_DirectMusicCollection), 250 GE(CLSID_DirectMusicCommandTrack), 251 GE(CLSID_DirectMusicComposer), 252 GE(CLSID_DirectMusicContainer), 253 GE(CLSID_DirectMusicGraph), 254 GE(CLSID_DirectMusicLoader), 255 GE(CLSID_DirectMusicLyricsTrack), 256 GE(CLSID_DirectMusicMarkerTrack), 257 GE(CLSID_DirectMusicMelodyFormulationTrack), 258 GE(CLSID_DirectMusicMotifTrack), 259 GE(CLSID_DirectMusicMuteTrack), 260 GE(CLSID_DirectMusicParamControlTrack), 261 GE(CLSID_DirectMusicPatternTrack), 262 GE(CLSID_DirectMusicPerformance), 263 GE(CLSID_DirectMusicScript), 264 GE(CLSID_DirectMusicScriptAutoImpSegment), 265 GE(CLSID_DirectMusicScriptAutoImpPerformance), 266 GE(CLSID_DirectMusicScriptAutoImpSegmentState), 267 GE(CLSID_DirectMusicScriptAutoImpAudioPathConfig), 268 GE(CLSID_DirectMusicScriptAutoImpAudioPath), 269 GE(CLSID_DirectMusicScriptAutoImpSong), 270 GE(CLSID_DirectMusicScriptSourceCodeLoader), 271 GE(CLSID_DirectMusicScriptTrack), 272 GE(CLSID_DirectMusicSection), 273 GE(CLSID_DirectMusicSegment), 274 GE(CLSID_DirectMusicSegmentState), 275 GE(CLSID_DirectMusicSegmentTriggerTrack), 276 GE(CLSID_DirectMusicSegTriggerTrack), 277 GE(CLSID_DirectMusicSeqTrack), 278 GE(CLSID_DirectMusicSignPostTrack), 279 GE(CLSID_DirectMusicSong), 280 GE(CLSID_DirectMusicStyle), 281 GE(CLSID_DirectMusicStyleTrack), 282 GE(CLSID_DirectMusicSynth), 283 GE(CLSID_DirectMusicSynthSink), 284 GE(CLSID_DirectMusicSysExTrack), 285 GE(CLSID_DirectMusicTemplate), 286 GE(CLSID_DirectMusicTempoTrack), 287 GE(CLSID_DirectMusicTimeSigTrack), 288 GE(CLSID_DirectMusicWaveTrack), 289 GE(CLSID_DirectSoundWave), 290 /* IIDs */ 291 GE(IID_IDirectMusic), 292 GE(IID_IDirectMusic2), 293 GE(IID_IDirectMusic8), 294 GE(IID_IDirectMusicAudioPath), 295 GE(IID_IDirectMusicBand), 296 GE(IID_IDirectMusicBuffer), 297 GE(IID_IDirectMusicChordMap), 298 GE(IID_IDirectMusicCollection), 299 GE(IID_IDirectMusicComposer), 300 GE(IID_IDirectMusicContainer), 301 GE(IID_IDirectMusicDownload), 302 GE(IID_IDirectMusicDownloadedInstrument), 303 GE(IID_IDirectMusicGetLoader), 304 GE(IID_IDirectMusicGraph), 305 GE(IID_IDirectMusicInstrument), 306 GE(IID_IDirectMusicLoader), 307 GE(IID_IDirectMusicLoader8), 308 GE(IID_IDirectMusicObject), 309 GE(IID_IDirectMusicPatternTrack), 310 GE(IID_IDirectMusicPerformance), 311 GE(IID_IDirectMusicPerformance2), 312 GE(IID_IDirectMusicPerformance8), 313 GE(IID_IDirectMusicPort), 314 GE(IID_IDirectMusicPortDownload), 315 GE(IID_IDirectMusicScript), 316 GE(IID_IDirectMusicSegment), 317 GE(IID_IDirectMusicSegment2), 318 GE(IID_IDirectMusicSegment8), 319 GE(IID_IDirectMusicSegmentState), 320 GE(IID_IDirectMusicSegmentState8), 321 GE(IID_IDirectMusicStyle), 322 GE(IID_IDirectMusicStyle8), 323 GE(IID_IDirectMusicSynth), 324 GE(IID_IDirectMusicSynth8), 325 GE(IID_IDirectMusicSynthSink), 326 GE(IID_IDirectMusicThru), 327 GE(IID_IDirectMusicTool), 328 GE(IID_IDirectMusicTool8), 329 GE(IID_IDirectMusicTrack), 330 GE(IID_IDirectMusicTrack8), 331 GE(IID_IUnknown), 332 GE(IID_IPersistStream), 333 GE(IID_IStream), 334 GE(IID_IClassFactory), 335 /* GUIDs */ 336 GE(GUID_DirectMusicAllTypes), 337 GE(GUID_NOTIFICATION_CHORD), 338 GE(GUID_NOTIFICATION_COMMAND), 339 GE(GUID_NOTIFICATION_MEASUREANDBEAT), 340 GE(GUID_NOTIFICATION_PERFORMANCE), 341 GE(GUID_NOTIFICATION_RECOMPOSE), 342 GE(GUID_NOTIFICATION_SEGMENT), 343 GE(GUID_BandParam), 344 GE(GUID_ChordParam), 345 GE(GUID_CommandParam), 346 GE(GUID_CommandParam2), 347 GE(GUID_CommandParamNext), 348 GE(GUID_IDirectMusicBand), 349 GE(GUID_IDirectMusicChordMap), 350 GE(GUID_IDirectMusicStyle), 351 GE(GUID_MuteParam), 352 GE(GUID_Play_Marker), 353 GE(GUID_RhythmParam), 354 GE(GUID_TempoParam), 355 GE(GUID_TimeSignature), 356 GE(GUID_Valid_Start_Time), 357 GE(GUID_Clear_All_Bands), 358 GE(GUID_ConnectToDLSCollection), 359 GE(GUID_Disable_Auto_Download), 360 GE(GUID_DisableTempo), 361 GE(GUID_DisableTimeSig), 362 GE(GUID_Download), 363 GE(GUID_DownloadToAudioPath), 364 GE(GUID_Enable_Auto_Download), 365 GE(GUID_EnableTempo), 366 GE(GUID_EnableTimeSig), 367 GE(GUID_IgnoreBankSelectForGM), 368 GE(GUID_SeedVariations), 369 GE(GUID_StandardMIDIFile), 370 GE(GUID_Unload), 371 GE(GUID_UnloadFromAudioPath), 372 GE(GUID_Variations), 373 GE(GUID_PerfMasterTempo), 374 GE(GUID_PerfMasterVolume), 375 GE(GUID_PerfMasterGrooveLevel), 376 GE(GUID_PerfAutoDownload), 377 GE(GUID_DefaultGMCollection), 378 GE(GUID_Synth_Default), 379 GE(GUID_Buffer_Reverb), 380 GE(GUID_Buffer_EnvReverb), 381 GE(GUID_Buffer_Stereo), 382 GE(GUID_Buffer_3D_Dry), 383 GE(GUID_Buffer_Mono), 384 GE(GUID_DMUS_PROP_GM_Hardware), 385 GE(GUID_DMUS_PROP_GS_Capable), 386 GE(GUID_DMUS_PROP_GS_Hardware), 387 GE(GUID_DMUS_PROP_DLS1), 388 GE(GUID_DMUS_PROP_DLS2), 389 GE(GUID_DMUS_PROP_Effects), 390 GE(GUID_DMUS_PROP_INSTRUMENT2), 391 GE(GUID_DMUS_PROP_LegacyCaps), 392 GE(GUID_DMUS_PROP_MemorySize), 393 GE(GUID_DMUS_PROP_SampleMemorySize), 394 GE(GUID_DMUS_PROP_SamplePlaybackRate), 395 GE(GUID_DMUS_PROP_SetSynthSink), 396 GE(GUID_DMUS_PROP_SinkUsesDSound), 397 GE(GUID_DMUS_PROP_SynthSink_DSOUND), 398 GE(GUID_DMUS_PROP_SynthSink_WAVE), 399 GE(GUID_DMUS_PROP_Volume), 400 GE(GUID_DMUS_PROP_WavesReverb), 401 GE(GUID_DMUS_PROP_WriteLatency), 402 GE(GUID_DMUS_PROP_WritePeriod), 403 GE(GUID_DMUS_PROP_XG_Capable), 404 GE(GUID_DMUS_PROP_XG_Hardware) 405 }; 406 407 unsigned int i; 408 409 if (!id) return "(null)"; 410 411 for (i = 0; i < sizeof(guids)/sizeof(guids[0]); i++) { 412 if (IsEqualGUID(id, guids[i].guid)) 413 return guids[i].name; 414 } 415 /* if we didn't find it, act like standard debugstr_guid */ 416 return debugstr_guid(id); 417 } 418 419 /* generic flag-dumping function */ 420 static const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ 421 char buffer[128] = "", *ptr = &buffer[0]; 422 unsigned int i; 423 int size = sizeof(buffer); 424 425 for (i=0; i < num_names; i++) 426 { 427 if ((flags & names[i].val) || /* standard flag*/ 428 ((!flags) && (!names[i].val))) { /* zero value only */ 429 int cnt = snprintf(ptr, size, "%s ", names[i].name); 430 if (cnt < 0 || cnt >= size) break; 431 size -= cnt; 432 ptr += cnt; 433 } 434 } 435 436 return wine_dbg_sprintf("%s", buffer); 437 } 438 439 /* dump DMUS_OBJ flags */ 440 static const char *debugstr_DMUS_OBJ_FLAGS (DWORD flagmask) { 441 static const flag_info flags[] = { 442 FE(DMUS_OBJ_OBJECT), 443 FE(DMUS_OBJ_CLASS), 444 FE(DMUS_OBJ_NAME), 445 FE(DMUS_OBJ_CATEGORY), 446 FE(DMUS_OBJ_FILENAME), 447 FE(DMUS_OBJ_FULLPATH), 448 FE(DMUS_OBJ_URL), 449 FE(DMUS_OBJ_VERSION), 450 FE(DMUS_OBJ_DATE), 451 FE(DMUS_OBJ_LOADED), 452 FE(DMUS_OBJ_MEMORY), 453 FE(DMUS_OBJ_STREAM) 454 }; 455 return debugstr_flags (flagmask, flags, sizeof(flags)/sizeof(flags[0])); 456 } 457 458 /* Dump whole DMUS_OBJECTDESC struct */ 459 void dump_DMUS_OBJECTDESC(LPDMUS_OBJECTDESC desc) 460 { 461 TRACE("DMUS_OBJECTDESC (%p):\n", desc); 462 TRACE(" - dwSize = %d\n", desc->dwSize); 463 TRACE(" - dwValidData = %s\n", debugstr_DMUS_OBJ_FLAGS (desc->dwValidData)); 464 if (desc->dwValidData & DMUS_OBJ_CLASS) TRACE(" - guidClass = %s\n", debugstr_dmguid(&desc->guidClass)); 465 if (desc->dwValidData & DMUS_OBJ_OBJECT) TRACE(" - guidObject = %s\n", debugstr_guid(&desc->guidObject)); 466 if (desc->dwValidData & DMUS_OBJ_DATE) TRACE(" - ftDate = FIXME\n"); 467 if (desc->dwValidData & DMUS_OBJ_VERSION) TRACE(" - vVersion = %s\n", debugstr_dmversion(&desc->vVersion)); 468 if (desc->dwValidData & DMUS_OBJ_NAME) TRACE(" - wszName = %s\n", debugstr_w(desc->wszName)); 469 if (desc->dwValidData & DMUS_OBJ_CATEGORY) TRACE(" - wszCategory = %s\n", debugstr_w(desc->wszCategory)); 470 if (desc->dwValidData & DMUS_OBJ_FILENAME) TRACE(" - wszFileName = %s\n", debugstr_w(desc->wszFileName)); 471 if (desc->dwValidData & DMUS_OBJ_MEMORY) TRACE(" - llMemLength = 0x%s\n - pbMemData = %p\n", 472 wine_dbgstr_longlong(desc->llMemLength), desc->pbMemData); 473 if (desc->dwValidData & DMUS_OBJ_STREAM) TRACE(" - pStream = %p\n", desc->pStream); 474 } 475 476 /* Dump DMUS_PORTPARAMS flags */ 477 static const char* debugstr_DMUS_PORTPARAMS_FLAGS(DWORD flagmask) 478 { 479 static const flag_info flags[] = { 480 FE(DMUS_PORTPARAMS_VOICES), 481 FE(DMUS_PORTPARAMS_CHANNELGROUPS), 482 FE(DMUS_PORTPARAMS_AUDIOCHANNELS), 483 FE(DMUS_PORTPARAMS_SAMPLERATE), 484 FE(DMUS_PORTPARAMS_EFFECTS), 485 FE(DMUS_PORTPARAMS_SHARE) 486 }; 487 return debugstr_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0])); 488 } 489 490 /* Dump whole DMUS_PORTPARAMS struct */ 491 void dump_DMUS_PORTPARAMS(LPDMUS_PORTPARAMS params) 492 { 493 TRACE("DMUS_PORTPARAMS (%p):\n", params); 494 TRACE(" - dwSize = %d\n", params->dwSize); 495 TRACE(" - dwValidParams = %s\n", debugstr_DMUS_PORTPARAMS_FLAGS(params->dwValidParams)); 496 if (params->dwValidParams & DMUS_PORTPARAMS_VOICES) TRACE(" - dwVoices = %u\n", params->dwVoices); 497 if (params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) TRACE(" - dwChannelGroup = %u\n", params->dwChannelGroups); 498 if (params->dwValidParams & DMUS_PORTPARAMS_AUDIOCHANNELS) TRACE(" - dwAudioChannels = %u\n", params->dwAudioChannels); 499 if (params->dwValidParams & DMUS_PORTPARAMS_SAMPLERATE) TRACE(" - dwSampleRate = %u\n", params->dwSampleRate); 500 if (params->dwValidParams & DMUS_PORTPARAMS_EFFECTS) TRACE(" - dwEffectFlags = %x\n", params->dwEffectFlags); 501 if (params->dwValidParams & DMUS_PORTPARAMS_SHARE) TRACE(" - fShare = %u\n", params->fShare); 502 } 503