OpenTTD/music_gui.c
Darkvater 58b4fd7683 (svn r5669) - Backport from trunk (r5464, r3641):
Codechange: verify the presence of music files in the gm folder. Slightly altered r5464
  to exclude the addition of music.c and left out the extra functionality. While in essence
  this is not a true fix, several people have reported a rising CPU usage because Dmusic
  kept indefinitely looping the file list. This should solve that.
2006-07-31 11:50:23 +00:00

510 lines
13 KiB
C

/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "window.h"
#include "gfx.h"
#include "sound.h"
#include "hal.h"
#include "macros.h"
#include "variables.h"
#include "music.h"
static byte _music_wnd_cursong;
static bool _song_is_active;
static byte _cur_playlist[NUM_SONGS_PLAYLIST];
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,
};
const SongSpecs origin_songs_specs[NUM_SONGS_AVAILABLE] = {
{"gm_tt00.gm", "Tycoon DELUXE Theme"},
{"gm_tt02.gm", "Easy Driver"},
{"gm_tt03.gm", "Little Red Diesel"},
{"gm_tt17.gm", "Cruise Control"},
{"gm_tt07.gm", "Don't Walk!"},
{"gm_tt09.gm", "Fell Apart On Me"},
{"gm_tt04.gm", "City Groove"},
{"gm_tt19.gm", "Funk Central"},
{"gm_tt06.gm", "Stoke It"},
{"gm_tt12.gm", "Road Hog"},
{"gm_tt05.gm", "Aliens Ate My Railway"},
{"gm_tt01.gm", "Snarl Up"},
{"gm_tt18.gm", "Stroll On"},
{"gm_tt10.gm", "Can't Get There From Here"},
{"gm_tt08.gm", "Sawyer's Tune"},
{"gm_tt13.gm", "Hold That Train!"},
{"gm_tt21.gm", "Movin' On"},
{"gm_tt15.gm", "Goss Groove"},
{"gm_tt16.gm", "Small Town"},
{"gm_tt14.gm", "Broomer's Oil Rag"},
{"gm_tt20.gm", "Jammit"},
{"gm_tt11.gm", "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;
byte t;
t = b[0];
if (t != 0) {
while (b[1] != 0) {
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), "%s%s",
_path.gm_dir, origin_songs_specs[_music_wnd_cursong - 1].filename);
_music_driver->play_song(filename);
}
static void DoStopMusic(void)
{
_music_driver->stop_song();
}
static void SelectSongToPlay(void)
{
uint i = 0;
uint j = 0;
char filename[256];
memset(_cur_playlist, 0, sizeof(_cur_playlist));
do {
snprintf(filename, sizeof(filename), "%s%s",
_path.gm_dir, origin_songs_specs[_playlists[msf.playlist][i]].filename);
//we are now checking for the existence of that file prior
//to add it to the list of available songs
if (FileExists(filename)) {
_cur_playlist[j] = _playlists[msf.playlist][i];
j++;
}
} while (_playlists[msf.playlist][i++] != 0 && i < lengthof(_cur_playlist) - 1);
if (msf.shuffle) {
i = 500;
do {
uint32 r = InteractiveRandom();
byte *a = &_cur_playlist[GB(r, 0, 5)];
byte *b = &_cur_playlist[GB(r, 8, 5)];
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 there is not songs in the playlist, it may indicate
//no file on the gm folder, or even no gm folder.
//Stop the playback, then
if (_cur_playlist[0] == 0) {
_song_is_active = false;
_music_wnd_cursong = 0;
msf.playing = false;
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.playing && _song_is_active) {
StopMusic();
} else if (msf.playing && !_song_is_active) {
PlayPlaylistSong();
}
if (!_song_is_active) return;
if (!_music_driver->is_song_playing()) {
if (_game_mode != GM_MENU) {
StopMusic();
SkipToNextSong();
PlayPlaylistSong();
} else {
ResetMusic();
}
}
}
static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT: {
const byte* p;
uint i;
int y;
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; 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(1, SPECSTR_SONGNAME);
SetDParam(2, i);
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;
uint i;
byte *p;
if (msf.playlist < 4) return;
if (!IS_INT_INSIDE(y, 0, NUM_SONGS_AVAILABLE)) return;
p = _playlists[msf.playlist];
for (i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
if (p[i] == 0) {
p[i] = 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_CLOSEBOX, 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: {
uint i;
StringID str;
w->click_state |= 0x280;
DrawWindowWidgets(w);
GfxFillRect(187, 16, 200, 33, 0);
for (i = 0; i != 8; i++) {
int color = 0xD0;
if (i > 4) {
color = 0xBF;
if (i > 6) {
color = 0xB8;
}
}
GfxFillRect(187, NUM_SONGS_PLAYLIST - i * 2, 200, NUM_SONGS_PLAYLIST - i * 2, color);
}
GfxFillRect(60, 46, 239, 52, 0);
if (_song_is_active == 0 || _music_wnd_cursong == 0) {
str = STR_01E3;
} else {
SetDParam(0, _music_wnd_cursong);
str = (_music_wnd_cursong < 10) ? STR_01E4_0 : 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, FR_LOWERED);
DrawFrameRect(214, 23, 280, 26, 14, FR_LOWERED);
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.playing = false;
break;
case 5: // start playing
msf.playing = 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_CLOSEBOX, 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);
}