00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "fileio_func.h"
00008 #include "music.h"
00009 #include "music/music_driver.hpp"
00010 #include "window_gui.h"
00011 #include "strings_func.h"
00012 #include "window_func.h"
00013 #include "sound_func.h"
00014 #include "gfx_func.h"
00015 #include "core/math_func.hpp"
00016 #include "core/random_func.hpp"
00017
00018 #include "table/strings.h"
00019 #include "table/sprites.h"
00020
00021 static byte _music_wnd_cursong;
00022 static bool _song_is_active;
00023 static byte _cur_playlist[NUM_SONGS_PLAYLIST];
00024
00025
00026
00027 static byte _playlist_all[] = {
00028 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0
00029 };
00030
00031 static byte _playlist_old_style[] = {
00032 2, 9, 3, 10, 15, 16, 20, 14, 0
00033 };
00034
00035 static byte _playlist_new_style[] = {
00036 7, 12, 11, 18, 22, 19, 6, 0
00037 };
00038
00039 static byte _playlist_ezy_street[] = {
00040 13, 8, 17, 4, 21, 5, 0
00041 };
00042
00043 static byte * const _playlists[] = {
00044 _playlist_all,
00045 _playlist_old_style,
00046 _playlist_new_style,
00047 _playlist_ezy_street,
00048 msf.custom_1,
00049 msf.custom_2,
00050 };
00051
00052 static void SkipToPrevSong()
00053 {
00054 byte *b = _cur_playlist;
00055 byte *p = b;
00056 byte t;
00057
00058 if (b[0] == 0) return;
00059
00060 do p++; while (p[0] != 0);
00061
00062 t = *--p;
00063 while (p != b) {
00064 p--;
00065 p[1] = p[0];
00066 }
00067 *b = t;
00068
00069 _song_is_active = false;
00070 }
00071
00072 static void SkipToNextSong()
00073 {
00074 byte *b = _cur_playlist;
00075 byte t;
00076
00077 t = b[0];
00078 if (t != 0) {
00079 while (b[1] != 0) {
00080 b[0] = b[1];
00081 b++;
00082 }
00083 b[0] = t;
00084 }
00085
00086 _song_is_active = false;
00087 }
00088
00089 static void MusicVolumeChanged(byte new_vol)
00090 {
00091 _music_driver->SetVolume(new_vol);
00092 }
00093
00094 static void DoPlaySong()
00095 {
00096 char filename[MAX_PATH];
00097 FioFindFullPath(filename, lengthof(filename), GM_DIR,
00098 _origin_songs_specs[_music_wnd_cursong - 1].filename);
00099 _music_driver->PlaySong(filename);
00100 }
00101
00102 static void DoStopMusic()
00103 {
00104 _music_driver->StopSong();
00105 }
00106
00107 static void SelectSongToPlay()
00108 {
00109 uint i = 0;
00110 uint j = 0;
00111
00112 memset(_cur_playlist, 0, sizeof(_cur_playlist));
00113 do {
00114
00115
00116 if (FioCheckFileExists(_origin_songs_specs[_playlists[msf.playlist][i] - 1].filename, GM_DIR)) {
00117 _cur_playlist[j] = _playlists[msf.playlist][i];
00118 j++;
00119 }
00120 } while (_playlists[msf.playlist][++i] != 0 && j < lengthof(_cur_playlist) - 1);
00121
00122
00123 if (msf.shuffle && _game_mode != GM_MENU) {
00124 i = 500;
00125 do {
00126 uint32 r = InteractiveRandom();
00127 byte *a = &_cur_playlist[GB(r, 0, 5)];
00128 byte *b = &_cur_playlist[GB(r, 8, 5)];
00129
00130 if (*a != 0 && *b != 0) {
00131 byte t = *a;
00132 *a = *b;
00133 *b = t;
00134 }
00135 } while (--i);
00136 }
00137 }
00138
00139 static void StopMusic()
00140 {
00141 _music_wnd_cursong = 0;
00142 DoStopMusic();
00143 _song_is_active = false;
00144 InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
00145 }
00146
00147 static void PlayPlaylistSong()
00148 {
00149 if (_cur_playlist[0] == 0) {
00150 SelectSongToPlay();
00151
00152
00153
00154 if (_cur_playlist[0] == 0) {
00155 _song_is_active = false;
00156 _music_wnd_cursong = 0;
00157 msf.playing = false;
00158 return;
00159 }
00160 }
00161 _music_wnd_cursong = _cur_playlist[0];
00162 DoPlaySong();
00163 _song_is_active = true;
00164
00165 InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
00166 }
00167
00168 void ResetMusic()
00169 {
00170 _music_wnd_cursong = 1;
00171 DoPlaySong();
00172 }
00173
00174 void MusicLoop()
00175 {
00176 if (!msf.playing && _song_is_active) {
00177 StopMusic();
00178 } else if (msf.playing && !_song_is_active) {
00179 PlayPlaylistSong();
00180 }
00181
00182 if (!_song_is_active) return;
00183
00184 if (!_music_driver->IsSongPlaying()) {
00185 if (_game_mode != GM_MENU) {
00186 StopMusic();
00187 SkipToNextSong();
00188 PlayPlaylistSong();
00189 } else {
00190 ResetMusic();
00191 }
00192 }
00193 }
00194
00195 struct MusicTrackSelectionWindow : public Window {
00196 private:
00197 enum MusicTrackSelectionWidgets {
00198 MTSW_CLOSE,
00199 MTSW_CAPTION,
00200 MTSW_BACKGROUND,
00201 MTSW_LIST_LEFT,
00202 MTSW_LIST_RIGHT,
00203 MTSW_ALL,
00204 MTSW_OLD,
00205 MTSW_NEW,
00206 MTSW_EZY,
00207 MTSW_CUSTOM1,
00208 MTSW_CUSTOM2,
00209 MTSW_CLEAR,
00210 MTSW_SAVE,
00211 };
00212
00213 public:
00214 MusicTrackSelectionWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
00215 {
00216 this->FindWindowPlacementAndResize(desc);
00217 }
00218
00219 virtual void OnPaint()
00220 {
00221 const byte *p;
00222 uint i;
00223 int y;
00224
00225 this->SetWidgetDisabledState(MTSW_CLEAR, msf.playlist <= 3);
00226 this->LowerWidget(MTSW_LIST_LEFT);
00227 this->LowerWidget(MTSW_LIST_RIGHT);
00228 this->DrawWidgets();
00229
00230 GfxFillRect( 3, 23, 3 + 177, 23 + 191, 0);
00231 GfxFillRect(251, 23, 251 + 177, 23 + 191, 0);
00232
00233 DrawStringCentered(92, 15, STR_01EE_TRACK_INDEX, TC_FROMSTRING);
00234
00235 SetDParam(0, STR_01D5_ALL + msf.playlist);
00236 DrawStringCentered(340, 15, STR_01EF_PROGRAM, TC_FROMSTRING);
00237
00238 for (i = 1; i <= NUM_SONGS_AVAILABLE; i++) {
00239 SetDParam(0, i);
00240 SetDParam(2, i);
00241 SetDParam(1, SPECSTR_SONGNAME);
00242 DrawString(4, 23 + (i - 1) * 6, (i < 10) ? STR_01EC_0 : STR_01ED, TC_FROMSTRING);
00243 }
00244
00245 for (i = 0; i != 6; i++) {
00246 DrawStringCentered(216, 45 + i * 8, STR_01D5_ALL + i, (i == msf.playlist) ? TC_WHITE : TC_BLACK);
00247 }
00248
00249 DrawStringCentered(216, 45 + 8 * 6 + 16, STR_01F0_CLEAR, TC_FROMSTRING);
00250 #if 0
00251 DrawStringCentered(216, 45 + 8 * 6 + 16 * 2, STR_01F1_SAVE, TC_FROMSTRING);
00252 #endif
00253
00254 y = 23;
00255 for (p = _playlists[msf.playlist], i = 0; (i = *p) != 0; p++) {
00256 SetDParam(0, i);
00257 SetDParam(1, SPECSTR_SONGNAME);
00258 SetDParam(2, i);
00259 DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, TC_FROMSTRING);
00260 y += 6;
00261 }
00262 }
00263
00264 virtual void OnClick(Point pt, int widget)
00265 {
00266 switch (widget) {
00267 case MTSW_LIST_LEFT: {
00268 int y = (pt.y - 23) / 6;
00269 uint i;
00270 byte *p;
00271
00272 if (msf.playlist < 4) return;
00273 if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
00274
00275 p = _playlists[msf.playlist];
00276 for (i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
00277 if (p[i] == 0) {
00278 p[i] = y + 1;
00279 p[i + 1] = 0;
00280 this->SetDirty();
00281 SelectSongToPlay();
00282 break;
00283 }
00284 }
00285 } break;
00286
00287 case MTSW_LIST_RIGHT: {
00288 int y = (pt.y - 23) / 6;
00289 uint i;
00290 byte *p;
00291
00292 if (msf.playlist < 4) return;
00293 if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
00294
00295 p = _playlists[msf.playlist];
00296 for (i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
00297 p[i] = p[i + 1];
00298 }
00299
00300 this->SetDirty();
00301 SelectSongToPlay();
00302 } break;
00303
00304 case MTSW_CLEAR:
00305 _playlists[msf.playlist][0] = 0;
00306 this->SetDirty();
00307 StopMusic();
00308 SelectSongToPlay();
00309 break;
00310
00311 #if 0
00312 case MTSW_SAVE:
00313 ShowInfo("MusicTrackSelectionWndProc:save not implemented");
00314 break;
00315 #endif
00316
00317 case MTSW_ALL: case MTSW_OLD: case MTSW_NEW:
00318 case MTSW_EZY: case MTSW_CUSTOM1: case MTSW_CUSTOM2:
00319 msf.playlist = widget - MTSW_ALL;
00320 this->SetDirty();
00321 InvalidateWindow(WC_MUSIC_WINDOW, 0);
00322 StopMusic();
00323 SelectSongToPlay();
00324 break;
00325 }
00326 }
00327 };
00328
00329 static const Widget _music_track_selection_widgets[] = {
00330 { WWT_CLOSEBOX, RESIZE_NONE, COLOUR_GREY, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00331 { WWT_CAPTION, RESIZE_NONE, COLOUR_GREY, 11, 431, 0, 13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00332 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 0, 431, 14, 217, 0x0, STR_NULL},
00333 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 2, 181, 22, 215, 0x0, STR_01FA_CLICK_ON_MUSIC_TRACK_TO},
00334 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 250, 429, 22, 215, 0x0, STR_CLICK_ON_TRACK_TO_REMOVE},
00335 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 44, 51, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
00336 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 52, 59, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC},
00337 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 60, 67, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC},
00338 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 68, 75, 0x0, STR_0330_SELECT_EZY_STREET_STYLE},
00339 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 76, 83, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
00340 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 84, 91, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
00341 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 108, 115, 0x0, STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1},
00342 #if 0
00343 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 186, 245, 124, 131, 0x0, STR_01F9_SAVE_MUSIC_SETTINGS},
00344 #endif
00345 { WIDGETS_END},
00346 };
00347
00348 static const WindowDesc _music_track_selection_desc(
00349 104, 131, 432, 218, 432, 218,
00350 WC_MUSIC_TRACK_SELECTION, WC_NONE,
00351 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00352 _music_track_selection_widgets
00353 );
00354
00355 static void ShowMusicTrackSelection()
00356 {
00357 AllocateWindowDescFront<MusicTrackSelectionWindow>(&_music_track_selection_desc, 0);
00358 }
00359
00360 struct MusicWindow : public Window {
00361 private:
00362 enum MusicWidgets {
00363 MW_CLOSE,
00364 MW_CAPTION,
00365 MW_PREV,
00366 MW_NEXT,
00367 MW_STOP,
00368 MW_PLAY,
00369 MW_SLIDERS,
00370 MW_GAUGE,
00371 MW_BACKGROUND,
00372 MW_INFO,
00373 MW_SHUFFLE,
00374 MW_PROGRAMME,
00375 MW_ALL,
00376 MW_OLD,
00377 MW_NEW,
00378 MW_EZY,
00379 MW_CUSTOM1,
00380 MW_CUSTOM2,
00381 };
00382
00383 public:
00384 MusicWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
00385 {
00386 this->FindWindowPlacementAndResize(desc);
00387 }
00388
00389 virtual void OnPaint()
00390 {
00391 uint i;
00392 StringID str;
00393
00394 this->RaiseWidget(MW_GAUGE);
00395 this->RaiseWidget(MW_INFO);
00396 this->DrawWidgets();
00397
00398 GfxFillRect(187, 16, 200, 33, 0);
00399
00400 for (i = 0; i != 8; i++) {
00401 int colour = 0xD0;
00402 if (i > 4) {
00403 colour = 0xBF;
00404 if (i > 6) {
00405 colour = 0xB8;
00406 }
00407 }
00408 GfxFillRect(187, NUM_SONGS_PLAYLIST - i * 2, 200, NUM_SONGS_PLAYLIST - i * 2, colour);
00409 }
00410
00411 GfxFillRect(60, 46, 239, 52, 0);
00412
00413 if (_song_is_active == 0 || _music_wnd_cursong == 0) {
00414 str = STR_01E3;
00415 } else {
00416 SetDParam(0, _music_wnd_cursong);
00417 str = (_music_wnd_cursong < 10) ? STR_01E4_0 : STR_01E5;
00418 }
00419 DrawString(62, 46, str, TC_FROMSTRING);
00420
00421 str = STR_01E6;
00422 if (_song_is_active != 0 && _music_wnd_cursong != 0) {
00423 str = STR_01E7;
00424 SetDParam(0, SPECSTR_SONGNAME);
00425 SetDParam(1, _music_wnd_cursong);
00426 }
00427 DrawStringCentered(155, 46, str, TC_FROMSTRING);
00428
00429
00430 DrawString(60, 38, STR_01E8_TRACK_XTITLE, TC_FROMSTRING);
00431
00432 for (i = 0; i != 6; i++) {
00433 DrawStringCentered(25 + i * 50, 59, STR_01D5_ALL + i, msf.playlist == i ? TC_WHITE : TC_BLACK);
00434 }
00435
00436 DrawStringCentered( 31, 43, STR_01E9_SHUFFLE, (msf.shuffle ? TC_WHITE : TC_BLACK));
00437 DrawStringCentered(269, 43, STR_01EA_PROGRAM, TC_FROMSTRING);
00438 DrawStringCentered(141, 15, STR_01DB_MUSIC_VOLUME, TC_FROMSTRING);
00439 DrawStringCentered(141, 29, STR_01DD_MIN_MAX, TC_FROMSTRING);
00440 DrawStringCentered(247, 15, STR_01DC_EFFECTS_VOLUME, TC_FROMSTRING);
00441 DrawStringCentered(247, 29, STR_01DD_MIN_MAX, TC_FROMSTRING);
00442
00443 DrawFrameRect(108, 23, 174, 26, COLOUR_GREY, FR_LOWERED);
00444 DrawFrameRect(214, 23, 280, 26, COLOUR_GREY, FR_LOWERED);
00445
00446 DrawFrameRect(
00447 108 + msf.music_vol / 2, 22, 111 + msf.music_vol / 2, 28, COLOUR_GREY, FR_NONE
00448 );
00449
00450 DrawFrameRect(
00451 214 + msf.effect_vol / 2, 22, 217 + msf.effect_vol / 2, 28, COLOUR_GREY, FR_NONE
00452 );
00453 }
00454
00455 virtual void OnClick(Point pt, int widget)
00456 {
00457 switch (widget) {
00458 case MW_PREV:
00459 if (!_song_is_active) return;
00460 SkipToPrevSong();
00461 break;
00462
00463 case MW_NEXT:
00464 if (!_song_is_active) return;
00465 SkipToNextSong();
00466 break;
00467
00468 case MW_STOP:
00469 msf.playing = false;
00470 break;
00471
00472 case MW_PLAY:
00473 msf.playing = true;
00474 break;
00475
00476 case MW_SLIDERS: {
00477 byte *vol, new_vol;
00478 int x = pt.x - 88;
00479
00480 if (x < 0) return;
00481
00482 vol = &msf.music_vol;
00483 if (x >= 106) {
00484 vol = &msf.effect_vol;
00485 x -= 106;
00486 }
00487
00488 new_vol = min(max(x - 21, 0) * 2, 127);
00489 if (new_vol != *vol) {
00490 *vol = new_vol;
00491 if (vol == &msf.music_vol) MusicVolumeChanged(new_vol);
00492 this->SetDirty();
00493 }
00494
00495 _left_button_clicked = false;
00496 } break;
00497
00498 case MW_SHUFFLE:
00499 msf.shuffle ^= 1;
00500 StopMusic();
00501 SelectSongToPlay();
00502 break;
00503
00504 case MW_PROGRAMME:
00505 ShowMusicTrackSelection();
00506 break;
00507
00508 case MW_ALL: case MW_OLD: case MW_NEW:
00509 case MW_EZY: case MW_CUSTOM1: case MW_CUSTOM2:
00510 msf.playlist = widget - MW_ALL;
00511 this->SetDirty();
00512 InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0);
00513 StopMusic();
00514 SelectSongToPlay();
00515 break;
00516 }
00517 }
00518
00519 #if 0
00520 virtual void OnTick()
00521 {
00522 this->InvalidateWidget(MW_GAUGE);
00523 }
00524 #endif
00525 };
00526
00527 static const Widget _music_window_widgets[] = {
00528 { WWT_CLOSEBOX, RESIZE_NONE, COLOUR_GREY, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00529 { WWT_CAPTION, RESIZE_NONE, COLOUR_GREY, 11, 299, 0, 13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS},
00530 { WWT_PUSHIMGBTN, RESIZE_NONE, COLOUR_GREY, 0, 21, 14, 35, SPR_IMG_SKIP_TO_PREV, STR_01DE_SKIP_TO_PREVIOUS_TRACK},
00531 { WWT_PUSHIMGBTN, RESIZE_NONE, COLOUR_GREY, 22, 43, 14, 35, SPR_IMG_SKIP_TO_NEXT, STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION},
00532 { WWT_PUSHIMGBTN, RESIZE_NONE, COLOUR_GREY, 44, 65, 14, 35, SPR_IMG_STOP_MUSIC, STR_01E0_STOP_PLAYING_MUSIC},
00533 { WWT_PUSHIMGBTN, RESIZE_NONE, COLOUR_GREY, 66, 87, 14, 35, SPR_IMG_PLAY_MUSIC, STR_01E1_START_PLAYING_MUSIC},
00534 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 88, 299, 14, 35, 0x0, STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC},
00535 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 186, 201, 15, 34, 0x0, STR_NULL},
00536 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 0, 299, 36, 57, 0x0, STR_NULL},
00537 { WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 59, 240, 45, 53, 0x0, STR_NULL},
00538 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 6, 55, 42, 49, 0x0, STR_01FB_TOGGLE_PROGRAM_SHUFFLE},
00539 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 244, 293, 42, 49, 0x0, STR_01FC_SHOW_MUSIC_TRACK_SELECTION},
00540 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 0, 49, 58, 65, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
00541 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 50, 99, 58, 65, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC},
00542 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 100, 149, 58, 65, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC},
00543 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 150, 199, 58, 65, 0x0, STR_0330_SELECT_EZY_STREET_STYLE},
00544 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 200, 249, 58, 65, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
00545 { WWT_PUSHBTN, RESIZE_NONE, COLOUR_GREY, 250, 299, 58, 65, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
00546 { WIDGETS_END},
00547 };
00548
00549 static const WindowDesc _music_window_desc(
00550 0, 22, 300, 66, 300, 66,
00551 WC_MUSIC_WINDOW, WC_NONE,
00552 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00553 _music_window_widgets
00554 );
00555
00556 void ShowMusicWindow()
00557 {
00558 AllocateWindowDescFront<MusicWindow>(&_music_window_desc, 0);
00559 }