music/win32.c
changeset 2174 41d7c884dc52
parent 2173 dabe358aec40
child 2175 c29911d0d400
equal deleted inserted replaced
2173:dabe358aec40 2174:41d7c884dc52
     1 #include "stdafx.h"
       
     2 #include "openttd.h"
       
     3 #include "music/win32.h"
       
     4 #include <windows.h>
       
     5 
       
     6 static struct {
       
     7 	bool stop_song;
       
     8 	bool terminate;
       
     9 	bool playing;
       
    10 	int new_vol;
       
    11 	HANDLE wait_obj;
       
    12 	char start_song[260];
       
    13 } _midi;
       
    14 
       
    15 static void Win32MidiPlaySong(const char *filename)
       
    16 {
       
    17 	strcpy(_midi.start_song, filename);
       
    18 	_midi.playing = true;
       
    19 	_midi.stop_song = false;
       
    20 	SetEvent(_midi.wait_obj);
       
    21 }
       
    22 
       
    23 static void Win32MidiStopSong(void)
       
    24 {
       
    25 	if (_midi.playing) {
       
    26 		_midi.stop_song = true;
       
    27 		_midi.start_song[0] = '\0';
       
    28 		SetEvent(_midi.wait_obj);
       
    29 	}
       
    30 }
       
    31 
       
    32 static bool Win32MidiIsSongPlaying(void)
       
    33 {
       
    34 	return _midi.playing;
       
    35 }
       
    36 
       
    37 static void Win32MidiSetVolume(byte vol)
       
    38 {
       
    39 	_midi.new_vol = vol;
       
    40 	SetEvent(_midi.wait_obj);
       
    41 }
       
    42 
       
    43 static long CDECL MidiSendCommand(const char *cmd, ...) {
       
    44 	va_list va;
       
    45 	char buf[512];
       
    46 
       
    47 	va_start(va, cmd);
       
    48 	vsprintf(buf, cmd, va);
       
    49 	va_end(va);
       
    50 	return mciSendStringA(buf, NULL, 0, 0);
       
    51 }
       
    52 
       
    53 static bool MidiIntPlaySong(const char *filename)
       
    54 {
       
    55 	MidiSendCommand("close all");
       
    56 	if (MidiSendCommand("open \"%s\" type sequencer alias song", filename) != 0)
       
    57 		return false;
       
    58 
       
    59 	if (MidiSendCommand("play song from 0") != 0)
       
    60 		return false;
       
    61 	return true;
       
    62 }
       
    63 
       
    64 static void MidiIntStopSong(void)
       
    65 {
       
    66 	MidiSendCommand("close all");
       
    67 }
       
    68 
       
    69 static void MidiIntSetVolume(int vol)
       
    70 {
       
    71 	uint v = (vol * 65535 / 127);
       
    72 	midiOutSetVolume((HMIDIOUT)-1, v + (v << 16));
       
    73 }
       
    74 
       
    75 static bool MidiIntIsSongPlaying(void)
       
    76 {
       
    77 	char buf[16];
       
    78 	mciSendStringA("status song mode", buf, sizeof(buf), 0);
       
    79 	return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0;
       
    80 }
       
    81 
       
    82 static DWORD WINAPI MidiThread(LPVOID arg)
       
    83 {
       
    84 	_midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL);
       
    85 
       
    86 	do {
       
    87 		char *s;
       
    88 		int vol;
       
    89 
       
    90 		vol = _midi.new_vol;
       
    91 		if (vol != -1) {
       
    92 			_midi.new_vol = -1;
       
    93 			MidiIntSetVolume(vol);
       
    94 		}
       
    95 
       
    96 		s = _midi.start_song;
       
    97 		if (s[0] != '\0') {
       
    98 			_midi.playing = MidiIntPlaySong(s);
       
    99 			s[0] = '\0';
       
   100 
       
   101 			// Delay somewhat in case we don't manage to play.
       
   102 			if (!_midi.playing) {
       
   103 				Sleep(5000);
       
   104 			}
       
   105 		}
       
   106 
       
   107 		if (_midi.stop_song && _midi.playing) {
       
   108 			_midi.stop_song = false;
       
   109 			_midi.playing = false;
       
   110 			MidiIntStopSong();
       
   111 		}
       
   112 
       
   113 		if (_midi.playing && !MidiIntIsSongPlaying())
       
   114 			_midi.playing = false;
       
   115 
       
   116 		WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000);
       
   117 	} while (!_midi.terminate);
       
   118 
       
   119 	DeleteObject(_midi.wait_obj);
       
   120 	return 0;
       
   121 }
       
   122 
       
   123 static const char *Win32MidiStart(const char * const *parm)
       
   124 {
       
   125 	DWORD threadId;
       
   126 
       
   127 	memset(&_midi, 0, sizeof(_midi));
       
   128 	_midi.new_vol = -1;
       
   129 	CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId);
       
   130 	return 0;
       
   131 }
       
   132 
       
   133 static void Win32MidiStop(void)
       
   134 {
       
   135 	_midi.terminate = true;
       
   136 	SetEvent(_midi.wait_obj);
       
   137 }
       
   138 
       
   139 const HalMusicDriver _win32_music_driver = {
       
   140 	Win32MidiStart,
       
   141 	Win32MidiStop,
       
   142 	Win32MidiPlaySong,
       
   143 	Win32MidiStopSong,
       
   144 	Win32MidiIsSongPlaying,
       
   145 	Win32MidiSetVolume,
       
   146 };