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