Added an played tracklist

This commit is contained in:
emeric
2018-08-03 14:01:56 +02:00
parent 5c182f2868
commit a7e279ce42
23 changed files with 360 additions and 727 deletions
-5
View File
@@ -8,11 +8,6 @@
</div>
${most-played-artists}
<div class="page-header">
<h2>${tr:Lms.Explore.recently-played-artists}</h2>
</div>
${recently-played-artists}
<div class="page-header">
<h2>${tr:Lms.Explore.recently-added-artists}</h2>
</div>
-5
View File
@@ -8,11 +8,6 @@
</div>
${most-played-releases}
<div class="page-header">
<h2>${tr:Lms.Explore.recently-played-releases}</h2>
</div>
${recently-played-releases}
<div class="page-header">
<h2>${tr:Lms.Explore.recently-added-releases}</h2>
</div>
+1 -2
View File
@@ -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 \
+4 -9
View File
@@ -31,17 +31,14 @@
#include <Wt/Auth/PasswordStrengthValidator.h>
#include <Wt/Auth/PasswordVerifier.h>
#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>("artist");
_session.mapClass<Cluster>("cluster");
_session.mapClass<ClusterType>("cluster_type");
_session.mapClass<Playlist>("playlist");
_session.mapClass<PlaylistEntry>("playlist_entry");
_session.mapClass<TrackList>("tracklist");
_session.mapClass<TrackListEntry>("tracklist_entry");
_session.mapClass<Release>("release");
_session.mapClass<Setting>("setting");
_session.mapClass<Track>("track");
_session.mapClass<TrackStats>("track_stats");
_session.mapClass<ScanSettings>("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);
-208
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include "Playlist.hpp"
#include <cassert>
#include <random>
#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> user)
: _name(name),
_isPublic(isPublic),
_user(user)
{
}
Playlist::pointer
Playlist::create(Wt::Dbo::Session& session, std::string name, bool isPublic, Wt::Dbo::ptr<User> user)
{
return session.add( std::make_unique<Playlist>(name, isPublic, user) );
}
PlaylistEntry::PlaylistEntry()
{
}
PlaylistEntry::pointer
PlaylistEntry::getById(Wt::Dbo::Session& session, IdType id)
{
return session.find<PlaylistEntry>().where("id = ?").bind(id);
}
Playlist::pointer
Playlist::get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> user)
{
return session.find<Playlist>().where("name = ? AND user_id = ?").bind(name).bind(user.id());
}
std::vector<Playlist::pointer>
Playlist::getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user)
{
Wt::Dbo::collection<Playlist::pointer> res = session.find<Playlist>().where("user_id = ?").bind(user.id()).orderBy("name");
return std::vector<Playlist::pointer>(res.begin(), res.end());
}
Playlist::pointer
Playlist::getById(Wt::Dbo::Session& session, IdType id)
{
return session.find<Playlist>().where("id = ?").bind(id);
}
PlaylistEntry::PlaylistEntry(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<Playlist> playlist)
: _track(track),
_playlist(playlist)
{
}
PlaylistEntry::pointer
PlaylistEntry::create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<Playlist> playlist)
{
return session.add( std::make_unique<PlaylistEntry>( track, playlist) );
}
std::vector<Wt::Dbo::ptr<PlaylistEntry>>
Playlist::getEntries(int offset, int size, bool& moreResults) const
{
assert(session());
assert(IdIsValid(self()->id()));
moreResults = false;
Wt::Dbo::collection<Wt::Dbo::ptr<PlaylistEntry>> entries =
session()->find<PlaylistEntry>()
.where("playlist_id = ?").bind(self().id())
.orderBy("id")
.limit(size != -1 ? size + 1 : -1)
.offset(offset);
std::vector<Wt::Dbo::ptr<PlaylistEntry>> res;
for (auto entry : entries)
{
if (size != -1 && res.size() == static_cast<std::size_t>(size))
{
moreResults = true;
break;
}
res.push_back(entry);
}
return res;
}
std::vector<Wt::Dbo::ptr<PlaylistEntry>>
Playlist::getAllEntries() const
{
bool moreResults;
return getEntries(-1, -1, moreResults);
}
Wt::Dbo::ptr<PlaylistEntry>
Playlist::getEntry(std::size_t pos) const
{
Wt::Dbo::ptr<PlaylistEntry> 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<Wt::Dbo::ptr<Cluster>>
Playlist::getClusters() const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<Cluster::pointer> res = session()->query<Cluster::pointer>("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<Wt::Dbo::ptr<Cluster>>(res.begin(), res.end());
}
bool
Playlist::hasTrack(IdType trackId) const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<PlaylistEntry::pointer> res = session()->query<PlaylistEntry::pointer>("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<IdType>
Playlist::getTrackIds() const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<IdType> res = session()->query<IdType>("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<IdType>(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<std::chrono::milliseconds>(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
-133
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<Setting>(std::make_unique<Setting>(name));
}
Setting::pointer
Setting::getByName(Wt::Dbo::Session& session, std::string name)
{
return session.find<Setting>().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
-71
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <Wt/Dbo/Dbo.h>
#include <Wt/WTime.h>
namespace Database {
// class meant to store general settings
class Setting
{
public:
using pointer = Wt::Dbo::ptr<Setting>;
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<class Action>
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
+2 -4
View File
@@ -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<Track>
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<Track>
Wt::Dbo::ptr<Artist> _artist;
Wt::Dbo::ptr<Release> _release;
Wt::Dbo::collection<Wt::Dbo::ptr<Cluster>> _clusters;
Wt::Dbo::collection<Wt::Dbo::ptr<PlaylistEntry>> _playlistEntries;
Wt::Dbo::collection<Wt::Dbo::ptr<TrackStats>> _stats;
Wt::Dbo::collection<Wt::Dbo::ptr<TrackListEntry>> _playlistEntries;
};
+238
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include "TrackList.hpp"
#include <cassert>
#include <random>
#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> user)
: _name(name),
_isPublic(isPublic),
_user(user)
{
}
TrackList::pointer
TrackList::create(Wt::Dbo::Session& session, std::string name, bool isPublic, Wt::Dbo::ptr<User> user)
{
assert(user);
auto res = session.add( std::make_unique<TrackList>(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> user)
{
return session.find<TrackList>().where("name = ? AND user_id = ?").bind(name).bind(user.id());
}
std::vector<TrackList::pointer>
TrackList::getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user)
{
Wt::Dbo::collection<TrackList::pointer> res = session.find<TrackList>().where("user_id = ?").bind(user.id()).orderBy("name");
return std::vector<TrackList::pointer>(res.begin(), res.end());
}
TrackList::pointer
TrackList::getById(Wt::Dbo::Session& session, IdType id)
{
return session.find<TrackList>().where("id = ?").bind(id);
}
std::vector<Wt::Dbo::ptr<TrackListEntry>>
TrackList::getEntries(int offset, int size) const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<Wt::Dbo::ptr<TrackListEntry>> entries =
session()->find<TrackListEntry>()
.where("tracklist_id = ?").bind(self().id())
.orderBy("id")
.limit(size)
.offset(offset);
return std::vector<Wt::Dbo::ptr<TrackListEntry>>(entries.begin(), entries.end());
}
Wt::Dbo::ptr<TrackListEntry>
TrackList::getEntry(std::size_t pos) const
{
Wt::Dbo::ptr<TrackListEntry> 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<Wt::Dbo::ptr<Cluster>>
TrackList::getClusters() const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<Cluster::pointer> res = session()->query<Cluster::pointer>("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<Wt::Dbo::ptr<Cluster>>(res.begin(), res.end());
}
bool
TrackList::hasTrack(IdType trackId) const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<TrackListEntry::pointer> res = session()->query<TrackListEntry::pointer>("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<IdType>
TrackList::getTrackIds() const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<IdType> res = session()->query<IdType>("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<IdType>(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<std::chrono::milliseconds>(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<Artist::pointer>
TrackList::getTopArtists(int limit) const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<Artist::pointer> res = session()->query<Artist::pointer>("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<Artist::pointer>(res.begin(), res.end());
}
std::vector<Release::pointer>
TrackList::getTopReleases(int limit) const
{
assert(session());
assert(IdIsValid(self()->id()));
Wt::Dbo::collection<Release::pointer> res = session()->query<Release::pointer>("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<Release::pointer>(res.begin(), res.end());
}
TrackListEntry::TrackListEntry(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<TrackList> tracklist)
: _track(track),
_tracklist(tracklist)
{
}
TrackListEntry::TrackListEntry()
{
}
TrackListEntry::pointer
TrackListEntry::create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<TrackList> tracklist)
{
assert(track);
assert(tracklist);
auto res = session.add( std::make_unique<TrackListEntry>( track, tracklist) );
session.flush();
return res;
}
TrackListEntry::pointer
TrackListEntry::getById(Wt::Dbo::Session& session, IdType id)
{
return session.find<TrackListEntry>().where("id = ?").bind(id);
}
} // namespace Database
@@ -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<Playlist>
class TrackList : public Wt::Dbo::Dbo<TrackList>
{
public:
using pointer = Wt::Dbo::ptr<Playlist>;
using pointer = Wt::Dbo::ptr<TrackList>;
Playlist();
Playlist(std::string name, bool isPublic, Wt::Dbo::ptr<User> user);
TrackList();
TrackList(std::string name, bool isPublic, Wt::Dbo::ptr<User> user);
// Stats utility
std::vector<Wt::Dbo::ptr<Artist>> getTopArtists(int limit = 1) const;
std::vector<Wt::Dbo::ptr<Release>> getTopReleases(int limit = 1) const;
// Search utility
static pointer get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> user);
static pointer getById(Wt::Dbo::Session& session, IdType playlistId);
static pointer getById(Wt::Dbo::Session& session, IdType tracklistId);
static std::vector<pointer> getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user);
// Create utility
@@ -53,14 +59,14 @@ class Playlist : public Wt::Dbo::Dbo<Playlist>
bool isPublic() const { return _isPublic; }
// Modifiers
Wt::Dbo::ptr<TrackListEntry> add(IdType trackId);
void clear() { _entries.clear(); }
void shuffle();
// Get tracks, ordered by position
std::size_t getCount() const;
Wt::Dbo::ptr<PlaylistEntry> getEntry(std::size_t pos) const;
std::vector<Wt::Dbo::ptr<PlaylistEntry>> getEntries(int offset, int size, bool& moreResults) const;
std::vector<Wt::Dbo::ptr<PlaylistEntry>> getAllEntries() const;
Wt::Dbo::ptr<TrackListEntry> getEntry(std::size_t pos) const;
std::vector<Wt::Dbo::ptr<TrackListEntry>> getEntries(int offset = -1, int size = -1) const;
std::vector<IdType> getTrackIds() const;
@@ -75,7 +81,7 @@ class Playlist : public Wt::Dbo::Dbo<Playlist>
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<Playlist>
std::string _name;
bool _isPublic;
Wt::Dbo::ptr<User> _user;
Wt::Dbo::collection< Wt::Dbo::ptr<PlaylistEntry> > _entries;
Wt::Dbo::collection< Wt::Dbo::ptr<TrackListEntry> > _entries;
};
class PlaylistEntry
class TrackListEntry : public Wt::Dbo::Dbo<TrackListEntry>
{
public:
using pointer = Wt::Dbo::ptr<PlaylistEntry>;
using pointer = Wt::Dbo::ptr<TrackListEntry>;
PlaylistEntry();
PlaylistEntry(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<Playlist> playlist);
TrackListEntry();
TrackListEntry(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<TrackList> tracklist);
static pointer getById(Wt::Dbo::Session& session, IdType id);
// Create utility
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<Playlist> playlist);
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<TrackList> tracklist);
// Accessors
Wt::Dbo::ptr<Track> 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> _track;
Wt::Dbo::ptr<Playlist> _playlist;
Wt::Dbo::ptr<TrackList> _tracklist;
};
} // namespace Database
-101
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include "TrackStats.hpp"
#include "Artist.hpp"
#include "Release.hpp"
#include "Track.hpp"
#include "User.hpp"
namespace Database {
TrackStats::TrackStats(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<User> user)
: _track(track),
_user(user)
{}
std::vector<Artist::pointer>
TrackStats::getMostPlayedArtists(Wt::Dbo::Session& session, User::pointer user, int limit)
{
Wt::Dbo::collection<Artist::pointer> res = session.query<Artist::pointer>
("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<Artist::pointer>(res.begin(), res.end());
}
std::vector<Artist::pointer>
TrackStats::getLastPlayedArtists(Wt::Dbo::Session& session, User::pointer user, int limit)
{
Wt::Dbo::collection<Artist::pointer> res = session.query<Artist::pointer>
("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<Artist::pointer>(res.begin(), res.end());
}
std::vector<Release::pointer>
TrackStats::getMostPlayedReleases(Wt::Dbo::Session& session, User::pointer user, int limit)
{
Wt::Dbo::collection<Release::pointer> res = session.query<Release::pointer>
("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<Release::pointer>(res.begin(), res.end());
}
std::vector<Release::pointer>
TrackStats::getLastPlayedReleases(Wt::Dbo::Session& session, User::pointer user, int limit)
{
Wt::Dbo::collection<Release::pointer> res = session.query<Release::pointer>
("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<Release::pointer>(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<TrackStats>()
.where("track_id = ?").bind(track.id())
.where("user_id = ?").bind(user.id());
if (!res)
res = session.add(std::make_unique<TrackStats>(track, user));
return res;
}
} // namespace Database
-75
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <Wt/Dbo/Dbo.h>
#include <Wt/WDateTime.h>
#include <string>
#include "Types.hpp"
namespace Database {
class Artist;
class Release;
class Track;
class User;
class TrackStats
{
public:
using pointer = Wt::Dbo::ptr<TrackStats>;
TrackStats() {}
TrackStats(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<User> user);
static std::vector<Wt::Dbo::ptr<Artist>> getMostPlayedArtists(Wt::Dbo::Session& session, Wt::Dbo::ptr<User>, int limit = 1);
static std::vector<Wt::Dbo::ptr<Artist>> getLastPlayedArtists(Wt::Dbo::Session& session, Wt::Dbo::ptr<User>, int limit = 1);
static std::vector<Wt::Dbo::ptr<Release>> getMostPlayedReleases(Wt::Dbo::Session& session, Wt::Dbo::ptr<User>, int limit = 1);
static std::vector<Wt::Dbo::ptr<Release>> getLastPlayedReleases(Wt::Dbo::Session& session, Wt::Dbo::ptr<User>, int limit = 1);
// Get utility (will create if does not exist)
static pointer get(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<User> user);
void incPlayCount() { _playCount++; }
void setLastPlayed(Wt::WDateTime lastPlayed) { _lastPlayed = lastPlayed; }
template<class Action>
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> _track;
Wt::Dbo::ptr<User> _user;
};
} // namespace Database
+34
View File
@@ -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<TrackList>
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<TrackList>
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
+6 -3
View File
@@ -31,7 +31,7 @@ namespace Database {
class User;
using AuthInfo = Wt::Auth::Dbo::AuthInfo<User>;
class Playlist;
class TrackList;
// User selectable audio formats
enum class AudioEncoding
@@ -85,6 +85,9 @@ class User : public Wt::Dbo::Dbo<User>
std::size_t getMaxAudioBitrate() const;
std::size_t getCurPlayingTrackPos() const { return _curPlayingTrackPos; }
Wt::Dbo::ptr<TrackList> getQueuedTrackList() const;
Wt::Dbo::ptr<TrackList> getPlayedTrackList() const;
template<class Action>
void persist(Action& a)
{
@@ -94,7 +97,7 @@ class User : public Wt::Dbo::Dbo<User>
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>
// User's dynamic data
int _curPlayingTrackPos; // Current track position in queue
Wt::Dbo::collection< Wt::Dbo::ptr<Playlist> > _playlists;
Wt::Dbo::collection< Wt::Dbo::ptr<TrackList> > _tracklists;
};
+7 -1
View File
@@ -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
+37 -48
View File
@@ -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<unsigned>(getPlaylist()->getCount())));
_nbTracks->setText(Wt::WString::tr("Lms.PlayQueue.nb-tracks").arg(static_cast<unsigned>(getTrackList()->getCount())));
}
void
@@ -229,10 +219,10 @@ PlayQueue::enqueueTracks(const std::vector<Database::Track::pointer>& 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::WTemplate>(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<std::size_t>(_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<std::chrono::milliseconds>(now.time_since_epoch()).count());
auto playlist = getPlaylist();
auto tracklist = getTrackList();
std::set<Database::IdType> playlistTrackIds;
std::set<Database::IdType> trackIds;
{
auto ids = playlist->getTrackIds();
playlistTrackIds = std::set<Database::IdType>(ids.begin(), ids.end());
auto ids = tracklist->getTrackIds();
trackIds = std::set<Database::IdType>(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<Database::IdType> candidateTrackIds;
std::set_difference(clusterTrackIds.begin(), clusterTrackIds.end(),
playlistTrackIds.begin(), playlistTrackIds.end(),
trackIds.begin(), trackIds.end(),
std::inserter(candidateTrackIds, candidateTrackIds.end()));
if (candidateTrackIds.empty())
+3 -3
View File
@@ -27,7 +27,7 @@
#include <boost/optional.hpp>
#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<Database::Track::pointer>& tracks);
@@ -66,7 +66,7 @@ class PlayQueue : public Wt::WTemplate
void play(std::size_t pos);
void stop();
boost::optional<Database::IdType> _playlistId;
boost::optional<Database::IdType> _tracklistId;
Wt::WCheckBox* _radioMode;
Wt::WContainerWidget* _entriesContainer;
Wt::WTemplate* _showMore;
-1
View File
@@ -25,7 +25,6 @@
#include <Wt/WText.h>
#include "database/Artist.hpp"
#include "database/Setting.hpp"
#include "utils/Logger.hpp"
#include "utils/Utils.hpp"
+2 -15
View File
@@ -25,8 +25,7 @@
#include <Wt/WTemplate.h>
#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);
-1
View File
@@ -39,7 +39,6 @@ class Artists : public Wt::WTemplate
Wt::Signal<Database::IdType> artistPlay;
void refreshRecentlyAdded();
void refreshRecentlyPlayed();
void refreshMostPlayed();
private:
-3
View File
@@ -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<Tracks>(_filters);
+2 -20
View File
@@ -26,7 +26,7 @@
#include <Wt/WTemplate.h>
#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);
-1
View File
@@ -39,7 +39,6 @@ class Releases : public Wt::WTemplate
Wt::Signal<Database::IdType> releasePlay;
void refreshRecentlyAdded();
void refreshRecentlyPlayed();
void refreshMostPlayed();
private: