media library: preserve filters/selections on update
This commit is contained in:
@@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user