From 49f92ba0f98a8a37517e08eb3f19195f2849e86d Mon Sep 17 00:00:00 2001 From: emeric Date: Fri, 8 Jun 2018 16:01:03 +0200 Subject: [PATCH] Make recetnly played/most played info update --- approot/artists.xml | 5 +++++ approot/messages.xml | 6 ++++-- approot/releases.xml | 5 +++++ src/database/TrackStats.cpp | 26 ++++++++++++++++++++++++++ src/database/TrackStats.hpp | 7 +++++++ src/ui/LmsApplication.cpp | 27 ++++++++++++++++++++------- src/ui/PlayQueueView.cpp | 6 +++++- src/ui/explore/ArtistsView.cpp | 27 +++++++++++++-------------- src/ui/explore/ArtistsView.hpp | 5 ++++- src/ui/explore/Explore.cpp | 17 +++++++++++++++++ src/ui/explore/Explore.hpp | 6 ++++++ src/ui/explore/ReleasesView.cpp | 32 ++++++++++++++++++-------------- src/ui/explore/ReleasesView.hpp | 5 ++++- 13 files changed, 134 insertions(+), 40 deletions(-) diff --git a/approot/artists.xml b/approot/artists.xml index 23425af9..0b467c46 100644 --- a/approot/artists.xml +++ b/approot/artists.xml @@ -8,6 +8,11 @@ ${most-played-artists} + + ${recently-played-artists} + diff --git a/approot/messages.xml b/approot/messages.xml index e50b99e3..467646ca 100644 --- a/approot/messages.xml +++ b/approot/messages.xml @@ -57,9 +57,11 @@ Add filter Artists Most played artists -Most played releases +Most played albums Recently added artists -Recently added releases +Recently added albums +Recently played artists +Recently played albums Albums Search... Show more diff --git a/approot/releases.xml b/approot/releases.xml index 92cf00ce..5bf6e950 100644 --- a/approot/releases.xml +++ b/approot/releases.xml @@ -8,6 +8,11 @@ ${most-played-releases} + + ${recently-played-releases} + diff --git a/src/database/TrackStats.cpp b/src/database/TrackStats.cpp index c8844503..944ac7a2 100644 --- a/src/database/TrackStats.cpp +++ b/src/database/TrackStats.cpp @@ -44,6 +44,19 @@ TrackStats::getMostPlayedArtists(Wt::Dbo::Session& session, User::pointer user, return std::vector(res.begin(), res.end()); } +std::vector +TrackStats::getLastPlayedArtists(Wt::Dbo::Session& session, User::pointer user, int limit) +{ + Wt::Dbo::collection res = session.query + ("SELECT a FROM artist a INNER JOIN track t ON a.id = t.artist_id INNER JOIN track_stats t_s ON t.id = t_s.track_id") + .where("t_s.user_id = ?").bind(user.id()) + .groupBy("a.id") + .orderBy("t_s.last_played DESC") + .limit(limit); + + return std::vector(res.begin(), res.end()); +} + std::vector TrackStats::getMostPlayedReleases(Wt::Dbo::Session& session, User::pointer user, int limit) { @@ -57,6 +70,19 @@ TrackStats::getMostPlayedReleases(Wt::Dbo::Session& session, User::pointer user, return std::vector(res.begin(), res.end()); } +std::vector +TrackStats::getLastPlayedReleases(Wt::Dbo::Session& session, User::pointer user, int limit) +{ + Wt::Dbo::collection res = session.query + ("SELECT r FROM release r INNER JOIN track t ON r.id = t.release_id INNER JOIN track_stats t_s ON t.id = t_s.track_id") + .where("t_s.user_id = ?").bind(user.id()) + .groupBy("r.id") + .orderBy("t_s.last_played DESC") + .limit(limit); + + return std::vector(res.begin(), res.end()); +} + TrackStats::pointer TrackStats::get(Wt::Dbo::Session& session, Track::pointer track, User::pointer user) { diff --git a/src/database/TrackStats.hpp b/src/database/TrackStats.hpp index c599abc8..6c4d66d6 100644 --- a/src/database/TrackStats.hpp +++ b/src/database/TrackStats.hpp @@ -20,6 +20,7 @@ #pragma once #include +#include #include @@ -41,17 +42,22 @@ class TrackStats TrackStats(Wt::Dbo::ptr track, Wt::Dbo::ptr user); static std::vector> getMostPlayedArtists(Wt::Dbo::Session& session, Wt::Dbo::ptr, int limit = 1); + static std::vector> getLastPlayedArtists(Wt::Dbo::Session& session, Wt::Dbo::ptr, int limit = 1); + static std::vector> getMostPlayedReleases(Wt::Dbo::Session& session, Wt::Dbo::ptr, int limit = 1); + static std::vector> getLastPlayedReleases(Wt::Dbo::Session& session, Wt::Dbo::ptr, int limit = 1); // Get utility (will create if does not exist) static pointer get(Wt::Dbo::Session& session, Wt::Dbo::ptr track, Wt::Dbo::ptr user); void incPlayCount() { _playCount++; } + void setLastPlayed(Wt::WDateTime lastPlayed) { _lastPlayed = lastPlayed; } template void persist(Action& a) { Wt::Dbo::field(a, _playCount, "play_count"); + Wt::Dbo::field(a, _lastPlayed, "last_played"); Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade); Wt::Dbo::belongsTo(a, _user, "user", Wt::Dbo::OnDeleteCascade); } @@ -59,6 +65,7 @@ class TrackStats private: int _playCount = 0; + Wt::WDateTime _lastPlayed; Wt::Dbo::ptr _track; Wt::Dbo::ptr _user; }; diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp index 90df1480..a0eb5030 100644 --- a/src/ui/LmsApplication.cpp +++ b/src/ui/LmsApplication.cpp @@ -384,16 +384,20 @@ LmsApplication::handleAuthEvent(void) })); // Events from the PlayQueue + playqueue->playTrack.connect(explore, &Explore::handleTrackPlayed); + playqueue->playTrack.connect(player, &MediaPlayer::playTrack); playqueue->playbackStop.connect(player, &MediaPlayer::stop); // Events from MediaScanner - if (_isAdmin) + std::string sessionId = this->sessionId(); + _scanner.scanComplete().connect([=] (Scanner::MediaScanner::Stats stats) { - std::string sessionId = this->sessionId(); - _scanner.scanComplete().connect(std::bind([=] (Scanner::MediaScanner::Stats stats) + Wt::WServer::instance()->post(sessionId, [=] { - Wt::WServer::instance()->post(sessionId, [=] + bool changes = false; + + if (_isAdmin) { notifyMsg(Wt::WString::tr("Lms.Admin.Database.scan-complete") .arg(static_cast(stats.nbFiles())) @@ -402,10 +406,19 @@ LmsApplication::handleAuthEvent(void) .arg(static_cast(stats.deletions)) .arg(static_cast(stats.nbDuplicates())) .arg(static_cast(stats.nbErrors()))); + changes = true; + } + + if (stats.nbChanges() > 0) + { + explore->handleDbChanged(); + changes = true; + } + + if (changes) triggerUpdate(); - }); - }, std::placeholders::_1)); - } + }); + }); internalPathChanged().connect(std::bind([=] { diff --git a/src/ui/PlayQueueView.cpp b/src/ui/PlayQueueView.cpp index 6f124884..333f2e40 100644 --- a/src/ui/PlayQueueView.cpp +++ b/src/ui/PlayQueueView.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include "utils/Logger.hpp" @@ -121,7 +122,10 @@ PlayQueue::play(std::size_t pos) trackId = track.id(); - Database::TrackStats::get(LmsApp->getDboSession(), track, LmsApp->getCurrentUser()).modify()->incPlayCount(); + auto stats = Database::TrackStats::get(LmsApp->getDboSession(), track, LmsApp->getCurrentUser()); + + stats.modify()->incPlayCount(); + stats.modify()->setLastPlayed(Wt::WLocalDateTime::currentServerDateTime().toUTC()); updateCurrentTrack(true); } diff --git a/src/ui/explore/ArtistsView.cpp b/src/ui/explore/ArtistsView.cpp index 26d89f67..b664daec 100644 --- a/src/ui/explore/ArtistsView.cpp +++ b/src/ui/explore/ArtistsView.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "database/Artist.hpp" @@ -68,6 +67,7 @@ Artists::Artists(Filters* filters) _container = bindNew("artists"); _mostPlayedContainer = bindNew("most-played-artists"); _recentlyAddedContainer = bindNew("recently-added-artists"); + _recentlyPlayedContainer = bindNew("recently-played-artists"); _showMore = bindNew("show-more", Wt::WString::tr("Lms.Explore.template.show-more")); _showMore->addFunction("tr", &Wt::WTemplate::Functions::tr); @@ -80,21 +80,9 @@ Artists::Artists(Filters* filters) refresh(); refreshMostPlayed(); refreshRecentlyAdded(); + refreshRecentlyPlayed(); filters->updated().connect(this, &Artists::refresh); - - std::string sessionId = LmsApp->sessionId(); - LmsApp->getMediaScanner().scanComplete().connect([=] (Scanner::MediaScanner::Stats stats) - { - if (stats.nbChanges() > 0) - { - Wt::WServer::instance()->post(sessionId, [=] - { - refreshRecentlyAdded(); - LmsApp->triggerUpdate(); - }); - } - }); } void @@ -109,6 +97,17 @@ Artists::refreshRecentlyAdded() addCompactEntries(_recentlyAddedContainer, artists); } +void +Artists::refreshRecentlyPlayed() +{ + Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); + auto artists = TrackStats::getLastPlayedArtists(LmsApp->getDboSession(), LmsApp->getCurrentUser(), 5); + + _recentlyPlayedContainer->clear(); + addCompactEntries(_recentlyPlayedContainer, artists); +} + + void Artists::refreshMostPlayed() { diff --git a/src/ui/explore/ArtistsView.hpp b/src/ui/explore/ArtistsView.hpp index 3a6f6974..f39c5fe4 100644 --- a/src/ui/explore/ArtistsView.hpp +++ b/src/ui/explore/ArtistsView.hpp @@ -38,9 +38,11 @@ class Artists : public Wt::WTemplate Wt::Signal artistAdd; Wt::Signal artistPlay; - private: void refreshRecentlyAdded(); + void refreshRecentlyPlayed(); void refreshMostPlayed(); + + private: void refresh(); void addSome(); @@ -50,6 +52,7 @@ class Artists : public Wt::WTemplate Wt::WContainerWidget* _container; Wt::WContainerWidget* _mostPlayedContainer; Wt::WContainerWidget* _recentlyAddedContainer; + Wt::WContainerWidget* _recentlyPlayedContainer; }; } // namespace UserInterface diff --git a/src/ui/explore/Explore.cpp b/src/ui/explore/Explore.cpp index 4d376b86..6b62da7f 100644 --- a/src/ui/explore/Explore.cpp +++ b/src/ui/explore/Explore.cpp @@ -79,6 +79,7 @@ Explore::Explore() Wt::WStackedWidget* stack = bindNew("contents"); auto artists = std::make_unique(_filters); + auto artists_raw = artists.get(); artists->artistAdd.connect(this, &Explore::handleArtistAdd); artists->artistPlay.connect(this, &Explore::handleArtistPlay); stack->addWidget(std::move(artists)); @@ -91,6 +92,7 @@ Explore::Explore() stack->addWidget(std::move(artist)); auto releases = std::make_unique(_filters); + auto releases_raw = releases.get(); releases->releaseAdd.connect(this, &Explore::handleReleaseAdd); releases->releasePlay.connect(this, &Explore::handleReleasePlay); stack->addWidget(std::move(releases)); @@ -102,6 +104,21 @@ Explore::Explore() release->trackPlay.connect(this, &Explore::handleTrackPlay); stack->addWidget(std::move(release)); + _dbChanged.connect([=] + { + artists_raw->refreshRecentlyAdded(); + releases_raw->refreshRecentlyAdded(); + }); + + _trackPlayed.connect([=] + { + artists_raw->refreshMostPlayed(); + artists_raw->refreshRecentlyPlayed(); + releases_raw->refreshMostPlayed(); + releases_raw->refreshRecentlyPlayed(); + + }); + auto tracks = std::make_unique(_filters); tracks->trackAdd.connect(this, &Explore::handleTrackAdd); tracks->trackPlay.connect(this, &Explore::handleTrackPlay); diff --git a/src/ui/explore/Explore.hpp b/src/ui/explore/Explore.hpp index ea538876..e00c8bc7 100644 --- a/src/ui/explore/Explore.hpp +++ b/src/ui/explore/Explore.hpp @@ -36,6 +36,9 @@ class Explore : public Wt::WTemplate Wt::Signal> tracksAdd; Wt::Signal> tracksPlay; + void handleDbChanged() { _dbChanged.emit(); }; + void handleTrackPlayed(Database::IdType trackId) { _trackPlayed.emit(); } + private: void handleArtistAdd(Database::IdType id); @@ -48,6 +51,9 @@ class Explore : public Wt::WTemplate void handleTracksPlay(std::vector tracks); Filters* _filters; + + Wt::Signal<> _dbChanged; + Wt::Signal<> _trackPlayed; }; } // namespace UserInterface diff --git a/src/ui/explore/ReleasesView.cpp b/src/ui/explore/ReleasesView.cpp index bdbecaf4..8c58108c 100644 --- a/src/ui/explore/ReleasesView.cpp +++ b/src/ui/explore/ReleasesView.cpp @@ -18,7 +18,6 @@ */ #include "ReleasesView.hpp" - #include #include #include @@ -87,6 +86,7 @@ _filters(filters) _container = bindNew("releases"); _mostPlayedContainer = bindNew("most-played-releases"); _recentlyAddedContainer = bindNew("recently-added-releases"); + _recentlyPlayedContainer = bindNew("recently-played-releases"); _showMore = bindNew("show-more", Wt::WString::tr("Lms.Explore.show-more")); _showMore->addFunction("tr", &Wt::WTemplate::Functions::tr); @@ -96,28 +96,18 @@ _filters(filters) })); refreshRecentlyAdded(); + refreshRecentlyPlayed(); refreshMostPlayed(); refresh(); filters->updated().connect(this, &Releases::refresh); - - std::string sessionId = LmsApp->sessionId(); - LmsApp->getMediaScanner().scanComplete().connect([=] (Scanner::MediaScanner::Stats stats) - { - if (stats.nbChanges() > 0) - { - Wt::WServer::instance()->post(sessionId, [=] - { - refreshRecentlyAdded(); - LmsApp->triggerUpdate(); - }); - } - }); } void Releases::refreshRecentlyAdded() { + LMS_LOG(UI, DEBUG) << "Refreshing recently added releases"; + auto after = Wt::WLocalDateTime::currentServerDateTime().toUTC().addMonths(-1); Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); @@ -128,9 +118,23 @@ Releases::refreshRecentlyAdded() addCompactEntries(_recentlyAddedContainer, releases); } +void +Releases::refreshRecentlyPlayed() +{ + LMS_LOG(UI, DEBUG) << "Refreshing recently played releases"; + + Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); + + auto releases = TrackStats::getLastPlayedReleases(LmsApp->getDboSession(), LmsApp->getCurrentUser(), 5); + + _recentlyPlayedContainer->clear(); + addCompactEntries(_recentlyPlayedContainer, releases); +} + void Releases::refreshMostPlayed() { + LMS_LOG(UI, DEBUG) << "Refreshing most played releases"; Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); diff --git a/src/ui/explore/ReleasesView.hpp b/src/ui/explore/ReleasesView.hpp index 5c8374a2..fff677f1 100644 --- a/src/ui/explore/ReleasesView.hpp +++ b/src/ui/explore/ReleasesView.hpp @@ -38,9 +38,11 @@ class Releases : public Wt::WTemplate Wt::Signal releaseAdd; Wt::Signal releasePlay; - private: void refreshRecentlyAdded(); + void refreshRecentlyPlayed(); void refreshMostPlayed(); + + private: void refresh(); void addSome(); @@ -50,6 +52,7 @@ class Releases : public Wt::WTemplate Wt::WContainerWidget* _container; Wt::WContainerWidget* _mostPlayedContainer; Wt::WContainerWidget* _recentlyAddedContainer; + Wt::WContainerWidget* _recentlyPlayedContainer; }; } // namespace UserInterface