File diff r2173:6185ef9f111b → r2174:494188320cb1
music/win32_m.c
Show inline comments
 
new file 100644
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "music/win32_m.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,
 
};