media library: preserve filters/selections on update

This commit is contained in:
Andrzej Rybczak
2012-10-03 19:58:48 +02:00
parent d3dc560602
commit 6e33c2ef0f
3 changed files with 104 additions and 58 deletions

View File

@@ -67,18 +67,18 @@ bool SongEntryMatcher(const Regex &rx, const MPD::Song &s);
void DisplayAlbums(NC::Menu<AlbumEntry> &menu); void DisplayAlbums(NC::Menu<AlbumEntry> &menu);
void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu); void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu);
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b); struct SortSongs {
struct SortAllTracks {
static const std::array<MPD::Song::GetFunction, 3> GetFuns; static const std::array<MPD::Song::GetFunction, 3> GetFuns;
LocaleStringComparison m_cmp; LocaleStringComparison m_cmp;
std::ptrdiff_t m_offset;
public: public:
SortAllTracks() : m_cmp(std::locale(), Config.ignore_leading_the) { } SortSongs(bool disc_only)
: m_cmp(std::locale(), Config.ignore_leading_the), m_offset(disc_only ? 2 : 0) { }
bool operator()(const MPD::Song &a, const MPD::Song &b) { bool operator()(const MPD::Song &a, const MPD::Song &b) {
for (auto get = GetFuns.begin(); get != GetFuns.end(); ++get) { for (auto get = GetFuns.begin()+m_offset; get != GetFuns.end(); ++get) {
int ret = m_cmp(a.getTags(*get, Config.tags_separator), int ret = m_cmp(a.getTags(*get, Config.tags_separator),
b.getTags(*get, Config.tags_separator)); b.getTags(*get, Config.tags_separator));
if (ret != 0) if (ret != 0)
@@ -88,7 +88,7 @@ public:
} }
}; };
const std::array<MPD::Song::GetFunction, 3> SortAllTracks::GetFuns = {{ const std::array<MPD::Song::GetFunction, 3> SortSongs::GetFuns = {{
&MPD::Song::getDate, &MPD::Song::getDate,
&MPD::Song::getAlbum, &MPD::Song::getAlbum,
&MPD::Song::getDisc &MPD::Song::getDisc
@@ -242,9 +242,10 @@ void MediaLibrary::update()
if (hasTwoColumns) if (hasTwoColumns)
{ {
if (Albums.reallyEmpty()) if (Albums.reallyEmpty() || m_albums_update_request)
{ {
Songs.clear(); Albums.clearSearchResults();
m_albums_update_request = false;
std::map<std::tuple<std::string, std::string, std::string>, time_t> albums; std::map<std::tuple<std::string, std::string, std::string>, time_t> albums;
Mpd.GetDirectoryRecursive("/", [&albums](MPD::Song &&s) { Mpd.GetDirectoryRecursive("/", [&albums](MPD::Song &&s) {
unsigned idx = 0; unsigned idx = 0;
@@ -260,22 +261,33 @@ void MediaLibrary::update()
} }
while (!(tag = s.get(Config.media_lib_primary_tag, ++idx)).empty()); while (!(tag = s.get(Config.media_lib_primary_tag, ++idx)).empty());
}); });
for (auto it = albums.begin(); it != albums.end(); ++it) withUnfilteredMenuReapplyFilter(Albums, [this, &albums]() {
Albums.addItem(AlbumEntry(Album( size_t idx = 0;
std::move(std::get<0>(it->first)), for (auto it = albums.begin(); it != albums.end(); ++it, ++idx)
std::move(std::get<1>(it->first)), {
std::move(std::get<2>(it->first)), auto &&entry = AlbumEntry(Album(
it->second))); std::move(std::get<0>(it->first)),
std::move(std::get<1>(it->first)),
std::move(std::get<2>(it->first)),
it->second));
if (idx < Albums.size())
Albums[idx].value() = entry;
else
Albums.addItem(entry);
}
if (idx < Albums.size())
Albums.resizeList(idx);
std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries()); std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries());
});
Albums.refresh(); Albums.refresh();
} }
} }
else else
{ {
if (Tags.reallyEmpty()) if (Tags.reallyEmpty() || m_tags_update_request)
{ {
Albums.clear(); Tags.clearSearchResults();
Songs.clear(); m_tags_update_request = false;
std::map<std::string, time_t> tags; std::map<std::string, time_t> tags;
Mpd.GetDirectoryRecursive("/", [&tags](MPD::Song &&s) { Mpd.GetDirectoryRecursive("/", [&tags](MPD::Song &&s) {
unsigned idx = 0; unsigned idx = 0;
@@ -290,13 +302,26 @@ void MediaLibrary::update()
} }
while (!(tag = s.get(Config.media_lib_primary_tag, ++idx)).empty()); while (!(tag = s.get(Config.media_lib_primary_tag, ++idx)).empty());
}); });
for (auto it = tags.begin(); it != tags.end(); ++it) withUnfilteredMenuReapplyFilter(Tags, [this, &tags]() {
Tags.addItem(PrimaryTag(std::move(it->first), it->second)); size_t idx = 0;
for (auto it = tags.begin(); it != tags.end(); ++it, ++idx)
{
auto &&tag = PrimaryTag(std::move(it->first), it->second);
if (idx < Tags.size())
Tags[idx].value() = tag;
else
Tags.addItem(tag);
}
if (idx < Tags.size())
Tags.resizeList(idx);
});
Tags.refresh(); Tags.refresh();
} }
if (!Tags.empty() && Albums.reallyEmpty()) if ((!Tags.empty() && Albums.reallyEmpty()) || m_albums_update_request)
{ {
Albums.clearSearchResults();
m_albums_update_request = false;
auto &primary_tag = Tags.current().value().tag(); auto &primary_tag = Tags.current().value().tag();
Mpd.StartSearch(true); Mpd.StartSearch(true);
Mpd.AddSearch(Config.media_lib_primary_tag, primary_tag); Mpd.AddSearch(Config.media_lib_primary_tag, primary_tag);
@@ -309,25 +334,40 @@ void MediaLibrary::update()
else else
it->second = s.getMTime(); it->second = s.getMTime();
}); });
for (auto it = albums.begin(); it != albums.end(); ++it) withUnfilteredMenuReapplyFilter(Albums, [this, &albums, &primary_tag]() {
Albums.addItem(AlbumEntry(Album( size_t idx = 0;
primary_tag, for (auto it = albums.begin(); it != albums.end(); ++it, ++idx)
std::move(std::get<0>(it->first)), {
std::move(std::get<1>(it->first)), auto &&entry = AlbumEntry(Album(
it->second))); primary_tag,
std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries()); std::move(std::get<0>(it->first)),
if (albums.size() > 1) std::move(std::get<1>(it->first)),
{ it->second));
Albums.addSeparator(); if (idx < Albums.size())
Albums.addItem(AlbumEntry::mkAllTracksEntry(primary_tag)); {
} Albums[idx].value() = entry;
Albums[idx].setSeparator(false);
}
else
Albums.addItem(entry);
}
if (idx < Albums.size())
Albums.resizeList(idx);
std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries());
if (albums.size() > 1)
{
Albums.addSeparator();
Albums.addItem(AlbumEntry::mkAllTracksEntry(primary_tag));
}
});
Albums.refresh(); Albums.refresh();
} }
} }
if (!Albums.empty() && Songs.reallyEmpty()) if ((!Albums.empty() && Songs.reallyEmpty()) || m_songs_update_request)
{ {
Songs.reset(); Songs.clearSearchResults();
m_songs_update_request = false;
auto &album = Albums.current().value(); auto &album = Albums.current().value();
Mpd.StartSearch(true); Mpd.StartSearch(true);
Mpd.AddSearch(Config.media_lib_primary_tag, album.entry().tag()); Mpd.AddSearch(Config.media_lib_primary_tag, album.entry().tag());
@@ -336,15 +376,23 @@ void MediaLibrary::update()
Mpd.AddSearch(MPD_TAG_ALBUM, album.entry().album()); Mpd.AddSearch(MPD_TAG_ALBUM, album.entry().album());
Mpd.AddSearch(MPD_TAG_DATE, album.entry().date()); Mpd.AddSearch(MPD_TAG_DATE, album.entry().date());
} }
Mpd.CommitSearchSongs([this](MPD::Song &&s) { withUnfilteredMenuReapplyFilter(Songs, [this, &album]() {
Songs.addItem(s, myPlaylist->checkForSong(s)); size_t idx = 0;
Mpd.CommitSearchSongs([this, &idx](MPD::Song &&s) {
bool is_playlist = myPlaylist->checkForSong(s);
if (idx < Songs.size())
{
Songs[idx].value() = s;
Songs[idx].setBold(is_playlist);
}
else
Songs.addItem(s, is_playlist);
++idx;
});
if (idx < Songs.size())
Songs.resizeList(idx);
std::sort(Songs.beginV(), Songs.endV(), SortSongs(!album.isAllTracksEntry()));
}); });
if (album.isAllTracksEntry())
std::sort(Songs.beginV(), Songs.endV(), SortAllTracks());
else
std::sort(Songs.beginV(), Songs.endV(), SortSongsByTrack);
Songs.refresh(); Songs.refresh();
} }
@@ -640,7 +688,7 @@ MPD::SongList MediaLibrary::getSelectedSongs()
Mpd.CommitSearchSongs([&result](MPD::Song &&s) { Mpd.CommitSearchSongs([&result](MPD::Song &&s) {
result.push_back(s); result.push_back(s);
}); });
std::sort(result.begin()+begin, result.end(), SortSongsByTrack); std::sort(result.begin()+begin, result.end(), SortSongs(false));
} }
} }
// if no item is selected, add songs from right column // if no item is selected, add songs from right column
@@ -998,14 +1046,4 @@ void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu)
menu << tag; menu << tag;
} }
/***********************************************************************/
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b)
{
int cmp = a.getDisc().compare(b.getDisc());
if (cmp != 0)
return cmp < 0;
return a.getTrack() < b.getTrack();
}
} }

View File

@@ -74,9 +74,14 @@ struct MediaLibrary: Screen<NC::Window *>, Filterable, HasColumns, HasSongs, Sea
void LocateSong(const MPD::Song &); void LocateSong(const MPD::Song &);
ProxySongList songsProxyList(); ProxySongList songsProxyList();
void toggleSortMode(); void toggleSortMode();
void requestTagsUpdate() { m_tags_update_request = true; }
void requestAlbumsUpdate() { m_albums_update_request = true; }
void requestSongsUpdate() { m_songs_update_request = true; }
struct PrimaryTag struct PrimaryTag
{ {
PrimaryTag() : m_mtime(0) { }
PrimaryTag(std::string tag_, time_t mtime_) PrimaryTag(std::string tag_, time_t mtime_)
: m_tag(std::move(tag_)), m_mtime(mtime_) { } : m_tag(std::move(tag_)), m_mtime(mtime_) { }
@@ -134,6 +139,10 @@ protected:
private: private:
void AddToPlaylist(bool); void AddToPlaylist(bool);
bool m_tags_update_request;
bool m_albums_update_request;
bool m_songs_update_request;
}; };
extern MediaLibrary *myLibrary; extern MediaLibrary *myLibrary;

View File

@@ -193,10 +193,9 @@ void Status::Changes::database()
# ifdef HAVE_TAGLIB_H # ifdef HAVE_TAGLIB_H
myTagEditor->Dirs->clear(); myTagEditor->Dirs->clear();
# endif // HAVE_TAGLIB_H # endif // HAVE_TAGLIB_H
if (myLibrary->Columns() == 2) myLibrary->requestTagsUpdate();
myLibrary->Albums.clear(); myLibrary->requestAlbumsUpdate();
else myLibrary->requestSongsUpdate();
myLibrary->Tags.clear();
} }
void Status::Changes::playerState() void Status::Changes::playerState()