truelight@0: #include "stdafx.h" truelight@0: #include "ttd.h" tron@507: #include "table/strings.h" truelight@0: #include "window.h" truelight@0: #include "gui.h" truelight@0: #include "gfx.h" truelight@0: #include "sound.h" truelight@0: #include "hal.h" truelight@0: truelight@0: #define NUM_SONGS_AVAILABLE 22 truelight@0: truelight@0: truelight@0: static byte _playlist_all[] = { truelight@0: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,0, truelight@0: }; truelight@0: truelight@0: static byte _playlist_old_style[] = { truelight@0: 1, 8, 2, 9, 14, 15, 19, 13, 0, truelight@0: }; truelight@0: truelight@0: static byte _playlist_new_style[] = { truelight@0: 6, 11, 10, 17, 21, 18, 5, 0 truelight@0: }; truelight@0: truelight@0: static byte _playlist_ezy_street[] = { truelight@0: 12, 7, 16, 3, 20, 4, 0 truelight@0: }; truelight@0: truelight@0: static byte * const _playlists[] = { truelight@0: _playlist_all, truelight@0: _playlist_old_style, truelight@0: _playlist_new_style, truelight@0: _playlist_ezy_street, truelight@0: msf.custom_1, truelight@0: msf.custom_2, truelight@0: }; truelight@0: tron@341: // Map the order of the song names to the numbers of the midi filenames tron@341: static const int midi_idx[] = { tron@341: 0, // Tycoon DELUXE Theme tron@341: 2, // Easy Driver tron@341: 3, // Little Red Diesel tron@341: 17, // Cruise Control tron@341: 7, // Don't Walk! tron@341: 9, // Fell Apart On Me tron@341: 4, // City Groove tron@341: 19, // Funk Central tron@341: 6, // Stoke It tron@341: 12, // Road Hog tron@341: 5, // Aliens Ate My Railway tron@341: 1, // Snarl Up tron@341: 18, // Stroll On tron@341: 10, // Can't Get There From Here tron@341: 8, // Sawyer's Tune tron@341: 13, // Hold That Train! tron@341: 21, // Movin' On tron@341: 15, // Goss Groove tron@341: 16, // Small Town tron@341: 14, // Broomer's Oil Rag tron@341: 20, // Jammit tron@341: 11 // Hard Drivin' tron@341: }; tron@341: truelight@0: truelight@0: static void SkipToPrevSong() truelight@0: { truelight@0: byte *b = _cur_playlist; truelight@0: byte *p = b; truelight@0: byte t; truelight@0: truelight@0: // empty playlist truelight@0: if (b[0] == 0) truelight@0: return; truelight@193: truelight@0: // find the end truelight@0: do p++; while (p[0] != 0); truelight@0: truelight@0: // and copy the bytes truelight@0: t = *--p; truelight@0: while (p != b) { truelight@0: p--; truelight@0: p[1] = p[0]; truelight@0: } truelight@0: *b = t; truelight@0: truelight@0: _song_is_active = false; truelight@0: } truelight@0: truelight@0: static void SkipToNextSong() truelight@0: { truelight@0: byte *b = _cur_playlist, t; truelight@0: truelight@0: if ((t=b[0]) != 0) { truelight@0: while (b[1]) { truelight@0: b[0] = b[1]; truelight@0: b++; truelight@0: } truelight@0: b[0] = t; truelight@0: } truelight@0: truelight@0: _song_is_active = false; truelight@0: } truelight@0: truelight@0: static void MusicVolumeChanged(byte new_vol) truelight@0: { truelight@0: _music_driver->set_volume(new_vol); truelight@0: } truelight@0: truelight@0: static void DoPlaySong() truelight@0: { truelight@0: char filename[256]; tron@341: snprintf(filename, sizeof(filename), "%sgm_tt%.2d.gm", tron@341: _path.gm_dir, midi_idx[_music_wnd_cursong - 1]); truelight@0: _music_driver->play_song(filename); truelight@0: } truelight@0: truelight@0: static void DoStopMusic() truelight@0: { truelight@0: _music_driver->stop_song(); truelight@0: } truelight@0: truelight@0: static void SelectSongToPlay() truelight@0: { truelight@0: int i; truelight@0: truelight@0: memset(_cur_playlist, 0, 33); truelight@0: strcpy(_cur_playlist, _playlists[msf.playlist]); truelight@0: truelight@0: if (msf.shuffle) { truelight@0: i = 500; truelight@0: do { truelight@0: uint32 r = InteractiveRandom(); truelight@0: byte *a = &_cur_playlist[r & 0x1F]; truelight@0: byte *b = &_cur_playlist[(r >> 8)&0x1F]; truelight@0: truelight@0: if (*a != 0 && *b != 0) { truelight@0: byte t = *a; truelight@0: *a = *b; truelight@0: *b = t; truelight@0: } truelight@0: } while (--i); truelight@0: } truelight@0: } truelight@0: truelight@0: static void StopMusic() truelight@0: { truelight@0: _music_wnd_cursong = 0; truelight@0: DoStopMusic(); truelight@0: _song_is_active = false; truelight@0: InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9); truelight@0: } truelight@0: truelight@0: static void PlayPlaylistSong() truelight@0: { truelight@0: if (_cur_playlist[0] == 0) { truelight@0: SelectSongToPlay(); truelight@0: if (_cur_playlist[0] == 0) truelight@0: return; truelight@0: } truelight@0: _music_wnd_cursong = _cur_playlist[0]; truelight@0: DoPlaySong(); truelight@0: _song_is_active = true; truelight@193: truelight@0: InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9); truelight@0: } truelight@0: truelight@0: void ResetMusic() truelight@0: { truelight@0: _music_wnd_cursong = 1; truelight@0: DoPlaySong(); truelight@0: } truelight@0: truelight@0: void MusicLoop() truelight@0: { truelight@0: if (!msf.btn_down && _song_is_active) { truelight@0: StopMusic(); truelight@0: } else if (msf.btn_down && !_song_is_active) { truelight@0: PlayPlaylistSong(); truelight@0: } truelight@0: truelight@0: if (_song_is_active == false) truelight@0: return; truelight@0: truelight@0: if (!_music_driver->is_song_playing()) { truelight@0: StopMusic(); truelight@0: SkipToNextSong(); truelight@0: PlayPlaylistSong(); truelight@0: } truelight@0: } truelight@0: truelight@0: static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: switch(e->event) { truelight@0: case WE_PAINT: { truelight@0: int y,i; truelight@0: byte *p; truelight@0: truelight@0: w->disabled_state = (msf.playlist <= 3) ? (1 << 11) : 0; truelight@0: w->click_state |= 0x18; truelight@0: DrawWindowWidgets(w); truelight@0: truelight@0: GfxFillRect(3, 23, 3+177,23+191,0); truelight@0: GfxFillRect(251, 23, 251+177,23+191,0); truelight@0: truelight@0: DrawStringCentered(92, 15, STR_01EE_TRACK_INDEX, 0); truelight@0: tron@534: SetDParam(0, STR_01D5_ALL + msf.playlist); truelight@0: DrawStringCentered(340, 15, STR_01EF_PROGRAM, 0); truelight@0: truelight@0: for(i=1; (uint)i <= NUM_SONGS_AVAILABLE; i++) { tron@534: SetDParam(0, i); tron@534: SetDParam(2, i); tron@534: SetDParam(1, SPECSTR_SONGNAME); truelight@0: DrawString(4, 23+(i-1)*6, (i < 10) ? STR_01EC_0 : STR_01ED, 0); truelight@0: } truelight@0: truelight@0: for(i=0; i!=6; i++) { truelight@0: DrawStringCentered(216, 45 + i*8, STR_01D5_ALL + i, (i==msf.playlist) ? 0xC : 0x10); truelight@0: } truelight@0: truelight@193: DrawStringCentered(216, 45+8*6+16, STR_01F0_CLEAR, 0); truelight@0: DrawStringCentered(216, 45+8*6+16*2, STR_01F1_SAVE, 0); truelight@0: truelight@0: y = 23; truelight@0: for(p = _playlists[msf.playlist],i=0; (i=*p) != 0; p++) { tron@534: SetDParam(0, i); tron@534: SetDParam(2, i); tron@534: SetDParam(1, SPECSTR_SONGNAME); truelight@0: DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, 0); truelight@0: y += 6; truelight@0: } truelight@0: break; truelight@0: } truelight@193: truelight@0: case WE_CLICK: truelight@0: switch(e->click.widget) { truelight@0: case 3: { /* add to playlist */ truelight@0: int y = (e->click.pt.y - 23) / 6; truelight@0: int i; truelight@0: byte *p; truelight@0: if (msf.playlist < 4) return; truelight@0: if ((uint)y >= NUM_SONGS_AVAILABLE) return; truelight@0: truelight@0: p = _playlists[msf.playlist]; truelight@0: for(i=0; i!=32; i++) { truelight@0: if (p[i] == 0) { truelight@0: p[i] = (byte)(y + 1); truelight@0: p[i+1] = 0; truelight@0: SetWindowDirty(w); truelight@0: SelectSongToPlay(); truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: } break; truelight@0: case 11: /* clear */ truelight@0: _playlists[msf.playlist][0] = 0; truelight@0: SetWindowDirty(w); truelight@0: StopMusic(); truelight@0: SelectSongToPlay(); truelight@0: break; truelight@0: case 12: /* save */ truelight@0: ShowInfo("MusicTrackSelectionWndProc:save not implemented\n"); truelight@0: break; truelight@0: case 5: case 6: case 7: case 8: case 9: case 10: /* set playlist */ truelight@0: msf.playlist = e->click.widget - 5; truelight@0: SetWindowDirty(w); truelight@0: InvalidateWindow(WC_MUSIC_WINDOW, 0); truelight@0: StopMusic(); truelight@0: SelectSongToPlay(); truelight@0: break; truelight@0: } truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: static const Widget _music_track_selection_widgets[] = { darkvater@176: { WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, truelight@0: { WWT_CAPTION, 14, 11, 431, 0, 13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, darkvater@176: { WWT_IMGBTN, 14, 0, 431, 14, 217, 0x0, STR_NULL}, darkvater@176: { WWT_IMGBTN, 14, 2, 181, 22, 215, 0x0, STR_01FA_CLICK_ON_MUSIC_TRACK_TO}, darkvater@176: { WWT_IMGBTN, 14, 250, 429, 22, 215, 0x0, STR_01F2_CURRENT_PROGRAM_OF_MUSIC}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 44, 51, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 52, 59, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 60, 67, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 68, 75, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 76, 83, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 84, 91, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 108, 115, 0x0, STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1}, darkvater@176: { WWT_PUSHIMGBTN, 14, 186, 245, 124, 131, 0x0, STR_01F9_SAVE_MUSIC_SETTINGS_TO}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _music_track_selection_desc = { truelight@0: 104, 131, 432, 218, truelight@0: WC_MUSIC_TRACK_SELECTION,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, truelight@0: _music_track_selection_widgets, truelight@0: MusicTrackSelectionWndProc truelight@0: }; truelight@0: truelight@0: static void ShowMusicTrackSelection() truelight@0: { truelight@0: AllocateWindowDescFront(&_music_track_selection_desc, 0); truelight@0: } truelight@0: truelight@0: static void MusicWindowWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: switch(e->event) { truelight@0: case WE_PAINT: { truelight@0: int i,num; truelight@0: StringID str; truelight@0: truelight@0: w->click_state |= 0x280; truelight@0: DrawWindowWidgets(w); truelight@0: truelight@0: GfxFillRect(187, 16, 200, 33, 0); truelight@0: truelight@0: num = 8; truelight@0: for (i=0; i!=num; i++) { truelight@0: int color = 0xD0; truelight@0: if (i > 4) { truelight@0: color = 0xBF; truelight@0: if (i > 6) { truelight@0: color = 0xB8; truelight@0: } truelight@0: } truelight@0: GfxFillRect(187, 33 - i*2, 200, 33 - i*2, color); truelight@0: } truelight@0: truelight@0: GfxFillRect(60, 46, 239, 52, 0); truelight@0: truelight@0: str = STR_01E3; truelight@0: if (_song_is_active != 0 && _music_wnd_cursong != 0) { truelight@0: str = STR_01E4_0; tron@534: SetDParam(0, _music_wnd_cursong); truelight@0: if (_music_wnd_cursong >= 10) truelight@0: str = STR_01E5; truelight@0: } truelight@0: DrawString(62, 46, str, 0); truelight@0: truelight@0: str = STR_01E6; truelight@0: if (_song_is_active != 0 && _music_wnd_cursong != 0) { truelight@0: str = STR_01E7; tron@534: SetDParam(0, SPECSTR_SONGNAME); tron@534: SetDParam(1, _music_wnd_cursong); truelight@0: } truelight@0: DrawStringCentered(155, 46, str, 0); truelight@0: truelight@0: truelight@0: DrawString(60, 38, STR_01E8_TRACK_XTITLE, 0); truelight@193: truelight@0: for(i=0; i!=6; i++) { truelight@0: DrawStringCentered(25+i*50, 59, STR_01D5_ALL+i, msf.playlist == i ? 0xC : 0x10); truelight@0: } truelight@0: truelight@0: DrawStringCentered(31, 43, STR_01E9_SHUFFLE, (msf.shuffle ? 0xC : 0x10)); truelight@0: DrawStringCentered(269, 43, STR_01EA_PROGRAM, 0); truelight@0: DrawStringCentered(141, 15, STR_01DB_MUSIC_VOLUME, 0); truelight@0: DrawStringCentered(141, 29, STR_01DD_MIN_MAX, 0); truelight@0: DrawStringCentered(247, 15, STR_01DC_EFFECTS_VOLUME, 0); truelight@0: DrawStringCentered(247, 29, STR_01DD_MIN_MAX, 0); truelight@0: truelight@0: DrawFrameRect(108, 23, 174, 26, 14, 0x20); truelight@0: DrawFrameRect(214, 23, 280, 26, 14, 0x20); truelight@0: truelight@193: DrawFrameRect(108 + (msf.music_vol>>1), truelight@0: 22, truelight@0: 111 + (msf.music_vol>>1), truelight@0: 28, truelight@0: 14, truelight@0: 0); truelight@0: truelight@193: DrawFrameRect(214 + (msf.effect_vol>>1), truelight@0: 22, truelight@0: 217 + (msf.effect_vol>>1), truelight@0: 28, truelight@0: 14, truelight@0: 0); truelight@0: } break; truelight@0: truelight@0: case WE_CLICK: truelight@0: switch(e->click.widget) { truelight@0: case 2: // skip to prev truelight@0: if (!_song_is_active) truelight@0: return; truelight@0: SkipToPrevSong(); truelight@0: break; truelight@0: case 3: // skip to next truelight@0: if (!_song_is_active) truelight@0: return; truelight@0: SkipToNextSong(); truelight@0: break; truelight@0: case 4: // stop playing truelight@0: msf.btn_down = false; truelight@0: break; truelight@0: case 5: // start playing truelight@0: msf.btn_down = true; truelight@0: break; truelight@0: case 6:{ // volume sliders truelight@0: byte *vol,new_vol; truelight@193: int x = e->click.pt.x - 88; truelight@0: truelight@0: if (x < 0) truelight@0: return; truelight@0: truelight@0: vol = &msf.music_vol; truelight@0: if (x >= 106) { truelight@0: vol = &msf.effect_vol; truelight@0: x -= 106; truelight@0: } truelight@0: truelight@0: new_vol = min(max(x-21,0)*2,127); truelight@0: if (new_vol != *vol) { truelight@0: *vol = new_vol; truelight@0: if (vol == &msf.music_vol) truelight@0: MusicVolumeChanged(new_vol); truelight@0: SetWindowDirty(w); truelight@0: } truelight@0: truelight@0: _left_button_clicked = false; truelight@0: } break; truelight@0: case 10: //toggle shuffle truelight@0: msf.shuffle ^= 1; truelight@0: StopMusic(); truelight@0: SelectSongToPlay(); truelight@0: break; truelight@0: case 11: //show track selection truelight@0: ShowMusicTrackSelection(); truelight@0: break; truelight@0: case 12: case 13: case 14: case 15: case 16: case 17: // playlist truelight@0: msf.playlist = e->click.widget - 12; truelight@0: SetWindowDirty(w); truelight@0: InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0); truelight@0: StopMusic(); truelight@0: SelectSongToPlay(); truelight@0: break; truelight@0: } truelight@0: break; truelight@0: truelight@0: case WE_MOUSELOOP: truelight@0: InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7); truelight@0: break; truelight@0: } truelight@0: truelight@0: } truelight@0: truelight@0: static const Widget _music_window_widgets[] = { darkvater@176: { WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@0: { WWT_CAPTION, 14, 11, 299, 0, 13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS}, darkvater@176: { WWT_PUSHIMGBTN, 14, 0, 21, 14, 35, 0x2C5, STR_01DE_SKIP_TO_PREVIOUS_TRACK}, darkvater@176: { WWT_PUSHIMGBTN, 14, 22, 43, 14, 35, 0x2C6, STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION}, darkvater@176: { WWT_PUSHIMGBTN, 14, 44, 65, 14, 35, 0x2C7, STR_01E0_STOP_PLAYING_MUSIC}, darkvater@176: { WWT_PUSHIMGBTN, 14, 66, 87, 14, 35, 0x2C8, STR_01E1_START_PLAYING_MUSIC}, darkvater@176: { WWT_IMGBTN, 14, 88, 299, 14, 35, 0x0, STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC}, darkvater@176: { WWT_IMGBTN, 14, 186, 201, 15, 34, 0x0, STR_NULL}, darkvater@176: { WWT_IMGBTN, 14, 0, 299, 36, 57, 0x0, STR_NULL}, darkvater@176: { WWT_IMGBTN, 14, 59, 240, 45, 53, 0x0, STR_NULL}, darkvater@176: { WWT_PUSHIMGBTN, 14, 6, 55, 42, 49, 0x0, STR_01FB_TOGGLE_PROGRAM_SHUFFLE}, darkvater@176: { WWT_PUSHIMGBTN, 14, 244, 293, 42, 49, 0x0, STR_01FC_SHOW_MUSIC_TRACK_SELECTION}, darkvater@176: { WWT_PUSHIMGBTN, 14, 0, 49, 58, 65, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, darkvater@176: { WWT_PUSHIMGBTN, 14, 50, 99, 58, 65, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, darkvater@176: { WWT_PUSHIMGBTN, 14, 100, 149, 58, 65, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, darkvater@176: { WWT_PUSHIMGBTN, 14, 150, 199, 58, 65, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, darkvater@176: { WWT_PUSHIMGBTN, 14, 200, 249, 58, 65, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, darkvater@176: { WWT_PUSHIMGBTN, 14, 250, 299, 58, 65, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _music_window_desc = { truelight@0: 0, 22, 300, 66, truelight@0: WC_MUSIC_WINDOW,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, truelight@0: _music_window_widgets, truelight@0: MusicWindowWndProc truelight@0: }; truelight@0: truelight@0: void ShowMusicWindow() truelight@0: { truelight@0: AllocateWindowDescFront(&_music_window_desc, 0); truelight@0: }