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