summaryrefslogtreecommitdiff
path: root/music/win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'music/win32.c')
-rw-r--r--music/win32.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/music/win32.c b/music/win32.c
new file mode 100644
index 000000000..eb4d42d25
--- /dev/null
+++ b/music/win32.c
@@ -0,0 +1,146 @@
+#include "stdafx.h"
+#include "openttd.h"
+#include "music/win32.h"
+#include <windows.h>
+
+static struct {
+ bool stop_song;
+ bool terminate;
+ bool playing;
+ int new_vol;
+ HANDLE wait_obj;
+ char start_song[260];
+} _midi;
+
+static void Win32MidiPlaySong(const char *filename)
+{
+ strcpy(_midi.start_song, filename);
+ _midi.playing = true;
+ _midi.stop_song = false;
+ SetEvent(_midi.wait_obj);
+}
+
+static void Win32MidiStopSong(void)
+{
+ if (_midi.playing) {
+ _midi.stop_song = true;
+ _midi.start_song[0] = '\0';
+ SetEvent(_midi.wait_obj);
+ }
+}
+
+static bool Win32MidiIsSongPlaying(void)
+{
+ return _midi.playing;
+}
+
+static void Win32MidiSetVolume(byte vol)
+{
+ _midi.new_vol = vol;
+ SetEvent(_midi.wait_obj);
+}
+
+static long CDECL MidiSendCommand(const char *cmd, ...) {
+ va_list va;
+ char buf[512];
+
+ va_start(va, cmd);
+ vsprintf(buf, cmd, va);
+ va_end(va);
+ return mciSendStringA(buf, NULL, 0, 0);
+}
+
+static bool MidiIntPlaySong(const char *filename)
+{
+ MidiSendCommand("close all");
+ if (MidiSendCommand("open \"%s\" type sequencer alias song", filename) != 0)
+ return false;
+
+ if (MidiSendCommand("play song from 0") != 0)
+ return false;
+ return true;
+}
+
+static void MidiIntStopSong(void)
+{
+ MidiSendCommand("close all");
+}
+
+static void MidiIntSetVolume(int vol)
+{
+ uint v = (vol * 65535 / 127);
+ midiOutSetVolume((HMIDIOUT)-1, v + (v << 16));
+}
+
+static bool MidiIntIsSongPlaying(void)
+{
+ char buf[16];
+ mciSendStringA("status song mode", buf, sizeof(buf), 0);
+ return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0;
+}
+
+static DWORD WINAPI MidiThread(LPVOID arg)
+{
+ _midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ do {
+ char *s;
+ int vol;
+
+ vol = _midi.new_vol;
+ if (vol != -1) {
+ _midi.new_vol = -1;
+ MidiIntSetVolume(vol);
+ }
+
+ s = _midi.start_song;
+ if (s[0] != '\0') {
+ _midi.playing = MidiIntPlaySong(s);
+ s[0] = '\0';
+
+ // Delay somewhat in case we don't manage to play.
+ if (!_midi.playing) {
+ Sleep(5000);
+ }
+ }
+
+ if (_midi.stop_song && _midi.playing) {
+ _midi.stop_song = false;
+ _midi.playing = false;
+ MidiIntStopSong();
+ }
+
+ if (_midi.playing && !MidiIntIsSongPlaying())
+ _midi.playing = false;
+
+ WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000);
+ } while (!_midi.terminate);
+
+ DeleteObject(_midi.wait_obj);
+ return 0;
+}
+
+static const char *Win32MidiStart(const char * const *parm)
+{
+ DWORD threadId;
+
+ memset(&_midi, 0, sizeof(_midi));
+ _midi.new_vol = -1;
+ CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId);
+ return 0;
+}
+
+static void Win32MidiStop(void)
+{
+ _midi.terminate = true;
+ SetEvent(_midi.wait_obj);
+}
+
+const HalMusicDriver _win32_music_driver = {
+ Win32MidiStart,
+ Win32MidiStop,
+ Win32MidiPlaySong,
+ Win32MidiStopSong,
+ Win32MidiIsSongPlaying,
+ Win32MidiSetVolume,
+};