diff --git a/music/win32_m.c b/music/win32_m.c new file mode 100644 --- /dev/null +++ b/music/win32_m.c @@ -0,0 +1,146 @@ +#include "stdafx.h" +#include "openttd.h" +#include "music/win32_m.h" +#include + +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, +};