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