Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ missing
**/.deps/
src/ncmpcpp
stamp-h1
.cache/
compile_commands.json
1 change: 1 addition & 0 deletions doc/config
Original file line number Diff line number Diff line change
Expand Up @@ -613,3 +613,4 @@
#
#active_window_border = red
#
#allow_playlist_duplicates = yes
3 changes: 3 additions & 0 deletions doc/ncmpcpp.1
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ Type of currently used regular expressions.
.B ignore_leading_the = yes/no
If enabled, word "the" at the beginning of tags/filenames/sort format will be ignored while sorting items.
.TP
.B allow_playlist_duplicates = yes/no
If enabled, allows adding duplicate songs to playlists. Does not change existing playlists.
.TP
.B ignore_diacritics = yes/no
If enabled, diacritics in strings will be ignored while searching and filtering lists.
.TP
Expand Down
16 changes: 16 additions & 0 deletions src/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,19 @@ void writeCyclicBuffer(const NC::WBuffer &buf, NC::Window &w, size_t &start_pos,
else
w << buf;
}

boost::optional<size_t> GetSongIndexInPlaylist(MPD::Playlist playlist, const MPD::Song &song)
{
size_t index = 0;
MPD::SongIterator it = Mpd.GetPlaylistContentNoInfo(playlist.path()), end;

for (;;)
{
if (it == end)
return boost::none;
if (*it == song)
return index;

++it, ++index;
}
}
3 changes: 3 additions & 0 deletions src/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,4 +542,7 @@ std::wstring Scroller(const std::wstring &str, size_t &pos, size_t width);
void writeCyclicBuffer(const NC::WBuffer &buf, NC::Window &w, size_t &start_pos,
size_t width, const std::wstring &separator);


boost::optional<size_t> GetSongIndexInPlaylist(MPD::Playlist playlist, const MPD::Song &song);

#endif // NCMPCPP_HELPERS_H
17 changes: 0 additions & 17 deletions src/screens/playlist_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ size_t RightColumnWidth;
std::string SongToString(const MPD::Song &s);
bool PlaylistEntryMatcher(const Regex::Regex &rx, const MPD::Playlist &playlist);
bool SongEntryMatcher(const Regex::Regex &rx, const MPD::Song &s);
boost::optional<size_t> GetSongIndexInPlaylist(MPD::Playlist playlist, const MPD::Song &song);
}

PlaylistEditor::PlaylistEditor()
Expand Down Expand Up @@ -590,20 +589,4 @@ bool SongEntryMatcher(const Regex::Regex &rx, const MPD::Song &s)
return Regex::search(SongToString(s), rx, Config.ignore_diacritics);
}

boost::optional<size_t> GetSongIndexInPlaylist(MPD::Playlist playlist, const MPD::Song &song)
{
size_t index = 0;
MPD::SongIterator it = Mpd.GetPlaylistContentNoInfo(playlist.path()), end;

for (;;)
{
if (it == end)
return boost::none;
if (*it == song)
return index;

++it, ++index;
}
}

}
38 changes: 33 additions & 5 deletions src/screens/sel_items_adder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ void SelectedItemsAdder::populatePlaylistSelector(BaseScreen *old_screen)
for (MPD::PlaylistIterator it = Mpd.GetPlaylists(), end; it != end; ++it)
{
m_playlist_selector.addItem(Entry(it->path(),
std::bind(&Self::addToExistingPlaylist, this, it->path())
std::bind(&Self::addToExistingPlaylist, this, it->path(), false)
));
};
std::sort(m_playlist_selector.beginV()+begin, m_playlist_selector.endV(),
Expand All @@ -277,15 +277,43 @@ void SelectedItemsAdder::addToNewPlaylist() const
Statusbar::put() << "Save playlist as: ";
playlist = Global::wFooter->prompt();
}
addToExistingPlaylist(playlist);
addToExistingPlaylist(MPD::Playlist(playlist), true);
}

void SelectedItemsAdder::addToExistingPlaylist(const std::string &playlist) const
void SelectedItemsAdder::addToExistingPlaylist(const MPD::Playlist &playlist, bool new_playlist) const
{
std::vector<MPD::Song> filtered_songs;
bool filter = !Config.allow_playlist_duplicates && !new_playlist;
if (filter)
{
std::remove_copy_if(
m_selected_items.begin(),
m_selected_items.end(),
std::back_inserter(filtered_songs),
[playlist](const MPD::Song s) { return GetSongIndexInPlaylist(playlist, s) != boost::none; });
}

Mpd.StartCommandsList();
for (auto s = m_selected_items.begin(); s != m_selected_items.end(); ++s)
Mpd.AddToPlaylist(playlist, *s);

auto songs = filter ? filtered_songs : m_selected_items;

for (auto s = songs.begin(); s != songs.end(); ++s)
Mpd.AddToPlaylist(playlist.path(), *s);

Mpd.CommitCommandsList();
if (!songs.empty())
Statusbar::printf("Selected item(s) added to playlist \"%1%\"", playlist.path());
for (auto s = m_selected_items.begin(); s != m_selected_items.end(); ++s){
for (MPD::SongIterator s2 = Mpd.GetPlaylistContent(playlist), end; s2 != end; ++s2)
if(s2->getURI() == s->getURI()){
goto next_song;
}
Mpd.StartCommandsList();
Mpd.AddToPlaylist(playlist, *s);
Mpd.CommitCommandsList();
next_song:;
}

Statusbar::printf("Selected item(s) added to playlist \"%1%\"", playlist);
switchToPreviousScreen();
}
Expand Down
3 changes: 2 additions & 1 deletion src/screens/sel_items_adder.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "regex_filter.h"
#include "screens/screen.h"
#include "song.h"
#include "mpdpp.h"

struct SelectedItemsAdder: Screen<NC::Menu<RunnableItem<std::string, void()>> *>, HasActions, Searchable, Tabbable
{
Expand Down Expand Up @@ -65,7 +66,7 @@ struct SelectedItemsAdder: Screen<NC::Menu<RunnableItem<std::string, void()>> *>

void addToCurrentPlaylist();
void addToNewPlaylist() const;
void addToExistingPlaylist(const std::string &playlist) const;
void addToExistingPlaylist(const MPD::Playlist &playlist, bool new_playlist) const;
void addAtTheEndOfPlaylist() const;
void addAtTheBeginningOfPlaylist() const;
void addAfterCurrentSong() const;
Expand Down
1 change: 1 addition & 0 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
invalid_value(v);
});
p.add("ignore_leading_the", &ignore_leading_the, "no", yes_no);
p.add("allow_playlist_duplicates", &allow_playlist_duplicates, "yes", yes_no);
p.add("ignore_diacritics", &ignore_diacritics, "no", yes_no);
p.add("block_search_constraints_change_if_items_found",
&block_search_constraints_change, "yes", yes_no);
Expand Down
1 change: 1 addition & 0 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct Configuration
bool display_bitrate;
bool display_remaining_time;
bool ignore_leading_the;
bool allow_playlist_duplicates;
bool ignore_diacritics;
bool block_search_constraints_change;
bool use_console_editor;
Expand Down