ref: 7791ace57ee6c238f5f6704eba0970a63e19e424
parent: 6f366890c4dec2ffbd0842735a6fcb631feb857d
author: Alex Mayfield <alexmax2742@gmail.com>
date: Sat Feb 18 17:47:22 EST 2017
Add server shutdown and music overrides - The process will now cut the music and shut down when Chocolate Doom does. - The process will now peacefully coexist with music overrides, such as digital music packs.
--- a/midiproc/main.c
+++ b/midiproc/main.c
@@ -41,11 +41,40 @@
static HANDLE midi_process_out; // Standard Out.
static buffer_t *midi_buffer; // Data from client.
-// Currently playing music track
-static Mix_Music *music = NULL;
+// Currently playing music track.
+static Mix_Music *music = NULL;
//=============================================================================
//
+// Private functions
+//
+
+//
+// Unregisters the currently playing song. This is never called from the
+// protocol, we simply do this before playing a new song.
+//
+static void UnregisterSong()
+{
+ if (music == NULL)
+ {
+ return;
+ }
+
+ Mix_FreeMusic(music);
+}
+
+//
+// Bookkeeping stuff we need to do when we're shutting off the subprocess.
+//
+static void ShutdownSDL(void)
+{
+ UnregisterSong();
+ Mix_CloseAudio();
+ SDL_Quit();
+}
+
+//=============================================================================
+//
// SDL_mixer Interface
//
@@ -53,6 +82,7 @@
{
fprintf(stderr, "%s %s\n", __FUNCTION__, filename);
+ UnregisterSong();
music = Mix_LoadMUS(filename);
fprintf(stderr, "<-- %p\n", music);
@@ -76,8 +106,19 @@
static void PlaySong(int loops)
{
fprintf(stderr, "%s %d\n", __FUNCTION__, loops);
+ fprintf(stderr, "%s %d\n", "Playing at volume", Mix_VolumeMusic(-1));
Mix_PlayMusic(music, loops);
+
+ // [AM] BUG: In my testing, setting the volume of a MIDI track while there
+ // is no song playing appears to be a no-op. This can happen when
+ // you're mixing midiproc with vanilla SDL_Mixer, such as when you
+ // are alternating between a digital music pack (in the parent
+ // process) and MIDI (in this process).
+ //
+ // To work around this bug, we set the volume to itself after the MIDI
+ // has started playing.
+ Mix_VolumeMusic(Mix_VolumeMusic(-1));
}
static void StopSong()
@@ -87,16 +128,6 @@
Mix_HaltMusic();
}
-//
-// ShutdownSDL
-//
-static void ShutdownSDL()
-{
- UnregisterSong();
- Mix_CloseAudio();
- SDL_Quit();
-}
-
//=============================================================================
//
// Pipe Server Interface
@@ -151,7 +182,7 @@
return true;
}
-boolean MidiPipe_StopSong(buffer_reader_t *reader)
+boolean MidiPipe_StopSong()
{
StopSong();
@@ -158,6 +189,11 @@
return true;
}
+boolean MidiPipe_Shutdown()
+{
+ exit(EXIT_SUCCESS);
+}
+
//=============================================================================
//
// Server Implementation
@@ -177,7 +213,9 @@
case NET_MIDIPIPE_PACKET_TYPE_PLAY_SONG:
return MidiPipe_PlaySong(reader);
case NET_MIDIPIPE_PACKET_TYPE_STOP_SONG:
- return MidiPipe_StopSong(reader);
+ return MidiPipe_StopSong();
+ case NET_MIDIPIPE_PACKET_TYPE_SHUTDOWN:
+ return MidiPipe_Shutdown(reader);
default:
return false;
}
@@ -287,6 +325,8 @@
{
return false;
}
+
+ atexit(ShutdownSDL);
return true;
}
--- a/src/i_midipipe.c
+++ b/src/i_midipipe.c
@@ -47,7 +47,6 @@
static HANDLE midi_process_out_writer;
static boolean server_init = false; // if true, server was started
-static boolean client_init = false; // if true, client was bound
//=============================================================================
//
@@ -144,7 +143,7 @@
// Tells the MIDI subprocess to load a specific filename for playing. This
// function blocks until there is an acknowledgement from the server.
//
-Mix_Music *I_MidiPipe_RegisterSong(const char *filename)
+boolean I_MidiPipe_RegisterSong(const char *filename)
{
boolean ok;
net_packet_t *packet;
@@ -248,6 +247,32 @@
}
DEBUGOUT("I_MidiPipe_StopSong succeeded");
+}
+
+//
+// I_MidiPipe_StopSong
+//
+// Tells the MIDI subprocess to shutdown.
+//
+void I_MidiPipe_ShutdownServer()
+{
+ boolean ok;
+ net_packet_t *packet;
+
+ packet = NET_NewPacket(2);
+ NET_WriteInt16(packet, NET_MIDIPIPE_PACKET_TYPE_SHUTDOWN);
+ ok = WritePipe(packet);
+ NET_FreePacket(packet);
+
+ server_init = false;
+
+ if (!ok)
+ {
+ DEBUGOUT("I_MidiPipe_ShutdownServer failed");
+ return;
+ }
+
+ DEBUGOUT("I_MidiPipe_ShutdownServer succeeded");
}
//=============================================================================
--- a/src/i_midipipe.h
+++ b/src/i_midipipe.h
@@ -25,10 +25,11 @@
#include "doomtype.h"
-Mix_Music *I_MidiPipe_RegisterSong(const char *filename);
+boolean I_MidiPipe_RegisterSong(const char *filename);
void I_MidiPipe_SetVolume(int vol);
void I_MidiPipe_PlaySong(int loops);
void I_MidiPipe_StopSong();
+void I_MidiPipe_ShutdownServer();
boolean I_MidiPipe_InitServer();
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -133,6 +133,9 @@
// If true, the currently playing track is being played on loop.
static boolean current_track_loop;
+// If true, the current track is being handled via midiproc.
+static boolean using_midiproc;
+
// Given a time string (for LOOP_START/LOOP_END), parse it and return
// the time (in # samples since start of track) it represents.
static unsigned int ParseVorbisTime(unsigned int samplerate_hz, char *value)
@@ -878,6 +881,9 @@
{
if (music_initialized)
{
+#if defined(_WIN32)
+ I_MidiPipe_ShutdownServer();
+#endif
Mix_HaltMusic();
music_initialized = false;
@@ -974,7 +980,8 @@
LoadSubstituteConfigs();
}
-#if WIN32
+#if defined(_WIN32)
+ // [AM] Start up midiproc to handle playing MIDI music.
I_MidiPipe_InitServer();
#endif
@@ -999,11 +1006,10 @@
vol = (current_music_volume * MIX_MAX_VOLUME) / 127;
}
-#if WIN32
+#if defined(_WIN32)
I_MidiPipe_SetVolume(vol);
-#else
- Mix_VolumeMusic(vol);
#endif
+ Mix_VolumeMusic(vol);
}
// Set music volume (0 - 127)
@@ -1027,7 +1033,7 @@
return;
}
- if (handle == NULL)
+ if (handle == NULL && !using_midiproc)
{
return;
}
@@ -1055,7 +1061,14 @@
}
#if defined(_WIN32)
- I_MidiPipe_PlaySong(loops);
+ if (using_midiproc)
+ {
+ I_MidiPipe_PlaySong(loops);
+ }
+ else
+ {
+ Mix_PlayMusic(current_track_music, loops);
+ }
#else
Mix_PlayMusic(current_track_music, loops);
#endif
@@ -1093,7 +1106,15 @@
}
#if defined(_WIN32)
- I_MidiPipe_StopSong();
+ if (using_midiproc)
+ {
+ I_MidiPipe_StopSong();
+ using_midiproc = false;
+ }
+ else
+ {
+ Mix_HaltMusic();
+ }
#else
Mix_HaltMusic();
#endif
@@ -1116,9 +1137,7 @@
return;
}
-#if !defined(_WIN32)
Mix_FreeMusic(music);
-#endif
}
// Determine whether memory block is a .mid file
@@ -1182,6 +1201,9 @@
}
else
{
+ // [AM] Substitute music never uses midiproc.
+ using_midiproc = false;
+
// Read loop point metadata from the file so that we know where
// to loop the music.
playing_substitute = true;
@@ -1211,17 +1233,39 @@
// we have to generate a temporary file.
#if defined(_WIN32)
- music = I_MidiPipe_RegisterSong(filename);
+ // [AM] If we do not have an external music command defined, play
+ // music with midiproc.exe.
+ if (strlen(snd_musiccmd) == 0)
+ {
+ music = NULL;
+ if (I_MidiPipe_RegisterSong(filename))
+ {
+ using_midiproc = true;
+ }
+ else
+ {
+ fprintf(stderr, "Error loading midi: %s\n",
+ "Could not communicate with midiproc.");
+ }
+ }
+ else
+ {
+ using_midiproc = false;
+ music = Mix_LoadMUS(filename);
+ if (music == NULL)
+ {
+ // Failed to load
+ fprintf(stderr, "Error loading midi: %s\n", Mix_GetError());
+ }
+ }
#else
music = Mix_LoadMUS(filename);
-#endif
-
if (music == NULL)
{
// Failed to load
-
fprintf(stderr, "Error loading midi: %s\n", Mix_GetError());
}
+#endif
// Remove the temporary MIDI file; however, when using an external
// MIDI program we can't delete the file. Otherwise, the program
--- a/src/net_defs.h
+++ b/src/net_defs.h
@@ -148,6 +148,7 @@
NET_MIDIPIPE_PACKET_TYPE_SET_VOLUME,
NET_MIDIPIPE_PACKET_TYPE_PLAY_SONG,
NET_MIDIPIPE_PACKET_TYPE_STOP_SONG,
+ NET_MIDIPIPE_PACKET_TYPE_SHUTDOWN
} net_midipipe_packet_type_t;
// Settings specified when the client connects to the server.