00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
00013
00014 #define INITGUID
00015 #include "../stdafx.h"
00016 #ifdef WIN32_LEAN_AND_MEAN
00017 #undef WIN32_LEAN_AND_MEAN // Don't exclude rarely-used stuff from Windows headers
00018 #endif
00019 #include "../debug.h"
00020 #include "../os/windows/win32.h"
00021 #include "dmusic.h"
00022
00023 #include <windows.h>
00024 #include <dmksctrl.h>
00025 #include <dmusici.h>
00026 #include <dmusicc.h>
00027 #include <dmusicf.h>
00028
00029 static FMusicDriver_DMusic iFMusicDriver_DMusic;
00030
00032 static IDirectMusicPerformance *performance = NULL;
00033
00035 static IDirectMusicLoader *loader = NULL;
00036
00038 static IDirectMusicSegment *segment = NULL;
00039
00040 static bool seeking = false;
00041
00042
00043 #define M(x) x "\0"
00044 static const char ole_files[] =
00045 M("ole32.dll")
00046 M("CoCreateInstance")
00047 M("CoInitialize")
00048 M("CoUninitialize")
00049 M("")
00050 ;
00051 #undef M
00052
00053 struct ProcPtrs {
00054 unsigned long (WINAPI * CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);
00055 HRESULT (WINAPI * CoInitialize)(LPVOID pvReserved);
00056 void (WINAPI * CoUninitialize)();
00057 };
00058
00059 static ProcPtrs proc;
00060
00061
00062 const char *MusicDriver_DMusic::Start(const char * const *parm)
00063 {
00064 if (performance != NULL) return NULL;
00065
00066 if (proc.CoCreateInstance == NULL) {
00067 if (!LoadLibraryList((Function*)&proc, ole_files)) {
00068 return "ole32.dll load failed";
00069 }
00070 }
00071
00072
00073 if (FAILED(proc.CoInitialize(NULL))) {
00074 return "COM initialization failed";
00075 }
00076
00077
00078 if (FAILED(proc.CoCreateInstance(
00079 CLSID_DirectMusicPerformance,
00080 NULL,
00081 CLSCTX_INPROC,
00082 IID_IDirectMusicPerformance,
00083 (LPVOID*)&performance
00084 ))) {
00085 proc.CoUninitialize();
00086 return "Failed to create the performance object";
00087 }
00088
00089
00090 if (FAILED(performance->Init(NULL, NULL, NULL))) {
00091 performance->Release();
00092 performance = NULL;
00093 proc.CoUninitialize();
00094 return "Failed to initialize performance object";
00095 }
00096
00097
00098 if (FAILED(performance->AddPort(NULL))) {
00099 performance->CloseDown();
00100 performance->Release();
00101 performance = NULL;
00102 proc.CoUninitialize();
00103 return "AddPort failed";
00104 }
00105
00106
00107 if (FAILED(proc.CoCreateInstance(
00108 CLSID_DirectMusicLoader,
00109 NULL,
00110 CLSCTX_INPROC,
00111 IID_IDirectMusicLoader,
00112 (LPVOID*)&loader
00113 ))) {
00114 performance->CloseDown();
00115 performance->Release();
00116 performance = NULL;
00117 proc.CoUninitialize();
00118 return "Failed to create loader object";
00119 }
00120
00121 return NULL;
00122 }
00123
00124
00125 void MusicDriver_DMusic::Stop()
00126 {
00127 seeking = false;
00128
00129 if (performance != NULL) performance->Stop(NULL, NULL, 0, 0);
00130
00131 if (segment != NULL) {
00132 segment->SetParam(GUID_Unload, 0xFFFFFFFF, 0, 0, performance);
00133 segment->Release();
00134 segment = NULL;
00135 }
00136
00137 if (performance != NULL) {
00138 performance->CloseDown();
00139 performance->Release();
00140 performance = NULL;
00141 }
00142
00143 if (loader != NULL) {
00144 loader->Release();
00145 loader = NULL;
00146 }
00147
00148 proc.CoUninitialize();
00149 }
00150
00151
00152 void MusicDriver_DMusic::PlaySong(const char *filename)
00153 {
00154
00155 DMUS_OBJECTDESC obj_desc;
00156 ZeroMemory(&obj_desc, sizeof(obj_desc));
00157 obj_desc.dwSize = sizeof(obj_desc);
00158 obj_desc.guidClass = CLSID_DirectMusicSegment;
00159 obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
00160 MultiByteToWideChar(
00161 CP_ACP, MB_PRECOMPOSED,
00162 filename, -1,
00163 obj_desc.wszFileName, lengthof(obj_desc.wszFileName)
00164 );
00165
00166
00167 if (segment != NULL) {
00168 segment->Release();
00169 segment = NULL;
00170 }
00171
00172
00173 if (FAILED(loader->GetObject(
00174 &obj_desc, IID_IDirectMusicSegment, (LPVOID*)&segment
00175 ))) {
00176 DEBUG(driver, 0, "DirectMusic: GetObject failed");
00177 return;
00178 }
00179
00180
00181 if (FAILED(segment->SetParam(
00182 GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, performance
00183 ))) {
00184 DEBUG(driver, 0, "DirectMusic: SetParam (MIDI file) failed");
00185 return;
00186 }
00187
00188
00189 if (FAILED(segment->SetParam(GUID_Download, 0xFFFFFFFF, 0, 0, performance))) {
00190 DEBUG(driver, 0, "DirectMusic: failed to download instruments");
00191 return;
00192 }
00193
00194
00195 if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) {
00196 DEBUG(driver, 0, "DirectMusic: PlaySegment failed");
00197 return;
00198 }
00199
00200 seeking = true;
00201 }
00202
00203
00204 void MusicDriver_DMusic::StopSong()
00205 {
00206 if (FAILED(performance->Stop(segment, NULL, 0, 0))) {
00207 DEBUG(driver, 0, "DirectMusic: StopSegment failed");
00208 }
00209 seeking = false;
00210 }
00211
00212
00213 bool MusicDriver_DMusic::IsSongPlaying()
00214 {
00215
00216
00217 if (performance->IsPlaying(segment, NULL) == S_OK) {
00218 seeking = false;
00219 return true;
00220 } else {
00221 return seeking;
00222 }
00223 }
00224
00225
00226 void MusicDriver_DMusic::SetVolume(byte vol)
00227 {
00228 long db = vol * 2000 / 127 - 2000;
00229 performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db));
00230 }
00231
00232
00233 #endif