12 #ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
15 #include "../stdafx.h"
16 #ifdef WIN32_LEAN_AND_MEAN
17 #undef WIN32_LEAN_AND_MEAN // Don't exclude rarely-used stuff from Windows headers
20 #include "../os/windows/win32.h"
21 #include "../core/mem_func.hpp"
25 #undef FACILITY_DIRECTMUSIC // Needed for newer Windows SDK version.
31 #include "../safeguards.h"
36 static IDirectMusic *music = NULL;
39 static IDirectMusicPerformance *performance = NULL;
42 static IDirectMusicLoader *loader = NULL;
45 static IDirectMusicSegment *segment = NULL;
47 static bool seeking =
false;
51 static const char ole_files[] =
61 unsigned long (WINAPI * CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);
62 HRESULT (WINAPI * CoInitialize)(LPVOID pvReserved);
63 void (WINAPI * CoUninitialize)();
71 if (performance != NULL)
return NULL;
73 if (proc.CoCreateInstance == NULL) {
75 return "ole32.dll load failed";
80 if (FAILED(proc.CoInitialize(NULL))) {
81 return "COM initialization failed";
85 if (FAILED(proc.CoCreateInstance(
86 CLSID_DirectMusicPerformance,
89 IID_IDirectMusicPerformance,
92 return "Failed to create the performance object";
96 if (FAILED(performance->Init(&music, NULL, NULL))) {
97 return "Failed to initialize performance object";
102 #ifndef NO_DEBUG_MESSAGES
103 if (_debug_driver_level > 0) {
105 char desc[DMUS_MAX_DESCRIPTION];
109 caps.dwSize =
sizeof(DMUS_PORTCAPS);
111 DEBUG(driver, 1,
"Detected DirectMusic ports:");
112 for (
int i = 0; music->EnumPort(i, &caps) == S_OK; i++) {
113 if (caps.dwClass == DMUS_PC_OUTPUTCLASS) {
121 IDirectMusicPort *music_port = NULL;
127 caps.dwSize =
sizeof(DMUS_PORTCAPS);
128 if (FAILED(music->EnumPort(port, &caps)))
return "Supplied port parameter is not a valid port";
129 if (caps.dwClass != DMUS_PC_OUTPUTCLASS)
return "Supplied port parameter is not an output port";
132 DMUS_PORTPARAMS params;
134 params.dwSize =
sizeof(DMUS_PORTPARAMS);
135 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;
136 params.dwChannelGroups = 1;
138 if (FAILED(music->CreatePort(caps.guidPort, ¶ms, &music_port, NULL))) {
139 return "Failed to create port";
143 if (FAILED(music_port->Activate(TRUE))) {
144 music_port->Release();
145 return "Failed to activate port";
150 if (FAILED(performance->AddPort(music_port))) {
151 if (music_port != NULL) music_port->Release();
152 return "AddPort failed";
157 if (music_port != NULL) {
158 if (FAILED(performance->AssignPChannelBlock(0, music_port, 1))) {
159 music_port->Release();
160 return "Failed to assign PChannel block";
163 music_port->Release();
167 if (FAILED(proc.CoCreateInstance(
168 CLSID_DirectMusicLoader,
171 IID_IDirectMusicLoader,
174 return "Failed to create loader object";
181 MusicDriver_DMusic::~MusicDriver_DMusic()
191 if (performance != NULL) performance->Stop(NULL, NULL, 0, 0);
193 if (segment != NULL) {
194 segment->SetParam(GUID_Unload, 0xFFFFFFFF, 0, 0, performance);
204 if (performance != NULL) {
205 performance->CloseDown();
206 performance->Release();
210 if (loader != NULL) {
215 proc.CoUninitialize();
222 DMUS_OBJECTDESC obj_desc;
223 ZeroMemory(&obj_desc,
sizeof(obj_desc));
224 obj_desc.dwSize =
sizeof(obj_desc);
225 obj_desc.guidClass = CLSID_DirectMusicSegment;
226 obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
228 CP_ACP, MB_PRECOMPOSED,
230 obj_desc.wszFileName,
lengthof(obj_desc.wszFileName)
234 if (segment != NULL) {
240 if (FAILED(loader->GetObject(
241 &obj_desc, IID_IDirectMusicSegment, (LPVOID*)&segment
243 DEBUG(driver, 0,
"DirectMusic: GetObject failed");
248 if (FAILED(segment->SetParam(
249 GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, performance
251 DEBUG(driver, 0,
"DirectMusic: SetParam (MIDI file) failed");
256 if (FAILED(segment->SetParam(GUID_Download, 0xFFFFFFFF, 0, 0, performance))) {
257 DEBUG(driver, 0,
"DirectMusic: failed to download instruments");
262 if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) {
263 DEBUG(driver, 0,
"DirectMusic: PlaySegment failed");
273 if (FAILED(performance->Stop(segment, NULL, 0, 0))) {
274 DEBUG(driver, 0,
"DirectMusic: StopSegment failed");
284 if (performance->IsPlaying(segment, NULL) == S_OK) {
295 long db = vol * 2000 / 127 - 2000;
296 performance->SetGlobalParam(GUID_PerfMasterVolume, &db,
sizeof(db));