diff --git a/src/FileBrowserPage.cxx b/src/FileBrowserPage.cxx index 25f9648f..d897b5b9 100644 --- a/src/FileBrowserPage.cxx +++ b/src/FileBrowserPage.cxx @@ -315,12 +315,6 @@ FileBrowserPage::OnCommand(struct mpdclient &c, Command cmd) ChangeToParent(c); return true; - case Command::LOCATE: - /* don't let browser_cmd() evaluate the locate command - - it's a no-op, and by the way, leads to a - segmentation fault in the current implementation */ - return false; - case Command::SCREEN_UPDATE: Reload(c); screen_browser_sync_highlights(*filelist, c.playlist); diff --git a/src/FileListPage.cxx b/src/FileListPage.cxx index f2d1f626..c8966994 100644 --- a/src/FileListPage.cxx +++ b/src/FileListPage.cxx @@ -4,9 +4,7 @@ #include "config.h" #include "FileListPage.hxx" #include "FileBrowserPage.hxx" -#include "SongPage.hxx" #include "EditPlaylistPage.hxx" -#include "LyricsPage.hxx" #include "Command.hxx" #include "screen_status.hxx" #include "screen_find.hxx" @@ -397,29 +395,6 @@ FileListPage::OnCommand(struct mpdclient &c, Command cmd) SchedulePaint(); return true; -#ifdef ENABLE_SONG_SCREEN - case Command::SCREEN_SONG: - if (const auto *song = GetSelectedSong()) { - screen_song_switch(screen, c, *song); - return true; - } else - return false; - -#endif - -#ifdef ENABLE_LYRICS_SCREEN - case Command::SCREEN_LYRICS: - if (const auto *song = GetSelectedSong()) { - screen_lyrics_switch(screen, c, *song, false); - return true; - } else - return false; - -#endif - case Command::SCREEN_SWAP: - screen.Swap(c, GetSelectedSong()); - return true; - default: break; } @@ -455,14 +430,6 @@ FileListPage::OnCommand(struct mpdclient &c, Command cmd) HandleSelectAll(c); return true; - case Command::LOCATE: - if (const auto *song = GetSelectedSong()) { - screen_file_goto_song(screen, c, *song); - return true; - } else - return false; - - default: break; } diff --git a/src/FileListPage.hxx b/src/FileListPage.hxx index abb610fe..c508428c 100644 --- a/src/FileListPage.hxx +++ b/src/FileListPage.hxx @@ -37,9 +37,6 @@ protected: [[gnu::pure]] const struct mpd_entity *GetSelectedEntity() const noexcept; - [[gnu::pure]] - const struct mpd_song *GetSelectedSong() const noexcept; - [[gnu::pure]] FileListEntry *GetIndex(unsigned i) const noexcept; @@ -76,6 +73,8 @@ public: bool OnMouse(struct mpdclient &c, Point p, mmask_t bstate) override; #endif + + const struct mpd_song *GetSelectedSong() const noexcept override; }; #ifndef NCMPC_MINI diff --git a/src/LyricsPage.cxx b/src/LyricsPage.cxx index ff786eb1..65f1a42b 100644 --- a/src/LyricsPage.cxx +++ b/src/LyricsPage.cxx @@ -6,8 +6,6 @@ #include "LyricsLoader.hxx" #include "PageMeta.hxx" #include "screen_status.hxx" -#include "FileBrowserPage.hxx" -#include "SongPage.hxx" #include "i18n.h" #include "Command.hxx" #include "Options.hxx" @@ -105,6 +103,10 @@ class LyricsPage final : public TextPage, PluginResponseHandler { bool OnCommand(struct mpdclient &c, Command cmd) override; std::string_view GetTitle(std::span buffer) const noexcept override; + const struct mpd_song *GetSelectedSong() const noexcept override { + return song; + } + private: /* virtual methods from class PluginResponseHandler */ void OnPluginSuccess(const char *plugin_name, @@ -417,27 +419,6 @@ LyricsPage::OnCommand(struct mpdclient &c, Command cmd) Reload(); return true; -#ifdef ENABLE_SONG_SCREEN - case Command::SCREEN_SONG: - if (song != nullptr) { - screen_song_switch(screen, c, *song); - return true; - } - - break; -#endif - case Command::SCREEN_SWAP: - screen.Swap(c, song); - return true; - - case Command::LOCATE: - if (song != nullptr) { - screen_file_goto_song(screen, c, *song); - return true; - } - - return false; - default: break; } diff --git a/src/QueuePage.cxx b/src/QueuePage.cxx index c504313f..3894b251 100644 --- a/src/QueuePage.cxx +++ b/src/QueuePage.cxx @@ -3,7 +3,6 @@ #include "QueuePage.hxx" #include "PageMeta.hxx" -#include "FileBrowserPage.hxx" #include "screen_status.hxx" #include "screen_find.hxx" #include "save_playlist.hxx" @@ -20,8 +19,6 @@ #include "time_format.hxx" #include "screen.hxx" #include "screen_utils.hxx" -#include "SongPage.hxx" -#include "LyricsPage.hxx" #include "db_completion.hxx" #include "page/ListPage.hxx" #include "ui/ListRenderer.hxx" @@ -85,9 +82,6 @@ class QueuePage final : public ListPage, ListRenderer, ListText { } private: - [[gnu::pure]] - const struct mpd_song *GetSelectedSong() const noexcept; - void SaveSelection() noexcept; void RestoreSelection() noexcept; @@ -135,6 +129,7 @@ class QueuePage final : public ListPage, ListRenderer, ListText { #endif std::string_view GetTitle(std::span buffer) const noexcept override; + const struct mpd_song *GetSelectedSong() const noexcept override; }; const struct mpd_song * @@ -559,38 +554,6 @@ QueuePage::OnCommand(struct mpdclient &c, Command cmd) SchedulePaint(); return true; -#ifdef ENABLE_SONG_SCREEN - case Command::SCREEN_SONG: - if (GetSelectedSong() != nullptr) { - screen_song_switch(screen, c, *GetSelectedSong()); - return true; - } - - break; -#endif - -#ifdef ENABLE_LYRICS_SCREEN - case Command::SCREEN_LYRICS: - if (lw.GetCursorIndex() < playlist->size()) { - struct mpd_song &selected = (*playlist)[lw.GetCursorIndex()]; - bool follow = false; - - if (&selected == c.GetPlayingSong()) - follow = true; - - screen_lyrics_switch(screen, c, selected, follow); - return true; - } - - break; -#endif - case Command::SCREEN_SWAP: - if (!playlist->empty()) - screen.Swap(c, &(*playlist)[lw.GetCursorIndex()]); - else - screen.Swap(c, nullptr); - return true; - default: break; } @@ -670,14 +633,6 @@ QueuePage::OnCommand(struct mpdclient &c, Command cmd) return true; } - case Command::LOCATE: - if (GetSelectedSong() != nullptr) { - screen_file_goto_song(screen, c, *GetSelectedSong()); - return true; - } - - break; - default: break; } diff --git a/src/SongPage.cxx b/src/SongPage.cxx index 3c568d63..300f5c41 100644 --- a/src/SongPage.cxx +++ b/src/SongPage.cxx @@ -3,8 +3,6 @@ #include "SongPage.hxx" #include "PageMeta.hxx" -#include "FileBrowserPage.hxx" -#include "LyricsPage.hxx" #include "screen_find.hxx" #include "Command.hxx" #include "i18n.h" @@ -148,6 +146,10 @@ class SongPage final : public ListPage, ListText { bool OnCommand(struct mpdclient &c, Command cmd) override; std::string_view GetTitle(std::span buffer) const noexcept override; + const struct mpd_song *GetSelectedSong() const noexcept override { + return selected_song != nullptr ? selected_song : played_song; + } + private: /* virtual methods from class ListText */ std::string_view GetListItemText(std::span buffer, @@ -478,45 +480,6 @@ SongPage::OnCommand(struct mpdclient &c, Command cmd) if (ListPage::OnCommand(c, cmd)) return true; - switch(cmd) { - case Command::LOCATE: - if (selected_song != nullptr) { - screen_file_goto_song(screen, c, *selected_song); - return true; - } - if (played_song != nullptr) { - screen_file_goto_song(screen, c, *played_song); - return true; - } - - return false; - -#ifdef ENABLE_LYRICS_SCREEN - case Command::SCREEN_LYRICS: - if (selected_song != nullptr) { - screen_lyrics_switch(screen, c, *selected_song, false); - return true; - } - if (played_song != nullptr) { - screen_lyrics_switch(screen, c, *played_song, true); - return true; - } - return false; - -#endif - - case Command::SCREEN_SWAP: - if (selected_song != nullptr) - screen.Swap(c, selected_song); - else - // No need to check if this is null - we'd pass null anyway - screen.Swap(c, played_song); - return true; - - default: - break; - } - if (screen_find(screen, lw, cmd, *this)) { SchedulePaint(); return true; diff --git a/src/page/Page.hxx b/src/page/Page.hxx index 7757da8c..51d75b32 100644 --- a/src/page/Page.hxx +++ b/src/page/Page.hxx @@ -14,6 +14,7 @@ #include enum class Command : unsigned; +struct mpd_song; struct mpdclient; struct Window; class PageContainer; @@ -106,4 +107,14 @@ public: [[gnu::pure]] virtual std::string_view GetTitle(std::span buffer) const noexcept = 0; + + /** + * Returns a pointer to the #mpd_song that is currently + * selected on this page. The pointed-to object is owned by + * this #Page instance and may be invalidated at any time. + */ + [[gnu::pure]] + virtual const struct mpd_song *GetSelectedSong() const noexcept { + return nullptr; + } }; diff --git a/src/page/ProxyPage.cxx b/src/page/ProxyPage.cxx index 896f01c7..60d30be8 100644 --- a/src/page/ProxyPage.cxx +++ b/src/page/ProxyPage.cxx @@ -91,6 +91,14 @@ ProxyPage::GetTitle(std::span buffer) const noexcept : std::string_view{}; } +const struct mpd_song * +ProxyPage::GetSelectedSong() const noexcept +{ + return current_page != nullptr + ? current_page->GetSelectedSong() + : nullptr; +} + void ProxyPage::SchedulePaint(Page &page) noexcept { diff --git a/src/page/ProxyPage.hxx b/src/page/ProxyPage.hxx index 1dc51eb0..73ac1ad2 100644 --- a/src/page/ProxyPage.hxx +++ b/src/page/ProxyPage.hxx @@ -46,6 +46,7 @@ public: #endif std::string_view GetTitle(std::span buffer) const noexcept override; + const struct mpd_song *GetSelectedSong() const noexcept override; // virtual methods from PageContainer void SchedulePaint(Page &page) noexcept override; diff --git a/src/screen.cxx b/src/screen.cxx index a5663a3e..ca4f32f5 100644 --- a/src/screen.cxx +++ b/src/screen.cxx @@ -13,7 +13,9 @@ #include "DelayedSeek.hxx" #include "player_command.hxx" #include "SongPage.hxx" +#include "FileBrowserPage.hxx" #include "LyricsPage.hxx" +#include "QueuePage.hxx" #include "page/Page.hxx" #include "ui/Options.hxx" #include "util/StringAPI.hxx" @@ -220,42 +222,81 @@ ScreenManager::OnCommand(struct mpdclient &c, DelayedSeek &seek, Command cmd) if (handle_player_command(c, seek, cmd)) return; - const auto *new_page = PageByCommand(cmd); - if (new_page != nullptr) { - Switch(*new_page, c); - return; - } - switch(cmd) { case Command::TOGGLE_FIND_WRAP: ui_options.find_wrap = !ui_options.find_wrap; screen_status_message(ui_options.find_wrap ? _("Find mode: Wrapped") : _("Find mode: Normal")); - break; + return; + case Command::TOGGLE_AUTOCENTER: options.auto_center = !options.auto_center; screen_status_message(options.auto_center ? _("Auto center mode: On") : _("Auto center mode: Off")); - break; + return; + case Command::SCREEN_UPDATE: main_dirty = true; SchedulePaint(); - break; + return; + case Command::SCREEN_PREVIOUS: NextMode(c, -1); - break; + return; + case Command::SCREEN_NEXT: NextMode(c, 1); - break; + return; + case Command::SCREEN_SWAP: - Swap(c, nullptr); + Swap(c, GetCurrentPage().GetSelectedSong()); + return; + + case Command::LOCATE: + if (!IsVisible(screen_browse)) { + if (const auto *song = GetCurrentPage().GetSelectedSong()) { + screen_file_goto_song(*this, c, *song); + return; + } + } + + break; + +#ifdef ENABLE_SONG_SCREEN + case Command::SCREEN_SONG: + if (!IsVisible(screen_song)) { + if (const auto *song = GetCurrentPage().GetSelectedSong()) { + screen_song_switch(*this, c, *song); + return; + } + } + break; +#endif + +#ifdef ENABLE_LYRICS_SCREEN + case Command::SCREEN_LYRICS: + if (!IsVisible(screen_lyrics)) { + if (const auto *song = GetCurrentPage().GetSelectedSong()) { + screen_lyrics_switch(*this, c, *song, + IsVisible(screen_queue) && song == c.GetPlayingSong()); + return; + } + } + + break; +#endif default: break; } + + if (const auto *new_page = PageByCommand(cmd)) { + Switch(*new_page, c); + return; + } } #ifdef HAVE_GETMOUSE diff --git a/src/screen.hxx b/src/screen.hxx index 05aff8ea..c4d266ac 100644 --- a/src/screen.hxx +++ b/src/screen.hxx @@ -118,6 +118,11 @@ public: void OnResize() noexcept; + [[gnu::pure]] + bool IsVisible(const PageMeta &page) const noexcept { + return &page == current_page->first; + } + [[gnu::pure]] bool IsVisible(const Page &page) const noexcept { return &page == current_page->second.get();