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