music_gui.c
author pasky
Sun, 27 Mar 2005 15:13:51 +0000
changeset 1583 7617a49e78e8
parent 1093 4fdc46eaf423
child 1608 70a3c1a6576d
permissions -rw-r--r--
(svn r2087) Show also the modified filenames along each change in svn log. Prevents enraging Darkvater, and we show the commit messages along changed files everywhere else too (on IRC and in mail).
#include "stdafx.h"
#include "ttd.h"
#include "table/strings.h"
#include "window.h"
#include "gui.h"
#include "gfx.h"
#include "sound.h"
#include "hal.h"

#define NUM_SONGS_AVAILABLE 22


static byte _playlist_all[] = {
	1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,0,
};

static byte _playlist_old_style[] = {
	1, 8, 2, 9, 14, 15, 19, 13, 0,
};

static byte _playlist_new_style[] = {
	6, 11, 10, 17, 21, 18, 5, 0
};

static byte _playlist_ezy_street[] = {
	12, 7, 16, 3, 20, 4, 0
};

static byte * const _playlists[] = {
	_playlist_all,
	_playlist_old_style,
	_playlist_new_style,
	_playlist_ezy_street,
	msf.custom_1,
	msf.custom_2,
};

// Map the order of the song names to the numbers of the midi filenames
static const int midi_idx[] = {
	 0, // Tycoon DELUXE Theme
	 2, // Easy Driver
	 3, // Little Red Diesel
	17, // Cruise Control
	 7, // Don't Walk!
	 9, // Fell Apart On Me
	 4, // City Groove
	19, // Funk Central
	 6, // Stoke It
	12, // Road Hog
	 5, // Aliens Ate My Railway
	 1, // Snarl Up
	18, // Stroll On
	10, // Can't Get There From Here
	 8, // Sawyer's Tune
	13, // Hold That Train!
	21, // Movin' On
	15, // Goss Groove
	16, // Small Town
	14, // Broomer's Oil Rag
	20, // Jammit
	11  // Hard Drivin'
};


static void SkipToPrevSong(void)
{
	byte *b = _cur_playlist;
	byte *p = b;
	byte t;

	// empty playlist
	if (b[0] == 0)
		return;

	// find the end
	do p++; while (p[0] != 0);

	// and copy the bytes
	t = *--p;
	while (p != b) {
		p--;
		p[1] = p[0];
	}
	*b = t;

	_song_is_active = false;
}

static void SkipToNextSong(void)
{
	byte *b = _cur_playlist, t;

	if ((t=b[0]) != 0) {
		while (b[1]) {
			b[0] = b[1];
			b++;
		}
		b[0] = t;
	}

	_song_is_active = false;
}

static void MusicVolumeChanged(byte new_vol)
{
	_music_driver->set_volume(new_vol);
}

static void DoPlaySong(void)
{
	char filename[256];
	snprintf(filename, sizeof(filename), "%sgm_tt%.2d.gm",
		_path.gm_dir, midi_idx[_music_wnd_cursong - 1]);
	_music_driver->play_song(filename);
}

static void DoStopMusic(void)
{
	_music_driver->stop_song();
}

static void SelectSongToPlay(void)
{
	int i;

	memset(_cur_playlist, 0, 33);
	strcpy(_cur_playlist, _playlists[msf.playlist]);

	if (msf.shuffle) {
		i = 500;
		do {
			uint32 r = InteractiveRandom();
			byte *a = &_cur_playlist[r & 0x1F];
			byte *b = &_cur_playlist[(r >> 8)&0x1F];

			if (*a != 0 && *b != 0) {
				byte t = *a;
				*a = *b;
				*b = t;
			}
		} while (--i);
	}
}

static void StopMusic(void)
{
	_music_wnd_cursong = 0;
	DoStopMusic();
	_song_is_active = false;
	InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
}

static void PlayPlaylistSong(void)
{
	if (_cur_playlist[0] == 0) {
		SelectSongToPlay();
		if (_cur_playlist[0] == 0)
			return;
	}
	_music_wnd_cursong = _cur_playlist[0];
	DoPlaySong();
	_song_is_active = true;

	InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
}

void ResetMusic(void)
{
	_music_wnd_cursong = 1;
	DoPlaySong();
}

void MusicLoop(void)
{
	if (!msf.btn_down && _song_is_active) {
		StopMusic();
	} else if (msf.btn_down && !_song_is_active) {
		PlayPlaylistSong();
	}

	if (_song_is_active == false)
		return;

	if (!_music_driver->is_song_playing()) {
		StopMusic();
		SkipToNextSong();
		PlayPlaylistSong();
	}
}

static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e)
{
	switch(e->event) {
	case WE_PAINT: {
		int y,i;
		byte *p;

		w->disabled_state = (msf.playlist  <= 3) ? (1 << 11) : 0;
		w->click_state |= 0x18;
		DrawWindowWidgets(w);

		GfxFillRect(3, 23, 3+177,23+191,0);
		GfxFillRect(251, 23, 251+177,23+191,0);

		DrawStringCentered(92, 15, STR_01EE_TRACK_INDEX, 0);

		SetDParam(0, STR_01D5_ALL + msf.playlist);
		DrawStringCentered(340, 15, STR_01EF_PROGRAM, 0);

		for(i=1; (uint)i <= NUM_SONGS_AVAILABLE; i++) {
			SetDParam(0, i);
			SetDParam(2, i);
			SetDParam(1, SPECSTR_SONGNAME);
			DrawString(4, 23+(i-1)*6, (i < 10) ? STR_01EC_0 : STR_01ED, 0);
		}

		for(i=0; i!=6; i++) {
			DrawStringCentered(216, 45 + i*8, STR_01D5_ALL + i, (i==msf.playlist) ? 0xC : 0x10);
		}

		DrawStringCentered(216, 45+8*6+16, STR_01F0_CLEAR, 0);
		DrawStringCentered(216, 45+8*6+16*2, STR_01F1_SAVE, 0);

		y = 23;
		for(p = _playlists[msf.playlist],i=0; (i=*p) != 0; p++) {
			SetDParam(0, i);
			SetDParam(2, i);
			SetDParam(1, SPECSTR_SONGNAME);
			DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, 0);
			y += 6;
		}
		break;
	}

	case WE_CLICK:
		switch(e->click.widget) {
		case 3: { /* add to playlist */
			int y = (e->click.pt.y - 23) / 6;
			int i;
			byte *p;
			if (msf.playlist < 4) return;
			if ((uint)y >= NUM_SONGS_AVAILABLE) return;

			p = _playlists[msf.playlist];
			for(i=0; i!=32; i++) {
				if (p[i] == 0) {
					p[i] = (byte)(y + 1);
					p[i+1] = 0;
					SetWindowDirty(w);
					SelectSongToPlay();
					break;
				}
			}

		} break;
		case 11: /* clear */
			_playlists[msf.playlist][0] = 0;
			SetWindowDirty(w);
			StopMusic();
			SelectSongToPlay();
			break;
		case 12: /* save */
			ShowInfo("MusicTrackSelectionWndProc:save not implemented\n");
			break;
		case 5: case 6: case 7: case 8: case 9: case 10: /* set playlist */
			msf.playlist = e->click.widget - 5;
			SetWindowDirty(w);
			InvalidateWindow(WC_MUSIC_WINDOW, 0);
			StopMusic();
			SelectSongToPlay();
			break;
		}
		break;
	}
}

static const Widget _music_track_selection_widgets[] = {
{    WWT_TEXTBTN,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,STR_018B_CLOSE_WINDOW},
{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   431,     0,    13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{     WWT_IMGBTN,   RESIZE_NONE,    14,     0,   431,    14,   217, 0x0,			STR_NULL},
{     WWT_IMGBTN,   RESIZE_NONE,    14,     2,   181,    22,   215, 0x0,			STR_01FA_CLICK_ON_MUSIC_TRACK_TO},
{     WWT_IMGBTN,   RESIZE_NONE,    14,   250,   429,    22,   215, 0x0,			STR_01F2_CURRENT_PROGRAM_OF_MUSIC},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,    44,    51, 0x0,			STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,    52,    59, 0x0,			STR_01F4_SELECT_OLD_STYLE_MUSIC},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,    60,    67, 0x0,			STR_01F5_SELECT_NEW_STYLE_MUSIC},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,    68,    75, 0x0,			STR_0330_SELECT_EZY_STREET_STYLE},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,    76,    83, 0x0,			STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,    84,    91, 0x0,			STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,   108,   115, 0x0,			STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   186,   245,   124,   131, 0x0,			STR_01F9_SAVE_MUSIC_SETTINGS},
{   WIDGETS_END},
};

static const WindowDesc _music_track_selection_desc = {
	104, 131, 432, 218,
	WC_MUSIC_TRACK_SELECTION,0,
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
	_music_track_selection_widgets,
	MusicTrackSelectionWndProc
};

static void ShowMusicTrackSelection(void)
{
	AllocateWindowDescFront(&_music_track_selection_desc, 0);
}

static void MusicWindowWndProc(Window *w, WindowEvent *e)
{
	switch(e->event) {
	case WE_PAINT: {
		int i,num;
		StringID str;

		w->click_state |= 0x280;
		DrawWindowWidgets(w);

		GfxFillRect(187, 16, 200, 33, 0);

		num = 8;
		for (i=0; i!=num; i++) {
			int color = 0xD0;
			if (i > 4) {
				color = 0xBF;
				if (i > 6) {
					color = 0xB8;
				}
			}
			GfxFillRect(187, 33 - i*2, 200, 33 - i*2, color);
		}

		GfxFillRect(60, 46, 239, 52, 0);

		str = STR_01E3;
		if (_song_is_active != 0 && _music_wnd_cursong != 0) {
			str = STR_01E4_0;
			SetDParam(0, _music_wnd_cursong);
			if (_music_wnd_cursong >= 10)
				str = STR_01E5;
		}
		DrawString(62, 46, str, 0);

		str = STR_01E6;
		if (_song_is_active != 0 && _music_wnd_cursong != 0) {
			str = STR_01E7;
			SetDParam(0, SPECSTR_SONGNAME);
			SetDParam(1, _music_wnd_cursong);
		}
		DrawStringCentered(155, 46, str, 0);


		DrawString(60, 38, STR_01E8_TRACK_XTITLE, 0);

		for(i=0; i!=6; i++) {
			DrawStringCentered(25+i*50, 59, STR_01D5_ALL+i, msf.playlist == i ? 0xC : 0x10);
		}

		DrawStringCentered(31, 43, STR_01E9_SHUFFLE, (msf.shuffle ? 0xC : 0x10));
		DrawStringCentered(269, 43, STR_01EA_PROGRAM, 0);
		DrawStringCentered(141, 15, STR_01DB_MUSIC_VOLUME, 0);
		DrawStringCentered(141, 29, STR_01DD_MIN_MAX, 0);
		DrawStringCentered(247, 15, STR_01DC_EFFECTS_VOLUME, 0);
		DrawStringCentered(247, 29, STR_01DD_MIN_MAX, 0);

		DrawFrameRect(108, 23, 174, 26, 14, 0x20);
		DrawFrameRect(214, 23, 280, 26, 14, 0x20);

		DrawFrameRect(108 + (msf.music_vol>>1),
									22,
									111 + (msf.music_vol>>1),
									28,
									14,
									0);

		DrawFrameRect(214 + (msf.effect_vol>>1),
									22,
									217 + (msf.effect_vol>>1),
									28,
									14,
									0);
	} break;

	case WE_CLICK:
		switch(e->click.widget) {
		case 2: // skip to prev
			if (!_song_is_active)
				return;
			SkipToPrevSong();
			break;
		case 3: // skip to next
			if (!_song_is_active)
				return;
			SkipToNextSong();
			break;
		case 4: // stop playing
			msf.btn_down = false;
			break;
		case 5: // start playing
			msf.btn_down = true;
			break;
		case 6:{ // volume sliders
			byte *vol,new_vol;
			int x = e->click.pt.x - 88;

			if (x < 0)
				return;

			vol = &msf.music_vol;
			if (x >= 106) {
				vol = &msf.effect_vol;
				x -= 106;
			}

			new_vol = min(max(x-21,0)*2,127);
			if (new_vol != *vol) {
				*vol = new_vol;
				if (vol == &msf.music_vol)
					MusicVolumeChanged(new_vol);
				SetWindowDirty(w);
			}

			_left_button_clicked = false;
		} break;
		case 10: //toggle shuffle
			msf.shuffle ^= 1;
			StopMusic();
			SelectSongToPlay();
			break;
		case 11: //show track selection
			ShowMusicTrackSelection();
			break;
		case 12: case 13: case 14: case 15: case 16: case 17: // playlist
			msf.playlist = e->click.widget - 12;
			SetWindowDirty(w);
			InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0);
			StopMusic();
			SelectSongToPlay();
			break;
		}
		break;

	case WE_MOUSELOOP:
		InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7);
		break;
	}

}

static const Widget _music_window_widgets[] = {
{    WWT_TEXTBTN,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,	STR_018B_CLOSE_WINDOW},
{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   299,     0,    13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,     0,    21,    14,    35, 0x2C5,			STR_01DE_SKIP_TO_PREVIOUS_TRACK},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    22,    43,    14,    35, 0x2C6,			STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    44,    65,    14,    35, 0x2C7,			STR_01E0_STOP_PLAYING_MUSIC},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    66,    87,    14,    35, 0x2C8,			STR_01E1_START_PLAYING_MUSIC},
{     WWT_IMGBTN,   RESIZE_NONE,    14,    88,   299,    14,    35, 0x0,				STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC},
{     WWT_IMGBTN,   RESIZE_NONE,    14,   186,   201,    15,    34, 0x0,				STR_NULL},
{     WWT_IMGBTN,   RESIZE_NONE,    14,     0,   299,    36,    57, 0x0,				STR_NULL},
{     WWT_IMGBTN,   RESIZE_NONE,    14,    59,   240,    45,    53, 0x0,				STR_NULL},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,     6,    55,    42,    49, 0x0,				STR_01FB_TOGGLE_PROGRAM_SHUFFLE},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   244,   293,    42,    49, 0x0,				STR_01FC_SHOW_MUSIC_TRACK_SELECTION},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,     0,    49,    58,    65, 0x0,				STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    50,    99,    58,    65, 0x0,				STR_01F4_SELECT_OLD_STYLE_MUSIC},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   100,   149,    58,    65, 0x0,				STR_01F5_SELECT_NEW_STYLE_MUSIC},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   150,   199,    58,    65, 0x0,				STR_0330_SELECT_EZY_STREET_STYLE},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   200,   249,    58,    65, 0x0,				STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,   250,   299,    58,    65, 0x0,				STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
{   WIDGETS_END},
};

static const WindowDesc _music_window_desc = {
	0, 22, 300, 66,
	WC_MUSIC_WINDOW,0,
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
	_music_window_widgets,
	MusicWindowWndProc
};

void ShowMusicWindow(void)
{
	AllocateWindowDescFront(&_music_window_desc, 0);
}