diff --git a/src/misc.cpp b/src/misc.cpp index aa0a355c..47c1b254 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -37,10 +37,23 @@ SelectedItemsAdder *mySelectedItemsAdder = new SelectedItemsAdder; void SelectedItemsAdder::Init() { SetDimensions(); - w = new Menu((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "Add selected items to...", Config.main_color, Config.window_border); - w->CyclicScrolling(Config.use_cyclic_scrolling); - w->HighlightColor(Config.main_highlight_color); - w->SetItemDisplayer(Display::Generic); + itsPlaylistSelector = new Menu((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "Add selected items to...", Config.main_color, Config.window_border); + itsPlaylistSelector->CyclicScrolling(Config.use_cyclic_scrolling); + itsPlaylistSelector->HighlightColor(Config.main_highlight_color); + itsPlaylistSelector->SetItemDisplayer(Display::Generic); + + itsPositionSelector = new Menu((COLS-itsPSWidth)/2, (MainHeight-itsPSHeight)/2+MainStartY, itsPSWidth, itsPSHeight, "Where?", Config.main_color, Config.window_border); + itsPositionSelector->CyclicScrolling(Config.use_cyclic_scrolling); + itsPositionSelector->HighlightColor(Config.main_highlight_color); + itsPositionSelector->SetItemDisplayer(Display::Generic); + itsPositionSelector->AddOption("At the end of playlist"); + itsPositionSelector->AddOption("At the beginning of playlist"); + itsPositionSelector->AddOption("After current track"); + itsPositionSelector->AddOption("After current album"); + itsPositionSelector->AddSeparator(); + itsPositionSelector->AddOption("Cancel"); + + w = itsPlaylistSelector; isInitialized = 1; } @@ -67,6 +80,9 @@ void SelectedItemsAdder::SwitchTo() if (!isInitialized) Init(); + // default to main window + w = itsPlaylistSelector; + // Resize() can fall back to old screen, so we need it updated myOldScreen = myScreen; @@ -102,8 +118,12 @@ void SelectedItemsAdder::Resize() SetDimensions(); if (itsHeight < 5) // screen too low to display this window return myOldScreen->SwitchTo(); - w->Resize(itsWidth, itsHeight); - w->MoveTo((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY); + itsPlaylistSelector->Resize(itsWidth, itsHeight); + itsPlaylistSelector->MoveTo((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY); + size_t poss_width = std::min(itsPSWidth, size_t(COLS)); + size_t poss_height = std::min(itsPSHeight, size_t(MainHeight)); + itsPositionSelector->Resize(poss_width, poss_height); + itsPositionSelector->MoveTo((COLS-poss_width)/2, (MainHeight-poss_height)/2+MainStartY); if (myOldScreen && myOldScreen->hasToBeResized) // resize background window { myOldScreen->Resize(); @@ -112,6 +132,17 @@ void SelectedItemsAdder::Resize() hasToBeResized = 0; } +void SelectedItemsAdder::Refresh() +{ + if (w == itsPositionSelector) + { + itsPlaylistSelector->Display(); + itsPositionSelector->Display(); + } + else + itsPlaylistSelector->Display(); +} + std::basic_string SelectedItemsAdder::Title() { return myOldScreen->Title(); @@ -122,46 +153,89 @@ void SelectedItemsAdder::EnterPressed() size_t pos = w->Choice(); MPD::SongList list; - if (pos != w->Size()-1) + if ((w != itsPlaylistSelector || pos != 0) && pos != w->Size()-1) myOldScreen->GetSelectedSongs(list); - if (pos == 0) // add to mpd playlist + if (w == itsPlaylistSelector) { - if (myPlaylist->Add(list, 0)) - ShowMessage("Selected items added!"); - } - else if (pos == 1) // create new playlist - { - LockStatusbar(); - Statusbar() << "Save playlist as: "; - std::string playlist = Global::wFooter->GetString(); - UnlockStatusbar(); - if (!playlist.empty()) + if (pos == 0) // add to mpd playlist { - std::string utf_playlist = locale_to_utf_cpy(playlist); + w = itsPositionSelector; + itsPositionSelector->Reset(); + return; + } + else if (pos == 1) // create new playlist + { + LockStatusbar(); + Statusbar() << "Save playlist as: "; + std::string playlist = Global::wFooter->GetString(); + UnlockStatusbar(); + if (!playlist.empty()) + { + std::string utf_playlist = locale_to_utf_cpy(playlist); + Mpd.StartCommandsList(); + for (MPD::SongList::const_iterator it = list.begin(); it != list.end(); ++it) + Mpd.AddToPlaylist(utf_playlist, **it); + if (Mpd.CommitCommandsList()) + ShowMessage("Selected items added to playlist \"%s\"!", playlist.c_str()); + } + } + else if (pos > 1 && pos < w->Size()-1) // add items to existing playlist + { + std::string playlist = locale_to_utf_cpy(w->Current()); Mpd.StartCommandsList(); for (MPD::SongList::const_iterator it = list.begin(); it != list.end(); ++it) - Mpd.AddToPlaylist(utf_playlist, **it); + Mpd.AddToPlaylist(playlist, **it); if (Mpd.CommitCommandsList()) - ShowMessage("Selected items added to playlist \"%s\"!", playlist.c_str()); + ShowMessage("Selected items added to playlist \"%s\"!", w->Current().c_str()); + } + if (pos != w->Size()-1) + { + // refresh playlist's lists + if (myBrowser->Main() && !myBrowser->isLocal() && myBrowser->CurrentDir() == "/") + myBrowser->GetDirectory("/"); + if (myPlaylistEditor->Main()) + myPlaylistEditor->Playlists->Clear(); // make playlist editor update itself } } - else if (pos > 1 && pos < w->Size()-1) // add items to existing playlist + else { - std::string playlist = locale_to_utf_cpy(w->Current()); - Mpd.StartCommandsList(); - for (MPD::SongList::const_iterator it = list.begin(); it != list.end(); ++it) - Mpd.AddToPlaylist(playlist, **it); - if (Mpd.CommitCommandsList()) - ShowMessage("Selected items added to playlist \"%s\"!", w->Current().c_str()); - } - if (pos != w->Size()-1) - { - // refresh playlist's lists - if (myBrowser->Main() && !myBrowser->isLocal() && myBrowser->CurrentDir() == "/") - myBrowser->GetDirectory("/"); - if (myPlaylistEditor->Main()) - myPlaylistEditor->Playlists->Clear(); // make playlist editor update itself + if (pos > 0 && pos < 3 && !Mpd.isPlaying()) + { + ShowMessage("Player is stopped!"); + return; + } + + bool successful_operation; + if (pos == 0) // end of playlist + { + successful_operation = myPlaylist->Add(list, 0); + } + else if (pos == 1) // beginning of playlist + { + successful_operation = myPlaylist->Add(list, 0, 0); + } + else if (pos == 2) // after currently playing track + { + successful_operation = myPlaylist->Add(list, 0, Mpd.GetCurrentSongPos()+1); + } + else if (pos == 3) // after currently playing album + { + std::string album = myPlaylist->CurrentSong()->GetAlbum(); + int i; + for (i = Mpd.GetCurrentSongPos()+1; i < int(myPlaylist->Items->Size()); ++i) + if ((*myPlaylist->Items)[i].GetAlbum() != album) + break; + successful_operation = myPlaylist->Add(list, 0, i); + } + else + { + w = itsPlaylistSelector; + return; + } + + if (successful_operation) + ShowMessage("Selected items added!"); } MPD::FreeSongList(list); SwitchTo(); diff --git a/src/misc.h b/src/misc.h index 8a3e6354..c2d6a199 100644 --- a/src/misc.h +++ b/src/misc.h @@ -27,8 +27,11 @@ class SelectedItemsAdder : public Screen< Menu > { public: + SelectedItemsAdder() : itsPSWidth(35), itsPSHeight(10) { } + virtual void SwitchTo(); virtual void Resize(); + virtual void Refresh(); virtual std::basic_string Title(); @@ -46,6 +49,12 @@ class SelectedItemsAdder : public Screen< Menu > private: void SetDimensions(); + Menu *itsPlaylistSelector; + Menu *itsPositionSelector; + + size_t itsPSWidth; + size_t itsPSHeight; + size_t itsWidth; size_t itsHeight; }; diff --git a/src/playlist.cpp b/src/playlist.cpp index 367ac9c5..904499ff 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -419,7 +419,7 @@ std::string Playlist::SongInColumnsToString(const MPD::Song &s, void *) return s.toString(result); } -bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play) +bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play, int position) { BlockItemListUpdate = 1; if (Config.ncmpc_like_songs_adding && in_playlist) @@ -457,7 +457,7 @@ bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play) } else { - int id = Mpd.AddSong(s); + int id = Mpd.AddSong(s, position); if (id >= 0) { ShowMessage("Added to playlist: %s", s.toString(Config.song_status_format_no_colors).c_str()); @@ -470,7 +470,7 @@ bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play) } } -bool Playlist::Add(const MPD::SongList &l, bool play) +bool Playlist::Add(const MPD::SongList &l, bool play, int position) { if (l.empty()) return false; @@ -479,15 +479,25 @@ bool Playlist::Add(const MPD::SongList &l, bool play) Mpd.StartCommandsList(); MPD::SongList::const_iterator it = l.begin(); - for (; it != l.end(); ++it) - if (Mpd.AddSong(**it) < 0) - break; + if (position < 0) + { + for (; it != l.end(); ++it) + if (Mpd.AddSong(**it) < 0) + break; + } + else + { + MPD::SongList::const_reverse_iterator j = l.rbegin(); + for (; j != l.rend(); ++j) + if (Mpd.AddSong(**j, position) < 0) + break; + } Mpd.CommitCommandsList(); if (play && old_playlist_size < Items->Size()) Mpd.Play(old_playlist_size); - if (Items->Back().GetHash() != l.back()->GetHash()) + if (position < 0 && Items->Back().GetHash() != l.back()->GetHash()) { if (it != l.begin()) ShowMessage("%s", MPD::Message::PartOfSongsAdded); diff --git a/src/playlist.h b/src/playlist.h index 79f21d4a..eac49124 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -64,8 +64,8 @@ class Playlist : public Screen void UpdateTimer() { time(&itsTimer); } time_t Timer() const { return itsTimer; } - bool Add(const MPD::Song &s, bool in_playlist, bool play); - bool Add(const MPD::SongList &l, bool play); + bool Add(const MPD::Song &s, bool in_playlist, bool play, int position = -1); + bool Add(const MPD::SongList &l, bool play, int position = -1); static std::string SongToString(const MPD::Song &, void *); static std::string SongInColumnsToString(const MPD::Song &, void *);