foxygit / doom Log in
commit 765ca3a04dafe63b8803443067293ee46f53b951
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sun Mar 23 00:55:13 2014 -0400
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sun Mar 23 00:55:13 2014 -0400

    music: Add config var for external music program.

    Mix_SetMusicCMD() allows a program to be specified to configure an
    external program to be invoked for music playback. Add a config
    variable (snd_musiccmd) to allow this to be set from a configuration
    file. Thanks to Holering for his comments on Doomworld about how to do
    this.
---
 src/i_sdlmusic.c  | 30 +++++++++++++++++++++++-------
 src/i_sound.c     |  5 +++++
 src/i_sound.h     |  1 +
 src/m_config.c    |  8 ++++++++
 src/setup/sound.c |  2 ++
 5 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/i_sdlmusic.c b/src/i_sdlmusic.c
index 79755890..fd5aa006 100644
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -222,6 +222,14 @@ static boolean I_SDL_InitMusic(void)

     RemoveTimidityConfig();

+    // If snd_musiccmd is set, we need to call Mix_SetMusicCMD to
+    // configure an external music playback program.
+
+    if (strlen(snd_musiccmd) > 0)
+    {
+        Mix_SetMusicCMD(snd_musiccmd);
+    }
+
     return music_initialized;
 }

@@ -378,27 +386,29 @@ static void *I_SDL_RegisterSong(void *data, int len)
     {
         return NULL;
     }
-
+
     // MUS files begin with "MUS"
     // Reject anything which doesnt have this signature
-
+
     filename = M_TempFile("doom.mid");

     if (IsMid(data, len) && len < MAXMIDLENGTH)
     {
         M_WriteFile(filename, data, len);
     }
-    else
+    else
     {
 	// Assume a MUS file and try to convert

         ConvertMus(data, len, filename);
     }

-    // Load the MIDI
+    // Load the MIDI. In an ideal world we'd be using Mix_LoadMUS_RW()
+    // by now, but Mix_SetMusicCMD() only works with Mix_LoadMUS(), so
+    // we have to generate a temporary file.

     music = Mix_LoadMUS(filename);
-
+
     if (music == NULL)
     {
         // Failed to load
@@ -406,9 +416,15 @@ static void *I_SDL_RegisterSong(void *data, int len)
         fprintf(stderr, "Error loading midi: %s\n", Mix_GetError());
     }

-    // remove file now
+    // Remove the temporary MIDI file; however, when using an external
+    // MIDI program we can't delete the file. Otherwise, the program
+    // won't find the file to play. This means we leave a mess on
+    // disk :(

-    remove(filename);
+    if (strlen(snd_musiccmd) == 0)
+    {
+        remove(filename);
+    }

     Z_Free(filename);

diff --git a/src/i_sound.c b/src/i_sound.c
index 7aa3a31b..d71dacd7 100644
--- a/src/i_sound.c
+++ b/src/i_sound.c
@@ -52,6 +52,10 @@ int snd_cachesize = 64 * 1024 * 1024;

 int snd_maxslicetime_ms = 28;

+// External command to invoke to play back music.
+
+char *snd_musiccmd = "";
+
 // Low-level sound and music modules we are using

 static sound_module_t *sound_module;
@@ -440,6 +444,7 @@ void I_BindSoundVariables(void)
     M_BindVariable("snd_sbdma",         &snd_sbdma);
     M_BindVariable("snd_mport",         &snd_mport);
     M_BindVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms);
+    M_BindVariable("snd_musiccmd",      &snd_musiccmd);
     M_BindVariable("snd_samplerate",    &snd_samplerate);
     M_BindVariable("snd_cachesize",     &snd_cachesize);
     M_BindVariable("opl_io_port",       &opl_io_port);
diff --git a/src/i_sound.h b/src/i_sound.h
index db00ab5c..8990e9c1 100644
--- a/src/i_sound.h
+++ b/src/i_sound.h
@@ -234,6 +234,7 @@ extern int snd_musicdevice;
 extern int snd_samplerate;
 extern int snd_cachesize;
 extern int snd_maxslicetime_ms;
+extern char *snd_musiccmd;

 void I_BindSoundVariables(void);

diff --git a/src/m_config.c b/src/m_config.c
index edc0a174..89d24eaf 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -806,6 +806,14 @@ static default_t extra_defaults_list[] =

     CONFIG_VARIABLE_INT(snd_maxslicetime_ms),

+    //!
+    // External command to invoke to perform MIDI playback. If set to
+    // the empty string, SDL_mixer's internal MIDI playback is used.
+    // This only has any effect when snd_musicdevice is set to General
+    // MIDI output.
+
+    CONFIG_VARIABLE_STRING(snd_musiccmd),
+
     //!
     // The I/O port to use to access the OPL chip.  Only relevant when
     // using native OPL music playback.
diff --git a/src/setup/sound.c b/src/setup/sound.c
index 9c635335..ab78cdf5 100644
--- a/src/setup/sound.c
+++ b/src/setup/sound.c
@@ -74,6 +74,7 @@ int snd_musicdevice = SNDDEVICE_SB;
 int snd_samplerate = 44100;
 int opl_io_port = 0x388;
 int snd_cachesize = 64 * 1024 * 1024;
+char *snd_musiccmd = "";

 static int numChannels = 8;
 static int sfxVolume = 15;
@@ -317,6 +318,7 @@ void BindSoundVariables(void)
     M_BindVariable("snd_sbirq",           &snd_sbirq);
     M_BindVariable("snd_sbdma",           &snd_sbdma);
     M_BindVariable("snd_mport",           &snd_mport);
+    M_BindVariable("snd_musiccmd",        &snd_musiccmd);

     M_BindVariable("snd_cachesize",       &snd_cachesize);
     M_BindVariable("opl_io_port",         &opl_io_port);