diff --git a/doc/ncmpcpp_keys b/doc/ncmpcpp_keys index 71fbd079..4f5a4e06 100644 --- a/doc/ncmpcpp_keys +++ b/doc/ncmpcpp_keys @@ -37,6 +37,8 @@ # #key_toggle_space_mode = 't' # +#key_toggle_add_mode = 'T' +# #key_screen_switcher = 9 # #key_help = '1' 265 diff --git a/doc/ncmpcpprc b/doc/ncmpcpprc index 87c78235..51220c15 100644 --- a/doc/ncmpcpprc +++ b/doc/ncmpcpprc @@ -94,7 +94,7 @@ # ##### various settings ##### # -#playlist_display_mode = "normal" (classic/columns) +#playlist_display_mode = "classic" (classic/columns) # #incremental_seeking = "yes" # @@ -118,6 +118,8 @@ # #follow_now_playing_lyrics = "no" # +#ncmpc_like_songs_adding = "no" (enabled - add/remove, disabled - always add) +# #enable_window_title = "yes" # ##### colors definitions ##### diff --git a/src/help.cpp b/src/help.cpp index 1cdbeb9b..2ce51905 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -114,6 +114,7 @@ string GetKeybindings() result += DisplayKeys(Key.VolumeUp) + "Increase volume\n\n"; result += DisplayKeys(Key.ToggleSpaceMode) + "Toggle space mode (select/add)\n"; + result += DisplayKeys(Key.ToggleAddMode) + "Toggle add mode\n"; result += DisplayKeys(Key.ReverseSelection) + "Reverse selection\n"; result += DisplayKeys(Key.DeselectAll) + "Deselect all items\n"; result += DisplayKeys(Key.AddSelected) + "Add selected items to playlist/m3u file\n\n"; diff --git a/src/menu.h b/src/menu.h index be198c2a..25d473b5 100644 --- a/src/menu.h +++ b/src/menu.h @@ -88,7 +88,8 @@ class Menu : public Window virtual int Size() const { return itsOptions.size(); } bool Empty() const { return itsOptions.empty(); } - virtual bool IsStatic(int) const; + bool IsBold(int = -1) const; + virtual bool IsStatic(int = -1) const; virtual Window * Clone() const { return new Menu(*this); } virtual Window * EmptyClone() const; @@ -668,12 +669,25 @@ int Menu::GetRealChoice() const return real_choice; } +template +bool Menu::IsBold(int option) const +{ + try + { + return itsOptions.at(option == -1 ? itsHighlight : option)->is_bold; + } + catch (std::out_of_range) + { + return 0; + } +} + template bool Menu::IsStatic(int option) const { try { - return itsOptions.at(option)->is_static; + return itsOptions.at(option == -1 ? itsHighlight : option)->is_static; } catch (std::out_of_range) { diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index 7b086361..2085c76f 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -899,6 +899,22 @@ int main(int argc, char *argv[]) case itSong: { block_item_list_update = 1; + if (Config.ncmpc_like_songs_adding && mBrowser->IsBold()) + { + bool found = 0; + long long hash = mBrowser->Current().song->GetHash(); + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->Play(i); + found = 1; + break; + } + } + if (found) + break; + } Song &s = *item.song; int id = Mpd->AddSong(s); if (id >= 0) @@ -1184,13 +1200,28 @@ int main(int argc, char *argv[]) default: { block_item_list_update = 1; - const Song &s = mSearcher->Current().second; - int id = Mpd->AddSong(s); - if (id >= 0) + if (Config.ncmpc_like_songs_adding && mSearcher->IsBold()) { - Mpd->PlayID(id); - ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); - mSearcher->BoldOption(mSearcher->GetChoice(), 1); + long long hash = mSearcher->Current().second.GetHash(); + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->Play(i); + break; + } + } + } + else + { + const Song &s = mSearcher->Current().second; + int id = Mpd->AddSong(s); + if (id >= 0) + { + Mpd->PlayID(id); + ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + mSearcher->BoldOption(mSearcher->GetChoice(), 1); + } } break; } @@ -1249,14 +1280,47 @@ int main(int argc, char *argv[]) if (!mLibSongs->Empty()) { block_item_list_update = 1; - Song &s = mLibSongs->Current(); - int id = Mpd->AddSong(s); - if (id >= 0) + if (Config.ncmpc_like_songs_adding && mLibSongs->IsBold()) { - ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + long long hash = mLibSongs->Current().GetHash(); if (Keypressed(input, Key.Enter)) - Mpd->PlayID(id); - mLibSongs->BoldOption(mLibSongs->GetChoice(), 1); + { + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->Play(i); + break; + } + } + } + else + { + block_playlist_update = 1; + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->QueueDeleteSong(i); + mPlaylist->DeleteOption(i); + i--; + } + } + Mpd->CommitQueue(); + mLibSongs->BoldOption(mLibSongs->GetChoice(), 0); + } + } + else + { + Song &s = mLibSongs->Current(); + int id = Mpd->AddSong(s); + if (id >= 0) + { + ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + if (Keypressed(input, Key.Enter)) + Mpd->PlayID(id); + mLibSongs->BoldOption(mLibSongs->GetChoice(), 1); + } } } } @@ -1304,14 +1368,47 @@ int main(int argc, char *argv[]) if (!mPlaylistEditor->Empty()) { block_item_list_update = 1; - Song &s = mPlaylistEditor->at(mPlaylistEditor->GetChoice()); - int id = Mpd->AddSong(s); - if (id >= 0) + if (Config.ncmpc_like_songs_adding && mPlaylistEditor->IsBold()) { - ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + long long hash = mPlaylistEditor->Current().GetHash(); if (Keypressed(input, Key.Enter)) - Mpd->PlayID(id); - mPlaylistEditor->BoldOption(mPlaylistEditor->GetChoice(), 1); + { + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->Play(i); + break; + } + } + } + else + { + block_playlist_update = 1; + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->QueueDeleteSong(i); + mPlaylist->DeleteOption(i); + i--; + } + } + Mpd->CommitQueue(); + mPlaylistEditor->BoldOption(mPlaylistEditor->GetChoice(), 0); + } + } + else + { + Song &s = mPlaylistEditor->at(mPlaylistEditor->GetChoice()); + int id = Mpd->AddSong(s); + if (id >= 0) + { + ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + if (Keypressed(input, Key.Enter)) + Mpd->PlayID(id); + mPlaylistEditor->BoldOption(mPlaylistEditor->GetChoice(), 1); + } } } } @@ -1522,7 +1619,7 @@ int main(int argc, char *argv[]) SongList list; Mpd->GetDirectoryRecursive(item.name, list); - + for (SongList::const_iterator it = list.begin(); it != list.end(); it++) Mpd->QueueAddSong(**it); if (Mpd->CommitQueue()) @@ -1538,11 +1635,30 @@ int main(int argc, char *argv[]) case itSong: { block_item_list_update = 1; - Song &s = *item.song; - if (Mpd->AddSong(s) != -1) + if (Config.ncmpc_like_songs_adding && mBrowser->IsBold()) { - ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); - mBrowser->BoldOption(mBrowser->GetChoice(), 1); + block_playlist_update = 1; + long long hash = mBrowser->Current().song->GetHash(); + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->QueueDeleteSong(i); + mPlaylist->DeleteOption(i); + i--; + } + } + Mpd->CommitQueue(); + mBrowser->BoldOption(mBrowser->GetChoice(), 0); + } + else + { + Song &s = *item.song; + if (Mpd->AddSong(s) != -1) + { + ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + mBrowser->BoldOption(mBrowser->GetChoice(), 1); + } } break; } @@ -1568,11 +1684,30 @@ int main(int argc, char *argv[]) else if (current_screen == csSearcher && mSearcher->Current().first == ".") { block_item_list_update = 1; - Song &s = mSearcher->Current().second; - if (Mpd->AddSong(s) != -1) + if (Config.ncmpc_like_songs_adding && mSearcher->IsBold()) { - ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); - mSearcher->BoldOption(mSearcher->GetChoice(), 1); + block_playlist_update = 1; + long long hash = mSearcher->Current().second.GetHash(); + for (int i = 0; i < mPlaylist->Size(); i++) + { + if (mPlaylist->at(i).GetHash() == hash) + { + Mpd->QueueDeleteSong(i); + mPlaylist->DeleteOption(i); + i--; + } + } + Mpd->CommitQueue(); + mSearcher->BoldOption(mSearcher->GetChoice(), 0); + } + else + { + Song &s = mSearcher->Current().second; + if (Mpd->AddSong(s) != -1) + { + ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format)); + mSearcher->BoldOption(mSearcher->GetChoice(), 1); + } } mSearcher->Go(wDown); } @@ -2803,6 +2938,11 @@ int main(int argc, char *argv[]) Config.space_selects = !Config.space_selects; ShowMessage("Space mode: " + string(Config.space_selects ? "Select/deselect" : "Add") + " item"); } + else if (Keypressed(input, Key.ToggleAddMode)) + { + Config.ncmpc_like_songs_adding = !Config.ncmpc_like_songs_adding; + ShowMessage("Add mode: " + string(Config.ncmpc_like_songs_adding ? "Add item to playlist, remove if already added" : "Always add item to playlist")); + } else if (Keypressed(input, Key.SongInfo)) { if (wCurrent == sInfo) diff --git a/src/settings.cpp b/src/settings.cpp index ce08a6c0..ef970cff 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -56,6 +56,7 @@ void DefaultKeys(ncmpcpp_keys &keys) keys.ToggleRepeatOne[0] = 'R'; keys.ToggleRandom[0] = 'z'; keys.ToggleSpaceMode[0] = 't'; + keys.ToggleAddMode[0] = 'T'; keys.Shuffle[0] = 'Z'; keys.ToggleCrossfade[0] = 'x'; keys.SetCrossfade[0] = 'X'; @@ -116,6 +117,7 @@ void DefaultKeys(ncmpcpp_keys &keys) keys.ToggleRepeatOne[1] = null_key; keys.ToggleRandom[1] = null_key; keys.ToggleSpaceMode[1] = null_key; + keys.ToggleAddMode[1] = null_key; keys.Shuffle[1] = null_key; keys.ToggleCrossfade[1] = null_key; keys.SetCrossfade[1] = null_key; @@ -184,6 +186,7 @@ void DefaultConfiguration(ncmpcpp_config &conf) conf.repeat_one_mode = false; conf.wrapped_search = true; conf.space_selects = false; + conf.ncmpc_like_songs_adding = false; conf.albums_in_tag_editor = false; conf.incremental_seeking = true; conf.now_playing_lyrics = false; @@ -362,6 +365,8 @@ void ReadKeys(ncmpcpp_keys &keys) GetKeys(*it, keys.ToggleRandom); else if (it->find("key_toggle_space_mode ") != string::npos) GetKeys(*it, keys.ToggleSpaceMode); + else if (it->find("key_toggle_add_mode ") != string::npos) + GetKeys(*it, keys.ToggleAddMode); else if (it->find("key_shuffle ") != string::npos) GetKeys(*it, keys.Shuffle); else if (it->find("key_toggle_crossfade ") != string::npos) @@ -574,6 +579,10 @@ void ReadConfiguration(ncmpcpp_config &conf) { conf.now_playing_lyrics = v == "yes"; } + else if (it->find("ncmpc_like_songs_adding") != string::npos) + { + conf.ncmpc_like_songs_adding = v == "yes"; + } else if (it->find("enable_window_title") != string::npos) { conf.set_window_title = v == "yes"; diff --git a/src/settings.h b/src/settings.h index 9529ddcc..508f5d4b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -58,6 +58,7 @@ struct ncmpcpp_keys int ToggleRepeatOne[2]; int ToggleRandom[2]; int ToggleSpaceMode[2]; + int ToggleAddMode[2]; int Shuffle[2]; int ToggleCrossfade[2]; int SetCrossfade[2]; @@ -133,6 +134,7 @@ struct ncmpcpp_config bool repeat_one_mode; bool wrapped_search; bool space_selects; + bool ncmpc_like_songs_adding; bool albums_in_tag_editor; bool incremental_seeking; bool now_playing_lyrics; diff --git a/src/window.h b/src/window.h index 2f7b3083..b540ad2b 100644 --- a/src/window.h +++ b/src/window.h @@ -119,7 +119,7 @@ class Window virtual int Size() const { return 0; } virtual bool IsAnySelected() const { return 0; } virtual void GetSelectedList(vector &) const { } - virtual bool IsStatic(int) const { return 0; } + virtual bool IsStatic(int = -1) const { return 0; } virtual void Highlight(int) { } virtual string GetOption(int = -1) const { return ""; } virtual void Go(Where) { } // for Menu and Scrollpad class