diff --git a/approot/artists.xml b/approot/artists.xml index 0b467c46..23425af9 100644 --- a/approot/artists.xml +++ b/approot/artists.xml @@ -8,11 +8,6 @@ ${most-played-artists} - - ${recently-played-artists} - diff --git a/approot/releases.xml b/approot/releases.xml index 5bf6e950..92cf00ce 100644 --- a/approot/releases.xml +++ b/approot/releases.xml @@ -8,11 +8,6 @@ ${most-played-releases} - - ${recently-played-releases} - diff --git a/src/Makefile.am b/src/Makefile.am index a8d7ec97..f0a622f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,12 +8,11 @@ lms_SOURCES = \ $(srcdir)/database/Artist.cpp \ $(srcdir)/database/Cluster.cpp \ $(srcdir)/database/DatabaseHandler.cpp \ - $(srcdir)/database/Playlist.cpp \ + $(srcdir)/database/TrackList.cpp \ $(srcdir)/database/Release.cpp \ $(srcdir)/database/ScanSettings.cpp \ $(srcdir)/database/SqlQuery.cpp \ $(srcdir)/database/Track.cpp \ - $(srcdir)/database/TrackStats.cpp \ $(srcdir)/database/User.cpp \ $(srcdir)/image/Image.cpp \ $(srcdir)/metadata/AvFormat.cpp \ diff --git a/src/database/DatabaseHandler.cpp b/src/database/DatabaseHandler.cpp index f835c09f..1473d7d1 100644 --- a/src/database/DatabaseHandler.cpp +++ b/src/database/DatabaseHandler.cpp @@ -31,17 +31,14 @@ #include #include -#include "Setting.hpp" - #include "utils/Logger.hpp" #include "Artist.hpp" #include "Cluster.hpp" -#include "Playlist.hpp" +#include "TrackList.hpp" #include "Release.hpp" #include "ScanSettings.hpp" #include "Track.hpp" -#include "TrackStats.hpp" namespace Database { @@ -102,12 +99,10 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool) _session.mapClass("artist"); _session.mapClass("cluster"); _session.mapClass("cluster_type"); - _session.mapClass("playlist"); - _session.mapClass("playlist_entry"); + _session.mapClass("tracklist"); + _session.mapClass("tracklist_entry"); _session.mapClass("release"); - _session.mapClass("setting"); _session.mapClass("track"); - _session.mapClass("track_stats"); _session.mapClass("scan_settings"); @@ -139,7 +134,7 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool) _session.execute("CREATE INDEX IF NOT EXISTS track_release_idx ON track(release_id)"); _session.execute("CREATE INDEX IF NOT EXISTS cluster_name_idx ON cluster(name)"); _session.execute("CREATE INDEX IF NOT EXISTS cluster_type_name_idx ON cluster_type(name)"); - _session.execute("CREATE INDEX IF NOT EXISTS settings_name_idx ON setting(name)"); + _session.execute("CREATE INDEX IF NOT EXISTS tracklist_name ON tracklist(name)"); } _users = new UserDatabase(_session); diff --git a/src/database/Playlist.cpp b/src/database/Playlist.cpp deleted file mode 100644 index b26cc91b..00000000 --- a/src/database/Playlist.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2014 Emeric Poupon - * - * This file is part of LMS. - * - * LMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LMS. If not, see . - */ -#include "Playlist.hpp" - -#include -#include - -#include "Cluster.hpp" -#include "User.hpp" -#include "Track.hpp" - -namespace Database { - -Playlist::Playlist() -: _isPublic(false) -{ - -} - -Playlist::Playlist(std::string name, bool isPublic, Wt::Dbo::ptr user) -: _name(name), - _isPublic(isPublic), - _user(user) -{ - -} - -Playlist::pointer -Playlist::create(Wt::Dbo::Session& session, std::string name, bool isPublic, Wt::Dbo::ptr user) -{ - return session.add( std::make_unique(name, isPublic, user) ); -} - -PlaylistEntry::PlaylistEntry() -{ -} - -PlaylistEntry::pointer -PlaylistEntry::getById(Wt::Dbo::Session& session, IdType id) -{ - return session.find().where("id = ?").bind(id); -} - -Playlist::pointer -Playlist::get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr user) -{ - return session.find().where("name = ? AND user_id = ?").bind(name).bind(user.id()); -} - -std::vector -Playlist::getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr user) -{ - Wt::Dbo::collection res = session.find().where("user_id = ?").bind(user.id()).orderBy("name"); - - return std::vector(res.begin(), res.end()); -} - -Playlist::pointer -Playlist::getById(Wt::Dbo::Session& session, IdType id) -{ - return session.find().where("id = ?").bind(id); -} - - -PlaylistEntry::PlaylistEntry(Wt::Dbo::ptr track, Wt::Dbo::ptr playlist) -: _track(track), - _playlist(playlist) -{ - -} - -PlaylistEntry::pointer -PlaylistEntry::create(Wt::Dbo::Session& session, Wt::Dbo::ptr track, Wt::Dbo::ptr playlist) -{ - return session.add( std::make_unique( track, playlist) ); -} - - -std::vector> -Playlist::getEntries(int offset, int size, bool& moreResults) const -{ - assert(session()); - assert(IdIsValid(self()->id())); - - moreResults = false; - - Wt::Dbo::collection> entries = - session()->find() - .where("playlist_id = ?").bind(self().id()) - .orderBy("id") - .limit(size != -1 ? size + 1 : -1) - .offset(offset); - - std::vector> res; - - for (auto entry : entries) - { - if (size != -1 && res.size() == static_cast(size)) - { - moreResults = true; - break; - } - - res.push_back(entry); - } - - return res; -} - -std::vector> -Playlist::getAllEntries() const -{ - bool moreResults; - return getEntries(-1, -1, moreResults); -} - -Wt::Dbo::ptr -Playlist::getEntry(std::size_t pos) const -{ - Wt::Dbo::ptr res; - - bool moreResults; - auto entries = getEntries(pos, 1, moreResults); - if (!entries.empty()) - res = entries.front(); - - return res; -} - -std::size_t -Playlist::getCount() const -{ - return _entries.size(); -} - -std::vector> -Playlist::getClusters() const -{ - assert(session()); - assert(IdIsValid(self()->id())); - - Wt::Dbo::collection res = session()->query("SELECT c from cluster c INNER JOIN track t ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id INNER JOIN playlist_entry p_e ON p_e.track_id = t.id INNER JOIN playlist p ON p.id = p_e.playlist_id") - .where("p.id = ?").bind(self()->id()) - .groupBy("c.id") - .orderBy("COUNT(c.id) DESC"); - - return std::vector>(res.begin(), res.end()); -} - -bool -Playlist::hasTrack(IdType trackId) const -{ - assert(session()); - assert(IdIsValid(self()->id())); - - Wt::Dbo::collection res = session()->query("SELECT p_e from playlist_entry p_e INNER JOIN playlist p ON p_e.playlist_id = p.id") - .where("p_e.track_id = ?").bind(trackId) - .where("p.id = ?").bind(self()->id()); - - return res.size() > 0; -} - -std::vector -Playlist::getTrackIds() const -{ - assert(session()); - assert(IdIsValid(self()->id())); - - Wt::Dbo::collection res = session()->query("SELECT p_e.track_id from playlist_entry p_e INNER JOIN playlist p ON p_e.playlist_id = p.id") - .where("p.id = ?").bind(self()->id()); - - return std::vector(res.begin(), res.end()); -} - -void -Playlist::shuffle() -{ - assert(session()); - - auto entries = getAllEntries(); - - auto now = std::chrono::system_clock::now(); - std::mt19937 randGenerator(std::chrono::duration_cast(now.time_since_epoch()).count()); - - std::shuffle(entries.begin(), entries.end(), randGenerator); - - clear(); - for (auto entry : entries) - PlaylistEntry::create(*session(), entry->getTrack(), self()); -} - -} // namespace Database diff --git a/src/database/Setting.cpp b/src/database/Setting.cpp deleted file mode 100644 index e987d111..00000000 --- a/src/database/Setting.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2016 Emeric Poupon - * - * This file is part of LMS. - * - * LMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LMS. If not, see . - */ - -#include "Setting.hpp" - -namespace Database { - -bool -Setting::exists(Wt::Dbo::Session& session, std::string setting) -{ - Wt::Dbo::Transaction transaction(session); - return (getByName(session, setting) != Setting::pointer()); -} - -std::string -Setting::getString(Wt::Dbo::Session& session, std::string setting, std::string defaultValue) -{ - Wt::Dbo::Transaction transaction(session); - - pointer res = getByName(session, setting); - if (!res) - return defaultValue; - - return res->_value; -} - -bool -Setting::getBool(Wt::Dbo::Session& session, std::string setting, bool defaultValue) -{ - Wt::Dbo::Transaction transaction(session); - - pointer res = getByName(session, setting); - if (!res) - return defaultValue; - - return (res->_value == "true"); -} - -Wt::WTime -Setting::getTime(Wt::Dbo::Session& session, std::string setting, Wt::WTime defaultValue) -{ - Wt::Dbo::Transaction transaction(session); - - pointer res = getByName(session, setting); - if (!res) - return defaultValue; - - return Wt::WTime::fromString(res->_value); -} - -int -Setting::getInt(Wt::Dbo::Session& session, std::string setting, int defaultValue) -{ - Wt::Dbo::Transaction transaction(session); - - pointer res = getByName(session, setting); - if (!res) - return defaultValue; - - return std::stoi(res->_value); -} - - - -Setting::pointer -Setting::create(Wt::Dbo::Session& session, std::string name) -{ - return session.add(std::make_unique(name)); -} - -Setting::pointer -Setting::getByName(Wt::Dbo::Session& session, std::string name) -{ - return session.find().where("name = ?").bind(name); -} - -Setting::pointer -Setting::getOrCreateByName(Wt::Dbo::Session& session, std::string name) -{ - pointer res = getByName(session, name); - if (!res) - res = create(session, name); - - return res; -} - -void -Setting::setString(Wt::Dbo::Session& session, std::string setting, std::string value) -{ - Wt::Dbo::Transaction transaction(session); - getOrCreateByName(session, setting).modify()->_value = value; -} - -void -Setting::setBool(Wt::Dbo::Session& session, std::string setting, bool value) -{ - Wt::Dbo::Transaction transaction(session); - getOrCreateByName(session, setting).modify()->_value = (value ? "true" : "false"); -} - -void -Setting::setTime(Wt::Dbo::Session& session, std::string setting, Wt::WTime value) -{ - Wt::Dbo::Transaction transaction(session); - getOrCreateByName(session, setting).modify()->_value = value.toString().toUTF8(); -} - -void -Setting::setInt(Wt::Dbo::Session& session, std::string setting, int value) -{ - Wt::Dbo::Transaction transaction(session); - getOrCreateByName(session, setting).modify()->_value = std::to_string(value); -} - - -} // namespace Database - diff --git a/src/database/Setting.hpp b/src/database/Setting.hpp deleted file mode 100644 index 808a0902..00000000 --- a/src/database/Setting.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2016 Emeric Poupon - * - * This file is part of LMS. - * - * LMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LMS. If not, see . - */ - -#pragma once - -#include -#include - -namespace Database { - -// class meant to store general settings -class Setting -{ - public: - using pointer = Wt::Dbo::ptr; - - Setting() {} - Setting(std::string name) : _name(name) {} - - // check if a setting exists or not - static bool exists(Wt::Dbo::Session& session, std::string setting); - - // Getters - // Nested transactions - static std::string getString(Wt::Dbo::Session& session, std::string setting, std::string defaultValue = ""); - static bool getBool(Wt::Dbo::Session& session, std::string setting, bool defaultValue = false); - static Wt::WTime getTime(Wt::Dbo::Session& session, std::string setting, Wt::WTime defaultValue = Wt::WTime()); - static int getInt(Wt::Dbo::Session& session, std::string setting, int defaultValue = 0); - - // Setters - // Nested transactions - static void setString(Wt::Dbo::Session& session, std::string setting, std::string value); - static void setBool(Wt::Dbo::Session& session, std::string setting, bool value); - static void setTime(Wt::Dbo::Session& session, std::string setting, Wt::WTime value); - static void setInt(Wt::Dbo::Session& session, std::string setting, int value); - - template - void persist(Action& a) - { - Wt::Dbo::field(a, _name, "name"); - Wt::Dbo::field(a, _value, "value"); - } - - private: - static pointer getByName(Wt::Dbo::Session& session, std::string name); - static pointer create(Wt::Dbo::Session& session, std::string name); - static pointer getOrCreateByName(Wt::Dbo::Session& session, std::string name); - - std::string _name; - std::string _value; -}; - - -} // namespace Database - diff --git a/src/database/Track.hpp b/src/database/Track.hpp index c63de183..550df65e 100644 --- a/src/database/Track.hpp +++ b/src/database/Track.hpp @@ -37,7 +37,7 @@ namespace Database { class Artist; class Cluster; class ClusterType; -class PlaylistEntry; +class TrackListEntry; class Release; class TrackStats; @@ -144,7 +144,6 @@ class Track : public Wt::Dbo::Dbo Wt::Dbo::belongsTo(a, _artist, "artist", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _clusters, Wt::Dbo::ManyToMany, "track_cluster", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _playlistEntries, Wt::Dbo::ManyToOne, "track"); - Wt::Dbo::hasMany(a, _stats, Wt::Dbo::ManyToOne, "track"); } private: @@ -173,8 +172,7 @@ class Track : public Wt::Dbo::Dbo Wt::Dbo::ptr _artist; Wt::Dbo::ptr _release; Wt::Dbo::collection> _clusters; - Wt::Dbo::collection> _playlistEntries; - Wt::Dbo::collection> _stats; + Wt::Dbo::collection> _playlistEntries; }; diff --git a/src/database/TrackList.cpp b/src/database/TrackList.cpp new file mode 100644 index 00000000..d46b4e58 --- /dev/null +++ b/src/database/TrackList.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2014 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ +#include "TrackList.hpp" + +#include +#include + +#include "utils/Logger.hpp" + +#include "Artist.hpp" +#include "Cluster.hpp" +#include "Release.hpp" +#include "User.hpp" +#include "Track.hpp" + +namespace Database { + +TrackList::TrackList() +: _isPublic(false) +{ + +} + +TrackList::TrackList(std::string name, bool isPublic, Wt::Dbo::ptr user) +: _name(name), + _isPublic(isPublic), + _user(user) +{ + +} + +TrackList::pointer +TrackList::create(Wt::Dbo::Session& session, std::string name, bool isPublic, Wt::Dbo::ptr user) +{ + assert(user); + + auto res = session.add( std::make_unique(name, isPublic, user) ); + session.flush(); + + return res; +} + +TrackListEntry::pointer +TrackList::add(IdType trackId) +{ + assert(session()); + assert(self()); + + return TrackListEntry::create(*session(), Database::Track::getById(*session(), trackId), self()); +} + +TrackList::pointer +TrackList::get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr user) +{ + return session.find().where("name = ? AND user_id = ?").bind(name).bind(user.id()); +} + +std::vector +TrackList::getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr user) +{ + Wt::Dbo::collection res = session.find().where("user_id = ?").bind(user.id()).orderBy("name"); + + return std::vector(res.begin(), res.end()); +} + +TrackList::pointer +TrackList::getById(Wt::Dbo::Session& session, IdType id) +{ + return session.find().where("id = ?").bind(id); +} + + +std::vector> +TrackList::getEntries(int offset, int size) const +{ + assert(session()); + assert(IdIsValid(self()->id())); + + Wt::Dbo::collection> entries = + session()->find() + .where("tracklist_id = ?").bind(self().id()) + .orderBy("id") + .limit(size) + .offset(offset); + + return std::vector>(entries.begin(), entries.end()); +} + +Wt::Dbo::ptr +TrackList::getEntry(std::size_t pos) const +{ + Wt::Dbo::ptr res; + + auto entries = getEntries(pos, 1); + if (!entries.empty()) + res = entries.front(); + + return res; +} + +std::size_t +TrackList::getCount() const +{ + return _entries.size(); +} + +std::vector> +TrackList::getClusters() const +{ + assert(session()); + assert(IdIsValid(self()->id())); + + Wt::Dbo::collection res = session()->query("SELECT c from cluster c INNER JOIN track t ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id INNER JOIN tracklist_entry p_e ON p_e.track_id = t.id INNER JOIN tracklist p ON p.id = p_e.tracklist_id") + .where("p.id = ?").bind(self()->id()) + .groupBy("c.id") + .orderBy("COUNT(c.id) DESC"); + + return std::vector>(res.begin(), res.end()); +} + +bool +TrackList::hasTrack(IdType trackId) const +{ + assert(session()); + assert(IdIsValid(self()->id())); + + Wt::Dbo::collection res = session()->query("SELECT p_e from tracklist_entry p_e INNER JOIN tracklist p ON p_e.tracklist_id = p.id") + .where("p_e.track_id = ?").bind(trackId) + .where("p.id = ?").bind(self()->id()); + + return res.size() > 0; +} + +std::vector +TrackList::getTrackIds() const +{ + assert(session()); + assert(IdIsValid(self()->id())); + + Wt::Dbo::collection res = session()->query("SELECT p_e.track_id from tracklist_entry p_e INNER JOIN tracklist p ON p_e.tracklist_id = p.id") + .where("p.id = ?").bind(self()->id()); + + return std::vector(res.begin(), res.end()); +} + +void +TrackList::shuffle() +{ + assert(session()); + + auto entries = getEntries(); + + auto now = std::chrono::system_clock::now(); + std::mt19937 randGenerator(std::chrono::duration_cast(now.time_since_epoch()).count()); + + std::shuffle(entries.begin(), entries.end(), randGenerator); + + clear(); + for (auto entry : entries) + TrackListEntry::create(*session(), entry->getTrack(), self()); +} + +std::vector +TrackList::getTopArtists(int limit) const +{ + assert(session()); + assert(IdIsValid(self()->id())); + + Wt::Dbo::collection res = session()->query("SELECT a from artist a INNER JOIN track t ON t.artist_id = a.id INNER JOIN tracklist_entry p_e ON p_e.track_id = t.id INNER JOIN tracklist p ON p.id = p_e.tracklist_id") + .where("p.id = ?").bind(self()->id()) + .groupBy("a.id") + .orderBy("COUNT(a.id) DESC") + .limit(limit); + + return std::vector(res.begin(), res.end()); +} + +std::vector +TrackList::getTopReleases(int limit) const +{ + assert(session()); + assert(IdIsValid(self()->id())); + + Wt::Dbo::collection res = session()->query("SELECT r from release r INNER JOIN track t ON t.release_id = r.id INNER JOIN tracklist_entry p_e ON p_e.track_id = t.id INNER JOIN tracklist p ON p.id = p_e.tracklist_id") + .where("p.id = ?").bind(self()->id()) + .groupBy("r.id") + .orderBy("COUNT(r.id) DESC") + .limit(limit); + + return std::vector(res.begin(), res.end()); +} + +TrackListEntry::TrackListEntry(Wt::Dbo::ptr track, Wt::Dbo::ptr tracklist) +: _track(track), + _tracklist(tracklist) +{ + +} + +TrackListEntry::TrackListEntry() +{ +} + +TrackListEntry::pointer +TrackListEntry::create(Wt::Dbo::Session& session, Wt::Dbo::ptr track, Wt::Dbo::ptr tracklist) +{ + assert(track); + assert(tracklist); + + auto res = session.add( std::make_unique( track, tracklist) ); + session.flush(); + + return res; +} + +TrackListEntry::pointer +TrackListEntry::getById(Wt::Dbo::Session& session, IdType id) +{ + return session.find().where("id = ?").bind(id); +} + +} // namespace Database diff --git a/src/database/Playlist.hpp b/src/database/TrackList.hpp similarity index 66% rename from src/database/Playlist.hpp rename to src/database/TrackList.hpp index 15795494..0a54a2c7 100644 --- a/src/database/Playlist.hpp +++ b/src/database/TrackList.hpp @@ -27,22 +27,28 @@ namespace Database { -class PlaylistEntry; +class Artist; +class Release; class User; class Track; +class TrackListEntry; class Cluster; -class Playlist : public Wt::Dbo::Dbo +class TrackList : public Wt::Dbo::Dbo { public: - using pointer = Wt::Dbo::ptr; + using pointer = Wt::Dbo::ptr; - Playlist(); - Playlist(std::string name, bool isPublic, Wt::Dbo::ptr user); + TrackList(); + TrackList(std::string name, bool isPublic, Wt::Dbo::ptr user); + + // Stats utility + std::vector> getTopArtists(int limit = 1) const; + std::vector> getTopReleases(int limit = 1) const; // Search utility static pointer get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr user); - static pointer getById(Wt::Dbo::Session& session, IdType playlistId); + static pointer getById(Wt::Dbo::Session& session, IdType tracklistId); static std::vector getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr user); // Create utility @@ -53,14 +59,14 @@ class Playlist : public Wt::Dbo::Dbo bool isPublic() const { return _isPublic; } // Modifiers + Wt::Dbo::ptr add(IdType trackId); void clear() { _entries.clear(); } void shuffle(); // Get tracks, ordered by position std::size_t getCount() const; - Wt::Dbo::ptr getEntry(std::size_t pos) const; - std::vector> getEntries(int offset, int size, bool& moreResults) const; - std::vector> getAllEntries() const; + Wt::Dbo::ptr getEntry(std::size_t pos) const; + std::vector> getEntries(int offset = -1, int size = -1) const; std::vector getTrackIds() const; @@ -75,7 +81,7 @@ class Playlist : public Wt::Dbo::Dbo Wt::Dbo::field(a, _name, "name"); Wt::Dbo::field(a, _isPublic, "public"); Wt::Dbo::belongsTo(a, _user, "user", Wt::Dbo::OnDeleteCascade); - Wt::Dbo::hasMany(a, _entries, Wt::Dbo::ManyToOne, "playlist"); + Wt::Dbo::hasMany(a, _entries, Wt::Dbo::ManyToOne, "tracklist"); } private: @@ -83,23 +89,23 @@ class Playlist : public Wt::Dbo::Dbo std::string _name; bool _isPublic; Wt::Dbo::ptr _user; - Wt::Dbo::collection< Wt::Dbo::ptr > _entries; + Wt::Dbo::collection< Wt::Dbo::ptr > _entries; }; -class PlaylistEntry +class TrackListEntry : public Wt::Dbo::Dbo { public: - using pointer = Wt::Dbo::ptr; + using pointer = Wt::Dbo::ptr; - PlaylistEntry(); - PlaylistEntry(Wt::Dbo::ptr track, Wt::Dbo::ptr playlist); + TrackListEntry(); + TrackListEntry(Wt::Dbo::ptr track, Wt::Dbo::ptr tracklist); static pointer getById(Wt::Dbo::Session& session, IdType id); // Create utility - static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr track, Wt::Dbo::ptr playlist); + static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr track, Wt::Dbo::ptr tracklist); // Accessors Wt::Dbo::ptr getTrack() const { return _track; } @@ -108,13 +114,13 @@ class PlaylistEntry void persist(Action& a) { Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade); - Wt::Dbo::belongsTo(a, _playlist, "playlist", Wt::Dbo::OnDeleteCascade); + Wt::Dbo::belongsTo(a, _tracklist, "tracklist", Wt::Dbo::OnDeleteCascade); } private: Wt::Dbo::ptr _track; - Wt::Dbo::ptr _playlist; + Wt::Dbo::ptr _tracklist; }; } // namespace Database diff --git a/src/database/TrackStats.cpp b/src/database/TrackStats.cpp deleted file mode 100644 index 944ac7a2..00000000 --- a/src/database/TrackStats.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2014 Emeric Poupon - * - * This file is part of LMS. - * - * LMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LMS. If not, see . - */ - -#include "TrackStats.hpp" - -#include "Artist.hpp" -#include "Release.hpp" -#include "Track.hpp" -#include "User.hpp" - -namespace Database { - -TrackStats::TrackStats(Wt::Dbo::ptr track, Wt::Dbo::ptr user) -: _track(track), - _user(user) -{} - -std::vector -TrackStats::getMostPlayedArtists(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("SUM(t_s.play_count) DESC") - .limit(limit); - - 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) -{ - 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("SUM(t_s.play_count) DESC") - .limit(limit); - - 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) -{ - Wt::Dbo::Transaction transaction(session); - - TrackStats::pointer res = session.find() - .where("track_id = ?").bind(track.id()) - .where("user_id = ?").bind(user.id()); - if (!res) - res = session.add(std::make_unique(track, user)); - - return res; -} - -} // namespace Database - diff --git a/src/database/TrackStats.hpp b/src/database/TrackStats.hpp deleted file mode 100644 index 6c4d66d6..00000000 --- a/src/database/TrackStats.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2014 Emeric Poupon - * - * This file is part of LMS. - * - * LMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LMS. If not, see . - */ - -#pragma once - -#include -#include - -#include - -#include "Types.hpp" - -namespace Database { - -class Artist; -class Release; -class Track; -class User; - -class TrackStats -{ - public: - using pointer = Wt::Dbo::ptr; - - 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); - } - - private: - - int _playCount = 0; - Wt::WDateTime _lastPlayed; - Wt::Dbo::ptr _track; - Wt::Dbo::ptr _user; -}; - - -} // namespace Database - diff --git a/src/database/User.cpp b/src/database/User.cpp index b687572f..2bd01e70 100644 --- a/src/database/User.cpp +++ b/src/database/User.cpp @@ -19,6 +19,8 @@ #include "User.hpp" +#include "TrackList.hpp" + namespace Database { // must be ordered @@ -93,6 +95,38 @@ User::getMaxAudioBitrate(void) const return _maxAudioBitrate; } +Wt::Dbo::ptr +User::getPlayedTrackList() const +{ + static const std::string listName = "__played_tracks__"; + + assert(self()); + assert(IdIsValid(self()->id())); + assert(session()); + + auto res = TrackList::get(*session(), listName, self()); + if (!res) + res = TrackList::create(*session(), listName, false, self()); + + return res; +} + +Wt::Dbo::ptr +User::getQueuedTrackList() const +{ + static const std::string listName = "__queued_tracks__"; + + assert(self()); + assert(IdIsValid(self()->id())); + assert(session()); + + auto res = TrackList::get(*session(), listName, self()); + if (!res) + res = TrackList::create(*session(), listName, false, self()); + + return res; +} + } // namespace Database diff --git a/src/database/User.hpp b/src/database/User.hpp index fd536172..cd3aa01a 100644 --- a/src/database/User.hpp +++ b/src/database/User.hpp @@ -31,7 +31,7 @@ namespace Database { class User; using AuthInfo = Wt::Auth::Dbo::AuthInfo; -class Playlist; +class TrackList; // User selectable audio formats enum class AudioEncoding @@ -85,6 +85,9 @@ class User : public Wt::Dbo::Dbo std::size_t getMaxAudioBitrate() const; std::size_t getCurPlayingTrackPos() const { return _curPlayingTrackPos; } + Wt::Dbo::ptr getQueuedTrackList() const; + Wt::Dbo::ptr getPlayedTrackList() const; + template void persist(Action& a) { @@ -94,7 +97,7 @@ class User : public Wt::Dbo::Dbo Wt::Dbo::field(a, _audioEncoding, "audio_encoding"); // User's dynamic data Wt::Dbo::field(a, _curPlayingTrackPos, "cur_playing_track_pos"); - Wt::Dbo::hasMany(a, _playlists, Wt::Dbo::ManyToOne, "user"); + Wt::Dbo::hasMany(a, _tracklists, Wt::Dbo::ManyToOne, "user"); } private: @@ -112,7 +115,7 @@ class User : public Wt::Dbo::Dbo // User's dynamic data int _curPlayingTrackPos; // Current track position in queue - Wt::Dbo::collection< Wt::Dbo::ptr > _playlists; + Wt::Dbo::collection< Wt::Dbo::ptr > _tracklists; }; diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp index b1e108b7..8dc0e9f5 100644 --- a/src/ui/LmsApplication.cpp +++ b/src/ui/LmsApplication.cpp @@ -419,9 +419,15 @@ LmsApplication::createHome() }); // Events from the PlayQueue - playqueue->playTrack.connect(explore, &Explore::handleTrackPlayed); + playqueue->playTrack.connect([=](Database::IdType trackId) + { + Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); + LmsApp->getUser()->getPlayedTrackList().modify()->add(trackId); + }); + playqueue->playTrack.connect(explore, &Explore::handleTrackPlayed); playqueue->playTrack.connect(player, &MediaPlayer::playTrack); + playqueue->playbackStop.connect(player, &MediaPlayer::stop); // Events from MediaScanner diff --git a/src/ui/PlayQueueView.cpp b/src/ui/PlayQueueView.cpp index b8c93d2e..f0334ae0 100644 --- a/src/ui/PlayQueueView.cpp +++ b/src/ui/PlayQueueView.cpp @@ -28,8 +28,7 @@ #include "utils/Logger.hpp" -#include "database/Playlist.hpp" -#include "database/TrackStats.hpp" +#include "database/TrackList.hpp" #include "LmsApplication.hpp" @@ -63,7 +62,7 @@ PlayQueue::PlayQueue() { Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - getPlaylist().modify()->shuffle(); + getTrackList().modify()->shuffle(); } _entriesContainer->clear(); addSome(); @@ -76,15 +75,15 @@ PlayQueue::PlayQueue() LmsApp->preQuit().connect([=] { - if (_playlistId) + if (_tracklistId) { - LMS_LOG(UI, DEBUG) << "Removing playlist id " << *_playlistId; + LMS_LOG(UI, DEBUG) << "Removing tracklist id " << *_tracklistId; Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - auto playlist = Database::Playlist::getById(LmsApp->getDboSession(), *_playlistId); - if (playlist) - playlist.remove(); + auto tracklist = Database::TrackList::getById(LmsApp->getDboSession(), *_tracklistId); + if (tracklist) + tracklist.remove(); } }); @@ -92,30 +91,26 @@ PlayQueue::PlayQueue() addSome(); } -Database::Playlist::pointer -PlayQueue::getPlaylist() +Database::TrackList::pointer +PlayQueue::getTrackList() { static const std::string currentPlayQueueName = "__current__playqueue__"; - Database::Playlist::pointer res; + Database::TrackList::pointer res; if (LmsApp->getUser()->isDemo()) { - if (!_playlistId) + if (!_tracklistId) { - res = Database::Playlist::create(LmsApp->getDboSession(), currentPlayQueueName, false, LmsApp->getUser()); + res = Database::TrackList::create(LmsApp->getDboSession(), currentPlayQueueName, false, LmsApp->getUser()); LmsApp->getDboSession().flush(); - _playlistId = res.id(); + _tracklistId = res.id(); return res; } - return Database::Playlist::getById(LmsApp->getDboSession(), *_playlistId); + return Database::TrackList::getById(LmsApp->getDboSession(), *_tracklistId); } - res = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser()); - if (!res) - res = Database::Playlist::create(LmsApp->getDboSession(), currentPlayQueueName, false, LmsApp->getUser()); - - return res; + return LmsApp->getUser()->getQueuedTrackList(); } void @@ -123,7 +118,7 @@ PlayQueue::clearTracks() { Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - getPlaylist().modify()->clear(); + getTrackList().modify()->clear(); _showMore->setHidden(true); _entriesContainer->clear(); updateInfo(); @@ -146,29 +141,24 @@ PlayQueue::play(std::size_t pos) { Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - auto playlist = getPlaylist(); + auto tracklist = getTrackList(); // If out of range, stop playing - if (pos >= playlist->getCount()) + if (pos >= tracklist->getCount()) { stop(); return; } // If last and radio mode, fill the next song - if (_radioMode->checkState() == Wt::CheckState::Checked && pos == playlist->getCount() - 1) + if (_radioMode->checkState() == Wt::CheckState::Checked && pos == tracklist->getCount() - 1) addRadioTrack(); _trackPos = pos; - auto track = playlist->getEntry(*_trackPos)->getTrack(); + auto track = tracklist->getEntry(*_trackPos)->getTrack(); trackId = track.id(); - auto stats = Database::TrackStats::get(LmsApp->getDboSession(), track, LmsApp->getUser()); - - stats.modify()->incPlayCount(); - stats.modify()->setLastPlayed(Wt::WLocalDateTime::currentServerDateTime().toUTC()); - updateCurrentTrack(true); } @@ -204,7 +194,7 @@ PlayQueue::updateInfo() { Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - _nbTracks->setText(Wt::WString::tr("Lms.PlayQueue.nb-tracks").arg(static_cast(getPlaylist()->getCount()))); + _nbTracks->setText(Wt::WString::tr("Lms.PlayQueue.nb-tracks").arg(static_cast(getTrackList()->getCount()))); } void @@ -229,10 +219,10 @@ PlayQueue::enqueueTracks(const std::vector& tracks) // Use a "session" playqueue in order to store the current playqueue // so that the user can disconnect and get its playqueue back - auto playlist = getPlaylist(); + auto tracklist = getTrackList(); for (auto track : tracks) - Database::PlaylistEntry::create(LmsApp->getDboSession(), track, playlist); + Database::TrackListEntry::create(LmsApp->getDboSession(), track, tracklist); updateInfo(); addSome(); @@ -269,14 +259,13 @@ PlayQueue::addSome() { Wt::Dbo::Transaction transaction (LmsApp->getDboSession()); - auto playlist = getPlaylist(); + auto tracklist = getTrackList(); - bool moreResults; - auto playlistEntries = playlist->getEntries(_entriesContainer->count(), 50, moreResults); - for (auto playlistEntry : playlistEntries) + auto tracklistEntries = tracklist->getEntries(_entriesContainer->count(), 50); + for (auto tracklistEntry : tracklistEntries) { - auto playlistEntryId = playlistEntry.id(); - auto track = playlistEntry->getTrack(); + auto tracklistEntryId = tracklistEntry.id(); + auto track = tracklistEntry->getTrack(); Wt::WTemplate* entry = _entriesContainer->addNew(Wt::WString::tr("Lms.PlayQueue.template.entry")); @@ -310,7 +299,7 @@ PlayQueue::addSome() { Wt::Dbo::Transaction transaction (LmsApp->getDboSession()); - auto entryToRemove = Database::PlaylistEntry::getById(LmsApp->getDboSession(), playlistEntryId); + auto entryToRemove = Database::TrackListEntry::getById(LmsApp->getDboSession(), tracklistEntryId); entryToRemove.remove(); } @@ -328,7 +317,7 @@ PlayQueue::addSome() } - _showMore->setHidden(!moreResults); + _showMore->setHidden(static_cast(_entriesContainer->count()) >= tracklist->getCount()); } void @@ -337,17 +326,17 @@ PlayQueue::addRadioTrack() auto now = std::chrono::system_clock::now(); std::mt19937 randGenerator(std::chrono::duration_cast(now.time_since_epoch()).count()); - auto playlist = getPlaylist(); + auto tracklist = getTrackList(); - std::set playlistTrackIds; + std::set trackIds; { - auto ids = playlist->getTrackIds(); - playlistTrackIds = std::set(ids.begin(), ids.end()); + auto ids = tracklist->getTrackIds(); + trackIds = std::set(ids.begin(), ids.end()); } - // Get all the tracks of the playlist, get the cluster that is mostly used + // Get all the tracks of the tracklist, get the cluster that is mostly used // and reuse it to get the next track - auto clusters = playlist->getClusters(); + auto clusters = tracklist->getClusters(); if (clusters.empty()) return; @@ -357,7 +346,7 @@ PlayQueue::addRadioTrack() std::set candidateTrackIds; std::set_difference(clusterTrackIds.begin(), clusterTrackIds.end(), - playlistTrackIds.begin(), playlistTrackIds.end(), + trackIds.begin(), trackIds.end(), std::inserter(candidateTrackIds, candidateTrackIds.end())); if (candidateTrackIds.empty()) diff --git a/src/ui/PlayQueueView.hpp b/src/ui/PlayQueueView.hpp index 75210d23..e95eec41 100644 --- a/src/ui/PlayQueueView.hpp +++ b/src/ui/PlayQueueView.hpp @@ -27,7 +27,7 @@ #include -#include "database/Playlist.hpp" +#include "database/TrackList.hpp" #include "database/Track.hpp" namespace UserInterface { @@ -53,7 +53,7 @@ class PlayQueue : public Wt::WTemplate Wt::Signal<> playbackStop; private: - Database::Playlist::pointer getPlaylist(); + Database::TrackList::pointer getTrackList(); void clearTracks(); void enqueueTracks(const std::vector& tracks); @@ -66,7 +66,7 @@ class PlayQueue : public Wt::WTemplate void play(std::size_t pos); void stop(); - boost::optional _playlistId; + boost::optional _tracklistId; Wt::WCheckBox* _radioMode; Wt::WContainerWidget* _entriesContainer; Wt::WTemplate* _showMore; diff --git a/src/ui/explore/ArtistView.cpp b/src/ui/explore/ArtistView.cpp index 665b98a6..71047dfa 100644 --- a/src/ui/explore/ArtistView.cpp +++ b/src/ui/explore/ArtistView.cpp @@ -25,7 +25,6 @@ #include #include "database/Artist.hpp" -#include "database/Setting.hpp" #include "utils/Logger.hpp" #include "utils/Utils.hpp" diff --git a/src/ui/explore/ArtistsView.cpp b/src/ui/explore/ArtistsView.cpp index 2ad6e681..b2b73e4a 100644 --- a/src/ui/explore/ArtistsView.cpp +++ b/src/ui/explore/ArtistsView.cpp @@ -25,8 +25,7 @@ #include #include "database/Artist.hpp" -#include "database/Setting.hpp" -#include "database/TrackStats.hpp" +#include "database/TrackList.hpp" #include "utils/Logger.hpp" #include "utils/Utils.hpp" @@ -80,7 +79,6 @@ Artists::Artists(Filters* filters) refresh(); refreshMostPlayed(); refreshRecentlyAdded(); - refreshRecentlyPlayed(); filters->updated().connect(this, &Artists::refresh); } @@ -97,22 +95,11 @@ Artists::refreshRecentlyAdded() addCompactEntries(_recentlyAddedContainer, artists); } -void -Artists::refreshRecentlyPlayed() -{ - Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - auto artists = TrackStats::getLastPlayedArtists(LmsApp->getDboSession(), LmsApp->getUser(), 5); - - _recentlyPlayedContainer->clear(); - addCompactEntries(_recentlyPlayedContainer, artists); -} - - void Artists::refreshMostPlayed() { Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - auto artists = TrackStats::getMostPlayedArtists(LmsApp->getDboSession(), LmsApp->getUser(), 5); + auto artists = LmsApp->getUser()->getPlayedTrackList()->getTopArtists(5); _mostPlayedContainer->clear(); addCompactEntries(_mostPlayedContainer, artists); diff --git a/src/ui/explore/ArtistsView.hpp b/src/ui/explore/ArtistsView.hpp index f39c5fe4..e6da4276 100644 --- a/src/ui/explore/ArtistsView.hpp +++ b/src/ui/explore/ArtistsView.hpp @@ -39,7 +39,6 @@ class Artists : public Wt::WTemplate Wt::Signal artistPlay; void refreshRecentlyAdded(); - void refreshRecentlyPlayed(); void refreshMostPlayed(); private: diff --git a/src/ui/explore/Explore.cpp b/src/ui/explore/Explore.cpp index 6b62da7f..d19a9a2c 100644 --- a/src/ui/explore/Explore.cpp +++ b/src/ui/explore/Explore.cpp @@ -113,10 +113,7 @@ Explore::Explore() _trackPlayed.connect([=] { artists_raw->refreshMostPlayed(); - artists_raw->refreshRecentlyPlayed(); releases_raw->refreshMostPlayed(); - releases_raw->refreshRecentlyPlayed(); - }); auto tracks = std::make_unique(_filters); diff --git a/src/ui/explore/ReleasesView.cpp b/src/ui/explore/ReleasesView.cpp index a7e0d60b..1dc79f8d 100644 --- a/src/ui/explore/ReleasesView.cpp +++ b/src/ui/explore/ReleasesView.cpp @@ -26,7 +26,7 @@ #include #include "database/Release.hpp" -#include "database/TrackStats.hpp" +#include "database/TrackList.hpp" #include "utils/Logger.hpp" #include "utils/Utils.hpp" @@ -96,7 +96,6 @@ _filters(filters) })); refreshRecentlyAdded(); - refreshRecentlyPlayed(); refreshMostPlayed(); refresh(); @@ -106,8 +105,6 @@ _filters(filters) 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()); @@ -118,27 +115,12 @@ 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->getUser(), 5); - - _recentlyPlayedContainer->clear(); - addCompactEntries(_recentlyPlayedContainer, releases); -} - void Releases::refreshMostPlayed() { - LMS_LOG(UI, DEBUG) << "Refreshing most played releases"; - Wt::Dbo::Transaction transaction(LmsApp->getDboSession()); - auto releases = TrackStats::getMostPlayedReleases(LmsApp->getDboSession(), LmsApp->getUser(), 5); + auto releases = LmsApp->getUser()->getPlayedTrackList()->getTopReleases(5); _mostPlayedContainer->clear(); addCompactEntries(_mostPlayedContainer, releases); diff --git a/src/ui/explore/ReleasesView.hpp b/src/ui/explore/ReleasesView.hpp index fff677f1..bbf45960 100644 --- a/src/ui/explore/ReleasesView.hpp +++ b/src/ui/explore/ReleasesView.hpp @@ -39,7 +39,6 @@ class Releases : public Wt::WTemplate Wt::Signal releasePlay; void refreshRecentlyAdded(); - void refreshRecentlyPlayed(); void refreshMostPlayed(); private: