summaryrefslogtreecommitdiff
path: root/src/music/dmusic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/music/dmusic.cpp')
-rw-r--r--src/music/dmusic.cpp76
1 files changed, 73 insertions, 3 deletions
diff --git a/src/music/dmusic.cpp b/src/music/dmusic.cpp
index 152bbb249..185d66a76 100644
--- a/src/music/dmusic.cpp
+++ b/src/music/dmusic.cpp
@@ -18,6 +18,7 @@
#endif
#include "../debug.h"
#include "../os/windows/win32.h"
+#include "../core/mem_func.hpp"
#include "dmusic.h"
#include <windows.h>
@@ -28,6 +29,9 @@
static FMusicDriver_DMusic iFMusicDriver_DMusic;
+/** the direct music object manages buffers and ports */
+static IDirectMusic *music = NULL;
+
/** the performance object controls manipulation of the segments */
static IDirectMusicPerformance *performance = NULL;
@@ -86,15 +90,76 @@ const char *MusicDriver_DMusic::Start(const char * const *parm)
}
/* initialize it */
- if (FAILED(performance->Init(NULL, NULL, NULL))) {
+ if (FAILED(performance->Init(&music, NULL, NULL))) {
return "Failed to initialize performance object";
}
- /* choose default Windows synth */
- if (FAILED(performance->AddPort(NULL))) {
+ int port = GetDriverParamInt(parm, "port", -1);
+
+#ifndef NO_DEBUG_MESSAGES
+ if (_debug_driver_level > 0) {
+ /* Print all valid output ports. */
+ char desc[DMUS_MAX_DESCRIPTION];
+
+ DMUS_PORTCAPS caps;
+ MemSetT(&caps, 0);
+ caps.dwSize = sizeof(DMUS_PORTCAPS);
+
+ DEBUG(driver, 1, "Detected DirectMusic ports:");
+ for (int i = 0; music->EnumPort(i, &caps) == S_OK; i++) {
+ if (caps.dwClass == DMUS_PC_OUTPUTCLASS) {
+ /* Description is UNICODE even for ANSI build. */
+ DEBUG(driver, 1, " %d: %s%s", i, convert_from_fs(caps.wszDescription, desc, lengthof(desc)), i == port ? " (selected)" : "");
+ }
+ }
+ }
+#endif
+
+ IDirectMusicPort *music_port = NULL; // NULL means 'use default port'.
+
+ if (port >= 0) {
+ /* Check if the passed port is a valid port. */
+ DMUS_PORTCAPS caps;
+ MemSetT(&caps, 0);
+ caps.dwSize = sizeof(DMUS_PORTCAPS);
+ if (FAILED(music->EnumPort(port, &caps))) return "Supplied port parameter is not a valid port";
+ if (caps.dwClass != DMUS_PC_OUTPUTCLASS) return "Supplied port parameter is not an output port";
+
+ /* Create new port. */
+ DMUS_PORTPARAMS params;
+ MemSetT(&params, 0);
+ params.dwSize = sizeof(DMUS_PORTPARAMS);
+ params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;
+ params.dwChannelGroups = 1;
+
+ if (FAILED(music->CreatePort(caps.guidPort, &params, &music_port, NULL))) {
+ return "Failed to create port";
+ }
+
+ /* Activate port. */
+ if (FAILED(music_port->Activate(TRUE))) {
+ music_port->Release();
+ return "Failed to activate port";
+ }
+ }
+
+ /* Add port to performance. */
+ if (FAILED(performance->AddPort(music_port))) {
+ if (music_port != NULL) music_port->Release();
return "AddPort failed";
}
+ /* Assign a performance channel block to the performance if we added
+ * a custom port to the performance. */
+ if (music_port != NULL) {
+ if (FAILED(performance->AssignPChannelBlock(0, music_port, 1))) {
+ music_port->Release();
+ return "Failed to assign PChannel block";
+ }
+ /* We don't need the port anymore. */
+ music_port->Release();
+ }
+
/* create the loader object; this will be used to load the MIDI file */
if (FAILED(proc.CoCreateInstance(
CLSID_DirectMusicLoader,
@@ -128,6 +193,11 @@ void MusicDriver_DMusic::Stop()
segment = NULL;
}
+ if (music != NULL) {
+ music->Release();
+ music = NULL;
+ }
+
if (performance != NULL) {
performance->CloseDown();
performance->Release();