summaryrefslogtreecommitdiff
path: root/src/music_gui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/music_gui.cpp')
-rw-r--r--src/music_gui.cpp666
1 files changed, 363 insertions, 303 deletions
diff --git a/src/music_gui.cpp b/src/music_gui.cpp
index c5cfb3bae..1edfbab41 100644
--- a/src/music_gui.cpp
+++ b/src/music_gui.cpp
@@ -10,6 +10,7 @@
/** @file music_gui.cpp GUI for the music playback. */
#include "stdafx.h"
+#include <vector>
#include "openttd.h"
#include "base_media_base.h"
#include "music/music_driver.hpp"
@@ -35,278 +36,393 @@
#include "safeguards.h"
-/**
- * Get the name of the song.
- * @param index of the song.
- * @return the name of the song.
- */
-static const char *GetSongName(int index)
+
+struct MusicSystem {
+ struct PlaylistEntry : MusicSongInfo {
+ const MusicSet *set; ///< music set the song comes from
+ uint set_index; ///< index of song in set
+
+ PlaylistEntry(const MusicSet *set, uint set_index) : MusicSongInfo(set->songinfo[set_index]), set(set), set_index(set_index) { }
+ bool IsValid() const { return !StrEmpty(this->songname); }
+ };
+ typedef std::vector<PlaylistEntry> Playlist;
+
+ enum PlaylistChoices {
+ PLCH_ALLMUSIC,
+ PLCH_OLDSTYLE,
+ PLCH_NEWSTYLE,
+ PLCH_EZYSTREET,
+ PLCH_CUSTOM1,
+ PLCH_CUSTOM2,
+ PLCH_THEMEONLY,
+ PLCH_MAX,
+ };
+
+ Playlist active_playlist; ///< current play order of songs, including any shuffle
+ Playlist displayed_playlist; ///< current playlist as displayed in GUI, never in shuffled order
+ Playlist music_set; ///< all songs in current music set, in set order
+
+ PlaylistChoices selected_playlist;
+
+ void BuildPlaylists();
+
+ void ChangePlaylist(PlaylistChoices pl);
+ void ChangeMusicSet(const char *set_name);
+ void Shuffle();
+ void Unshuffle();
+
+ void Play();
+ void Stop();
+ void Next();
+ void Prev();
+ void CheckStatus();
+
+ bool IsPlaying() const;
+ bool IsShuffle() const;
+ PlaylistEntry GetCurrentSong() const;
+
+ bool IsCustomPlaylist() const;
+ void PlaylistAdd(size_t song_index);
+ void PlaylistRemove(size_t song_index);
+ void PlaylistClear();
+
+private:
+ void ChangePlaylistPosition(int ofs);
+ int playlist_position;
+
+ void SaveCustomPlaylist(PlaylistChoices pl);
+
+ Playlist standard_playlists[PLCH_MAX];
+};
+
+MusicSystem _music;
+
+
+/** Rebuild all playlists for the current music set */
+void MusicSystem::BuildPlaylists()
{
- return BaseMusic::GetUsedSet()->songinfo[index].songname;
+ const MusicSet *set = BaseMusic::GetUsedSet();
+
+ /* Clear current playlists */
+ for (size_t i = 0; i < lengthof(this->standard_playlists); ++i) this->standard_playlists[i].clear();
+ this->music_set.clear();
+
+ /* Build standard playlists, and a list of available music */
+ for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
+ PlaylistEntry entry(set, i);
+ if (!entry.IsValid()) continue;
+
+ this->music_set.push_back(entry);
+
+ /* Add theme song to theme-only playlist */
+ if (i == 0) this->standard_playlists[PLCH_THEMEONLY].push_back(entry);
+
+ /* Don't add the theme song to standard playlists */
+ if (i > 0) {
+ this->standard_playlists[PLCH_ALLMUSIC].push_back(entry);
+ uint theme = (i - 1) / NUM_SONGS_CLASS;
+ this->standard_playlists[PLCH_OLDSTYLE + theme].push_back(entry);
+ }
+ }
+
+ /* Load custom playlists
+ * Song index offsets are 1-based, zero indicates invalid/end-of-list value */
+ for (uint i = 0; i < NUM_SONGS_PLAYLIST; i++) {
+ if (_settings_client.music.custom_1[i] > 0) {
+ PlaylistEntry entry(set, _settings_client.music.custom_1[i] - 1);
+ if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM1].push_back(entry);
+ }
+ if (_settings_client.music.custom_2[i] > 0) {
+ PlaylistEntry entry(set, _settings_client.music.custom_2[i] - 1);
+ if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM2].push_back(entry);
+ }
+ }
}
/**
- * Get the track number of the song.
- * @param index of the song.
- * @return the track number of the song.
+ * Switch to another playlist, or reload the current one.
+ * @param pl Playlist to select
*/
-static int GetTrackNumber(int index)
+void MusicSystem::ChangePlaylist(PlaylistChoices pl)
{
- return BaseMusic::GetUsedSet()->songinfo[index].tracknr;
-}
+ assert(pl < PLCH_MAX && pl >= PLCH_ALLMUSIC);
-/** The currently played song */
-static byte _music_wnd_cursong = 1;
-/** Whether a song is currently played */
-static bool _song_is_active = false;
-
-/** Indices of the songs in the current playlist */
-static byte _cur_playlist[NUM_SONGS_PLAYLIST + 1];
-
-/** Indices of all songs */
-static byte _playlist_all[NUM_SONGS_AVAILABLE + 1];
-/** Indices of all old style songs */
-static byte _playlist_old_style[NUM_SONGS_CLASS + 1];
-/** Indices of all new style songs */
-static byte _playlist_new_style[NUM_SONGS_CLASS + 1];
-/** Indices of all ezy street songs */
-static byte _playlist_ezy_street[NUM_SONGS_CLASS + 1];
-
-assert_compile(lengthof(_settings_client.music.custom_1) == NUM_SONGS_PLAYLIST + 1);
-assert_compile(lengthof(_settings_client.music.custom_2) == NUM_SONGS_PLAYLIST + 1);
-
-/** The different playlists that can be played. */
-static byte * const _playlists[] = {
- _playlist_all,
- _playlist_old_style,
- _playlist_new_style,
- _playlist_ezy_street,
- _settings_client.music.custom_1,
- _settings_client.music.custom_2,
-};
+ this->displayed_playlist = this->standard_playlists[pl];
+ this->active_playlist = this->displayed_playlist;
+ this->selected_playlist = pl;
+ this->playlist_position = 0;
+
+ if (this->selected_playlist != PLCH_THEMEONLY) _settings_client.music.playlist = this->selected_playlist;
+
+ if (_settings_client.music.shuffle) {
+ this->Shuffle();
+ /* Shuffle() will also Play() if necessary, only start once */
+ } else if (_settings_client.music.playing) {
+ this->Play();
+ }
+
+ InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
+}
/**
- * Validate a playlist.
- * @param playlist The playlist to validate.
- * @param last The last location in the list.
+ * Change to named music set, and reset playback.
+ * @param set_name Name of music set to select
*/
-void ValidatePlaylist(byte *playlist, byte *last)
+void MusicSystem::ChangeMusicSet(const char *set_name)
{
- while (*playlist != 0 && playlist <= last) {
- /* Song indices are saved off-by-one so 0 is "nothing". */
- if (*playlist <= NUM_SONGS_AVAILABLE && !StrEmpty(GetSongName(*playlist - 1))) {
- playlist++;
- continue;
- }
- for (byte *p = playlist; *p != 0 && p <= last; p++) {
- p[0] = p[1];
- }
- }
+ BaseMusic::SetSet(set_name);
- /* Make sure the list is null terminated. */
- *last = 0;
+ this->BuildPlaylists();
+ this->ChangePlaylist(this->selected_playlist);
+
+ InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
}
-/** Prepare the playlists */
-void InitializeMusic()
+/** Enable shuffle mode and restart playback */
+void MusicSystem::Shuffle()
{
- uint j = 0;
- for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
- if (StrEmpty(GetSongName(i))) continue;
- _playlist_all[j++] = i + 1;
- }
- /* Terminate the list */
- _playlist_all[j] = 0;
-
- /* Now make the 'styled' playlists */
- for (uint k = 0; k < NUM_SONG_CLASSES; k++) {
- j = 0;
- for (uint i = 0; i < NUM_SONGS_CLASS; i++) {
- int id = k * NUM_SONGS_CLASS + i + 1;
- if (StrEmpty(GetSongName(id))) continue;
- _playlists[k + 1][j++] = id + 1;
- }
- /* Terminate the list */
- _playlists[k + 1][j] = 0;
+ _settings_client.music.shuffle = true;
+
+ this->active_playlist = this->displayed_playlist;
+ for (size_t i = 0; i < this->active_playlist.size(); i++) {
+ size_t shuffle_index = InteractiveRandom() % (this->active_playlist.size() - i);
+ std::swap(this->active_playlist[i], this->active_playlist[i + shuffle_index]);
}
- ValidatePlaylist(_settings_client.music.custom_1, lastof(_settings_client.music.custom_1));
- ValidatePlaylist(_settings_client.music.custom_2, lastof(_settings_client.music.custom_2));
+ if (_settings_client.music.playing) this->Play();
- if (BaseMusic::GetUsedSet()->num_available < _music_wnd_cursong) {
- /* If there are less songs than the currently played song,
- * just pause and reset to no song. */
- _music_wnd_cursong = 0;
- _song_is_active = false;
- }
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
-static void SkipToPrevSong()
+/** Disable shuffle and restart playback */
+void MusicSystem::Unshuffle()
{
- byte *b = _cur_playlist;
- byte *p = b;
- byte t;
+ _settings_client.music.shuffle = false;
+ this->active_playlist = this->displayed_playlist;
- if (b[0] == 0) return; // empty playlist
+ if (_settings_client.music.playing) this->Play();
- do p++; while (p[0] != 0); // find the end
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
+}
- t = *--p; // and copy the bytes
- while (p != b) {
- p--;
- p[1] = p[0];
- }
- *b = t;
+/** Start/restart playback at current song */
+void MusicSystem::Play()
+{
+ /* Always set the playing flag, even if there is no music */
+ _settings_client.music.playing = true;
+ MusicDriver::GetInstance()->StopSong();
+ /* Make sure playlist_position is a valid index, if playlist has changed etc. */
+ this->ChangePlaylistPosition(0);
+
+ /* If there is no music, don't try to play it */
+ if (this->active_playlist.empty()) return;
- _song_is_active = false;
+ MusicSongInfo song = this->active_playlist[this->playlist_position];
+ if (_game_mode == GM_MENU && this->selected_playlist == PLCH_THEMEONLY) song.loop = true;
+ MusicDriver::GetInstance()->PlaySong(song);
+
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
-static void SkipToNextSong()
+/** Stop playback and set flag that we don't intend to play music */
+void MusicSystem::Stop()
{
- byte *b = _cur_playlist;
- byte t;
-
- t = b[0];
- if (t != 0) {
- while (b[1] != 0) {
- b[0] = b[1];
- b++;
- }
- b[0] = t;
- }
+ MusicDriver::GetInstance()->StopSong();
+ _settings_client.music.playing = false;
- _song_is_active = false;
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
-static void MusicVolumeChanged(byte new_vol)
+/** Skip to next track */
+void MusicSystem::Next()
{
- MusicDriver::GetInstance()->SetVolume(new_vol);
+ this->ChangePlaylistPosition(+1);
+ if (_settings_client.music.playing) this->Play();
+
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
-static void DoPlaySong()
+/** Skip to previous track */
+void MusicSystem::Prev()
{
- char filename[MAX_PATH];
- MusicSongInfo songinfo = BaseMusic::GetUsedSet()->songinfo[_music_wnd_cursong - 1]; // copy
- if (FioFindFullPath(filename, lastof(filename), BASESET_DIR, songinfo.filename) == NULL) {
- FioFindFullPath(filename, lastof(filename), OLD_GM_DIR, songinfo.filename);
+ this->ChangePlaylistPosition(-1);
+ if (_settings_client.music.playing) this->Play();
+
+ InvalidateWindowData(WC_MUSIC_WINDOW, 0);
+}
+
+/** Check that music is playing if it should, and that appropriate playlist is active for game/main menu */
+void MusicSystem::CheckStatus()
+{
+ if ((_game_mode == GM_MENU) != (this->selected_playlist == PLCH_THEMEONLY)) {
+ /* Make sure the theme-only playlist is active when on the title screen, and not during gameplay */
+ this->ChangePlaylist((_game_mode == GM_MENU) ? PLCH_THEMEONLY : (PlaylistChoices)_settings_client.music.playlist);
}
- songinfo.filename = filename; // non-owned pointer
- songinfo.loop = (_game_mode == GM_MENU) && (_music_wnd_cursong == 1);
- MusicDriver::GetInstance()->PlaySong(songinfo);
- SetWindowDirty(WC_MUSIC_WINDOW, 0);
+ if (this->active_playlist.empty()) return;
+ /* If we were supposed to be playing, but music has stopped, move to next song */
+ if (this->IsPlaying() && !MusicDriver::GetInstance()->IsSongPlaying()) this->Next();
}
-static void DoStopMusic()
+/** Is the player getting music right now? */
+bool MusicSystem::IsPlaying() const
{
- MusicDriver::GetInstance()->StopSong();
- SetWindowDirty(WC_MUSIC_WINDOW, 0);
+ return _settings_client.music.playing && !this->active_playlist.empty();
}
-/** Reload the active playlist data from playlist selection and shuffle setting */
-static void ResetPlaylist()
+/** Is shuffle mode enabled? */
+bool MusicSystem::IsShuffle() const
{
- uint i = 0;
- uint j = 0;
-
- memset(_cur_playlist, 0, sizeof(_cur_playlist));
- do {
- /* File is the index into the file table of the music set. The play list uses 0 as 'no entry',
- * so we need to subtract 1. In case of 'no entry' (file = -1), just skip adding it outright. */
- int file = _playlists[_settings_client.music.playlist][i] - 1;
- if (file >= 0) {
- const char *filename = BaseMusic::GetUsedSet()->files[file].filename;
- /* We are now checking for the existence of that file prior
- * to add it to the list of available songs */
- if (!StrEmpty(filename) && FioCheckFileExists(filename, BASESET_DIR)) {
- _cur_playlist[j] = _playlists[_settings_client.music.playlist][i];
- j++;
- }
- }
- } while (_playlists[_settings_client.music.playlist][++i] != 0 && j < lengthof(_cur_playlist) - 1);
-
- /* Do not shuffle when on the intro-start window, as the song to play has to be the original TTD Theme*/
- if (_settings_client.music.shuffle && _game_mode != GM_MENU) {
- 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);
- }
+ return _settings_client.music.shuffle;
}
-static void StopMusic()
+/** Return the current song, or a dummy if none */
+MusicSystem::PlaylistEntry MusicSystem::GetCurrentSong() const
{
- _music_wnd_cursong = 0;
- DoStopMusic();
- _song_is_active = false;
- SetWindowWidgetDirty(WC_MUSIC_WINDOW, 0, 9);
+ if (!this->IsPlaying()) return PlaylistEntry(BaseMusic::GetUsedSet(), 0);
+ return this->active_playlist[this->playlist_position];
+}
+
+/** Is one of the custom playlists selected? */
+bool MusicSystem::IsCustomPlaylist() const
+{
+ return (this->selected_playlist == PLCH_CUSTOM1) || (this->selected_playlist == PLCH_CUSTOM2);
+}
+
+/**
+ * Append a song to a custom playlist.
+ * Always adds to the currently active playlist.
+ * @param song_index Index of song in the current music set to add
+ */
+void MusicSystem::PlaylistAdd(size_t song_index)
+{
+ if (!this->IsCustomPlaylist()) return;
+
+ /* Pick out song from the music set */
+ if (song_index >= this->music_set.size()) return;
+ PlaylistEntry entry = this->music_set[song_index];
+
+ /* Check for maximum length */
+ if (this->standard_playlists[this->selected_playlist].size() >= NUM_SONGS_PLAYLIST) return;
+
+ /* Add it to the appropriate playlist, and the display */
+ this->standard_playlists[this->selected_playlist].push_back(entry);
+ this->displayed_playlist.push_back(entry);
+
+ /* Add it to the active playlist, if playback is shuffled select a random position to add at */
+ if (this->active_playlist.empty()) {
+ this->active_playlist.push_back(entry);
+ if (this->IsPlaying()) this->Play();
+ } else if (this->IsShuffle()) {
+ /* Generate a random position between 0 and n (inclusive, new length) to insert at */
+ size_t maxpos = this->displayed_playlist.size();
+ size_t newpos = InteractiveRandom() % maxpos;
+ this->active_playlist.insert(this->active_playlist.begin() + newpos, entry);
+ /* Make sure to shift up the current playback position if the song was inserted before it */
+ if ((int)newpos <= this->playlist_position) this->playlist_position++;
+ } else {
+ this->active_playlist.push_back(entry);
+ }
+
+ this->SaveCustomPlaylist(this->selected_playlist);
+
+ InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
}
-/** Begin playing the next song on the playlist */
-static void PlayPlaylistSong()
+/**
+ * Remove a song from a custom playlist.
+ * @param song_index Index in the custom playlist to remove.
+ */
+void MusicSystem::PlaylistRemove(size_t song_index)
{
- if (_cur_playlist[0] == 0) {
- ResetPlaylist();
- /* 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;
- _settings_client.music.playing = false;
- return;
+ if (!this->IsCustomPlaylist()) return;
+
+ Playlist &pl = this->standard_playlists[this->selected_playlist];
+ if (song_index >= pl.size()) return;
+
+ /* Remove from "simple" playlists */
+ PlaylistEntry song = pl[song_index];
+ pl.erase(pl.begin() + song_index);
+ this->displayed_playlist.erase(this->displayed_playlist.begin() + song_index);
+
+ /* Find in actual active playlist (may be shuffled) and remove,
+ * if it's the current song restart playback */
+ for (size_t i = 0; i < this->active_playlist.size(); i++) {
+ Playlist::iterator s2 = this->active_playlist.begin() + i;
+ if (s2->filename == song.filename && s2->cat_index == song.cat_index) {
+ this->active_playlist.erase(s2);
+ if ((int)i == this->playlist_position && this->IsPlaying()) this->Play();
+ break;
}
}
- _music_wnd_cursong = _cur_playlist[0];
- DoPlaySong();
- _song_is_active = true;
- SetWindowWidgetDirty(WC_MUSIC_WINDOW, 0, 9);
+ this->SaveCustomPlaylist(this->selected_playlist);
+
+ InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
}
-void ResetMusic()
+/**
+ * Remove all songs from the current custom playlist.
+ * Effectively stops playback too.
+ */
+void MusicSystem::PlaylistClear()
{
- _music_wnd_cursong = 1;
- DoPlaySong();
+ if (!this->IsCustomPlaylist()) return;
+
+ this->standard_playlists[this->selected_playlist].clear();
+ this->ChangePlaylist(this->selected_playlist);
+
+ this->SaveCustomPlaylist(this->selected_playlist);
}
/**
- * Check music playback status and start/stop/song-finished.
- * Called from main loop.
+ * Change playlist position pointer by the given offset, making sure to keep it within valid range.
+ * If the playlist is empty, position is always set to 0.
+ * @param ofs Amount to move playlist position by.
*/
-void MusicLoop()
+void MusicSystem::ChangePlaylistPosition(int ofs)
{
- if (!_settings_client.music.playing && _song_is_active) {
- StopMusic();
- } else if (_settings_client.music.playing && !_song_is_active) {
- PlayPlaylistSong();
+ if (this->active_playlist.empty()) {
+ this->playlist_position = 0;
+ } else {
+ this->playlist_position += ofs;
+ while (this->playlist_position >= (int)this->active_playlist.size()) this->playlist_position -= (int)this->active_playlist.size();
+ while (this->playlist_position < 0) this->playlist_position += (int)this->active_playlist.size();
}
+}
- if (!_song_is_active) return;
+/**
+ * Save a custom playlist to settings after modification.
+ * @param pl Playlist to store back
+ */
+void MusicSystem::SaveCustomPlaylist(PlaylistChoices pl)
+{
+ byte *settings_pl;
+ if (pl == PLCH_CUSTOM1) {
+ settings_pl = _settings_client.music.custom_1;
+ } else if (pl == PLCH_CUSTOM2) {
+ settings_pl = _settings_client.music.custom_2;
+ } else {
+ return;
+ }
- if (!MusicDriver::GetInstance()->IsSongPlaying()) {
- if (_game_mode != GM_MENU) {
- StopMusic();
- SkipToNextSong();
- PlayPlaylistSong();
- } else {
- ResetMusic();
- }
+ size_t num = 0;
+ MemSetT(settings_pl, 0, NUM_SONGS_PLAYLIST);
+
+ for (Playlist::const_iterator song = this->standard_playlists[pl].begin(); song != this->standard_playlists[pl].end(); ++song) {
+ /* Music set indices in the settings playlist are 1-based, 0 means unused slot */
+ settings_pl[num++] = (byte)song->set_index + 1;
}
}
-static void SelectPlaylist(byte list)
+
+/**
+ * Check music playback status and start/stop/song-finished.
+ * Called from main loop.
+ */
+void MusicLoop()
{
- _settings_client.music.playlist = list;
- InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
- InvalidateWindowData(WC_MUSIC_WINDOW, 0);
+ _music.CheckStatus();
}
/**
@@ -316,29 +432,20 @@ static void SelectPlaylist(byte list)
void ChangeMusicSet(int index)
{
if (BaseMusic::GetIndexOfUsedSet() == index) return;
-
- /* Resume playback after switching?
- * Always if music is already playing, and also if the user is switching
- * away from an empty music set.
- * If the user switches away from an empty set, assume it's because they
- * want to hear music now. */
- bool shouldplay = _song_is_active || (BaseMusic::GetUsedSet()->num_available == 0);
- StopMusic();
-
const char *name = BaseMusic::GetSet(index)->name;
- BaseMusic::SetSet(name);
- free(BaseMusic::ini_set);
- BaseMusic::ini_set = stredup(name);
-
- InitializeMusic();
- ResetPlaylist();
- _settings_client.music.playing = shouldplay;
+ _music.ChangeMusicSet(name);
+}
- InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
- InvalidateWindowData(WC_MUSIC_WINDOW, 0);
- InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
+/**
+ * Prepare the music system for use.
+ * Called from \c InitializeGame
+ */
+void InitializeMusic()
+{
+ _music.BuildPlaylists();
}
+
struct MusicTrackSelectionWindow : public Window {
MusicTrackSelectionWindow(WindowDesc *desc, WindowNumber number) : Window(desc)
{
@@ -395,13 +502,10 @@ struct MusicTrackSelectionWindow : public Window {
case WID_MTS_LIST_LEFT: case WID_MTS_LIST_RIGHT: {
Dimension d = {0, 0};
- for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
- const char *song_name = GetSongName(i);
- if (StrEmpty(song_name)) continue;
-
- SetDParam(0, GetTrackNumber(i));
+ for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
+ SetDParam(0, song->tracknr);
SetDParam(1, 2);
- SetDParamStr(2, GetSongName(i));
+ SetDParamStr(2, song->songname);
Dimension d2 = GetStringBoundingBox(STR_PLAYLIST_TRACK_NAME);
d.width = max(d.width, d2.width);
d.height += d2.height;
@@ -421,13 +525,10 @@ struct MusicTrackSelectionWindow : public Window {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
int y = r.top + WD_FRAMERECT_TOP;
- for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
- const char *song_name = GetSongName(i);
- if (StrEmpty(song_name)) continue;
-
- SetDParam(0, GetTrackNumber(i));
+ for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
+ SetDParam(0, song->tracknr);
SetDParam(1, 2);
- SetDParamStr(2, song_name);
+ SetDParamStr(2, song->songname);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
y += FONT_HEIGHT_SMALL;
}
@@ -438,11 +539,10 @@ struct MusicTrackSelectionWindow : public Window {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
int y = r.top + WD_FRAMERECT_TOP;
- for (const byte *p = _playlists[_settings_client.music.playlist]; *p != 0; p++) {
- uint i = *p - 1;
- SetDParam(0, GetTrackNumber(i));
+ for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
+ SetDParam(0, song->tracknr);
SetDParam(1, 2);
- SetDParamStr(2, GetSongName(i));
+ SetDParamStr(2, song->songname);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
y += FONT_HEIGHT_SMALL;
}
@@ -456,42 +556,13 @@ struct MusicTrackSelectionWindow : public Window {
switch (widget) {
case WID_MTS_LIST_LEFT: { // add to playlist
int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
-
- if (_settings_client.music.playlist < 4) return;
- if (!IsInsideMM(y, 0, BaseMusic::GetUsedSet()->num_available)) return;
-
- byte *p = _playlists[_settings_client.music.playlist];
- for (uint i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
- if (p[i] == 0) {
- /* Find the actual song number */
- for (uint j = 0; j < NUM_SONGS_AVAILABLE; j++) {
- if (GetTrackNumber(j) == y + 1) {
- p[i] = j + 1;
- break;
- }
- }
- p[i + 1] = 0;
- this->SetDirty();
- ResetPlaylist();
- break;
- }
- }
+ _music.PlaylistAdd(y);
break;
}
case WID_MTS_LIST_RIGHT: { // remove from playlist
int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
-
- if (_settings_client.music.playlist < 4) return;
- if (!IsInsideMM(y, 0, NUM_SONGS_PLAYLIST)) return;
-
- byte *p = _playlists[_settings_client.music.playlist];
- for (uint i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
- p[i] = p[i + 1];
- }
-
- this->SetDirty();
- ResetPlaylist();
+ _music.PlaylistRemove(y);
break;
}
@@ -503,17 +574,12 @@ struct MusicTrackSelectionWindow : public Window {
}
case WID_MTS_CLEAR: // clear
- for (uint i = 0; _playlists[_settings_client.music.playlist][i] != 0; i++) _playlists[_settings_client.music.playlist][i] = 0;
- this->SetDirty();
- StopMusic();
- ResetPlaylist();
+ _music.PlaylistClear();
break;
case WID_MTS_ALL: case WID_MTS_OLD: case WID_MTS_NEW:
case WID_MTS_EZY: case WID_MTS_CUSTOM1: case WID_MTS_CUSTOM2: // set playlist
- SelectPlaylist(widget - WID_MTS_ALL);
- StopMusic();
- ResetPlaylist();
+ _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_MTS_ALL));
break;
}
}
@@ -628,8 +694,8 @@ struct MusicWindow : public Window {
case WID_M_TRACK_NAME: {
Dimension d = GetStringBoundingBox(STR_MUSIC_TITLE_NONE);
- for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
- SetDParamStr(0, GetSongName(i));
+ for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
+ SetDParamStr(0, song->songname);
d = maxdim(d, GetStringBoundingBox(STR_MUSIC_TITLE_NAME));
}
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
@@ -655,8 +721,8 @@ struct MusicWindow : public Window {
break;
}
StringID str = STR_MUSIC_TRACK_NONE;
- if (_song_is_active != 0 && _music_wnd_cursong != 0) {
- SetDParam(0, GetTrackNumber(_music_wnd_cursong - 1));
+ if (_music.IsPlaying()) {
+ SetDParam(0, _music.GetCurrentSong().tracknr);
SetDParam(1, 2);
str = STR_MUSIC_TRACK_DIGIT;
}
@@ -669,9 +735,9 @@ struct MusicWindow : public Window {
StringID str = STR_MUSIC_TITLE_NONE;
if (BaseMusic::GetUsedSet()->num_available == 0) {
str = STR_MUSIC_TITLE_NOMUSIC;
- } else if (_song_is_active != 0 && _music_wnd_cursong != 0) {
+ } else if (_music.IsPlaying()) {
str = STR_MUSIC_TITLE_NAME;
- SetDParamStr(0, GetSongName(_music_wnd_cursong - 1));
+ SetDParamStr(0, _music.GetCurrentSong().songname);
}
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_FROMSTRING, SA_HOR_CENTER);
break;
@@ -711,23 +777,19 @@ struct MusicWindow : public Window {
{
switch (widget) {
case WID_M_PREV: // skip to prev
- if (!_song_is_active) return;
- SkipToPrevSong();
- this->SetDirty();
+ _music.Prev();
break;
case WID_M_NEXT: // skip to next
- if (!_song_is_active) return;
- SkipToNextSong();
- this->SetDirty();
+ _music.Next();
break;
case WID_M_STOP: // stop playing
- _settings_client.music.playing = false;
+ _music.Stop();
break;
case WID_M_PLAY: // start playing
- _settings_client.music.playing = true;
+ _music.Play();
break;
case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { // volume sliders
@@ -742,7 +804,7 @@ struct MusicWindow : public Window {
if (new_vol < 3) new_vol = 0;
if (new_vol != *vol) {
*vol = new_vol;
- if (widget == WID_M_MUSIC_VOL) MusicVolumeChanged(new_vol);
+ if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(new_vol);
this->SetDirty();
}
@@ -751,12 +813,13 @@ struct MusicWindow : public Window {
}
case WID_M_SHUFFLE: // toggle shuffle
- _settings_client.music.shuffle ^= 1;
- this->SetWidgetLoweredState(WID_M_SHUFFLE, _settings_client.music.shuffle);
+ if (_music.IsShuffle()) {
+ _music.Unshuffle();
+ } else {
+ _music.Shuffle();
+ }
+ this->SetWidgetLoweredState(WID_M_SHUFFLE, _music.IsShuffle());
this->SetWidgetDirty(WID_M_SHUFFLE);
- StopMusic();
- ResetPlaylist();
- this->SetDirty();
break;
case WID_M_PROGRAMME: // show track selection
@@ -765,10 +828,7 @@ struct MusicWindow : public Window {
case WID_M_ALL: case WID_M_OLD: case WID_M_NEW:
case WID_M_EZY: case WID_M_CUSTOM1: case WID_M_CUSTOM2: // playlist
- SelectPlaylist(widget - WID_M_ALL);
- StopMusic();
- ResetPlaylist();
- this->SetDirty();
+ _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_M_ALL));
break;
}
}