diff --git a/src/actions.cpp b/src/actions.cpp index 99c62a7e..b44c3a73 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -221,7 +221,7 @@ void resizeScreen(bool reload_main_window) applyToVisibleWindows(&BaseScreen::refresh); - Status::Changes::elapsedTime(); + Status::Changes::elapsedTime(false); Status::Changes::playerState(); // Note: routines for drawing separator if alternative user // interface is active and header is hidden are placed in @@ -350,13 +350,14 @@ void MouseEvent::run() && m_mouse_event.y == LINES-(Config.statusbar_visibility ? 2 : 1) ) // progressbar { - if (MpdStatus.playerState() == MPD::psStop) + if (Status::State::player() == MPD::psStop) return; - Mpd.Seek(MpdStatus.totalTime()*m_mouse_event.x/double(COLS)); + Mpd.Seek(myPlaylist->currentSongPosition(), + myPlaylist->currentSongLength()*m_mouse_event.x/double(COLS)); } else if (m_mouse_event.bstate & BUTTON1_PRESSED && (Config.statusbar_visibility || Config.new_design) - && MpdStatus.playerState() != MPD::psStop + && Status::State::player() != MPD::psStop && m_mouse_event.y == (Config.new_design ? 1 : LINES-1) && m_mouse_event.x < 9 ) // playing/paused { @@ -368,9 +369,9 @@ void MouseEvent::run() ) // volume { if (m_mouse_event.bstate & BUTTON2_PRESSED) - Mpd.SetVolume(MpdStatus.volume()-2); + get(Type::VolumeDown)->execute(); else - Mpd.SetVolume(MpdStatus.volume()+2); + get(Type::VolumeUp)->execute(); } else if (m_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON2_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED)) myScreen->mouseButtonPressed(m_mouse_event); @@ -513,7 +514,7 @@ void ToggleInterface::run() Statusbar::unlock(); resizeScreen(false); Status::Changes::mixer(); - Status::Changes::elapsedTime(); + Status::Changes::elapsedTime(false); Statusbar::msg("User interface: %s", Config.new_design ? "Alternative" : "Classic"); } @@ -624,13 +625,13 @@ void SlaveScreen::run() void VolumeUp::run() { - int volume = std::min(MpdStatus.volume()+Config.volume_change_step, 100); + int volume = std::min(Status::State::volume()+Config.volume_change_step, 100); Mpd.SetVolume(volume); } void VolumeDown::run() { - int volume = std::max(MpdStatus.volume()-Config.volume_change_step, 0); + int volume = std::max(Status::State::volume()-Config.volume_change_step, 0); Mpd.SetVolume(volume); } @@ -748,8 +749,8 @@ void DeleteStoredPlaylist::run() void ReplaySong::run() { - if (MpdStatus.playerState() != MPD::psStop) - Mpd.Seek(0); + if (Status::State::player() != MPD::psStop) + Mpd.Seek(myPlaylist->currentSongPosition(), 0); } void PreviousSong::run() @@ -977,7 +978,7 @@ void Add::run() bool SeekForward::canBeRun() const { - return MpdStatus.playerState() != MPD::psStop && MpdStatus.totalTime() > 0; + return Status::State::player() != MPD::psStop && myPlaylist->currentSongLength() > 0; } void SeekForward::run() @@ -987,7 +988,7 @@ void SeekForward::run() bool SeekBackward::canBeRun() const { - return MpdStatus.playerState() != MPD::psStop && MpdStatus.totalTime() > 0; + return Status::State::player() != MPD::psStop && myPlaylist->currentSongLength() > 0; } void SeekBackward::run() @@ -1093,9 +1094,9 @@ void TogglePlayingSongCentering::run() Config.autocenter_mode = !Config.autocenter_mode; Statusbar::msg("Centering playing song: %s", Config.autocenter_mode ? "On" : "Off"); if (Config.autocenter_mode - && MpdStatus.playerState() != MPD::psStop + && Status::State::player() != MPD::psStop && !myPlaylist->main().isFiltered()) - myPlaylist->main().highlight(MpdStatus.currentSongPosition()); + myPlaylist->main().highlight(myPlaylist->currentSongPosition()); } void UpdateDatabase::run() @@ -1115,13 +1116,13 @@ bool JumpToPlayingSong::canBeRun() const return ((myScreen == myPlaylist && !myPlaylist->isFiltered()) || myScreen == myBrowser || myScreen == myLibrary) - && MpdStatus.playerState() != MPD::psStop; + && Status::State::player() != MPD::psStop; } void JumpToPlayingSong::run() { if (myScreen == myPlaylist) - myPlaylist->main().highlight(MpdStatus.currentSongPosition()); + myPlaylist->main().highlight(myPlaylist->currentSongPosition()); else if (myScreen == myBrowser) { myBrowser->LocateSong(myPlaylist->nowPlayingSong()); @@ -1135,7 +1136,7 @@ void JumpToPlayingSong::run() void ToggleRepeat::run() { - Mpd.SetRepeat(!MpdStatus.repeat()); + Mpd.SetRepeat(!Status::State::repeat()); } void Shuffle::run() @@ -1145,7 +1146,7 @@ void Shuffle::run() void ToggleRandom::run() { - Mpd.SetRandom(!MpdStatus.random()); + Mpd.SetRandom(!Status::State::random()); } bool StartSearching::canBeRun() const @@ -1190,17 +1191,17 @@ void SaveTagChanges::run() void ToggleSingle::run() { - Mpd.SetSingle(!MpdStatus.single()); + Mpd.SetSingle(!Status::State::single()); } void ToggleConsume::run() { - Mpd.SetConsume(!MpdStatus.consume()); + Mpd.SetConsume(!Status::State::consume()); } void ToggleCrossfade::run() { - Mpd.SetCrossfade(MpdStatus.crossfade() ? 0 : Config.crossfade_time); + Mpd.SetCrossfade(Status::State::crossfade() ? 0 : Config.crossfade_time); } void SetCrossfade::run() @@ -1575,7 +1576,7 @@ void JumpToTagEditor::run() bool JumpToPositionInSong::canBeRun() const { - return MpdStatus.playerState() != MPD::psStop && MpdStatus.totalTime() > 0; + return Status::State::player() != MPD::psStop && myPlaylist->currentSongLength() > 0; } void JumpToPositionInSong::run() @@ -1597,16 +1598,16 @@ void JumpToPositionInSong::run() { newpos = boost::lexical_cast(position)*60 + boost::lexical_cast(position.substr(position.find(':')+1)); - if (newpos <= MpdStatus.totalTime()) - Mpd.Seek(newpos); + if (newpos <= myPlaylist->currentSongLength()) + Mpd.Seek(s.getPosition(), newpos); else Statusbar::msg("Out of bounds, 0:00-%s possible for mm:ss, %s given", s.getLength().c_str(), MPD::Song::ShowTime(newpos).c_str()); } else if (position.find('s') != std::string::npos) // probably position in seconds { newpos = boost::lexical_cast(position); - if (newpos <= MpdStatus.totalTime()) - Mpd.Seek(newpos); + if (newpos <= s.getDuration()) + Mpd.Seek(s.getPosition(), newpos); else Statusbar::msg("Out of bounds, 0-%d possible for seconds, %d given", s.getDuration(), newpos); } @@ -1614,7 +1615,7 @@ void JumpToPositionInSong::run() { newpos = boost::lexical_cast(position); if (newpos <= 100) - Mpd.Seek(MpdStatus.totalTime()*newpos/100.0); + Mpd.Seek(s.getPosition(), s.getDuration()*newpos/100.0); else Statusbar::msg("Out of bounds, 0-100 possible for %%, %d given", newpos); } @@ -2591,7 +2592,7 @@ void seek() using Global::Timer; using Global::SeekingInProgress; - if (!MpdStatus.totalTime()) + if (!myPlaylist->currentSongLength()) { Statusbar::msg("Unknown item length"); return; @@ -2600,7 +2601,7 @@ void seek() Progressbar::lock(); Statusbar::lock(); - unsigned songpos = MpdStatus.elapsedTime(); + unsigned songpos = Status::State::elapsedTime(); timeval t = Timer; int old_timeout = wFooter->getTimeout(); @@ -2624,8 +2625,8 @@ void seek() auto a = k.first->action(); if (a == seekForward) { - if (songpos < MpdStatus.totalTime()) - songpos = std::min(songpos + howmuch, MpdStatus.totalTime()); + if (songpos < myPlaylist->currentSongLength()) + songpos = std::min(songpos + howmuch, myPlaylist->currentSongLength()); } else if (a == seekBackward) { @@ -2647,12 +2648,12 @@ void seek() if (Config.display_remaining_time) { tracklength = "-"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-songpos); + tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()-songpos); } else tracklength = MPD::Song::ShowTime(songpos); tracklength += "/"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()); + tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()); *wHeader << NC::XY(0, 0) << tracklength << " "; wHeader->refresh(); } @@ -2662,21 +2663,21 @@ void seek() if (Config.display_remaining_time) { tracklength += "-"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-songpos); + tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()-songpos); } else tracklength += MPD::Song::ShowTime(songpos); tracklength += "/"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()); + tracklength += MPD::Song::ShowTime(myPlaylist->currentSongLength()); tracklength += "]"; *wFooter << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength; } *wFooter << NC::Format::NoBold; - Progressbar::draw(songpos, MpdStatus.totalTime()); + Progressbar::draw(songpos, myPlaylist->currentSongLength()); wFooter->refresh(); } SeekingInProgress = false; - Mpd.Seek(songpos); + Mpd.Seek(myPlaylist->currentSongPosition(), songpos); wFooter->setTimeout(old_timeout); diff --git a/src/display.cpp b/src/display.cpp index c3c9c1b0..cfa1f550 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -97,8 +97,8 @@ void setProperties(NC::Menu &menu, const MPD::Song &s, const ProxySongList &p discard_colors = Config.discard_colors_if_item_is_selected && is_selected; int song_pos = menu.isFiltered() ? s.getPosition() : drawn_pos; - is_now_playing = MpdStatus.playerState() != MPD::psStop && myPlaylist->isActiveWindow(menu) - && song_pos == MpdStatus.currentSongPosition(); + is_now_playing = Status::State::player() != MPD::psStop && myPlaylist->isActiveWindow(menu) + && song_pos == myPlaylist->currentSongPosition(); if (is_now_playing) menu << Config.now_playing_prefix; } diff --git a/src/mpdpp.cpp b/src/mpdpp.cpp index 67de2a1c..e0273f1b 100644 --- a/src/mpdpp.cpp +++ b/src/mpdpp.cpp @@ -28,7 +28,6 @@ #include "mpdpp.h" MPD::Connection Mpd; -MPD::Status MpdStatus; namespace MPD {// @@ -399,10 +398,10 @@ void Connection::Swap(unsigned from, unsigned to) } } -void Connection::Seek(unsigned where) +void Connection::Seek(unsigned pos, unsigned where) { prechecksNoCommandsList(); - mpd_run_seek_pos(m_connection, MpdStatus.currentSongPosition(), where); + mpd_run_seek_pos(m_connection, pos, where); checkErrors(); } diff --git a/src/mpdpp.h b/src/mpdpp.h index 9495be67..6e783e69 100644 --- a/src/mpdpp.h +++ b/src/mpdpp.h @@ -187,7 +187,7 @@ public: void Prev(); void Move(unsigned int from, unsigned int to); void Swap(unsigned, unsigned); - void Seek(unsigned); + void Seek(unsigned int pos, unsigned int where); void Shuffle(); void ClearMainPlaylist(); @@ -279,6 +279,5 @@ private: } extern MPD::Connection Mpd; -extern MPD::Status MpdStatus; #endif // NCMPCPP_MPDPP_H diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index e4456a02..72d71989 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -200,18 +200,15 @@ int main(int argc, char **argv) Mpd.Connect(); if (Mpd.Version() < 16) { - // FIXME workaround so we won't get assertion fails - MpdStatus = Mpd.getStatus(); Mpd.Disconnect(); throw MPD::ClientError(MPD_ERROR_STATE, "MPD < 0.16.0 is not supported", false); } - MpdStatus.clear(); wFooter->addFDCallback(Mpd.GetFD(), Statusbar::Helpers::mpd); Status::update(-1); // we need info about new connection if (Config.jump_to_now_playing_song_at_start) { - int curr_pos = MpdStatus.currentSongPosition(); + int curr_pos = myPlaylist->currentSongPosition(); if (curr_pos >= 0) myPlaylist->main().highlight(curr_pos); } diff --git a/src/playlist.cpp b/src/playlist.cpp index 3243e9ff..1f758f2e 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -223,9 +223,9 @@ MPD::SongList Playlist::getSelectedSongs() MPD::Song Playlist::nowPlayingSong() { MPD::Song s; - if (MpdStatus.playerState() != MPD::psStop) + if (Status::State::player() != MPD::psStop) withUnfilteredMenu(w, [this, &s]() { - s = w.at(MpdStatus.currentSongPosition()).value(); + s = w.at(currentSongPosition()).value(); }); return s; } @@ -277,7 +277,7 @@ std::string Playlist::TotalLength() if (Config.playlist_show_remaining_time && ReloadRemaining && !w.isFiltered()) { itsRemainingTime = 0; - for (size_t i = MpdStatus.currentSongPosition(); i < w.size(); ++i) + for (size_t i = currentSongPosition(); i < w.size(); ++i) itsRemainingTime += w[i].value().getDuration(); ReloadRemaining = false; } @@ -330,6 +330,26 @@ void Playlist::SetSelectedItemsPriority(int prio) Statusbar::msg("Priority set"); } +void Playlist::setStatus(MPD::Status status) +{ + m_status = status; +} + +unsigned int Playlist::version() const +{ + return m_status.empty() ? 0 : m_status.playlistVersion(); +} + +int Playlist::currentSongPosition() const +{ + return m_status.empty() ? -1 : m_status.currentSongPosition(); +} + +unsigned Playlist::currentSongLength() const +{ + return m_status.empty() ? 0 : m_status.totalTime(); +} + bool Playlist::checkForSong(const MPD::Song &s) { return itsSongHashes.find(s.getHash()) != itsSongHashes.end(); @@ -337,7 +357,7 @@ bool Playlist::checkForSong(const MPD::Song &s) void Playlist::registerHash(size_t hash) { - itsSongHashes[hash] += 1; + ++itsSongHashes[hash]; } void Playlist::unregisterHash(size_t hash) @@ -347,7 +367,7 @@ void Playlist::unregisterHash(size_t hash) if (it->second == 1) itsSongHashes.erase(it); else - it->second -= 1; + --it->second; } namespace {// diff --git a/src/playlist.h b/src/playlist.h index 6fc32fc3..55c7a2c5 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -78,8 +78,12 @@ struct Playlist: Screen>, Filterable, HasSongs, Searchable, void SetSelectedItemsPriority(int prio); - bool checkForSong(const MPD::Song &s); + void setStatus(MPD::Status status); + unsigned version() const; + int currentSongPosition() const; + unsigned currentSongLength() const; + bool checkForSong(const MPD::Song &s); void registerHash(size_t hash); void unregisterHash(size_t hash); @@ -101,6 +105,8 @@ private: size_t itsScrollBegin; time_t itsTimer; + + MPD::Status m_status; }; extern Playlist *myPlaylist; diff --git a/src/sel_items_adder.cpp b/src/sel_items_adder.cpp index 8643b0cb..b14a6978 100644 --- a/src/sel_items_adder.cpp +++ b/src/sel_items_adder.cpp @@ -253,9 +253,9 @@ void SelectedItemsAdder::addAtTheBeginningOfPlaylist() const void SelectedItemsAdder::addAfterCurrentSong() const { - if (MpdStatus.playerState() == MPD::psStop) + if (Status::State::player() == MPD::psStop) return; - size_t pos = MpdStatus.currentSongPosition(); + size_t pos = myPlaylist->currentSongPosition(); ++pos; addSongsToPlaylist(m_selected_items, false, pos); exitSuccessfully(); @@ -263,10 +263,10 @@ void SelectedItemsAdder::addAfterCurrentSong() const void SelectedItemsAdder::addAfterCurrentAlbum() const { - if (MpdStatus.playerState() == MPD::psStop) + if (Status::State::player() == MPD::psStop) return; auto &pl = myPlaylist->main(); - size_t pos = MpdStatus.currentSongPosition(); + size_t pos = myPlaylist->currentSongPosition(); withUnfilteredMenu(pl, [&pos, &pl]() { std::string album = pl[pos].value().getAlbum(); while (pos < pl.size() && pl[pos].value().getAlbum() == album) diff --git a/src/status.cpp b/src/status.cpp index e4109ed4..9e99085c 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -54,14 +54,18 @@ timeval past = { 0, 0 }; size_t playing_song_scroll_begin = 0; size_t first_line_scroll_begin = 0; size_t second_line_scroll_begin = 0; -std::string player_state; -char mpd_repeat; -char mpd_random; -char mpd_single; -char mpd_consume; -char mpd_crossfade; -char mpd_db_updating; +char m_repeat = 0; +char m_random = 0; +char m_single = 0; +char m_consume = 0; +char m_crossfade = 0; +char m_db_updating = 0; + +MPD::Status m_status; +MPD::PlayerState m_player_state = MPD::psUnknown; +int m_volume = -1; +unsigned m_elapsed_time = 0; void drawTitle(const MPD::Song &np) { @@ -69,6 +73,36 @@ void drawTitle(const MPD::Song &np) windowTitle(np.toString(Config.song_window_title_format, Config.tags_separator)); } +std::string playerStateToString(MPD::PlayerState ps) +{ + std::string result; + switch (ps) + { + case MPD::psUnknown: + result = "[unknown]"; + break; + case MPD::psPlay: + if (Config.new_design) + result = "[playing]"; + else + result = "Playing: "; + break; + case MPD::psPause: + if (Config.new_design) + result = "[paused] "; + else + result = "[Paused] "; + break; + case MPD::psStop: + if (Config.new_design) + result = "[stopped]"; + break; + default: + break; + } + return result; +} + } void Status::handleClientError(MPD::ClientError &e) @@ -97,16 +131,17 @@ void Status::handleServerError(MPD::ServerError &e) Statusbar::msg("MPD: %s", e.what()); } +/*************************************************************************/ + void Status::trace() { gettimeofday(&Timer, 0); if (Mpd.Connected()) { - if (MpdStatus.playerState() == MPD::psPlay && Global::Timer.tv_sec > past.tv_sec) + if (State::player() == MPD::psPlay && Global::Timer.tv_sec > past.tv_sec) { // update elapsed time/bitrate of the current song - MpdStatus = Mpd.getStatus(); - Status::Changes::elapsedTime(); + Status::Changes::elapsedTime(true); wFooter->refresh(); past = Timer; } @@ -128,11 +163,103 @@ void Status::trace() } } +void Status::update(int event) +{ + MPD::Status old_status = m_status; + m_status = Mpd.getStatus(); + + if (event & MPD_IDLE_DATABASE) + Changes::database(); + if (event & MPD_IDLE_STORED_PLAYLIST) + Changes::storedPlaylists(); + if (event & MPD_IDLE_PLAYLIST) + Changes::playlist(); + if (event & MPD_IDLE_PLAYER) + { + Changes::playerState(); + if (old_status.empty() || old_status.currentSongID() != m_status.currentSongID()) + Changes::songID(); + } + if (event & MPD_IDLE_MIXER) + Changes::mixer(); + if (event & MPD_IDLE_OUTPUT) + Changes::outputs(); + if (event & (MPD_IDLE_UPDATE | MPD_IDLE_OPTIONS)) + { + if (event & MPD_IDLE_UPDATE) + Changes::dbUpdateState(!old_status.empty()); + if (event & MPD_IDLE_OPTIONS) + { + if (old_status.empty() || old_status.repeat() != m_status.repeat()) + Changes::repeat(!old_status.empty()); + if (old_status.empty() || old_status.random() != m_status.random()) + Changes::random(!old_status.empty()); + if (old_status.empty() || old_status.single() != m_status.single()) + Changes::single(!old_status.empty()); + if (old_status.empty() || old_status.consume() != m_status.consume()) + Changes::consume(!old_status.empty()); + if (old_status.empty() || old_status.crossfade() != m_status.crossfade()) + Changes::crossfade(!old_status.empty()); + } + Changes::flags(); + } + + if (event & MPD_IDLE_PLAYER) + wFooter->refresh(); + + if (event & (MPD_IDLE_PLAYLIST | MPD_IDLE_DATABASE | MPD_IDLE_PLAYER)) + applyToVisibleWindows(&BaseScreen::refreshWindow); +} + +/*************************************************************************/ + +bool Status::State::repeat() +{ + return m_repeat; +} + +bool Status::State::random() +{ + return m_random; +} + +bool Status::State::single() +{ + return m_single; +} + +bool Status::State::consume() +{ + return m_consume; +} + +bool Status::State::crossfade() +{ + return m_crossfade; +} + +MPD::PlayerState Status::State::player() +{ + return m_player_state; +} + +int Status::State::volume() +{ + return m_volume; +} + +unsigned int Status::State::elapsedTime() +{ + return m_elapsed_time; +} + +/*************************************************************************/ + void Status::Changes::playlist() { myPlaylist->main().clearSearchResults(); withUnfilteredMenuReapplyFilter(myPlaylist->main(), []() { - size_t playlist_length = MpdStatus.playlistLength(); + size_t playlist_length = m_status.playlistLength(); if (playlist_length < myPlaylist->main().size()) { auto it = myPlaylist->main().begin()+playlist_length; @@ -142,7 +269,7 @@ void Status::Changes::playlist() myPlaylist->main().resizeList(playlist_length); } - Mpd.GetPlaylistChanges(myPlaylist->Version, [](MPD::Song &&s) { + Mpd.GetPlaylistChanges(myPlaylist->version(), [](MPD::Song &&s) { size_t pos = s.getPosition(); if (pos < myPlaylist->main().size()) { @@ -156,10 +283,10 @@ void Status::Changes::playlist() myPlaylist->registerHash(s.getHash()); }); - myPlaylist->Version = MpdStatus.playlistVersion(); + myPlaylist->setStatus(m_status); }); - if (MpdStatus.playerState() != MPD::psStop) + if (State::player() != MPD::psStop) drawTitle(myPlaylist->nowPlayingSong()); Playlist::ReloadTotalLength = true; @@ -203,28 +330,15 @@ void Status::Changes::database() void Status::Changes::playerState() { - MPD::PlayerState state = MpdStatus.playerState(); - switch (state) + m_player_state = m_status.playerState(); + + switch (State::player()) { - case MPD::psUnknown: - { - player_state = "[unknown]"; - break; - } case MPD::psPlay: - { drawTitle(myPlaylist->nowPlayingSong()); - player_state = Config.new_design ? "[playing]" : "Playing: "; Playlist::ReloadRemaining = true; break; - } - case MPD::psPause: - { - player_state = Config.new_design ? "[paused] " : "[Paused] "; - break; - } case MPD::psStop: - { windowTitle("ncmpcpp " VERSION); if (Progressbar::isUnlocked()) Progressbar::draw(0, 0); @@ -232,47 +346,48 @@ void Status::Changes::playerState() if (Config.new_design) { *wHeader << NC::XY(0, 0) << wclrtoeol << NC::XY(0, 1) << wclrtoeol; - player_state = "[stopped]"; mixer(); flags(); } - else - player_state.clear(); # ifdef ENABLE_VISUALIZER if (isVisible(myVisualizer)) myVisualizer->main().clear(); # endif // ENABLE_VISUALIZER break; - } + default: + break; } # ifdef ENABLE_VISUALIZER if (myScreen == myVisualizer) - wFooter->setTimeout(state == MPD::psPlay ? Visualizer::WindowTimeout : 500); + wFooter->setTimeout(State::player() == MPD::psPlay ? Visualizer::WindowTimeout : 500); # endif // ENABLE_VISUALIZER + std::string state = playerStateToString(State::player()); if (Config.new_design) { - *wHeader << NC::XY(0, 1) << NC::Format::Bold << player_state << NC::Format::NoBold; + *wHeader << NC::XY(0, 1) << NC::Format::Bold << state << NC::Format::NoBold; wHeader->refresh(); } else if (Statusbar::isUnlocked() && Config.statusbar_visibility) { *wFooter << NC::XY(0, 1); - if (player_state.empty()) + if (state.empty()) *wFooter << wclrtoeol; else - *wFooter << NC::Format::Bold << player_state << NC::Format::NoBold; + *wFooter << NC::Format::Bold << state << NC::Format::NoBold; } } void Status::Changes::songID() { + // update information about current song + myPlaylist->setStatus(m_status); Playlist::ReloadRemaining = true; playing_song_scroll_begin = 0; first_line_scroll_begin = 0; second_line_scroll_begin = 0; - if (MpdStatus.playerState() != MPD::psStop) + if (State::player() != MPD::psStop) { GNUC_UNUSED int res; if (!Config.execute_on_song_change.empty()) @@ -286,23 +401,31 @@ void Status::Changes::songID() drawTitle(myPlaylist->nowPlayingSong()); if (Config.autocenter_mode && !myPlaylist->main().isFiltered()) - myPlaylist->main().highlight(MpdStatus.currentSongPosition()); + myPlaylist->main().highlight(myPlaylist->currentSongPosition()); if (Config.now_playing_lyrics && isVisible(myLyrics) && myLyrics->previousScreen() == myPlaylist) myLyrics->ReloadNP = 1; } - elapsedTime(); + elapsedTime(false); } -void Status::Changes::elapsedTime() +void Status::Changes::elapsedTime(bool update_elapsed) { - if (MpdStatus.playerState() == MPD::psStop) + MPD::Status st = m_status; + if (update_elapsed) + { + st = Mpd.getStatus(); + m_elapsed_time = st.elapsedTime(); + } + + if (st.playerState() == MPD::psStop) { if (Statusbar::isUnlocked() && Config.statusbar_visibility) *wFooter << NC::XY(0, 1) << wclrtoeol; return; } + std::string ps = playerStateToString(st.playerState()); MPD::Song np = myPlaylist->nowPlayingSong(); drawTitle(np); @@ -312,20 +435,20 @@ void Status::Changes::elapsedTime() if (Config.display_remaining_time) { tracklength = "-"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-MpdStatus.elapsedTime()); + tracklength += MPD::Song::ShowTime(st.totalTime()-st.elapsedTime()); } else - tracklength = MPD::Song::ShowTime(MpdStatus.elapsedTime()); - if (MpdStatus.totalTime()) + tracklength = MPD::Song::ShowTime(st.elapsedTime()); + if (st.totalTime()) { tracklength += "/"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()); + tracklength += MPD::Song::ShowTime(st.totalTime()); } // bitrate here doesn't look good, but it can be moved somewhere else later - if (Config.display_bitrate && MpdStatus.kbps()) + if (Config.display_bitrate && st.kbps()) { tracklength += " "; - tracklength += boost::lexical_cast(MpdStatus.kbps()); + tracklength += boost::lexical_cast(st.kbps()); tracklength += " kbps"; } @@ -338,17 +461,17 @@ void Status::Changes::elapsedTime() size_t first_start = first_len < COLS-first_margin ? (COLS-first_len)/2 : tracklength.length()+1; size_t second_len = wideLength(second.str()); - size_t second_margin = (std::max(player_state.length(), size_t(8))+1)*2; - size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : player_state.length()+1; + size_t second_margin = (std::max(ps.length(), size_t(8))+1)*2; + size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : ps.length()+1; if (!Global::SeekingInProgress) *wHeader << NC::XY(0, 0) << wclrtoeol << tracklength; *wHeader << NC::XY(first_start, 0); writeCyclicBuffer(first, *wHeader, first_line_scroll_begin, COLS-tracklength.length()-VolumeState.length()-1, L" ** "); - *wHeader << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << player_state << NC::Format::NoBold; + *wHeader << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << ps << NC::Format::NoBold; *wHeader << NC::XY(second_start, 1); - writeCyclicBuffer(second, *wHeader, second_line_scroll_begin, COLS-player_state.length()-8-2, L" ** "); + writeCyclicBuffer(second, *wHeader, second_line_scroll_begin, COLS-ps.length()-8-2, L" ** "); *wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << Config.volume_color << VolumeState << NC::Color::End; @@ -356,82 +479,82 @@ void Status::Changes::elapsedTime() } else if (Statusbar::isUnlocked() && Config.statusbar_visibility) { - if (Config.display_bitrate && MpdStatus.kbps()) + if (Config.display_bitrate && st.kbps()) { tracklength += " ["; - tracklength += boost::lexical_cast(MpdStatus.kbps()); + tracklength += boost::lexical_cast(st.kbps()); tracklength += " kbps]"; } tracklength += " ["; - if (MpdStatus.totalTime()) + if (st.totalTime()) { if (Config.display_remaining_time) { tracklength += "-"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()-MpdStatus.elapsedTime()); + tracklength += MPD::Song::ShowTime(st.totalTime()-st.elapsedTime()); } else - tracklength += MPD::Song::ShowTime(MpdStatus.elapsedTime()); + tracklength += MPD::Song::ShowTime(st.elapsedTime()); tracklength += "/"; - tracklength += MPD::Song::ShowTime(MpdStatus.totalTime()); + tracklength += MPD::Song::ShowTime(st.totalTime()); tracklength += "]"; } else { - tracklength += MPD::Song::ShowTime(MpdStatus.elapsedTime()); + tracklength += MPD::Song::ShowTime(st.elapsedTime()); tracklength += "]"; } NC::WBuffer np_song; stringToBuffer(ToWString(Charset::utf8ToLocale(np.toString(Config.song_status_format, Config.tags_separator, "$"))), np_song); - *wFooter << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << player_state << NC::Format::NoBold; - writeCyclicBuffer(np_song, *wFooter, playing_song_scroll_begin, wFooter->getWidth()-player_state.length()-tracklength.length(), L" ** "); + *wFooter << NC::XY(0, 1) << wclrtoeol << NC::Format::Bold << ps << NC::Format::NoBold; + writeCyclicBuffer(np_song, *wFooter, playing_song_scroll_begin, wFooter->getWidth()-ps.length()-tracklength.length(), L" ** "); *wFooter << NC::Format::Bold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::Format::NoBold; } if (Progressbar::isUnlocked()) - Progressbar::draw(MpdStatus.elapsedTime(), MpdStatus.totalTime()); + Progressbar::draw(st.elapsedTime(), st.totalTime()); } void Status::Changes::repeat(bool show_msg) { - mpd_repeat = MpdStatus.repeat() ? 'r' : 0; + m_repeat = m_status.repeat() ? 'r' : 0; if (show_msg) - Statusbar::msg("Repeat mode is %s", !mpd_repeat ? "off" : "on"); + Statusbar::msg("Repeat mode is %s", !m_repeat ? "off" : "on"); } void Status::Changes::random(bool show_msg) { - mpd_random = MpdStatus.random() ? 'z' : 0; + m_random = m_status.random() ? 'z' : 0; if (show_msg) - Statusbar::msg("Random mode is %s", !mpd_random ? "off" : "on"); + Statusbar::msg("Random mode is %s", !m_random ? "off" : "on"); } void Status::Changes::single(bool show_msg) { - mpd_single = MpdStatus.single() ? 's' : 0; + m_single = m_status.single() ? 's' : 0; if (show_msg) - Statusbar::msg("Single mode is %s", !mpd_single ? "off" : "on"); + Statusbar::msg("Single mode is %s", !m_single ? "off" : "on"); } void Status::Changes::consume(bool show_msg) { - mpd_consume = MpdStatus.consume() ? 'c' : 0; + m_consume = m_status.consume() ? 'c' : 0; if (show_msg) - Statusbar::msg("Consume mode is %s", !mpd_consume ? "off" : "on"); + Statusbar::msg("Consume mode is %s", !m_consume ? "off" : "on"); } void Status::Changes::crossfade(bool show_msg) { - int crossfade = MpdStatus.crossfade(); - mpd_crossfade = crossfade ? 'x' : 0; + int crossfade = m_status.crossfade(); + m_crossfade = crossfade ? 'x' : 0; if (show_msg) Statusbar::msg("Crossfade set to %d seconds", crossfade); } void Status::Changes::dbUpdateState(bool show_msg) { - mpd_db_updating = MpdStatus.updateID() ? 'U' : 0; + m_db_updating = m_status.updateID() ? 'U' : 0; if (show_msg) - Statusbar::msg(MpdStatus.updateID() ? "Database update started" : "Database update finished"); + Statusbar::msg("Database update %s", m_status.updateID() ? "started" : "finished"); } void Status::Changes::flags() @@ -443,12 +566,12 @@ void Status::Changes::flags() if (Config.new_design) { switch_state += '['; - switch_state += mpd_repeat ? mpd_repeat : '-'; - switch_state += mpd_random ? mpd_random : '-'; - switch_state += mpd_single ? mpd_single : '-'; - switch_state += mpd_consume ? mpd_consume : '-'; - switch_state += mpd_crossfade ? mpd_crossfade : '-'; - switch_state += mpd_db_updating ? mpd_db_updating : '-'; + switch_state += m_repeat ? m_repeat : '-'; + switch_state += m_random ? m_random : '-'; + switch_state += m_single ? m_single : '-'; + switch_state += m_consume ? m_consume : '-'; + switch_state += m_crossfade ? m_crossfade : '-'; + switch_state += m_db_updating ? m_db_updating : '-'; switch_state += ']'; *wHeader << NC::XY(COLS-switch_state.length(), 1) << NC::Format::Bold << Config.state_flags_color << switch_state << NC::Color::End << NC::Format::NoBold; if (Config.new_design && !Config.header_visibility) // in this case also draw separator @@ -461,18 +584,18 @@ void Status::Changes::flags() } else { - if (mpd_repeat) - switch_state += mpd_repeat; - if (mpd_random) - switch_state += mpd_random; - if (mpd_single) - switch_state += mpd_single; - if (mpd_consume) - switch_state += mpd_consume; - if (mpd_crossfade) - switch_state += mpd_crossfade; - if (mpd_db_updating) - switch_state += mpd_db_updating; + if (m_repeat) + switch_state += m_repeat; + if (m_random) + switch_state += m_random; + if (m_single) + switch_state += m_single; + if (m_consume) + switch_state += m_consume; + if (m_crossfade) + switch_state += m_crossfade; + if (m_db_updating) + switch_state += m_db_updating; // this is done by raw ncurses because creating another // window only for handling this is quite silly @@ -495,16 +618,16 @@ void Status::Changes::flags() void Status::Changes::mixer() { + m_volume = m_status.volume(); if (!Config.display_volume_level || (!Config.header_visibility && !Config.new_design)) return; VolumeState = Config.new_design ? " Vol: " : " Volume: "; - int volume = MpdStatus.volume(); - if (volume < 0) + if (State::volume() < 0) VolumeState += "n/a"; else { - VolumeState += boost::lexical_cast(volume); + VolumeState += boost::lexical_cast(State::volume()); VolumeState += "%"; } *wHeader << Config.volume_color; @@ -519,51 +642,3 @@ void Status::Changes::outputs() myOutputs->FetchList(); # endif // ENABLE_OUTPUTS } - -void Status::update(int event) -{ - MPD::Status old = MpdStatus; - MpdStatus = Mpd.getStatus(); - - if (event & MPD_IDLE_DATABASE) - Changes::database(); - if (event & MPD_IDLE_STORED_PLAYLIST) - Changes::storedPlaylists(); - if (event & MPD_IDLE_PLAYLIST) - Changes::playlist(); - if (event & MPD_IDLE_PLAYER) - { - Changes::playerState(); - if (old.empty() || old.currentSongID() != MpdStatus.currentSongID()) - Changes::songID(); - } - if (event & MPD_IDLE_MIXER) - Changes::mixer(); - if (event & MPD_IDLE_OUTPUT) - Changes::outputs(); - if (event & (MPD_IDLE_UPDATE | MPD_IDLE_OPTIONS)) - { - if (event & MPD_IDLE_UPDATE) - Changes::dbUpdateState(!old.empty()); - if (event & MPD_IDLE_OPTIONS) - { - if (old.empty() || old.repeat() != MpdStatus.repeat()) - Changes::repeat(!old.empty()); - if (old.empty() || old.random() != MpdStatus.random()) - Changes::random(!old.empty()); - if (old.empty() || old.single() != MpdStatus.single()) - Changes::single(!old.empty()); - if (old.empty() || old.consume() != MpdStatus.consume()) - Changes::consume(!old.empty()); - if (old.empty() || old.crossfade() != MpdStatus.crossfade()) - Changes::crossfade(!old.empty()); - } - Changes::flags(); - } - - if (event & MPD_IDLE_PLAYER) - wFooter->refresh(); - - if (event & (MPD_IDLE_PLAYLIST | MPD_IDLE_DATABASE | MPD_IDLE_PLAYER)) - applyToVisibleWindows(&BaseScreen::refreshWindow); -} diff --git a/src/status.h b/src/status.h index 8047e109..5b0dd66c 100644 --- a/src/status.h +++ b/src/status.h @@ -32,6 +32,20 @@ void handleServerError(MPD::ServerError &e); void trace(); void update(int event); +namespace State {// + +bool repeat(); +bool random(); +bool single(); +bool consume(); +bool crossfade(); + +MPD::PlayerState player(); +int volume(); +unsigned elapsedTime(); + +} + namespace Changes {// void playlist(); @@ -39,7 +53,7 @@ void storedPlaylists(); void database(); void playerState(); void songID(); -void elapsedTime(); +void elapsedTime(bool update_elapsed); void repeat(bool show_msg); void random(bool show_msg); void single(bool show_msg); diff --git a/src/statusbar.cpp b/src/statusbar.cpp index 9412b8a6..34c490ae 100644 --- a/src/statusbar.cpp +++ b/src/statusbar.cpp @@ -23,6 +23,7 @@ #include "status.h" #include "statusbar.h" #include "bindings.h" +#include "playlist.h" #include "utility/wide_string.h" using Global::wFooter; @@ -122,10 +123,10 @@ void Statusbar::unlock() else progressbarBlockUpdate = false; } - if (MpdStatus.playerState() == MPD::psStop) + if (Status::State::player() == MPD::psStop) { if (Config.new_design) - Progressbar::draw(MpdStatus.elapsedTime(), MpdStatus.totalTime()); + Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength()); else put() << wclrtoeol; wFooter->refresh(); @@ -150,12 +151,12 @@ void Statusbar::tryRedraw() else progressbarBlockUpdate = !statusbarAllowUnlock; - if (MpdStatus.playerState() != MPD::psStop && !statusbarBlockUpdate && !progressbarBlockUpdate) + if (Status::State::player() != MPD::psStop && !statusbarBlockUpdate && !progressbarBlockUpdate) { if (Config.new_design) - Progressbar::draw(MpdStatus.elapsedTime(), MpdStatus.totalTime()); + Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength()); else - Status::Changes::elapsedTime(); + Status::Changes::elapsedTime(false); wFooter->refresh(); } }