Added an ApplicationGroup system to track the multiple sessions open by a user

This commit is contained in:
emeric
2018-06-22 13:10:19 +02:00
parent ed008533b2
commit c427396623
13 changed files with 274 additions and 71 deletions
+1
View File
@@ -15,6 +15,7 @@
<message id="Lms.password-confirm">Confirm password</message>
<message id="Lms.passwords-dont-match">Passwords don't match</message>
<message id="Lms.quit-confirm">Are you sure?</message>
<message id="Lms.quit-other-session">Another session has been open. Reopen this one?</message>
<message id="Lms.save">Save</message>
<!--Administration-->
+2 -1
View File
@@ -13,7 +13,7 @@ lms_SOURCES = \
$(srcdir)/database/ScanSettings.cpp \
$(srcdir)/database/SqlQuery.cpp \
$(srcdir)/database/Track.cpp \
$(srcdir)/database/TrackStats.cpp \
$(srcdir)/database/TrackStats.cpp \
$(srcdir)/database/User.cpp \
$(srcdir)/image/Image.cpp \
$(srcdir)/metadata/AvFormat.cpp \
@@ -21,6 +21,7 @@ lms_SOURCES = \
$(srcdir)/scanner/MediaScanner.cpp \
$(srcdir)/ui/Auth.cpp \
$(srcdir)/ui/LmsApplication.cpp \
$(srcdir)/ui/LmsApplicationGroup.cpp \
$(srcdir)/ui/MediaPlayer.cpp \
$(srcdir)/ui/PlayQueueView.cpp \
$(srcdir)/ui/SettingsView.cpp \
+2 -1
View File
@@ -122,12 +122,13 @@ int main(int argc, char* argv[])
// Initializing a connection pool to the database that will be shared along services
auto connectionPool = Database::Handler::createConnectionPool(Config::instance().getPath("working-dir") / "lms.db");
UserInterface::LmsApplicationGroups appGroups;
Scanner::MediaScanner scanner(*connectionPool);
// bind entry point
server.addEntryPoint(Wt::EntryPointType::Application,
std::bind(UserInterface::LmsApplication::create,
std::placeholders::_1, std::ref(*connectionPool), std::ref(scanner)));
std::placeholders::_1, std::ref(*connectionPool), std::ref(appGroups), std::ref(scanner)));
// Start
LMS_LOG(MAIN, INFO) << "Starting Media scanner...";
+83 -37
View File
@@ -50,13 +50,13 @@
namespace UserInterface {
std::unique_ptr<Wt::WApplication>
LmsApplication::create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner)
LmsApplication::create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, LmsApplicationGroups& appGroups, Scanner::MediaScanner& scanner)
{
/*
* You could read information from the environment to decide whether
* the user has permission to start a new application
*/
return std::make_unique<LmsApplication>(env, connectionPool, scanner);
return std::make_unique<LmsApplication>(env, connectionPool, appGroups, scanner);
}
LmsApplication*
@@ -71,9 +71,10 @@ LmsApplication::instance()
* constructor so it is typically also an argument for your custom
* application constructor.
*/
LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner)
LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, LmsApplicationGroups& appGroups, Scanner::MediaScanner& scanner)
: Wt::WApplication(env),
_db(connectionPool),
_appGroups(appGroups),
_scanner(scanner),
_imageResource(nullptr),
_transcodeResource(nullptr)
@@ -125,23 +126,23 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
}
else
{
LmsApp->getDb().getLogin().changed().connect(std::bind([=]
{
try
{
handleAuthEvent();
}
catch (std::exception& e)
{
LMS_LOG(UI, ERROR) << "Error while handling auth event: " << e.what();
throw std::runtime_error("Internal error");
}
}));
LmsApp->getDb().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent);
_auth = root()->addNew<Auth>();
}
}
LmsApplication::~LmsApplication()
{
LmsApplicationInfo info = LmsApplicationInfo::fromEnvironment(environment());
getApplicationGroup().postOthers([info]
{
LmsApp->getGroupEvents().appClosed(info);
});
getApplicationGroup().leave();
}
std::unique_ptr<Wt::WAnchor>
LmsApplication::createArtistAnchor(Database::Artist::pointer artist, bool addText)
{
@@ -250,25 +251,56 @@ handlePathChange(Wt::WStackedWidget* stack, bool isAdmin)
wApp->setInternalPath("/artists", true);
}
void
LmsApplication::handleAuthEvent(void)
LmsApplicationGroup&
LmsApplication::getApplicationGroup()
{
if (!LmsApp->getDb().getLogin().loggedIn())
return _appGroups[_userIdentity];
}
void
LmsApplication::handleAuthEvent()
{
try
{
LMS_LOG(UI, INFO) << "User logged out, session = " << Wt::WApplication::instance()->sessionId();
if (!getDb().getLogin().loggedIn())
{
LMS_LOG(UI, INFO) << "User '" << _userIdentity << " 'logged out, session = " << sessionId();
goHomeAndQuit();
return;
goHomeAndQuit();
return;
}
else
{
_userIdentity = getAuthUser().identity(Wt::Auth::Identity::LoginName);
LmsApplicationInfo info = LmsApplicationInfo::fromEnvironment(environment());
LMS_LOG(UI, INFO) << "User '" << _userIdentity << "' logged in from '" << environment().clientAddress() << "', user agent = " << environment().userAgent() << ", session = " << sessionId();
getApplicationGroup().join(info);
getApplicationGroup().postOthers([info]
{
LmsApp->getGroupEvents().appOpen(info);
});
createHome();
}
}
catch (std::exception& e)
{
LMS_LOG(UI, ERROR) << "Error while handling auth event: " << e.what();
throw std::runtime_error("Internal error");
}
}
LMS_LOG(UI, INFO) << "User '" << LmsApp->getCurrentAuthUser().identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().userAgent() << ", session = " << Wt::WApplication::instance()->sessionId();
// Since we plug into the Media Scanner events, we need to enable updates
void
LmsApplication::createHome()
{
// Handle Media Scanner events and other session events
enableUpdates(true);
{
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
_isAdmin = LmsApp->getCurrentUser()->isAdmin();
_isAdmin = LmsApp->getUser()->isAdmin();
}
_imageResource = std::make_shared<ImageResource>(_db);
@@ -355,33 +387,33 @@ LmsApplication::handleAuthEvent(void)
mainStack->addNew<UserView>();
}
explore->tracksAdd.connect(std::bind([=] (std::vector<Database::Track::pointer> tracks)
explore->tracksAdd.connect([=] (std::vector<Database::Track::pointer> tracks)
{
playqueue->addTracks(tracks);
}, std::placeholders::_1));
});
explore->tracksPlay.connect(std::bind([=] (std::vector<Database::Track::pointer> tracks)
explore->tracksPlay.connect([=] (std::vector<Database::Track::pointer> tracks)
{
playqueue->playTracks(tracks);
}, std::placeholders::_1));
});
// MediaPlayer
MediaPlayer* player = main->bindNew<MediaPlayer>("player");
// Events from MediaPlayer
player->playNext.connect(std::bind([=]
player->playNext.connect([=]
{
playqueue->playNext();
}));
player->playPrevious.connect(std::bind([=]
});
player->playPrevious.connect([=]
{
playqueue->playPrevious();
}));
player->playbackEnded.connect(std::bind([=]
});
player->playbackEnded.connect([=]
{
playqueue->playNext();
}));
});
// Events from the PlayQueue
playqueue->playTrack.connect(explore, &Explore::handleTrackPlayed);
@@ -390,7 +422,7 @@ LmsApplication::handleAuthEvent(void)
playqueue->playbackStop.connect(player, &MediaPlayer::stop);
// Events from MediaScanner
std::string sessionId = this->sessionId();
std::string sessionId = LmsApp->sessionId();
_scanner.scanComplete().connect([=] (Scanner::MediaScanner::Stats stats)
{
Wt::WServer::instance()->post(sessionId, [=]
@@ -420,6 +452,19 @@ LmsApplication::handleAuthEvent(void)
});
});
// Events from Application group
_groupEvents.appOpen.connect([=] (LmsApplicationInfo info)
{
// Only one active session by user
setConfirmCloseMessage("");
quit(Wt::WString::tr("Lms.quit-other-session"));
});
_groupEvents.appClosed.connect([=] (LmsApplicationInfo info)
{
;
});
internalPathChanged().connect(std::bind([=]
{
handlePathChange(mainStack, _isAdmin);
@@ -449,6 +494,7 @@ LmsApplication::notifyMsg(const Wt::WString& message)
root()->addNew<Wt::WText>(message);
}
} // namespace UserInterface
+26 -6
View File
@@ -30,6 +30,7 @@
#include "database/Cluster.hpp"
#include "database/Release.hpp"
#include "LmsApplicationGroup.hpp"
#include "Auth.hpp"
namespace UserInterface {
@@ -37,13 +38,20 @@ namespace UserInterface {
class TranscodeResource;
class ImageResource;
struct GroupEvents
{
Wt::Signal<LmsApplicationInfo> appOpen;
Wt::Signal<LmsApplicationInfo> appClosed;
};
class LmsApplication : public Wt::WApplication
{
public:
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, LmsApplicationGroups& appGroups, Scanner::MediaScanner& scanner);
~LmsApplication();
static std::unique_ptr<Wt::WApplication> create(const Wt::WEnvironment& env,
Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
Wt::Dbo::SqlConnectionPool& connectionPool, LmsApplicationGroups& appGroups, Scanner::MediaScanner& scanner);
static LmsApplication* instance();
// Session application data
@@ -52,11 +60,14 @@ class LmsApplication : public Wt::WApplication
Database::Handler& getDb() { return _db;}
Wt::Dbo::Session& getDboSession() { return _db.getSession();}
const Wt::Auth::User& getCurrentAuthUser() { return _db.getLogin().user(); }
Database::User::pointer getCurrentUser() { return _db.getCurrentUser(); }
const Wt::Auth::User& getAuthUser() { return _db.getLogin().user(); }
Database::User::pointer getUser() { return _db.getCurrentUser(); }
Wt::WString getUserIdentity() { return _userIdentity; }
Scanner::MediaScanner& getMediaScanner() { return _scanner; }
GroupEvents& getGroupEvents() { return _groupEvents; }
// Utils
void goHome();
void goHomeAndQuit();
@@ -68,10 +79,18 @@ class LmsApplication : public Wt::WApplication
private:
void handleAuthEvent(void);
LmsApplicationGroup& getApplicationGroup();
// Events
void handleAuthEvent();
void notify(const Wt::WEvent& event) override;
void createHome();
Database::Handler _db;
LmsApplicationGroups& _appGroups;
GroupEvents _groupEvents;
Wt::WString _userIdentity;
Auth* _auth;
Scanner::MediaScanner& _scanner;
std::shared_ptr<ImageResource> _imageResource;
@@ -79,7 +98,8 @@ class LmsApplication : public Wt::WApplication
bool _isAdmin = false;
};
// Helper to get session data
// Helper to get session instance
#define LmsApp LmsApplication::instance()
} // namespace UserInterface
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 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 "LmsApplicationGroup.hpp"
#include <algorithm>
#include <Wt/WServer.h>
#include <Wt/WApplication.h>
namespace UserInterface {
LmsApplicationInfo
LmsApplicationInfo::fromEnvironment(const Wt::WEnvironment& env)
{
LmsApplicationInfo info = {.userAgent = wApp->environment().agent()};
return info;
}
void
LmsApplicationGroup::join(LmsApplicationInfo info)
{
_apps.emplace(wApp->sessionId(), std::move(info));
}
void
LmsApplicationGroup::leave()
{
_apps.erase(wApp->sessionId());
}
std::vector<std::string>
LmsApplicationGroup::getOtherSessionIds() const
{
std::vector<std::string> res;
for (auto const& app : _apps)
{
if (app.first != wApp->sessionId())
res.push_back(app.first);
}
return res;
}
void
LmsApplicationGroup::postOthers(std::function<void()> func) const
{
for (auto const& sessionId : getOtherSessionIds())
{
Wt::WServer::instance()->post(sessionId, [=]
{
func();
wApp->triggerUpdate();
});
}
}
} // UserInterface
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2018 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 <map>
#include <Wt/WSignal.h>
#include <Wt/WEnvironment.h>
namespace UserInterface {
struct LmsApplicationInfo
{
Wt::UserAgent userAgent;
static LmsApplicationInfo fromEnvironment(const Wt::WEnvironment& env);
};
// LmsApplication instances are grouped by User
class LmsApplicationGroup
{
public:
void join(LmsApplicationInfo info);
void leave();
std::vector<LmsApplicationInfo> list() const;
void postOthers(std::function<void()> func) const;
private:
std::vector<std::string> getOtherSessionIds() const;
std::map<std::string, LmsApplicationInfo> _apps;
};
using LmsApplicationGroups = std::map<Wt::WString, LmsApplicationGroup>;
} // UserInterface
+12 -12
View File
@@ -58,11 +58,11 @@ PlayQueue::PlayQueue()
{
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
if (!playlist)
playlist = Database::Playlist::create(LmsApp->getDboSession(), currentPlayQueueName, false, LmsApp->getCurrentUser());
playlist = Database::Playlist::create(LmsApp->getDboSession(), currentPlayQueueName, false, LmsApp->getUser());
_trackPos = LmsApp->getCurrentUser()->getCurPlayingTrackPos();
_trackPos = LmsApp->getUser()->getCurPlayingTrackPos();
}
clearBtn->clicked().connect(std::bind([=]
@@ -70,7 +70,7 @@ PlayQueue::PlayQueue()
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
playlist.modify()->clear();
_showMore->setHidden(true);
}
@@ -84,7 +84,7 @@ PlayQueue::PlayQueue()
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
playlist.modify()->shuffle();
}
_entriesContainer->clear();
@@ -117,7 +117,7 @@ PlayQueue::play(std::size_t pos)
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
// If out of range, stop playing
if (pos >= playlist->getCount())
@@ -135,7 +135,7 @@ PlayQueue::play(std::size_t pos)
trackId = track.id();
auto stats = Database::TrackStats::get(LmsApp->getDboSession(), track, LmsApp->getCurrentUser());
auto stats = Database::TrackStats::get(LmsApp->getDboSession(), track, LmsApp->getUser());
stats.modify()->incPlayCount();
stats.modify()->setLastPlayed(Wt::WLocalDateTime::currentServerDateTime().toUTC());
@@ -175,7 +175,7 @@ PlayQueue::updateInfo()
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
_nbTracks->setText(Wt::WString::tr("Lms.PlayQueue.nb-tracks").arg(static_cast<unsigned>(playlist->getCount())));
}
@@ -201,7 +201,7 @@ 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 = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
for (auto track : tracks)
Database::PlaylistEntry::create(LmsApp->getDboSession(), track, playlist);
@@ -228,7 +228,7 @@ PlayQueue::playTracks(const std::vector<Database::Track::pointer>& tracks)
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playqueue = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playqueue = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
playqueue.modify()->clear();
_entriesContainer->clear();
@@ -245,7 +245,7 @@ PlayQueue::addSome()
{
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
bool moreResults;
auto playlistEntries = playlist->getEntries(_entriesContainer->count(), 50, moreResults);
@@ -313,7 +313,7 @@ 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 = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getUser());
std::set<Database::IdType> playlistTrackIds;
{
+7 -8
View File
@@ -68,11 +68,11 @@ class SettingsModel : public Wt::WFormModel
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto bitrate = getBitrateRow(LmsApp->getCurrentUser()->getAudioBitrate());
auto bitrate = getBitrateRow(LmsApp->getUser()->getAudioBitrate());
if (bitrate)
setValue(BitrateField, bitrateString(*bitrate));
auto encodingRow = getEncodingRow(LmsApp->getCurrentUser()->getAudioEncoding());
auto encodingRow = getEncodingRow(LmsApp->getUser()->getAudioEncoding());
if (encodingRow)
setValue(EncodingField, encodingString(*encodingRow));
@@ -84,14 +84,14 @@ class SettingsModel : public Wt::WFormModel
auto bitrateRow = getBitrateRow(Wt::asString(value(BitrateField)));
assert(bitrateRow);
LmsApp->getCurrentUser().modify()->setAudioBitrate(bitrate(*bitrateRow));
LmsApp->getUser().modify()->setAudioBitrate(bitrate(*bitrateRow));
auto encodingRow = getEncodingRow(Wt::asString(value(EncodingField)));
LmsApp->getCurrentUser().modify()->setAudioEncoding(encoding(*encodingRow));
LmsApp->getUser().modify()->setAudioEncoding(encoding(*encodingRow));
if (!valueText(PasswordField).empty())
{
Database::Handler::getPasswordService().updatePassword(LmsApp->getCurrentAuthUser(), valueText(PasswordField));
Database::Handler::getPasswordService().updatePassword(LmsApp->getAuthUser(), valueText(PasswordField));
}
}
@@ -104,8 +104,7 @@ class SettingsModel : public Wt::WFormModel
if (!valueText(PasswordField).empty())
{
// Evaluate the strength of the password
auto res = Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField),
LmsApp->getCurrentAuthUser().identity(Wt::Auth::Identity::LoginName), "");
auto res = Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField), LmsApp->getUserIdentity(), "");
if (!res.isValid())
error = res.message();
@@ -209,7 +208,7 @@ class SettingsModel : public Wt::WFormModel
std::size_t maxAudioBitrate;
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
maxAudioBitrate = LmsApp->getCurrentUser()->getMaxAudioBitrate();
maxAudioBitrate = LmsApp->getUser()->getMaxAudioBitrate();
}
std::size_t id = 0;
+1 -1
View File
@@ -78,7 +78,7 @@ class UserModel : public Wt::WFormModel
Wt::Auth::User authUser = LmsApp->getDb().getUserDatabase().findWithId( std::to_string(*_userId) );
Database::User::pointer user = LmsApp->getDb().getUser(authUser);
if (user == LmsApp->getCurrentUser())
if (user == LmsApp->getUser())
throw std::runtime_error("Cannot edit ourselves");
auto bitrate = getBitrateLimitRow(user->getMaxAudioBitrate());
+1 -1
View File
@@ -75,7 +75,7 @@ UsersView::refreshView()
entry->bindString("name", authUser.identity(Wt::Auth::Identity::LoginName), Wt::TextFormat::Plain);
// Don't edit ourself this way
if (LmsApp->getCurrentUser() == user)
if (LmsApp->getUser() == user)
continue;
entry->setCondition("if-edit", true);
+2 -2
View File
@@ -101,7 +101,7 @@ void
Artists::refreshRecentlyPlayed()
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto artists = TrackStats::getLastPlayedArtists(LmsApp->getDboSession(), LmsApp->getCurrentUser(), 5);
auto artists = TrackStats::getLastPlayedArtists(LmsApp->getDboSession(), LmsApp->getUser(), 5);
_recentlyPlayedContainer->clear();
addCompactEntries(_recentlyPlayedContainer, artists);
@@ -112,7 +112,7 @@ void
Artists::refreshMostPlayed()
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto artists = TrackStats::getMostPlayedArtists(LmsApp->getDboSession(), LmsApp->getCurrentUser(), 5);
auto artists = TrackStats::getMostPlayedArtists(LmsApp->getDboSession(), LmsApp->getUser(), 5);
_mostPlayedContainer->clear();
addCompactEntries(_mostPlayedContainer, artists);
+2 -2
View File
@@ -125,7 +125,7 @@ Releases::refreshRecentlyPlayed()
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto releases = TrackStats::getLastPlayedReleases(LmsApp->getDboSession(), LmsApp->getCurrentUser(), 5);
auto releases = TrackStats::getLastPlayedReleases(LmsApp->getDboSession(), LmsApp->getUser(), 5);
_recentlyPlayedContainer->clear();
addCompactEntries(_recentlyPlayedContainer, releases);
@@ -138,7 +138,7 @@ Releases::refreshMostPlayed()
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto releases = TrackStats::getMostPlayedReleases(LmsApp->getDboSession(), LmsApp->getCurrentUser(), 5);
auto releases = TrackStats::getMostPlayedReleases(LmsApp->getDboSession(), LmsApp->getUser(), 5);
_mostPlayedContainer->clear();
addCompactEntries(_mostPlayedContainer, releases);