/* $Id: extmidi.c 4692 2006-05-02 19:09:49Z peter1138 $ */
#ifndef __MORPHOS__
#include "../stdafx.h"
#include "../openttd.h"
#include "../sound.h"
#include "../string.h"
#include "../variables.h"
#include "../debug.h"
#include "extmidi.h"
#include "../wince/ppcttd_vs2005/Timidity/config.h"
#include "../wince/ppcttd_vs2005/Timidity/common.h"
#include "../wince/ppcttd_vs2005/Timidity/instrum.h"
#include "../wince/ppcttd_vs2005/Timidity/output.h"
#include "../wince/ppcttd_vs2005/Timidity/playmidi.h"
#include "../wince/ppcttd_vs2005/Timidity/tables.h"
extern void ShowOSErrorBox(const char *buf);

char song[MAX_PATH];
DWORD threadId;

int free_instruments_afterwards = 1;
static char def_instr_name[256] = "Patch\\acpiano.pat";
extern struct MidiEvent *current_event;

struct MIDICONTROL {
	bool stop_song;
	bool terminate;
	bool playing;
	int new_vol;
	//HANDLE wait_obj;
	char start_song[260];
};

struct MIDICONTROL _midi;

CRITICAL_SECTION critSect;

#define MAXWORDS 10

static int read_config_file (char* name)
{
	char* error="Error!";
	FILE *fp;
	char tmp[1024], *w[MAXWORDS], *cp;
	ToneBank *bank = 0;
	int i, j, k, line = 0, words;
	static int rcf_count = 0;
	char str[MAX_PATH];

	if (rcf_count > 50) {
		return (-1);
    }
	
	sprintf(str, "%s%s", _paths.personal_dir, name);

	if (!(fp = open_file (str, 1, OF_VERBOSE)))
		return -1;
	
	while (fgets (tmp, 1024, fp)) {
		line++;
		w[words = 0] = strtok (tmp, " \t\r\n\240");
		if (!w[0] || (*w[0] == '#')) {
			continue;
		}
		while (w[words] && (words < MAXWORDS)) {
			w[++words] = strtok (0, " \t\r\n\240");
		}
		if (!strcmp (w[0], "dir")) {
			if (words < 2) {
				return -2;
			}
			for (i = 1; i < words; i++)
				add_to_pathlist (w[i]);
		} else if (!strcmp (w[0], "source")) {
			if (words < 2) {
				return -2;
			}
			for (i = 1; i < words; i++) 
			{
				rcf_count++;
				sprintf(str, "%s", w[i]);
				read_config_file (str);
				rcf_count--;
			}
		} else if (!strcmp (w[0], "default")) {
			if (words != 2)	{
				return -2;
			}
			strncpy (def_instr_name, w[1], 255);
			def_instr_name[255] = '\0';
		} else if (!strcmp (w[0], "drumset")) {
			if (words < 2) {
				return -2;
			}
			i = atoi (w[1]);
			if (i < 0 || i > 127) {
				return -2;
			}
			if (!drumset[i]) {
				drumset[i] = (ToneBank *)safe_malloc (sizeof (ToneBank));
				memset (drumset[i], 0, sizeof (ToneBank));
			}
			bank = drumset[i];
		}
		else if (!strcmp (w[0], "bank")) {
			if (words < 2) {
				return -2;
			}
			i = atoi(w[1]);
			if (i < 0 || i > 127) {
				return -2;
			}
			if (!tonebank[i]) {
				tonebank[i] = (ToneBank *)safe_malloc (sizeof (ToneBank));
				memset (tonebank[i], 0, sizeof (ToneBank));
			}
			bank = tonebank[i];
		} else {
			if ((words < 2) || (*w[0] < '0' || *w[0] > '9')) {
				return -2;
			}
			i = atoi (w[0]);
			if (i < 0 || i > 127) {
				return -2;
			}
			if (!bank) {
				return -2;
			}
			if (bank->tone[i].name) {
				free (bank->tone[i].name);
			}
			strcpy ((bank->tone[i].name = (char*)safe_malloc(2*(strlen(w[1])+1))),w[1]);
			bank->tone[i].note = bank->tone[i].amp = bank->tone[i].pan =
				bank->tone[i].strip_loop = bank->tone[i].strip_envelope =
				bank->tone[i].strip_tail = -1;
			
			for (j = 2; j < words; j++) {
				if (!(cp = strchr (w[j], '='))) {
					return -2;
				}
				*cp++ = 0;
				if (!strcmp (w[j], "amp")) {
					k = atoi (cp);
					if ((k < 0 || k > MAX_AMPLIFICATION)
						|| (*cp < '0' || *cp > '9')) {
						return -2;
					}
					bank->tone[i].amp = k;
				} else if (!strcmp (w[j], "note")) {
					k = atoi (cp);
					if ((k < 0 || k > 127) || (*cp < '0' || *cp > '9'))	{
						return -2;
					}
					bank->tone[i].note = k;
				} else if (!strcmp (w[j], "pan")) {
					if (!strcmp (cp, "center"))
						k = 64;
					else if (!strcmp (cp, "left"))
						k = 0;
					else if (!strcmp (cp, "right"))
						k = 127;
					else
						k = ((atoi (cp) + 100) * 100) / 157;
					if ((k < 0 || k > 127) ||
						(k == 0 && *cp != '-' && (*cp < '0' || *cp > '9')))	{
						return -2;
					}
					bank->tone[i].pan = k;
				} else if (!strcmp (w[j], "keep")) {
					if (!strcmp (cp, "env"))
						bank->tone[i].strip_envelope = 0;
					else if (!strcmp (cp, "loop"))
						bank->tone[i].strip_loop = 0;
					else {
						return -2;
					}
				} else if (!strcmp (w[j], "strip")) {
					if (!strcmp (cp, "env"))
						bank->tone[i].strip_envelope = 1;
					else if (!strcmp (cp, "loop"))
						bank->tone[i].strip_loop = 1;
					else if (!strcmp (cp, "tail"))
						bank->tone[i].strip_tail = 1;
					else {
						return -2;
					}
				} else {
					return -2;
				}
			}
		}
    }
	if (ferror (fp)) {
		return -2;
    }
	close_file (fp);
	return 0;
}

static void ExtMidiStop(void)
{
	if (_midi.playing) 
	{
		_midi.stop_song = true;
		_midi.start_song[0] = '\0';
	}
	
	_midi.terminate = true;
	CloseHandle(&threadId);
	play_mode->close_output();
	DeleteCriticalSection(&critSect);
}

static void ExtMidiPlaySong(const char* filename)
{
	sprintf(_midi.start_song, "%s", filename);
	_midi.playing = true;
	_midi.stop_song = false;
}

static void ExtMidiStopSong(void)
{
	if (_midi.playing) 
	{
		_midi.stop_song = true;
		_midi.start_song[0] = '\0';
	}
}

static bool ExtMidiIsPlaying(void)
{
	return _midi.playing;
}

static void ExtMidiSetVolume(byte vol)
{
	_midi.new_vol = vol;
}

static DWORD WINAPI ExtMidiGo(LPVOID arg)
{
	do {
		char *s;
		s = _midi.start_song;
		if (s[0] != '\0') 
		{
			_midi.playing = play_midi_file(s);
			s[0] = '\0';

			// Delay somewhat in case we don't manage to play.
			if (!_midi.playing) 
			{
				Sleep(1000);
			}
		}
		else
		{
			Sleep(1000);
		}
		
		if (_midi.stop_song && _midi.playing) 
		{
			_midi.stop_song = false;
			_midi.playing = false;
			ExtMidiStopSong();
		}

		if (_midi.playing && !ExtMidiIsPlaying())
			_midi.playing = false;

	} while (!_midi.terminate);

	return 0;
}

static const char* ExtMidiStart(const char* const * parm)
{
	int songCount=0;
	int	got_a_configuration=0;
	int32 output_rate = DEFAULT_RATE;	
	int buffer_fragments = -1;
	int evil = 0;

	memset(&_midi, 0, sizeof(_midi));
	_midi.new_vol = -1;

	song[0] = '\0';	

	if (!read_config_file(CONFIG_FILE)) 
	{
		got_a_configuration=1;
	}
		
	//output_rate = 11025;
	antialiasing_allowed=1;
	buffer_fragments = 3;		/* On Win32 2 is chunky */

	if (!got_a_configuration)
    {
		ShowOSErrorBox("Cannot read timidity.cfg!");
    }
	
	/* Set play mode parameters */
	play_mode->rate = output_rate;
	if (buffer_fragments != -1)
		play_mode->extra_param[0] = buffer_fragments;
	
	
	init_tables ();
		
	/* Open output device */
	if (play_mode->open_output() < 0)
    {
		ShowOSErrorBox("Cannot open audio device!");
    }
		
	if (!control_ratio)
    {
		control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
		if (control_ratio < 1)
			control_ratio = 1;
		else if (control_ratio > MAX_CONTROL_RATIO)
			control_ratio = MAX_CONTROL_RATIO;
    }

	if (*def_instr_name)
	{
		set_default_instrument (def_instr_name);
	}

	InitializeCriticalSection (&critSect);

	CreateThread(NULL, 8192, ExtMidiGo, 0, 0, &threadId);

	return NULL;
}

const HalMusicDriver _extmidi_music_driver = {
	ExtMidiStart,
	ExtMidiStop,
	ExtMidiPlaySong,
	ExtMidiStopSong,
	ExtMidiIsPlaying,
	ExtMidiSetVolume,
};

#endif /* __MORPHOS__ */
