extmidi.c
changeset 1608 074dff2e4890
parent 1584 aa7fe51c4368
child 1892 45894b95a925
--- a/extmidi.c	Wed Mar 30 12:30:24 2005 +0000
+++ b/extmidi.c	Wed Mar 30 19:52:26 2005 +0000
@@ -5,6 +5,8 @@
 #include "ttd.h"
 #include "hal.h"
 #include "sound.h"
+#include "string.h"
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -12,89 +14,97 @@
 #include <sys/stat.h>
 #include <errno.h>
 
-static pid_t _pid;
+static struct {
+	char song[MAX_PATH];
+	int pid;
+} _midi;
 
-static void extmidi_kill(void)
+static void DoPlay(void);
+static void DoStop(void);
+
+static const char* ExtMidiStart(const char* const * parm)
 {
-	if (_pid > 0) {
-		kill(_pid, SIGKILL);
-		while (waitpid(_pid, NULL, WNOHANG) != _pid);
-	}
-	_pid = 0;
-}
-
-static const char *extmidi_start(const char * const *parm)
-{
-	_pid = 0;
+	_midi.song[0] = '\0';
+	_midi.pid = -1;
 	return NULL;
 }
 
-static void extmidi_stop(void)
+static void ExtMidiStop(void)
 {
-	extmidi_kill();
+	_midi.song[0] = '\0';
+	DoStop();
 }
 
-static void extmidi_play_song(const char *filename)
+static void ExtMidiPlaySong(const char* filename)
 {
-	extmidi_kill();
-
-	_pid = fork();
-	if (_pid < 0) {
-		fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno));
-		_pid = 0;
-		return;
-	}
-
-	if (_pid == 0) {
-		#if defined(MIDI_ARG)
-			execlp(msf.extmidi, "extmidi", MIDI_ARG, filename, NULL);
-		#else
-			execlp(msf.extmidi, "extmidi", filename, NULL);
-		#endif
-		fprintf(stderr, "extmidi: couldn't execl: %s\n", strerror(errno));
-		exit(0);
-	}
-
-	usleep(500);
-
-	if (_pid == waitpid(_pid, NULL, WNOHANG)) {
-		fprintf(stderr, "extmidi: play song failed\n");
-		_pid = 0;
-
-		usleep(5000);
-	}
+	ttd_strlcpy(_midi.song, filename, lengthof(_midi.song));
+	DoStop();
 }
 
-static void extmidi_stop_song(void)
+static void ExtMidiStopSong(void)
 {
-	extmidi_kill();
+	_midi.song[0] = '\0';
+	DoStop();
 }
 
-static bool extmidi_is_playing(void)
+static bool ExtMidiIsPlaying(void)
 {
-	if (_pid == 0)
-		return 0;
-
-	if (waitpid(_pid, NULL, WNOHANG) == _pid) {
-		_pid = 0;
-		return 0;
-	}
-
-	return 1;
+	if (_midi.pid != -1 && waitpid(_midi.pid, NULL, WNOHANG) == _midi.pid)
+		_midi.pid = -1;
+	if (_midi.pid == -1 && _midi.song[0] != '\0') DoPlay();
+	return _midi.pid != -1;
 }
 
-static void extmidi_set_volume(byte vol)
+static void ExtMidiSetVolume(byte vol)
 {
 	fprintf(stderr, "extmidi: set volume not implemented\n");
 }
 
+static void DoPlay(void)
+{
+	_midi.pid = fork();
+	switch (_midi.pid) {
+		case 0: {
+			int d;
+
+			close(0);
+			close(1);
+			close(2);
+			d = open("/dev/null", O_RDONLY);
+			if (d != -1) {
+				if (dup2(d, 1) != -1 && dup2(d, 2) != -1) {
+					#if defined(MIDI_ARG)
+						execlp(msf.extmidi, "extmidi", MIDI_ARG, _midi.song, NULL);
+					#else
+						execlp(msf.extmidi, "extmidi", _midi.song, NULL);
+					#endif
+				}
+			}
+			exit(1);
+		}
+
+		case -1:
+			fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno));
+			/* FALLTHROUGH */
+
+		default:
+			_midi.song[0] = '\0';
+			break;
+	}
+}
+
+static void DoStop(void)
+{
+	if (_midi.pid != -1) kill(_midi.pid, SIGTERM);
+}
+
 const HalMusicDriver _extmidi_music_driver = {
-	extmidi_start,
-	extmidi_stop,
-	extmidi_play_song,
-	extmidi_stop_song,
-	extmidi_is_playing,
-	extmidi_set_volume,
+	ExtMidiStart,
+	ExtMidiStop,
+	ExtMidiPlaySong,
+	ExtMidiStopSong,
+	ExtMidiIsPlaying,
+	ExtMidiSetVolume,
 };
 
 #endif /* __MORPHOS__ */