1 /***************************************************************************
2 * Copyright (C) 2008-2012 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
33 #include "utility/comparators.h"
39 #include "media_library.h"
43 #include "playlist_editor.h"
44 #include "search_engine.h"
45 #include "sel_items_adder.h"
46 #include "server_info.h"
47 #include "song_info.h"
49 #include "utility/string.h"
50 #include "utility/type_conversions.h"
51 #include "tag_editor.h"
52 #include "tiny_tag_editor.h"
53 #include "visualizer.h"
58 #endif // HAVE_TAGLIB_H
60 using namespace std::placeholders
;
61 using Global::myScreen
;
63 bool Action::OriginalStatusbarVisibility
;
64 bool Action::DesignChanged
;
65 bool Action::OrderResize
;
66 bool Action::ExitMainLoop
= false;
68 size_t Action::HeaderHeight
;
69 size_t Action::FooterHeight
;
70 size_t Action::FooterStartY
;
74 std::map
<ActionType
, Action
*> Actions
;
76 void insertAction(Action
*a
);
77 void populateActions();
81 void Action::ValidateScreenSize()
83 using Global::MainHeight
;
85 if (COLS
< 20 || MainHeight
< 3)
88 std::cout
<< "Screen is too small!\n";
93 void Action::SetResizeFlags()
95 myHelp
->hasToBeResized
= 1;
96 myPlaylist
->hasToBeResized
= 1;
97 myBrowser
->hasToBeResized
= 1;
98 mySearcher
->hasToBeResized
= 1;
99 myLibrary
->hasToBeResized
= 1;
100 myPlaylistEditor
->hasToBeResized
= 1;
101 myLyrics
->hasToBeResized
= 1;
102 mySelectedItemsAdder
->hasToBeResized
= 1;
103 mySongInfo
->hasToBeResized
= 1;
105 # ifdef HAVE_CURL_CURL_H
106 myLastfm
->hasToBeResized
= 1;
107 # endif // HAVE_CURL_CURL_H
109 # ifdef HAVE_TAGLIB_H
110 myTinyTagEditor
->hasToBeResized
= 1;
111 myTagEditor
->hasToBeResized
= 1;
112 # endif // HAVE_TAGLIB_H
114 # ifdef ENABLE_VISUALIZER
115 myVisualizer
->hasToBeResized
= 1;
116 # endif // ENABLE_VISUALIZER
118 # ifdef ENABLE_OUTPUTS
119 myOutputs
->hasToBeResized
= 1;
120 # endif // ENABLE_OUTPUTS
123 myClock
->hasToBeResized
= 1;
124 # endif // ENABLE_CLOCK
127 void Action::ResizeScreen()
129 using Global::MainHeight
;
130 using Global::RedrawHeader
;
131 using Global::RedrawStatusbar
;
132 using Global::wHeader
;
133 using Global::wFooter
;
137 # if defined(USE_PDCURSES)
140 // update internal screen dimensions
145 // get rid of KEY_RESIZE as it sometimes
146 // corrupts our new cool ReadKey() function
147 // because KEY_RESIZE doesn't come from stdin
148 // and thus select cannot detect it
156 MainHeight
= LINES
-(Config
.new_design
? 7 : 4);
158 ValidateScreenSize();
160 if (!Config
.header_visibility
)
162 if (!Config
.statusbar_visibility
)
167 ApplyToVisibleWindows(&BasicScreen::Resize
);
169 if (Config
.header_visibility
|| Config
.new_design
)
170 wHeader
->resize(COLS
, HeaderHeight
);
172 FooterStartY
= LINES
-(Config
.statusbar_visibility
? 2 : 1);
173 wFooter
->moveTo(0, FooterStartY
);
174 wFooter
->resize(COLS
, Config
.statusbar_visibility
? 2 : 1);
176 ApplyToVisibleWindows(&BasicScreen::Refresh
);
177 RedrawStatusbar
= true;
178 MPD::StatusChanges changes
;
179 if (!Mpd
.isPlaying() || DesignChanged
)
181 changes
.PlayerState
= 1;
185 // Note: routines for drawing separator if alternative user
186 // interface is active and header is hidden are placed in
187 // NcmpcppStatusChanges.StatusFlags
188 changes
.StatusFlags
= 1; // force status update
189 NcmpcppStatusChanged(&Mpd
, changes
, 0);
192 RedrawStatusbar
= true;
193 NcmpcppStatusChanged(&Mpd
, MPD::StatusChanges(), 0);
195 ShowMessage("User interface: %s", Config
.new_design
? "Alternative" : "Classic");
201 void Action::SetWindowsDimensions()
203 using Global::MainStartY
;
204 using Global::MainHeight
;
206 MainStartY
= Config
.new_design
? 5 : 2;
207 MainHeight
= LINES
-(Config
.new_design
? 7 : 4);
209 if (!Config
.header_visibility
)
214 if (!Config
.statusbar_visibility
)
217 HeaderHeight
= Config
.new_design
? (Config
.header_visibility
? 5 : 3) : 1;
218 FooterStartY
= LINES
-(Config
.statusbar_visibility
? 2 : 1);
219 FooterHeight
= Config
.statusbar_visibility
? 2 : 1;
224 using Global::wHeader
;
225 using Global::wFooter
;
226 using Global::SeekingInProgress
;
228 if (!Mpd
.GetTotalTime())
230 ShowMessage("Unknown item length");
237 int songpos
= Mpd
.GetElapsedTime();
240 int old_timeout
= wFooter
->getTimeout();
241 wFooter
->setTimeout(500);
243 SeekingInProgress
= true;
247 myPlaylist
->UpdateTimer();
249 int howmuch
= Config
.incremental_seeking
? (myPlaylist
->Timer()-t
)/2+Config
.seek_time
: Config
.seek_time
;
251 Key input
= Key::read(*wFooter
);
252 auto k
= Keys
.Bindings
.equal_range(input
);
253 if (k
.first
== k
.second
|| !k
.first
->second
.isSingle()) // no single action?
255 Action
*a
= k
.first
->second
.action();
256 if (dynamic_cast<SeekForward
*>(a
))
258 if (songpos
< Mpd
.GetTotalTime())
261 if (songpos
> Mpd
.GetTotalTime())
262 songpos
= Mpd
.GetTotalTime();
265 else if (dynamic_cast<SeekBackward
*>(a
))
277 *wFooter
<< NC::fmtBold
;
278 std::string tracklength
;
279 if (Config
.new_design
)
281 if (Config
.display_remaining_time
)
284 tracklength
+= MPD::Song::ShowTime(Mpd
.GetTotalTime()-songpos
);
287 tracklength
= MPD::Song::ShowTime(songpos
);
289 tracklength
+= MPD::Song::ShowTime(Mpd
.GetTotalTime());
290 *wHeader
<< NC::XY(0, 0) << tracklength
<< " ";
296 if (Config
.display_remaining_time
)
299 tracklength
+= MPD::Song::ShowTime(Mpd
.GetTotalTime()-songpos
);
302 tracklength
+= MPD::Song::ShowTime(songpos
);
304 tracklength
+= MPD::Song::ShowTime(Mpd
.GetTotalTime());
306 *wFooter
<< NC::XY(wFooter
->getWidth()-tracklength
.length(), 1) << tracklength
;
308 *wFooter
<< NC::fmtBoldEnd
;
309 DrawProgressbar(songpos
, Mpd
.GetTotalTime());
312 SeekingInProgress
= false;
315 wFooter
->setTimeout(old_timeout
);
321 void Action::FindItem(const FindDirection fd
)
323 using Global::wFooter
;
325 Searchable
*w
= dynamic_cast<Searchable
*>(myScreen
);
327 assert(w
->allowsSearching());
330 Statusbar() << "Find " << (fd
== fdForward
? "forward" : "backward") << ": ";
331 std::string findme
= wFooter
->getString();
335 ShowMessage("Searching...");
337 bool success
= w
->search(findme
);
343 ShowMessage("Searching finished");
345 ShowMessage("Unable to find \"%s\"", findme
.c_str());
348 w
->nextFound(Config
.wrapped_search
);
350 w
->prevFound(Config
.wrapped_search
);
352 if (myScreen
== myPlaylist
)
353 myPlaylist
->EnableHighlighting();
356 void Action::ListsChangeFinisher()
358 if (myScreen
== myLibrary
359 || myScreen
== myPlaylistEditor
360 # ifdef HAVE_TAGLIB_H
361 || myScreen
== myTagEditor
362 # endif // HAVE_TAGLIB_H
365 if (myScreen
->ActiveWindow() == myLibrary
->Tags
)
367 myLibrary
->Albums
->clear();
368 myLibrary
->Songs
->clear();
370 else if (myScreen
->ActiveWindow() == myLibrary
->Albums
)
372 myLibrary
->Songs
->clear();
374 else if (myScreen
->ActiveWindow() == myPlaylistEditor
->Playlists
)
376 myPlaylistEditor
->Content
->clear();
378 # ifdef HAVE_TAGLIB_H
379 else if (myScreen
->ActiveWindow() == myTagEditor
->Dirs
)
381 myTagEditor
->Tags
->clear();
383 # endif // HAVE_TAGLIB_H
387 bool Action::ConnectToMPD()
391 std::cout
<< "Couldn't connect to MPD ";
392 std::cout
<< "(host = " << Mpd
.GetHostname() << ", port = " << Mpd
.GetPort() << ")";
393 std::cout
<< ": " << Mpd
.GetErrorMessage() << std::endl
;
399 bool Action::AskYesNoQuestion(const std::string
&question
, void (*callback
)())
401 using Global::wFooter
;
404 Statusbar() << question
<< " [" << NC::fmtBold
<< 'y' << NC::fmtBoldEnd
<< '/' << NC::fmtBold
<< 'n' << NC::fmtBoldEnd
<< "]";
411 answer
= wFooter
->readKey();
413 while (answer
!= 'y' && answer
!= 'n');
415 return answer
== 'y';
418 bool Action::isMPDMusicDirSet()
420 if (Config
.mpd_music_dir
.empty())
422 ShowMessage("Proper mpd_music_dir variable has to be set in configuration file");
428 Action
*Action::Get(ActionType at
)
435 Action
*Action::Get(const std::string
&name
)
440 for (auto it
= Actions
.begin(); it
!= Actions
.end(); ++it
)
442 if (it
->second
->Name() == name
)
451 bool MouseEvent::canBeRun() const
453 return Config
.mouse_support
;
456 void MouseEvent::Run()
458 using Global::VolumeState
;
460 itsOldMouseEvent
= itsMouseEvent
;
461 getmouse(&itsMouseEvent
);
462 // workaround shitty ncurses behavior introduced in >=5.8, when we mysteriously get
463 // a few times after ncmpcpp startup 2^27 code instead of BUTTON{1,3}_RELEASED. since that
464 // 2^27 thing shows constantly instead of BUTTON2_PRESSED, it was redefined to be recognized
465 // as BUTTON2_PRESSED. but clearly we don't want to trigger behavior bound to BUTTON2
466 // after BUTTON{1,3} was pressed. so, here is the workaround: if last event was BUTTON{1,3}_PRESSED,
467 // we MUST get BUTTON{1,3}_RELEASED afterwards. if we get BUTTON2_PRESSED, erroneus behavior
468 // is about to occur and we need to prevent that.
469 if (itsOldMouseEvent
.bstate
& (BUTTON1_PRESSED
| BUTTON3_PRESSED
) && itsMouseEvent
.bstate
& BUTTON2_PRESSED
)
471 if (itsMouseEvent
.bstate
& BUTTON1_PRESSED
472 && itsMouseEvent
.y
== LINES
-(Config
.statusbar_visibility
? 2 : 1)
475 if (!myPlaylist
->isPlaying())
477 Mpd
.Seek(Mpd
.GetTotalTime()*itsMouseEvent
.x
/double(COLS
));
479 else if (itsMouseEvent
.bstate
& BUTTON1_PRESSED
480 && (Config
.statusbar_visibility
|| Config
.new_design
)
482 && itsMouseEvent
.y
== (Config
.new_design
? 1 : LINES
-1) && itsMouseEvent
.x
< 9
487 else if ((itsMouseEvent
.bstate
& BUTTON2_PRESSED
|| itsMouseEvent
.bstate
& BUTTON4_PRESSED
)
488 && Config
.header_visibility
489 && itsMouseEvent
.y
== 0 && size_t(itsMouseEvent
.x
) > COLS
-VolumeState
.length()
492 if (itsMouseEvent
.bstate
& BUTTON2_PRESSED
)
493 Mpd
.SetVolume(Mpd
.GetVolume()-2);
495 Mpd
.SetVolume(Mpd
.GetVolume()+2);
497 else if (itsMouseEvent
.bstate
& (BUTTON1_PRESSED
| BUTTON2_PRESSED
| BUTTON3_PRESSED
| BUTTON4_PRESSED
))
498 myScreen
->MouseButtonPressed(itsMouseEvent
);
503 myScreen
->Scroll(NC::wUp
);
504 ListsChangeFinisher();
507 void ScrollDown::Run()
509 myScreen
->Scroll(NC::wDown
);
510 ListsChangeFinisher();
513 bool ScrollUpArtist::canBeRun() const
515 return proxySongList(myScreen
).get();
518 void ScrollUpArtist::Run()
520 auto pl
= proxySongList(myScreen
);
522 size_t pos
= pl
->choice();
523 if (MPD::Song
*s
= pl
->getSong(pos
))
525 std::string artist
= s
->getArtist();
528 s
= pl
->getSong(--pos
);
529 if (!s
|| s
->getArtist() != artist
)
536 bool ScrollUpAlbum::canBeRun() const
538 return proxySongList(myScreen
).get();
541 void ScrollUpAlbum::Run()
543 auto pl
= proxySongList(myScreen
);
545 size_t pos
= pl
->choice();
546 if (MPD::Song
*s
= pl
->getSong(pos
))
548 std::string album
= s
->getAlbum();
551 s
= pl
->getSong(--pos
);
552 if (!s
|| s
->getAlbum() != album
)
559 bool ScrollDownArtist::canBeRun() const
561 return proxySongList(myScreen
).get();
564 void ScrollDownArtist::Run()
566 auto pl
= proxySongList(myScreen
);
568 size_t pos
= pl
->choice();
569 if (MPD::Song
*s
= pl
->getSong(pos
))
571 std::string artist
= s
->getArtist();
572 while (pos
< pl
->size() - 1)
574 s
= pl
->getSong(++pos
);
575 if (!s
|| s
->getArtist() != artist
)
582 bool ScrollDownAlbum::canBeRun() const
584 return proxySongList(myScreen
).get();
587 void ScrollDownAlbum::Run()
589 auto pl
= proxySongList(myScreen
);
591 size_t pos
= pl
->choice();
592 if (MPD::Song
*s
= pl
->getSong(pos
))
594 std::string album
= s
->getAlbum();
595 while (pos
< pl
->size() - 1)
597 s
= pl
->getSong(++pos
);
598 if (!s
|| s
->getAlbum() != album
)
607 myScreen
->Scroll(NC::wPageUp
);
608 ListsChangeFinisher();
613 myScreen
->Scroll(NC::wPageDown
);
614 ListsChangeFinisher();
619 myScreen
->Scroll(NC::wHome
);
620 ListsChangeFinisher();
625 myScreen
->Scroll(NC::wEnd
);
626 ListsChangeFinisher();
629 void ToggleInterface::Run()
631 Config
.new_design
= !Config
.new_design
;
632 Config
.statusbar_visibility
= Config
.new_design
? 0 : OriginalStatusbarVisibility
;
633 SetWindowsDimensions();
636 DesignChanged
= true;
640 bool JumpToParentDir::canBeRun() const
642 return myScreen
== myBrowser
643 # ifdef HAVE_TAGLIB_H
644 || myScreen
== myTagEditor
645 # endif // HAVE_TAGLIB_H
649 void JumpToParentDir::Run()
651 if (myScreen
== myBrowser
&& myBrowser
->CurrentDir() != "/")
653 myBrowser
->Main()->reset();
654 myBrowser
->EnterPressed();
656 # ifdef HAVE_TAGLIB_H
657 else if (myScreen
->ActiveWindow() == myTagEditor
->Dirs
&& myTagEditor
->CurrentDir() != "/")
659 myTagEditor
->Dirs
->reset();
660 myTagEditor
->EnterPressed();
662 # endif // HAVE_TAGLIB_H
665 void PressEnter::Run()
667 myScreen
->EnterPressed();
670 void PressSpace::Run()
672 myScreen
->SpacePressed();
675 bool PreviousColumn::canBeRun() const
677 return (myScreen
== myLibrary
&& myLibrary
->isPrevColumnAvailable())
678 || (myScreen
== myPlaylistEditor
&& myPlaylistEditor
->isPrevColumnAvailable())
679 # ifdef HAVE_TAGLIB_H
680 || (myScreen
== myTagEditor
&& myTagEditor
->isPrevColumnAvailable())
681 # endif // HAVE_TAGLIB_H
685 void PreviousColumn::Run()
687 if (myScreen
== myLibrary
)
688 myLibrary
->PrevColumn();
689 else if (myScreen
== myPlaylistEditor
)
690 myPlaylistEditor
->PrevColumn();
691 # ifdef HAVE_TAGLIB_H
692 else if (myScreen
== myTagEditor
)
693 myTagEditor
->PrevColumn();
694 # endif // HAVE_TAGLIB_H
697 bool NextColumn::canBeRun() const
699 return (myScreen
== myLibrary
&& myLibrary
->isNextColumnAvailable())
700 || (myScreen
== myPlaylistEditor
&& myPlaylistEditor
->isNextColumnAvailable())
701 # ifdef HAVE_TAGLIB_H
702 || (myScreen
== myTagEditor
&& myTagEditor
->isNextColumnAvailable())
703 # endif // HAVE_TAGLIB_H
707 void NextColumn::Run()
709 if (myScreen
== myLibrary
)
710 myLibrary
->NextColumn();
711 else if (myScreen
== myPlaylistEditor
)
712 myPlaylistEditor
->NextColumn();
713 # ifdef HAVE_TAGLIB_H
714 else if (myScreen
== myTagEditor
)
715 myTagEditor
->NextColumn();
716 # endif // HAVE_TAGLIB_H
719 bool MasterScreen::canBeRun() const
721 using Global::myLockedScreen
;
722 using Global::myInactiveScreen
;
724 return myLockedScreen
726 && myLockedScreen
!= myScreen
727 && myScreen
->isMergable();
730 void MasterScreen::Run()
732 using Global::myInactiveScreen
;
733 using Global::myLockedScreen
;
734 using Global::RedrawHeader
;
736 myInactiveScreen
= myScreen
;
737 myScreen
= myLockedScreen
;
741 bool SlaveScreen::canBeRun() const
743 using Global::myLockedScreen
;
744 using Global::myInactiveScreen
;
746 return myLockedScreen
748 && myLockedScreen
== myScreen
749 && myScreen
->isMergable();
752 void SlaveScreen::Run()
754 using Global::myInactiveScreen
;
755 using Global::myLockedScreen
;
756 using Global::RedrawHeader
;
758 myScreen
= myInactiveScreen
;
759 myInactiveScreen
= myLockedScreen
;
765 Mpd
.SetVolume(Mpd
.GetVolume()+1);
768 void VolumeDown::Run()
770 Mpd
.SetVolume(Mpd
.GetVolume()-1);
775 if (myScreen
== myPlaylist
&& !myPlaylist
->Items
->empty())
777 ShowMessage("Deleting items...");
778 auto delete_fun
= std::bind(&MPD::Connection::Delete
, _1
, _2
);
779 if (deleteSelectedSongs(*myPlaylist
->Items
, delete_fun
))
780 ShowMessage("Item(s) deleted");
783 else if (myScreen
== myBrowser
&& !myBrowser
->Main()->empty())
785 if (!myBrowser
->isLocal() && !isMPDMusicDirSet())
788 std::string question
;
789 if (myBrowser
->Main()->hasSelected())
790 question
= "Delete selected items?";
793 MPD::Item
&item
= myBrowser
->Main()->current().value();
794 std::string name
= item
.type
== MPD::itSong
? item
.song
->getName() : item
.name
;
795 question
= "Delete ";
796 question
+= itemTypeToString(item
.type
);
798 question
+= Shorten(TO_WSTRING(name
), COLS
-question
.size()-10);
801 bool yes
= AskYesNoQuestion(question
, TraceMpdStatus
);
805 auto list
= getSelectedOrCurrent(myBrowser
->Main()->begin(), myBrowser
->Main()->end(), myBrowser
->Main()->currentI());
806 for (auto it
= list
.begin(); it
!= list
.end(); ++it
)
808 const MPD::Item
&i
= (*it
)->value();
809 std::string name
= i
.type
== MPD::itSong
? i
.song
->getName() : i
.name
;
810 if (myBrowser
->deleteItem(i
))
812 const char msg
[] = "\"%s\" deleted";
813 ShowMessage(msg
, Shorten(TO_WSTRING(name
), COLS
-const_strlen(msg
)).c_str());
817 const char msg
[] = "Couldn't delete \"%s\": %s";
818 ShowMessage(msg
, Shorten(TO_WSTRING(name
), COLS
-const_strlen(msg
)-25).c_str(), strerror(errno
));
825 if (!myBrowser
->isLocal())
826 Mpd
.UpdateDirectory(myBrowser
->CurrentDir());
830 ShowMessage("Aborted");
833 else if (myScreen
== myPlaylistEditor
&& !myPlaylistEditor
->Content
->empty())
835 if (myScreen
->ActiveWindow() == myPlaylistEditor
->Playlists
)
837 std::string question
;
838 if (myPlaylistEditor
->Playlists
->hasSelected())
839 question
= "Delete selected playlists?";
842 question
= "Delete playlist \"";
843 question
+= Shorten(TO_WSTRING(myPlaylistEditor
->Playlists
->current().value()), COLS
-question
.size()-10);
846 bool yes
= AskYesNoQuestion(question
, TraceMpdStatus
);
849 auto list
= getSelectedOrCurrent(myPlaylistEditor
->Playlists
->begin(), myPlaylistEditor
->Playlists
->end(), myPlaylistEditor
->Playlists
->currentI());
850 Mpd
.StartCommandsList();
851 for (auto it
= list
.begin(); it
!= list
.end(); ++it
)
852 Mpd
.DeletePlaylist((*it
)->value());
853 if (Mpd
.CommitCommandsList())
854 ShowMessage("Playlist%s deleted", list
.size() == 1 ? "" : "s");
857 ShowMessage("Aborted");
859 else if (myScreen
->ActiveWindow() == myPlaylistEditor
->Content
)
861 std::string playlist
= myPlaylistEditor
->Playlists
->current().value();
862 auto delete_fun
= std::bind(&MPD::Connection::PlaylistDelete
, _1
, playlist
, _2
);
863 ShowMessage("Deleting items...");
864 if (deleteSelectedSongs(*myPlaylistEditor
->Content
, delete_fun
))
865 ShowMessage("Item(s) deleted");
870 void ReplaySong::Run()
876 void PreviousSong::Run()
891 void SavePlaylist::Run()
893 using Global::wFooter
;
896 Statusbar() << "Save playlist as: ";
897 std::string playlist_name
= wFooter
->getString();
898 std::string real_playlist_name
= locale_to_utf_cpy(playlist_name
);
900 if (playlist_name
.find("/") != std::string::npos
)
902 ShowMessage("Playlist name must not contain slashes");
905 if (!playlist_name
.empty())
907 if (myPlaylist
->Items
->isFiltered())
909 Mpd
.StartCommandsList();
910 for (size_t i
= 0; i
< myPlaylist
->Items
->size(); ++i
)
911 Mpd
.AddToPlaylist(real_playlist_name
, (*myPlaylist
->Items
)[i
].value());
912 Mpd
.CommitCommandsList();
913 if (Mpd
.GetErrorMessage().empty())
914 ShowMessage("Filtered items added to playlist \"%s\"", playlist_name
.c_str());
918 int result
= Mpd
.SavePlaylist(real_playlist_name
);
919 if (result
== MPD_ERROR_SUCCESS
)
921 ShowMessage("Playlist saved as \"%s\"", playlist_name
.c_str());
922 if (myPlaylistEditor
->Main()) // check if initialized
923 myPlaylistEditor
->Playlists
->clear(); // make playlist's list update itself
925 else if (result
== MPD_SERVER_ERROR_EXIST
)
927 bool yes
= AskYesNoQuestion("Playlist \"" + playlist_name
+ "\" already exists, overwrite?", TraceMpdStatus
);
930 Mpd
.DeletePlaylist(real_playlist_name
);
931 if (Mpd
.SavePlaylist(real_playlist_name
) == MPD_ERROR_SUCCESS
)
932 ShowMessage("Playlist overwritten");
935 ShowMessage("Aborted");
936 if (myPlaylistEditor
->Main()) // check if initialized
937 myPlaylistEditor
->Playlists
->clear(); // make playlist's list update itself
938 if (myScreen
== myPlaylist
)
939 myPlaylist
->EnableHighlighting();
943 if (myBrowser
->Main()
944 && !myBrowser
->isLocal()
945 && myBrowser
->CurrentDir() == "/"
946 && !myBrowser
->Main()->empty())
947 myBrowser
->GetDirectory(myBrowser
->CurrentDir());
955 bool MoveSortOrderUp::canBeRun() const
957 return myScreen
== myPlaylist
958 && myPlaylist
->SortingInProgress();
961 void MoveSortOrderUp::Run()
963 myPlaylist
->moveSortOrderUp();
966 bool MoveSortOrderDown::canBeRun() const
968 return myScreen
== myPlaylist
969 && myPlaylist
->SortingInProgress();
972 void MoveSortOrderDown::Run()
974 myPlaylist
->moveSortOrderDown();
977 bool MoveSelectedItemsUp::canBeRun() const
979 return ((myScreen
->ActiveWindow() == myPlaylist
->Items
980 && !myPlaylist
->Items
->empty()
981 && !myPlaylist
->Items
->isFiltered())
982 || (myScreen
->ActiveWindow() == myPlaylistEditor
->Content
983 && !myPlaylistEditor
->Content
->empty()
984 && !myPlaylistEditor
->Content
->isFiltered()));
987 void MoveSelectedItemsUp::Run()
989 if (myScreen
== myPlaylist
)
991 moveSelectedItemsUp(*myPlaylist
->Items
, std::bind(&MPD::Connection::Move
, _1
, _2
, _3
));
993 else if (myScreen
== myPlaylistEditor
)
995 assert(!myPlaylistEditor
->Playlists
->empty());
996 std::string playlist
= myPlaylistEditor
->Playlists
->current().value();
997 auto move_fun
= std::bind(&MPD::Connection::PlaylistMove
, _1
, playlist
, _2
, _3
);
998 moveSelectedItemsUp(*myPlaylistEditor
->Content
, move_fun
);
1002 bool MoveSelectedItemsDown::canBeRun() const
1004 return ((myScreen
->ActiveWindow() == myPlaylist
->Items
1005 && !myPlaylist
->Items
->empty()
1006 && !myPlaylist
->Items
->isFiltered())
1007 || (myScreen
->ActiveWindow() == myPlaylistEditor
->Content
1008 && !myPlaylistEditor
->Content
->empty()
1009 && !myPlaylistEditor
->Content
->isFiltered()));
1012 void MoveSelectedItemsDown::Run()
1014 if (myScreen
== myPlaylist
)
1016 moveSelectedItemsDown(*myPlaylist
->Items
, std::bind(&MPD::Connection::Move
, _1
, _2
, _3
));
1018 else if (myScreen
== myPlaylistEditor
)
1020 assert(!myPlaylistEditor
->Playlists
->empty());
1021 std::string playlist
= myPlaylistEditor
->Playlists
->current().value();
1022 auto move_fun
= std::bind(&MPD::Connection::PlaylistMove
, _1
, playlist
, _2
, _3
);
1023 moveSelectedItemsDown(*myPlaylistEditor
->Content
, move_fun
);
1027 bool MoveSelectedItemsTo::canBeRun() const
1029 return myScreen
->ActiveWindow() == myPlaylist
->Items
1030 || myScreen
->ActiveWindow() == myPlaylistEditor
->Content
;
1033 void MoveSelectedItemsTo::Run()
1035 if (myScreen
== myPlaylist
)
1036 moveSelectedItemsTo(*myPlaylist
->Items
, std::bind(&MPD::Connection::Move
, _1
, _2
, _3
));
1039 assert(!myPlaylistEditor
->Playlists
->empty());
1040 std::string playlist
= myPlaylistEditor
->Playlists
->current().value();
1041 auto move_fun
= std::bind(&MPD::Connection::PlaylistMove
, _1
, playlist
, _2
, _3
);
1042 moveSelectedItemsTo(*myPlaylistEditor
->Content
, move_fun
);
1046 bool Add::canBeRun() const
1048 return myScreen
!= myPlaylistEditor
1049 || !myPlaylistEditor
->Playlists
->empty();
1054 using Global::wFooter
;
1057 Statusbar() << (myScreen
== myPlaylistEditor
? "Add to playlist: " : "Add: ");
1058 std::string path
= wFooter
->getString();
1059 locale_to_utf(path
);
1063 Statusbar() << "Adding...";
1065 if (myScreen
== myPlaylistEditor
)
1066 Mpd
.AddToPlaylist(myPlaylistEditor
->Playlists
->current().value(), path
);
1069 const char lastfm_url
[] = "lastfm://";
1070 if (path
.compare(0, const_strlen(lastfm_url
), lastfm_url
) == 0
1071 || path
.find(".asx", path
.length()-4) != std::string::npos
1072 || path
.find(".cue", path
.length()-4) != std::string::npos
1073 || path
.find(".m3u", path
.length()-4) != std::string::npos
1074 || path
.find(".pls", path
.length()-4) != std::string::npos
1075 || path
.find(".xspf", path
.length()-5) != std::string::npos
)
1076 Mpd
.LoadPlaylist(path
);
1083 bool SeekForward::canBeRun() const
1085 return myPlaylist
->NowPlayingSong();
1088 void SeekForward::Run()
1093 bool SeekBackward::canBeRun() const
1095 return myPlaylist
->NowPlayingSong();
1098 void SeekBackward::Run()
1103 bool ToggleDisplayMode::canBeRun() const
1105 return myScreen
== myPlaylist
1106 || myScreen
== myBrowser
1107 || myScreen
== mySearcher
1108 || myScreen
->ActiveWindow() == myPlaylistEditor
->Content
;
1111 void ToggleDisplayMode::Run()
1113 if (myScreen
== myPlaylist
)
1115 Config
.columns_in_playlist
= !Config
.columns_in_playlist
;
1116 ShowMessage("Playlist display mode: %s", Config
.columns_in_playlist
? "Columns" : "Classic");
1118 if (Config
.columns_in_playlist
)
1120 myPlaylist
->Items
->setItemDisplayer(std::bind(Display::SongsInColumns
, _1
, myPlaylist
));
1121 if (Config
.titles_visibility
)
1122 myPlaylist
->Items
->setTitle(Display::Columns(myPlaylist
->Items
->getWidth()));
1124 myPlaylist
->Items
->setTitle("");
1128 myPlaylist
->Items
->setItemDisplayer(std::bind(Display::Songs
, _1
, myPlaylist
, Config
.song_list_format
));
1129 myPlaylist
->Items
->setTitle("");
1132 else if (myScreen
== myBrowser
)
1134 Config
.columns_in_browser
= !Config
.columns_in_browser
;
1135 ShowMessage("Browser display mode: %s", Config
.columns_in_browser
? "Columns" : "Classic");
1136 myBrowser
->Main()->setTitle(Config
.columns_in_browser
&& Config
.titles_visibility
? Display::Columns(myBrowser
->Main()->getWidth()) : "");
1138 else if (myScreen
== mySearcher
)
1140 Config
.columns_in_search_engine
= !Config
.columns_in_search_engine
;
1141 ShowMessage("Search engine display mode: %s", Config
.columns_in_search_engine
? "Columns" : "Classic");
1142 if (mySearcher
->Main()->size() > SearchEngine::StaticOptions
)
1143 mySearcher
->Main()->setTitle(Config
.columns_in_search_engine
&& Config
.titles_visibility
? Display::Columns(mySearcher
->Main()->getWidth()) : "");
1145 else if (myScreen
->ActiveWindow() == myPlaylistEditor
->Content
)
1147 Config
.columns_in_playlist_editor
= !Config
.columns_in_playlist_editor
;
1148 ShowMessage("Playlist editor display mode: %s", Config
.columns_in_playlist_editor
? "Columns" : "Classic");
1149 if (Config
.columns_in_playlist_editor
)
1150 myPlaylistEditor
->Content
->setItemDisplayer(std::bind(Display::SongsInColumns
, _1
, myPlaylistEditor
));
1152 myPlaylistEditor
->Content
->setItemDisplayer(std::bind(Display::Songs
, _1
, myPlaylistEditor
, Config
.song_list_format
));
1156 bool ToggleSeparatorsBetweenAlbums::canBeRun() const
1161 void ToggleSeparatorsBetweenAlbums::Run()
1163 Config
.playlist_separate_albums
= !Config
.playlist_separate_albums
;
1164 ShowMessage("Separators between albums: %s", Config
.playlist_separate_albums
? "On" : "Off");
1167 #ifndef HAVE_CURL_CURL_H
1168 bool ToggleLyricsFetcher::canBeRun() const
1172 #endif // NOT HAVE_CURL_CURL_H
1174 void ToggleLyricsFetcher::Run()
1176 # ifdef HAVE_CURL_CURL_H
1177 myLyrics
->ToggleFetcher();
1178 # endif // HAVE_CURL_CURL_H
1181 #ifndef HAVE_CURL_CURL_H
1182 bool ToggleFetchingLyricsInBackground::canBeRun() const
1186 #endif // NOT HAVE_CURL_CURL_H
1188 void ToggleFetchingLyricsInBackground::Run()
1190 # ifdef HAVE_CURL_CURL_H
1191 Config
.fetch_lyrics_in_background
= !Config
.fetch_lyrics_in_background
;
1192 ShowMessage("Fetching lyrics for playing songs in background: %s", Config
.fetch_lyrics_in_background
? "On" : "Off");
1193 # endif // HAVE_CURL_CURL_H
1196 void ToggleAutoCenter::Run()
1198 Config
.autocenter_mode
= !Config
.autocenter_mode
;
1199 ShowMessage("Auto center mode: %s", Config
.autocenter_mode
? "On" : "Off");
1200 if (Config
.autocenter_mode
&& myPlaylist
->isPlaying() && !myPlaylist
->Items
->isFiltered())
1201 myPlaylist
->Items
->highlight(myPlaylist
->NowPlaying
);
1204 void UpdateDatabase::Run()
1206 if (myScreen
== myBrowser
)
1207 Mpd
.UpdateDirectory(locale_to_utf_cpy(myBrowser
->CurrentDir()));
1208 # ifdef HAVE_TAGLIB_H
1209 else if (myScreen
== myTagEditor
)
1210 Mpd
.UpdateDirectory(myTagEditor
->CurrentDir());
1211 # endif // HAVE_TAGLIB_H
1213 Mpd
.UpdateDirectory("/");
1216 bool JumpToPlayingSong::canBeRun() const
1218 return (myScreen
== myPlaylist
|| myScreen
== myBrowser
|| myScreen
== myLibrary
)
1219 && myPlaylist
->isPlaying();
1222 void JumpToPlayingSong::Run()
1224 using Global::RedrawHeader
;
1226 if (myScreen
== myPlaylist
)
1228 if (myPlaylist
->isFiltered())
1230 assert(myPlaylist
->isPlaying());
1231 myPlaylist
->Items
->highlight(myPlaylist
->NowPlaying
);
1233 else if (myScreen
== myBrowser
)
1235 const MPD::Song
*s
= myPlaylist
->NowPlayingSong();
1237 myBrowser
->LocateSong(*s
);
1238 RedrawHeader
= true;
1240 else if (myScreen
== myLibrary
)
1242 const MPD::Song
*s
= myPlaylist
->NowPlayingSong();
1244 myLibrary
->LocateSong(*s
);
1248 void ToggleRepeat::Run()
1250 Mpd
.SetRepeat(!Mpd
.GetRepeat());
1258 void ToggleRandom::Run()
1260 Mpd
.SetRandom(!Mpd
.GetRandom());
1263 bool StartSearching::canBeRun() const
1265 return myScreen
== mySearcher
;
1268 void StartSearching::Run()
1270 if (mySearcher
->Main()->at(0).isInactive())
1272 mySearcher
->Main()->highlight(SearchEngine::SearchButton
);
1273 mySearcher
->Main()->setHighlighting(0);
1274 mySearcher
->Main()->refresh();
1275 mySearcher
->Main()->setHighlighting(1);
1276 mySearcher
->EnterPressed();
1279 bool SaveTagChanges::canBeRun() const
1281 # ifdef HAVE_TAGLIB_H
1282 return myScreen
== myTinyTagEditor
1283 || myScreen
->ActiveWindow() == myTagEditor
->TagTypes
;
1286 # endif // HAVE_TAGLIB_H
1289 void SaveTagChanges::Run()
1291 # ifdef HAVE_TAGLIB_H
1292 if (myScreen
== myTinyTagEditor
)
1294 myTinyTagEditor
->Main()->highlight(myTinyTagEditor
->Main()->size()-2); // Save
1295 myTinyTagEditor
->EnterPressed();
1297 else if (myScreen
->ActiveWindow() == myTagEditor
->TagTypes
)
1299 myTagEditor
->TagTypes
->highlight(myTagEditor
->TagTypes
->size()-1); // Save
1300 myTagEditor
->EnterPressed();
1302 # endif // HAVE_TAGLIB_H
1305 void ToggleSingle::Run()
1307 Mpd
.SetSingle(!Mpd
.GetSingle());
1310 void ToggleConsume::Run()
1312 Mpd
.SetConsume(!Mpd
.GetConsume());
1315 void ToggleCrossfade::Run()
1317 Mpd
.SetCrossfade(Mpd
.GetCrossfade() ? 0 : Config
.crossfade_time
);
1320 void SetCrossfade::Run()
1322 using Global::wFooter
;
1325 Statusbar() << "Set crossfade to: ";
1326 std::string crossfade
= wFooter
->getString(3);
1328 int cf
= stringToInt(crossfade
);
1331 Config
.crossfade_time
= cf
;
1332 Mpd
.SetCrossfade(cf
);
1336 bool EditSong::canBeRun() const
1338 # ifdef HAVE_TAGLIB_H
1339 return currentSong(myScreen
);
1342 # endif // HAVE_TAGLIB_H
1345 void EditSong::Run()
1347 # ifdef HAVE_TAGLIB_H
1348 if (!isMPDMusicDirSet())
1350 auto s
= currentSong(myScreen
);
1352 myTinyTagEditor
->SetEdited(*s
);
1353 myTinyTagEditor
->SwitchTo();
1354 # endif // HAVE_TAGLIB_H
1357 bool EditLibraryTag::canBeRun() const
1359 # ifdef HAVE_TAGLIB_H
1360 return myScreen
->ActiveWindow() == myLibrary
->Tags
1361 && !myLibrary
->Tags
->empty();
1364 # endif // HAVE_TAGLIB_H
1367 void EditLibraryTag::Run()
1369 # ifdef HAVE_TAGLIB_H
1370 using Global::wFooter
;
1372 if (!isMPDMusicDirSet())
1375 Statusbar() << NC::fmtBold
<< tagTypeToString(Config
.media_lib_primary_tag
) << NC::fmtBoldEnd
<< ": ";
1376 std::string new_tag
= wFooter
->getString(myLibrary
->Tags
->current().value());
1378 if (!new_tag
.empty() && new_tag
!= myLibrary
->Tags
->current().value())
1380 ShowMessage("Updating tags...");
1382 Mpd
.AddSearch(Config
.media_lib_primary_tag
, locale_to_utf_cpy(myLibrary
->Tags
->current().value()));
1383 MPD::MutableSong::SetFunction set
= tagTypeToSetFunction(Config
.media_lib_primary_tag
);
1385 bool success
= true;
1386 MPD::SongList songs
= Mpd
.CommitSearchSongs();
1387 for (auto s
= songs
.begin(); s
!= songs
.end(); ++s
)
1389 MPD::MutableSong es
= *s
;
1390 es
.setTag(set
, new_tag
);
1391 ShowMessage("Updating tags in \"%s\"...", es
.getName().c_str());
1392 std::string path
= Config
.mpd_music_dir
+ es
.getURI();
1393 if (!TagEditor::WriteTags(es
))
1395 const char msg
[] = "Error while updating tags in \"%s\"";
1396 ShowMessage(msg
, Shorten(TO_WSTRING(es
.getURI()), COLS
-const_strlen(msg
)).c_str());
1403 Mpd
.UpdateDirectory(getSharedDirectory(songs
.begin(), songs
.end()));
1404 ShowMessage("Tags updated successfully");
1407 # endif // HAVE_TAGLIB_H
1410 bool EditLibraryAlbum::canBeRun() const
1412 # ifdef HAVE_TAGLIB_H
1413 return myScreen
->ActiveWindow() == myLibrary
->Albums
1414 && !myLibrary
->Albums
->empty();
1417 # endif // HAVE_TAGLIB_H
1420 void EditLibraryAlbum::Run()
1422 # ifdef HAVE_TAGLIB_H
1423 using Global::wFooter
;
1425 if (!isMPDMusicDirSet())
1428 Statusbar() << NC::fmtBold
<< "Album: " << NC::fmtBoldEnd
;
1429 std::string new_album
= wFooter
->getString(myLibrary
->Albums
->current().value().Album
);
1431 if (!new_album
.empty() && new_album
!= myLibrary
->Albums
->current().value().Album
)
1434 ShowMessage("Updating tags...");
1435 for (size_t i
= 0; i
< myLibrary
->Songs
->size(); ++i
)
1437 ShowMessage("Updating tags in \"%s\"...", (*myLibrary
->Songs
)[i
].value().getName().c_str());
1438 std::string path
= Config
.mpd_music_dir
+ (*myLibrary
->Songs
)[i
].value().getURI();
1439 TagLib::FileRef
f(path
.c_str());
1442 const char msg
[] = "Error while opening file \"%s\"";
1443 ShowMessage(msg
, Shorten(TO_WSTRING((*myLibrary
->Songs
)[i
].value().getURI()), COLS
-const_strlen(msg
)).c_str());
1447 f
.tag()->setAlbum(ToWString(new_album
));
1450 const char msg
[] = "Error while writing tags in \"%s\"";
1451 ShowMessage(msg
, Shorten(TO_WSTRING((*myLibrary
->Songs
)[i
].value().getURI()), COLS
-const_strlen(msg
)).c_str());
1458 Mpd
.UpdateDirectory(getSharedDirectory(myLibrary
->Songs
->beginV(), myLibrary
->Songs
->endV()));
1459 ShowMessage("Tags updated successfully");
1462 # endif // HAVE_TAGLIB_H
1465 bool EditDirectoryName::canBeRun() const
1467 return (myScreen
== myBrowser
1468 && !myBrowser
->Main()->empty()
1469 && myBrowser
->Main()->current().value().type
== MPD::itDirectory
)
1470 # ifdef HAVE_TAGLIB_H
1471 || (myScreen
->ActiveWindow() == myTagEditor
->Dirs
1472 && !myTagEditor
->Dirs
->empty()
1473 && myTagEditor
->Dirs
->choice() > 0)
1474 # endif // HAVE_TAGLIB_H
1478 void EditDirectoryName::Run()
1480 using Global::wFooter
;
1482 if (!isMPDMusicDirSet())
1484 if (myScreen
== myBrowser
)
1486 std::string old_dir
= myBrowser
->Main()->current().value().name
;
1488 Statusbar() << NC::fmtBold
<< "Directory: " << NC::fmtBoldEnd
;
1489 std::string new_dir
= wFooter
->getString(old_dir
);
1491 if (!new_dir
.empty() && new_dir
!= old_dir
)
1493 std::string full_old_dir
;
1494 if (!myBrowser
->isLocal())
1495 full_old_dir
+= Config
.mpd_music_dir
;
1496 full_old_dir
+= locale_to_utf_cpy(old_dir
);
1497 std::string full_new_dir
;
1498 if (!myBrowser
->isLocal())
1499 full_new_dir
+= Config
.mpd_music_dir
;
1500 full_new_dir
+= locale_to_utf_cpy(new_dir
);
1501 int rename_result
= rename(full_old_dir
.c_str(), full_new_dir
.c_str());
1502 if (rename_result
== 0)
1504 const char msg
[] = "Directory renamed to \"%s\"";
1505 ShowMessage(msg
, Shorten(TO_WSTRING(new_dir
), COLS
-const_strlen(msg
)).c_str());
1506 if (!myBrowser
->isLocal())
1507 Mpd
.UpdateDirectory(locale_to_utf_cpy(getSharedDirectory(old_dir
, new_dir
)));
1508 myBrowser
->GetDirectory(myBrowser
->CurrentDir());
1512 const char msg
[] = "Couldn't rename \"%s\": %s";
1513 ShowMessage(msg
, Shorten(TO_WSTRING(old_dir
), COLS
-const_strlen(msg
)-25).c_str(), strerror(errno
));
1517 # ifdef HAVE_TAGLIB_H
1518 else if (myScreen
->ActiveWindow() == myTagEditor
->Dirs
)
1520 std::string old_dir
= myTagEditor
->Dirs
->current().value().first
;
1522 Statusbar() << NC::fmtBold
<< "Directory: " << NC::fmtBoldEnd
;
1523 std::string new_dir
= wFooter
->getString(old_dir
);
1525 if (!new_dir
.empty() && new_dir
!= old_dir
)
1527 std::string full_old_dir
= Config
.mpd_music_dir
+ myTagEditor
->CurrentDir() + "/" + locale_to_utf_cpy(old_dir
);
1528 std::string full_new_dir
= Config
.mpd_music_dir
+ myTagEditor
->CurrentDir() + "/" + locale_to_utf_cpy(new_dir
);
1529 if (rename(full_old_dir
.c_str(), full_new_dir
.c_str()) == 0)
1531 const char msg
[] = "Directory renamed to \"%s\"";
1532 ShowMessage(msg
, Shorten(TO_WSTRING(new_dir
), COLS
-const_strlen(msg
)).c_str());
1533 Mpd
.UpdateDirectory(myTagEditor
->CurrentDir());
1537 const char msg
[] = "Couldn't rename \"%s\": %s";
1538 ShowMessage(msg
, Shorten(TO_WSTRING(old_dir
), COLS
-const_strlen(msg
)-25).c_str(), strerror(errno
));
1542 # endif // HAVE_TAGLIB_H
1545 bool EditPlaylistName::canBeRun() const
1547 return (myScreen
->ActiveWindow() == myPlaylistEditor
->Playlists
1548 && !myPlaylistEditor
->Playlists
->empty())
1549 || (myScreen
== myBrowser
1550 && !myBrowser
->Main()->empty()
1551 && myBrowser
->Main()->current().value().type
== MPD::itPlaylist
);
1554 void EditPlaylistName::Run()
1556 using Global::wFooter
;
1558 std::string old_name
;
1559 if (myScreen
->ActiveWindow() == myPlaylistEditor
->Playlists
)
1560 old_name
= myPlaylistEditor
->Playlists
->current().value();
1562 old_name
= myBrowser
->Main()->current().value().name
;
1564 Statusbar() << NC::fmtBold
<< "Playlist: " << NC::fmtBoldEnd
;
1565 std::string new_name
= wFooter
->getString(old_name
);
1567 if (!new_name
.empty() && new_name
!= old_name
)
1569 if (Mpd
.Rename(locale_to_utf_cpy(old_name
), locale_to_utf_cpy(new_name
)))
1571 const char msg
[] = "Playlist renamed to \"%s\"";
1572 ShowMessage(msg
, Shorten(TO_WSTRING(new_name
), COLS
-const_strlen(msg
)).c_str());
1573 if (myBrowser
->Main() && !myBrowser
->isLocal())
1574 myBrowser
->GetDirectory("/");
1575 if (myPlaylistEditor
->Main())
1576 myPlaylistEditor
->Playlists
->clear();
1581 bool EditLyrics::canBeRun() const
1583 return myScreen
== myLyrics
;
1586 void EditLyrics::Run()
1591 bool JumpToBrowser::canBeRun() const
1593 return currentSong(myScreen
);
1596 void JumpToBrowser::Run()
1598 auto s
= currentSong(myScreen
);
1600 myBrowser
->LocateSong(*s
);
1603 bool JumpToMediaLibrary::canBeRun() const
1605 return currentSong(myScreen
);
1608 void JumpToMediaLibrary::Run()
1610 auto s
= currentSong(myScreen
);
1612 myLibrary
->LocateSong(*s
);
1615 bool JumpToPlaylistEditor::canBeRun() const
1617 return myScreen
== myBrowser
1618 && myBrowser
->Main()->current().value().type
== MPD::itPlaylist
;
1621 void JumpToPlaylistEditor::Run()
1623 myPlaylistEditor
->Locate(myBrowser
->Main()->current().value().name
);
1626 void ToggleScreenLock::Run()
1628 using Global::wFooter
;
1629 using Global::myLockedScreen
;
1631 if (myLockedScreen
!= 0)
1633 BasicScreen::Unlock();
1634 Action::SetResizeFlags();
1635 ShowMessage("Screen unlocked");
1639 int part
= Config
.locked_screen_width_part
*100;
1640 if (Config
.ask_for_locked_screen_width_part
)
1643 Statusbar() << "% of the locked screen's width to be reserved (20-80): ";
1644 std::string str_part
= wFooter
->getString(intTo
<std::string
>::apply(Config
.locked_screen_width_part
*100));
1646 if (str_part
.empty())
1648 part
= stringToInt(str_part
);
1650 if (part
< 20 || part
> 80)
1652 ShowMessage("Number is out of range");
1655 Config
.locked_screen_width_part
= part
/100.0;
1656 if (myScreen
->Lock())
1657 ShowMessage("Screen locked (with %d%% width)", part
);
1659 ShowMessage("Current screen can't be locked");
1663 bool JumpToTagEditor::canBeRun() const
1665 # ifdef HAVE_TAGLIB_H
1666 return currentSong(myScreen
);
1669 # endif // HAVE_TAGLIB_H
1672 void JumpToTagEditor::Run()
1674 # ifdef HAVE_TAGLIB_H
1675 if (!isMPDMusicDirSet())
1677 auto s
= currentSong(myScreen
);
1679 myTagEditor
->LocateSong(*s
);
1680 # endif // HAVE_TAGLIB_H
1683 bool JumpToPositionInSong::canBeRun() const
1685 return myPlaylist
->NowPlayingSong();
1688 void JumpToPositionInSong::Run()
1690 using Global::wFooter
;
1692 if (!Mpd
.GetTotalTime())
1694 ShowMessage("Unknown item length");
1698 const MPD::Song
*s
= myPlaylist
->NowPlayingSong();
1702 Statusbar() << "Position to go (in %/mm:ss/seconds(s)): ";
1703 std::string position
= wFooter
->getString();
1706 if (position
.empty())
1710 if (position
.find(':') != std::string::npos
) // probably time in mm:ss
1712 newpos
= stringToInt(position
)*60 + stringToInt(position
.substr(position
.find(':')+1));
1713 if (newpos
>= 0 && newpos
<= Mpd
.GetTotalTime())
1716 ShowMessage("Out of bounds, 0:00-%s possible for mm:ss, %s given", s
->getLength().c_str(), MPD::Song::ShowTime(newpos
).c_str());
1718 else if (position
.find('s') != std::string::npos
) // probably position in seconds
1720 newpos
= stringToInt(position
);
1721 if (newpos
>= 0 && newpos
<= Mpd
.GetTotalTime())
1724 ShowMessage("Out of bounds, 0-%d possible for seconds, %d given", s
->getDuration(), newpos
);
1728 newpos
= stringToInt(position
);
1729 if (newpos
>= 0 && newpos
<= 100)
1730 Mpd
.Seek(Mpd
.GetTotalTime()*newpos
/100.0);
1732 ShowMessage("Out of bounds, 0-100 possible for %%, %d given", newpos
);
1736 bool ReverseSelection::canBeRun() const
1738 auto w
= hasSongs(myScreen
);
1739 return w
&& w
->allowsSelection();
1742 void ReverseSelection::Run()
1744 auto w
= hasSongs(myScreen
);
1746 w
->reverseSelection();
1747 ShowMessage("Selection reversed");
1750 bool DeselectItems::canBeRun() const
1752 return proxySongList(myScreen
).get();
1755 void DeselectItems::Run()
1757 auto pl
= proxySongList(myScreen
);
1759 for (size_t i
= 0; i
< pl
->size(); ++i
)
1760 pl
->setSelected(i
, false);
1763 bool SelectAlbum::canBeRun() const
1765 auto w
= hasSongs(myScreen
);
1766 return w
&& w
->allowsSelection() && w
->getProxySongList().get();
1769 void SelectAlbum::Run()
1771 auto pl
= proxySongList(myScreen
);
1773 size_t pos
= pl
->choice();
1774 if (MPD::Song
*s
= pl
->getSong(pos
))
1776 std::string album
= s
->getAlbum();
1777 // select song under cursor
1778 pl
->setSelected(pos
, true);
1782 s
= pl
->getSong(--pos
);
1783 if (!s
|| s
->getAlbum() != album
)
1786 pl
->setSelected(pos
, true);
1790 while (pos
< pl
->size() - 1)
1792 s
= pl
->getSong(++pos
);
1793 if (!s
|| s
->getAlbum() != album
)
1796 pl
->setSelected(pos
, true);
1798 ShowMessage("Album around cursor position selected");
1802 void AddSelectedItems::Run()
1804 mySelectedItemsAdder
->SwitchTo();
1807 void CropMainPlaylist::Run()
1810 if (Config
.ask_before_clearing_main_playlist
)
1811 yes
= AskYesNoQuestion("Do you really want to crop main playlist?", TraceMpdStatus
);
1814 ShowMessage("Cropping playlist...");
1815 if (cropPlaylist(*myPlaylist
->Items
, std::bind(&MPD::Connection::Delete
, _1
, _2
)))
1816 ShowMessage("Cropping playlist...");
1820 bool CropPlaylist::canBeRun() const
1822 return myScreen
== myPlaylistEditor
;
1825 void CropPlaylist::Run()
1827 assert(!myPlaylistEditor
->Playlists
->empty());
1828 std::string playlist
= myPlaylistEditor
->Playlists
->current().value();
1830 if (Config
.ask_before_clearing_main_playlist
)
1831 yes
= AskYesNoQuestion("Do you really want to crop playlist \"" + playlist
+ "\"?", TraceMpdStatus
);
1834 auto delete_fun
= std::bind(&MPD::Connection::PlaylistDelete
, _1
, playlist
, _2
);
1835 ShowMessage("Cropping playlist \"%s\"...", playlist
.c_str());
1836 if (cropPlaylist(*myPlaylistEditor
->Content
, delete_fun
))
1837 ShowMessage("Playlist \"%s\" cropped", playlist
.c_str());
1841 void ClearMainPlaylist::Run()
1844 if (Config
.ask_before_clearing_main_playlist
)
1845 yes
= AskYesNoQuestion("Do you really want to clear main playlist?", TraceMpdStatus
);
1848 auto delete_fun
= std::bind(&MPD::Connection::Delete
, _1
, _2
);
1849 auto clear_fun
= std::bind(&MPD::Connection::ClearMainPlaylist
, _1
);
1850 ShowMessage("Deleting items...");
1851 if (clearPlaylist(*myPlaylist
->Items
, delete_fun
, clear_fun
))
1852 ShowMessage("Items deleted");
1856 bool ClearPlaylist::canBeRun() const
1858 return myScreen
== myPlaylistEditor
;
1861 void ClearPlaylist::Run()
1863 assert(!myPlaylistEditor
->Playlists
->empty());
1864 std::string playlist
= myPlaylistEditor
->Playlists
->current().value();
1866 if (Config
.ask_before_clearing_main_playlist
)
1867 yes
= AskYesNoQuestion("Do you really want to clear playlist \"" + playlist
+ "\"?", TraceMpdStatus
);
1870 auto delete_fun
= std::bind(&MPD::Connection::PlaylistDelete
, _1
, playlist
, _2
);
1871 auto clear_fun
= std::bind(&MPD::Connection::ClearPlaylist
, _1
, playlist
);
1872 ShowMessage("Deleting items from \"%s\"...", playlist
.c_str());
1873 if (clearPlaylist(*myPlaylistEditor
->Content
, delete_fun
, clear_fun
))
1874 ShowMessage("Items deleted from \"%s\"", playlist
.c_str());
1878 bool SortPlaylist::canBeRun() const
1880 return myScreen
== myPlaylist
;
1883 void SortPlaylist::Run()
1888 bool ReversePlaylist::canBeRun() const
1890 return myScreen
== myPlaylist
;
1893 void ReversePlaylist::Run()
1895 myPlaylist
->Reverse();
1898 bool ApplyFilter::canBeRun() const
1900 auto w
= dynamic_cast<Filterable
*>(myScreen
);
1901 return w
&& w
->allowsFiltering();
1904 void ApplyFilter::Run()
1906 using Global::RedrawHeader
;
1907 using Global::wFooter
;
1909 Filterable
*f
= dynamic_cast<Filterable
*>(myScreen
);
1911 assert(f
->allowsFiltering());
1914 Statusbar() << NC::fmtBold
<< "Apply filter: " << NC::fmtBoldEnd
;
1915 wFooter
->setGetStringHelper(std::bind(StatusbarApplyFilterImmediately
, f
, _1
));
1916 wFooter
->getString(f
->currentFilter());
1917 wFooter
->setGetStringHelper(StatusbargetStringHelper
);
1920 std::string filter
= f
->currentFilter();
1923 myPlaylist
->Items
->clearFilterResults();
1924 ShowMessage("Filtering disabled");
1927 ShowMessage("Using filter \"%s\"", filter
.c_str());
1929 if (myScreen
== myPlaylist
)
1931 myPlaylist
->EnableHighlighting();
1932 Playlist::ReloadTotalLength
= true;
1933 RedrawHeader
= true;
1935 ListsChangeFinisher();
1938 void DisableFilter::Run()
1940 using Global::wFooter
;
1942 ApplyFilter
*applyFilter
= dynamic_cast<ApplyFilter
*>(Get(aApplyFilter
));
1943 if (applyFilter
&& applyFilter
->canBeRun())
1945 // delete current filter
1946 wFooter
->pushChar(KEY_CTRL_U
);
1947 wFooter
->pushChar(KEY_ENTER
);
1948 applyFilter
->Execute();
1952 bool Find::canBeRun() const
1954 return myScreen
== myHelp
1955 || myScreen
== myLyrics
1956 # ifdef HAVE_CURL_CURL_H
1957 || myScreen
== myLastfm
1958 # endif // HAVE_CURL_CURL_H
1964 using Global::wFooter
;
1967 Statusbar() << "Find: ";
1968 std::string findme
= wFooter
->getString();
1971 ShowMessage("Searching...");
1972 Screen
<NC::Scrollpad
> *s
= static_cast<Screen
<NC::Scrollpad
> *>(myScreen
);
1973 s
->Main()->removeFormatting();
1974 ShowMessage("%s", findme
.empty() || s
->Main()->setFormatting(NC::fmtReverse
, TO_WSTRING(findme
), NC::fmtReverseEnd
, 0) ? "Done!" : "No matching patterns found");
1978 bool FindItemBackward::canBeRun() const
1980 auto w
= dynamic_cast<Searchable
*>(myScreen
);
1981 return w
&& w
->allowsSearching();
1984 void FindItemForward::Run()
1986 FindItem(fdForward
);
1987 ListsChangeFinisher();
1990 bool FindItemForward::canBeRun() const
1992 auto w
= dynamic_cast<Searchable
*>(myScreen
);
1993 return w
&& w
->allowsSearching();
1996 void FindItemBackward::Run()
1998 FindItem(fdBackward
);
1999 ListsChangeFinisher();
2002 bool NextFoundItem::canBeRun() const
2004 return dynamic_cast<Searchable
*>(myScreen
);
2007 void NextFoundItem::Run()
2009 Searchable
*w
= dynamic_cast<Searchable
*>(myScreen
);
2011 w
->nextFound(Config
.wrapped_search
);
2012 ListsChangeFinisher();
2015 bool PreviousFoundItem::canBeRun() const
2017 return dynamic_cast<Searchable
*>(myScreen
);
2020 void PreviousFoundItem::Run()
2022 Searchable
*w
= dynamic_cast<Searchable
*>(myScreen
);
2024 w
->prevFound(Config
.wrapped_search
);
2025 ListsChangeFinisher();
2028 void ToggleFindMode::Run()
2030 Config
.wrapped_search
= !Config
.wrapped_search
;
2031 ShowMessage("Search mode: %s", Config
.wrapped_search
? "Wrapped" : "Normal");
2034 void ToggleReplayGainMode::Run()
2036 using Global::wFooter
;
2038 if (Mpd
.Version() < 16)
2040 ShowMessage("Replay gain mode control is supported in MPD >= 0.16.0");
2045 Statusbar() << "Replay gain mode? [" << NC::fmtBold
<< 'o' << NC::fmtBoldEnd
<< "ff/" << NC::fmtBold
<< 't' << NC::fmtBoldEnd
<< "rack/" << NC::fmtBold
<< 'a' << NC::fmtBoldEnd
<< "lbum]";
2051 answer
= wFooter
->readKey();
2053 while (answer
!= 'o' && answer
!= 't' && answer
!= 'a');
2055 Mpd
.SetReplayGainMode(answer
== 't' ? MPD::rgmTrack
: (answer
== 'a' ? MPD::rgmAlbum
: MPD::rgmOff
));
2056 ShowMessage("Replay gain mode: %s", Mpd
.GetReplayGainMode().c_str());
2059 void ToggleSpaceMode::Run()
2061 Config
.space_selects
= !Config
.space_selects
;
2062 ShowMessage("Space mode: %s item", Config
.space_selects
? "Select" : "Add");
2065 void ToggleAddMode::Run()
2067 Config
.ncmpc_like_songs_adding
= !Config
.ncmpc_like_songs_adding
;
2068 ShowMessage("Add mode: %s", Config
.ncmpc_like_songs_adding
? "Add item to playlist, remove if already added" : "Always add item to playlist");
2071 void ToggleMouse::Run()
2073 Config
.mouse_support
= !Config
.mouse_support
;
2074 mousemask(Config
.mouse_support
? ALL_MOUSE_EVENTS
: 0, 0);
2075 ShowMessage("Mouse support %s", Config
.mouse_support
? "enabled" : "disabled");
2078 void ToggleBitrateVisibility::Run()
2080 Config
.display_bitrate
= !Config
.display_bitrate
;
2081 ShowMessage("Bitrate visibility %s", Config
.display_bitrate
? "enabled" : "disabled");
2084 void AddRandomItems::Run()
2086 using Global::wFooter
;
2089 Statusbar() << "Add random? [" << NC::fmtBold
<< 's' << NC::fmtBoldEnd
<< "ongs/" << NC::fmtBold
<< 'a' << NC::fmtBoldEnd
<< "rtists/al" << NC::fmtBold
<< 'b' << NC::fmtBoldEnd
<< "ums] ";
2095 answer
= wFooter
->readKey();
2097 while (answer
!= 's' && answer
!= 'a' && answer
!= 'b');
2100 mpd_tag_type tag_type
= charToTagType(answer
);
2101 std::string tag_type_str
= answer
== 's' ? "song" : tagTypeToString(tag_type
);
2102 lowercase(tag_type_str
);
2105 Statusbar() << "Number of random " << tag_type_str
<< "s: ";
2106 size_t number
= stringToLongInt(wFooter
->getString());
2108 if (number
&& (answer
== 's' ? Mpd
.AddRandomSongs(number
) : Mpd
.AddRandomTag(tag_type
, number
)))
2109 ShowMessage("%zu random %s%s added to playlist", number
, tag_type_str
.c_str(), number
== 1 ? "" : "s");
2112 bool ToggleBrowserSortMode::canBeRun() const
2114 return myScreen
== myBrowser
;
2117 void ToggleBrowserSortMode::Run()
2119 switch (Config
.browser_sort_mode
)
2122 if (!myBrowser
->isLocal())
2124 Config
.browser_sort_mode
= smMTime
;
2125 ShowMessage("Sort songs by: Modification time");
2128 // local browser doesn't support sorting by mtime, so we just skip it.
2130 Config
.browser_sort_mode
= smCustomFormat
;
2131 ShowMessage("Sort songs by: Custom format");
2133 case smCustomFormat
:
2134 Config
.browser_sort_mode
= smName
;
2135 ShowMessage("Sort songs by: Name");
2138 std::sort(myBrowser
->Main()->beginV()+(myBrowser
->CurrentDir() != "/"), myBrowser
->Main()->endV(), CaseInsensitiveSorting());
2141 bool ToggleLibraryTagType::canBeRun() const
2143 return (myScreen
->ActiveWindow() == myLibrary
->Tags
)
2144 || (myLibrary
->Columns() == 2 && myScreen
->ActiveWindow() == myLibrary
->Albums
);
2147 void ToggleLibraryTagType::Run()
2149 using Global::wFooter
;
2152 Statusbar() << "Tag type? [" << NC::fmtBold
<< 'a' << NC::fmtBoldEnd
<< "rtist/album" << NC::fmtBold
<< 'A' << NC::fmtBoldEnd
<< "rtist/" << NC::fmtBold
<< 'y' << NC::fmtBoldEnd
<< "ear/" << NC::fmtBold
<< 'g' << NC::fmtBoldEnd
<< "enre/" << NC::fmtBold
<< 'c' << NC::fmtBoldEnd
<< "omposer/" << NC::fmtBold
<< 'p' << NC::fmtBoldEnd
<< "erformer] ";
2158 answer
= wFooter
->readKey();
2160 while (answer
!= 'a' && answer
!= 'A' && answer
!= 'y' && answer
!= 'g' && answer
!= 'c' && answer
!= 'p');
2162 mpd_tag_type new_tagitem
= charToTagType(answer
);
2163 if (new_tagitem
!= Config
.media_lib_primary_tag
)
2165 Config
.media_lib_primary_tag
= new_tagitem
;
2166 std::string item_type
= tagTypeToString(Config
.media_lib_primary_tag
);
2167 myLibrary
->Tags
->setTitle(Config
.titles_visibility
? item_type
+ "s" : "");
2168 myLibrary
->Tags
->reset();
2169 lowercase(item_type
);
2170 if (myLibrary
->Columns() == 2)
2172 myLibrary
->Songs
->clear();
2173 myLibrary
->Albums
->reset();
2174 myLibrary
->Albums
->clear();
2175 myLibrary
->Albums
->setTitle(Config
.titles_visibility
? "Albums (sorted by " + item_type
+ ")" : "");
2176 myLibrary
->Albums
->display();
2180 myLibrary
->Tags
->clear();
2181 myLibrary
->Tags
->display();
2183 ShowMessage("Switched to list of %s tag", item_type
.c_str());
2187 bool RefetchLyrics::canBeRun() const
2189 # ifdef HAVE_CURL_CURL_H
2190 return myScreen
== myLyrics
;
2193 # endif // HAVE_CURL_CURL_H
2196 void RefetchLyrics::Run()
2198 # ifdef HAVE_CURL_CURL_H
2199 myLyrics
->Refetch();
2200 # endif // HAVE_CURL_CURL_H
2203 bool RefetchArtistInfo::canBeRun() const
2205 # ifdef HAVE_CURL_CURL_H
2206 return myScreen
== myLastfm
;
2209 # endif // HAVE_CURL_CURL_H
2212 void RefetchArtistInfo::Run()
2214 # ifdef HAVE_CURL_CURL_H
2215 myLastfm
->Refetch();
2216 # endif // HAVE_CURL_CURL_H
2219 bool SetSelectedItemsPriority::canBeRun() const
2221 return myScreen
->ActiveWindow() == myPlaylist
->Items
;
2224 void SetSelectedItemsPriority::Run()
2226 using Global::wFooter
;
2228 assert(myScreen
->ActiveWindow() == myPlaylist
->Items
);
2229 if (myPlaylist
->Items
->empty())
2232 if (Mpd
.Version() < 17)
2234 ShowMessage("Priorities are supported in MPD >= 0.17.0");
2239 Statusbar() << "Set priority [0-255]: ";
2240 std::string strprio
= wFooter
->getString();
2242 if (!isInteger(strprio
.c_str()))
2244 int prio
= atoi(strprio
.c_str());
2245 if (prio
< 0 || prio
> 255)
2247 ShowMessage("Number is out of range");
2250 myPlaylist
->SetSelectedItemsPriority(prio
);
2253 void ShowSongInfo::Run()
2255 mySongInfo
->SwitchTo();
2258 bool ShowArtistInfo::canBeRun() const
2260 #ifdef HAVE_CURL_CURL_H
2261 return myScreen
== myLastfm
2262 || (myScreen
->ActiveWindow() == myLibrary
->Tags
2263 && !myLibrary
->Tags
->empty()
2264 && Config
.media_lib_primary_tag
== MPD_TAG_ARTIST
)
2265 || currentSong(myScreen
);
2268 # endif // NOT HAVE_CURL_CURL_H
2271 void ShowArtistInfo::Run()
2273 # ifdef HAVE_CURL_CURL_H
2274 if (myScreen
== myLastfm
|| myLastfm
->isDownloading())
2276 myLastfm
->SwitchTo();
2281 if (myScreen
->ActiveWindow() == myLibrary
->Tags
)
2283 assert(!myLibrary
->Tags
->empty());
2284 assert(Config
.media_lib_primary_tag
== MPD_TAG_ARTIST
);
2285 artist
= myLibrary
->Tags
->current().value();
2289 auto s
= currentSong(myScreen
);
2291 artist
= s
->getArtist();
2294 if (!artist
.empty() && myLastfm
->SetArtistInfoArgs(artist
, Config
.lastfm_preferred_language
))
2295 myLastfm
->SwitchTo();
2296 # endif // HAVE_CURL_CURL_H
2299 void ShowLyrics::Run()
2301 myLyrics
->SwitchTo();
2306 ExitMainLoop
= true;
2309 void NextScreen::Run()
2311 using Global::myOldScreen
;
2312 using Global::myPrevScreen
;
2314 if (Config
.screen_switcher_previous
)
2316 if (myScreen
->isTabbable())
2317 myPrevScreen
->SwitchTo();
2319 myOldScreen
->SwitchTo();
2321 else if (!Config
.screens_seq
.empty())
2323 std::list
<BasicScreen
*>::const_iterator screen
= std::find(Config
.screens_seq
.begin(), Config
.screens_seq
.end(), myScreen
);
2324 if (++screen
== Config
.screens_seq
.end())
2325 Config
.screens_seq
.front()->SwitchTo();
2327 (*screen
)->SwitchTo();
2331 void PreviousScreen::Run()
2333 using Global::myOldScreen
;
2334 using Global::myPrevScreen
;
2336 if (Config
.screen_switcher_previous
)
2338 if (myScreen
->isTabbable())
2339 myPrevScreen
->SwitchTo();
2341 myOldScreen
->SwitchTo();
2343 else if (!Config
.screens_seq
.empty())
2345 std::list
<BasicScreen
*>::const_iterator screen
= std::find(Config
.screens_seq
.begin(), Config
.screens_seq
.end(), myScreen
);
2346 if (screen
== Config
.screens_seq
.begin())
2347 Config
.screens_seq
.back()->SwitchTo();
2349 (*--screen
)->SwitchTo();
2353 #ifdef HAVE_TAGLIB_H
2354 bool ShowHelp::canBeRun() const
2356 return myScreen
!= myTinyTagEditor
;
2358 #endif // HAVE_TAGLIB_H
2360 void ShowHelp::Run()
2365 #ifdef HAVE_TAGLIB_H
2366 bool ShowPlaylist::canBeRun() const
2368 return myScreen
!= myTinyTagEditor
;
2370 #endif // HAVE_TAGLIB_H
2372 void ShowPlaylist::Run()
2374 myPlaylist
->SwitchTo();
2377 #ifdef HAVE_TAGLIB_H
2378 bool ShowBrowser::canBeRun() const
2380 return myScreen
!= myTinyTagEditor
;
2382 #endif // HAVE_TAGLIB_H
2384 void ShowBrowser::Run()
2386 myBrowser
->SwitchTo();
2389 #ifdef HAVE_TAGLIB_H
2390 bool ShowSearchEngine::canBeRun() const
2392 return myScreen
!= myTinyTagEditor
;
2394 #endif // HAVE_TAGLIB_H
2396 void ShowSearchEngine::Run()
2398 mySearcher
->SwitchTo();
2401 #ifdef HAVE_TAGLIB_H
2402 bool ShowMediaLibrary::canBeRun() const
2404 return myScreen
!= myTinyTagEditor
;
2406 #endif // HAVE_TAGLIB_H
2408 void ShowMediaLibrary::Run()
2410 myLibrary
->SwitchTo();
2413 #ifdef HAVE_TAGLIB_H
2414 bool ShowPlaylistEditor::canBeRun() const
2416 return myScreen
!= myTinyTagEditor
;
2418 #endif // HAVE_TAGLIB_H
2420 void ShowPlaylistEditor::Run()
2422 myPlaylistEditor
->SwitchTo();
2425 bool ShowTagEditor::canBeRun() const
2427 # ifdef HAVE_TAGLIB_H
2428 return myScreen
!= myTinyTagEditor
;
2431 # endif // HAVE_TAGLIB_H
2434 void ShowTagEditor::Run()
2436 # ifdef HAVE_TAGLIB_H
2437 if (isMPDMusicDirSet())
2438 myTagEditor
->SwitchTo();
2439 # endif // HAVE_TAGLIB_H
2442 bool ShowOutputs::canBeRun() const
2444 # ifdef ENABLE_OUTPUTS
2445 # ifdef HAVE_TAGLIB_H
2446 return myScreen
!= myTinyTagEditor
;
2449 # endif // HAVE_TAGLIB_H
2452 # endif // ENABLE_OUTPUTS
2455 void ShowOutputs::Run()
2457 # ifdef ENABLE_OUTPUTS
2458 myOutputs
->SwitchTo();
2459 # endif // ENABLE_OUTPUTS
2462 bool ShowVisualizer::canBeRun() const
2464 # ifdef ENABLE_OUTPUTS
2465 # ifdef HAVE_TAGLIB_H
2466 return myScreen
!= myTinyTagEditor
;
2469 # endif // HAVE_TAGLIB_H
2472 # endif // ENABLE_OUTPUTS
2475 void ShowVisualizer::Run()
2477 # ifdef ENABLE_VISUALIZER
2478 myVisualizer
->SwitchTo();
2479 # endif // ENABLE_VISUALIZER
2482 bool ShowClock::canBeRun() const
2484 # ifdef ENABLE_CLOCK
2485 # ifdef HAVE_TAGLIB_H
2486 return myScreen
!= myTinyTagEditor
;
2489 # endif // HAVE_TAGLIB_H
2492 # endif // ENABLE_CLOCK
2495 void ShowClock::Run()
2497 # ifdef ENABLE_CLOCK
2498 myClock
->SwitchTo();
2499 # endif // ENABLE_CLOCK
2502 #ifdef HAVE_TAGLIB_H
2503 bool ShowServerInfo::canBeRun() const
2505 return myScreen
!= myTinyTagEditor
;
2507 #endif // HAVE_TAGLIB_H
2509 void ShowServerInfo::Run()
2511 myServerInfo
->SwitchTo();
2516 void insertAction(Action
*a
)
2518 Actions
[a
->Type()] = a
;
2521 void populateActions()
2523 insertAction(new Dummy());
2524 insertAction(new MouseEvent());
2525 insertAction(new ScrollUp());
2526 insertAction(new ScrollDown());
2527 insertAction(new ScrollUpArtist());
2528 insertAction(new ScrollUpAlbum());
2529 insertAction(new ScrollDownArtist());
2530 insertAction(new ScrollDownAlbum());
2531 insertAction(new PageUp());
2532 insertAction(new PageDown());
2533 insertAction(new MoveHome());
2534 insertAction(new MoveEnd());
2535 insertAction(new ToggleInterface());
2536 insertAction(new JumpToParentDir());
2537 insertAction(new PressEnter());
2538 insertAction(new PressSpace());
2539 insertAction(new PreviousColumn());
2540 insertAction(new NextColumn());
2541 insertAction(new MasterScreen());
2542 insertAction(new SlaveScreen());
2543 insertAction(new VolumeUp());
2544 insertAction(new VolumeDown());
2545 insertAction(new Delete());
2546 insertAction(new ReplaySong());
2547 insertAction(new PreviousSong());
2548 insertAction(new NextSong());
2549 insertAction(new Pause());
2550 insertAction(new Stop());
2551 insertAction(new SavePlaylist());
2552 insertAction(new MoveSortOrderUp());
2553 insertAction(new MoveSortOrderDown());
2554 insertAction(new MoveSelectedItemsUp());
2555 insertAction(new MoveSelectedItemsDown());
2556 insertAction(new MoveSelectedItemsTo());
2557 insertAction(new Add());
2558 insertAction(new SeekForward());
2559 insertAction(new SeekBackward());
2560 insertAction(new ToggleDisplayMode());
2561 insertAction(new ToggleSeparatorsBetweenAlbums());
2562 insertAction(new ToggleLyricsFetcher());
2563 insertAction(new ToggleFetchingLyricsInBackground());
2564 insertAction(new ToggleAutoCenter());
2565 insertAction(new UpdateDatabase());
2566 insertAction(new JumpToPlayingSong());
2567 insertAction(new ToggleRepeat());
2568 insertAction(new Shuffle());
2569 insertAction(new ToggleRandom());
2570 insertAction(new StartSearching());
2571 insertAction(new SaveTagChanges());
2572 insertAction(new ToggleSingle());
2573 insertAction(new ToggleConsume());
2574 insertAction(new ToggleCrossfade());
2575 insertAction(new SetCrossfade());
2576 insertAction(new EditSong());
2577 insertAction(new EditLibraryTag());
2578 insertAction(new EditLibraryAlbum());
2579 insertAction(new EditDirectoryName());
2580 insertAction(new EditPlaylistName());
2581 insertAction(new EditLyrics());
2582 insertAction(new JumpToBrowser());
2583 insertAction(new JumpToMediaLibrary());
2584 insertAction(new JumpToPlaylistEditor());
2585 insertAction(new ToggleScreenLock());
2586 insertAction(new JumpToTagEditor());
2587 insertAction(new JumpToPositionInSong());
2588 insertAction(new ReverseSelection());
2589 insertAction(new DeselectItems());
2590 insertAction(new SelectAlbum());
2591 insertAction(new AddSelectedItems());
2592 insertAction(new CropMainPlaylist());
2593 insertAction(new CropPlaylist());
2594 insertAction(new ClearMainPlaylist());
2595 insertAction(new ClearPlaylist());
2596 insertAction(new SortPlaylist());
2597 insertAction(new ReversePlaylist());
2598 insertAction(new ApplyFilter());
2599 insertAction(new DisableFilter());
2600 insertAction(new Find());
2601 insertAction(new FindItemForward());
2602 insertAction(new FindItemBackward());
2603 insertAction(new NextFoundItem());
2604 insertAction(new PreviousFoundItem());
2605 insertAction(new ToggleFindMode());
2606 insertAction(new ToggleReplayGainMode());
2607 insertAction(new ToggleSpaceMode());
2608 insertAction(new ToggleAddMode());
2609 insertAction(new ToggleMouse());
2610 insertAction(new ToggleBitrateVisibility());
2611 insertAction(new AddRandomItems());
2612 insertAction(new ToggleBrowserSortMode());
2613 insertAction(new ToggleLibraryTagType());
2614 insertAction(new RefetchLyrics());
2615 insertAction(new RefetchArtistInfo());
2616 insertAction(new SetSelectedItemsPriority());
2617 insertAction(new ShowSongInfo());
2618 insertAction(new ShowArtistInfo());
2619 insertAction(new ShowLyrics());
2620 insertAction(new Quit());
2621 insertAction(new NextScreen());
2622 insertAction(new PreviousScreen());
2623 insertAction(new ShowHelp());
2624 insertAction(new ShowPlaylist());
2625 insertAction(new ShowBrowser());
2626 insertAction(new ShowSearchEngine());
2627 insertAction(new ShowMediaLibrary());
2628 insertAction(new ShowPlaylistEditor());
2629 insertAction(new ShowTagEditor());
2630 insertAction(new ShowOutputs());
2631 insertAction(new ShowVisualizer());
2632 insertAction(new ShowClock());
2633 insertAction(new ShowServerInfo());