[UI] Restore the playing queue when creating the session
This commit is contained in:
@@ -71,7 +71,8 @@ _isAdmin(false),
|
|||||||
_audioBitrate(defaultAudioBitrate),
|
_audioBitrate(defaultAudioBitrate),
|
||||||
_audioEncoding(AudioEncoding::AUTO),
|
_audioEncoding(AudioEncoding::AUTO),
|
||||||
_videoBitrate(defaultVideoBitrate),
|
_videoBitrate(defaultVideoBitrate),
|
||||||
_videoEncoding(VideoEncoding::AUTO)
|
_videoEncoding(VideoEncoding::AUTO),
|
||||||
|
_curPlayingTrackPos(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class User
|
|||||||
void setVideoEncoding(VideoEncoding encoding) { _videoEncoding = encoding; }
|
void setVideoEncoding(VideoEncoding encoding) { _videoEncoding = encoding; }
|
||||||
void setMaxAudioBitrate(std::size_t bitrate);
|
void setMaxAudioBitrate(std::size_t bitrate);
|
||||||
void setMaxVideoBitrate(std::size_t bitrate);
|
void setMaxVideoBitrate(std::size_t bitrate);
|
||||||
|
void setCurPlayingTrackPos(std::size_t pos) { _curPlayingTrackPos = pos; }
|
||||||
|
|
||||||
// read
|
// read
|
||||||
bool isAdmin() const {return _isAdmin;}
|
bool isAdmin() const {return _isAdmin;}
|
||||||
@@ -87,6 +88,7 @@ class User
|
|||||||
VideoEncoding getVideoEncoding() const { return _videoEncoding;}
|
VideoEncoding getVideoEncoding() const { return _videoEncoding;}
|
||||||
std::size_t getMaxAudioBitrate() const;
|
std::size_t getMaxAudioBitrate() const;
|
||||||
std::size_t getMaxVideoBitrate() const;
|
std::size_t getMaxVideoBitrate() const;
|
||||||
|
std::size_t getCurPlayingTrackPos() const { return _curPlayingTrackPos; }
|
||||||
|
|
||||||
template<class Action>
|
template<class Action>
|
||||||
void persist(Action& a)
|
void persist(Action& a)
|
||||||
@@ -98,6 +100,8 @@ class User
|
|||||||
Wt::Dbo::field(a, _audioEncoding, "audio_encoding");
|
Wt::Dbo::field(a, _audioEncoding, "audio_encoding");
|
||||||
Wt::Dbo::field(a, _videoBitrate, "video_bitrate");
|
Wt::Dbo::field(a, _videoBitrate, "video_bitrate");
|
||||||
Wt::Dbo::field(a, _videoEncoding, "video_encoding");
|
Wt::Dbo::field(a, _videoEncoding, "video_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, _playlists, Wt::Dbo::ManyToOne, "user");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +124,9 @@ class User
|
|||||||
int _videoBitrate;
|
int _videoBitrate;
|
||||||
VideoEncoding _videoEncoding;
|
VideoEncoding _videoEncoding;
|
||||||
|
|
||||||
|
// 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<Playlist> > _playlists;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ void WPopupMenuClear(Wt::WPopupMenu* menu)
|
|||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
namespace Desktop {
|
namespace Desktop {
|
||||||
|
|
||||||
|
// Special playlist generated each time the playque gets changed
|
||||||
|
// Restored at the beginning of the session
|
||||||
|
static const std::string CurrentQueuePlaylistName = "__current__";
|
||||||
|
|
||||||
Audio::Audio(SessionData& sessionData, Wt::WContainerWidget* parent)
|
Audio::Audio(SessionData& sessionData, Wt::WContainerWidget* parent)
|
||||||
: UserInterface::Audio(parent),
|
: UserInterface::Audio(parent),
|
||||||
_db(sessionData.getDatabaseHandler()),
|
_db(sessionData.getDatabaseHandler()),
|
||||||
@@ -180,6 +184,11 @@ _playQueue(nullptr)
|
|||||||
playQueueLayout->addLayout(playlistControls);
|
playQueueLayout->addLayout(playlistControls);
|
||||||
|
|
||||||
mainLayout->addWidget(playQueueContainer, 0, 0, 2, 1);
|
mainLayout->addWidget(playQueueContainer, 0, 0, 2, 1);
|
||||||
|
|
||||||
|
// Load the last known queue
|
||||||
|
playlistLoadToPlayqueue(CurrentQueuePlaylistName);
|
||||||
|
// Select the last known playing track
|
||||||
|
_playQueue->select(user->getCurPlayingTrackPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLayout->setRowStretch(1, 1);
|
mainLayout->setRowStretch(1, 1);
|
||||||
@@ -212,6 +221,13 @@ _playQueue(nullptr)
|
|||||||
_mediaPlayer->shuffle().connect(boost::bind(&PlayQueue::setShuffle, _playQueue, _1));
|
_mediaPlayer->shuffle().connect(boost::bind(&PlayQueue::setShuffle, _playQueue, _1));
|
||||||
_mediaPlayer->loop().connect(boost::bind(&PlayQueue::setLoop,_playQueue, _1));
|
_mediaPlayer->loop().connect(boost::bind(&PlayQueue::setLoop,_playQueue, _1));
|
||||||
|
|
||||||
|
_playQueue->tracksUpdated().connect(std::bind([=] () {
|
||||||
|
LMS_LOG(MOD_UI, SEV_INFO) << "Playqueue updated!";
|
||||||
|
|
||||||
|
playlistSaveFromPlayqueue(CurrentQueuePlaylistName);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
playlistRefreshMenus();
|
playlistRefreshMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,17 +353,21 @@ Audio::playlistLoadToPlayqueue(std::string playlistName)
|
|||||||
{
|
{
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Loading playlist '" << playlistName << "' to playqueue";
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "Loading playlist '" << playlistName << "' to playqueue";
|
||||||
|
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
std::vector<Database::Track::id_type> entries;
|
||||||
|
|
||||||
Database::User::pointer user = _db.getCurrentUser();
|
{
|
||||||
if (!user)
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
return;
|
|
||||||
|
|
||||||
Database::Playlist::pointer playlist = Database::Playlist::get(_db.getSession(), playlistName, user);
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
if (!playlist)
|
if (!user)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<Database::Track::id_type> entries = Database::PlaylistEntry::getEntries(_db.getSession(), playlist);
|
Database::Playlist::pointer playlist = Database::Playlist::get(_db.getSession(), playlistName, user);
|
||||||
|
if (!playlist)
|
||||||
|
return;
|
||||||
|
|
||||||
|
entries = Database::PlaylistEntry::getEntries(_db.getSession(), playlist);
|
||||||
|
}
|
||||||
|
|
||||||
_playQueue->clear();
|
_playQueue->clear();
|
||||||
_playQueue->addTracks(entries);
|
_playQueue->addTracks(entries);
|
||||||
@@ -414,6 +434,9 @@ Audio::playlistRefreshMenus()
|
|||||||
|
|
||||||
BOOST_FOREACH(Database::Playlist::pointer playlist, playlists)
|
BOOST_FOREACH(Database::Playlist::pointer playlist, playlists)
|
||||||
{
|
{
|
||||||
|
if (playlist->getName() == CurrentQueuePlaylistName)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Add playlists in each menu
|
// Add playlists in each menu
|
||||||
_popupMenuDelete->addItem(playlist->getName())->triggered().connect(std::bind([=] ()
|
_popupMenuDelete->addItem(playlist->getName())->triggered().connect(std::bind([=] ()
|
||||||
{
|
{
|
||||||
@@ -496,7 +519,7 @@ Audio::playSelectedTracks(PlayQueueAddType addType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Audio::playTrack(boost::filesystem::path p)
|
Audio::playTrack(boost::filesystem::path p, int pos)
|
||||||
{
|
{
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "play track '" << p << "'";
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "play track '" << p << "'";
|
||||||
try {
|
try {
|
||||||
@@ -508,7 +531,10 @@ Audio::playTrack(boost::filesystem::path p)
|
|||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
Database::User::pointer user = _db.getCurrentUser();
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
if (user)
|
if (user)
|
||||||
|
{
|
||||||
bitrate = user->getAudioBitrate();
|
bitrate = user->getAudioBitrate();
|
||||||
|
user.modify()->setCurPlayingTrackPos(pos);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LMS_LOG(MOD_UI, SEV_ERROR) << "Can't play: user does not exists!";
|
LMS_LOG(MOD_UI, SEV_ERROR) << "Can't play: user does not exists!";
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class Audio : public UserInterface::Audio
|
|||||||
void playlistShowDeleteDialog(std::string name);
|
void playlistShowDeleteDialog(std::string name);
|
||||||
void playlistRefreshMenus();
|
void playlistRefreshMenus();
|
||||||
|
|
||||||
void playTrack(boost::filesystem::path p);
|
void playTrack(boost::filesystem::path p, int pos);
|
||||||
|
|
||||||
enum PlayQueueAddType
|
enum PlayQueueAddType
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -357,14 +357,25 @@ PlayQueue::play(int rowId)
|
|||||||
playNext();
|
playNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PlayQueue::select(int rowId)
|
||||||
|
{
|
||||||
|
// Update the track selector to use the requested track as current position
|
||||||
|
_trackSelector->setPosByRowId(rowId);
|
||||||
|
|
||||||
|
Wt::WTableView::select(_model->index(_trackSelector->getCurrent(), 0));
|
||||||
|
|
||||||
|
this->scrollTo( _model->index(_trackSelector->getCurrent(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
|
PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
|
||||||
{
|
{
|
||||||
// Add tracks to model
|
// Add tracks to model
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
//
|
||||||
|
|
||||||
BOOST_FOREACH(Database::Track::id_type trackId, trackIds)
|
BOOST_FOREACH(Database::Track::id_type trackId, trackIds)
|
||||||
{
|
{
|
||||||
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
Database::Track::pointer track (Database::Track::getById(_db.getSession(), trackId));
|
Database::Track::pointer track (Database::Track::getById(_db.getSession(), trackId));
|
||||||
|
|
||||||
if (track)
|
if (track)
|
||||||
@@ -391,6 +402,8 @@ PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_trackSelector->setSize( _model->rowCount() );
|
_trackSelector->setSize( _model->rowCount() );
|
||||||
|
|
||||||
|
_sigTracksUpdated.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -401,6 +414,8 @@ PlayQueue::clear(void)
|
|||||||
// Reset play id
|
// Reset play id
|
||||||
_curPlayedTrackPos = trackPosInvalid;
|
_curPlayedTrackPos = trackPosInvalid;
|
||||||
_trackSelector->setSize( 0 );
|
_trackSelector->setSize( 0 );
|
||||||
|
|
||||||
|
_sigTracksUpdated.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -458,7 +473,7 @@ PlayQueue::readTrack(int rowPos)
|
|||||||
{
|
{
|
||||||
setPlayingTrackPos(rowPos);
|
setPlayingTrackPos(rowPos);
|
||||||
|
|
||||||
_sigTrackPlay.emit(track->getPath());
|
_sigTrackPlay.emit(track->getPath(), rowPos);
|
||||||
|
|
||||||
this->scrollTo( _model->index(_trackSelector->getCurrent(), 0));
|
this->scrollTo( _model->index(_trackSelector->getCurrent(), 0));
|
||||||
|
|
||||||
@@ -504,6 +519,7 @@ PlayQueue::delSelected(void)
|
|||||||
_trackSelector->setSize(_model->rowCount());
|
_trackSelector->setSize(_model->rowCount());
|
||||||
|
|
||||||
renumber(minId, _model->rowCount() - 1);
|
renumber(minId, _model->rowCount() - 1);
|
||||||
|
_sigTracksUpdated.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -511,6 +527,7 @@ PlayQueue::delAll(void)
|
|||||||
{
|
{
|
||||||
_model->removeRows(0, _model->rowCount());
|
_model->removeRows(0, _model->rowCount());
|
||||||
_trackSelector->setSize(0);
|
_trackSelector->setSize(0);
|
||||||
|
_sigTracksUpdated.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -551,6 +568,8 @@ PlayQueue::moveSelectedUp(void)
|
|||||||
this->setSelectedIndexes( newIndexSet );
|
this->setSelectedIndexes( newIndexSet );
|
||||||
|
|
||||||
renumber(minId, maxId);
|
renumber(minId, maxId);
|
||||||
|
|
||||||
|
_sigTracksUpdated.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -592,6 +611,8 @@ PlayQueue::moveSelectedDown(void)
|
|||||||
this->setSelectedIndexes( newIndexSet );
|
this->setSelectedIndexes( newIndexSet );
|
||||||
|
|
||||||
renumber(minId, maxId);
|
renumber(minId, maxId);
|
||||||
|
|
||||||
|
_sigTracksUpdated.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class PlayQueue : public Wt::WTableView
|
|||||||
// Play functions
|
// Play functions
|
||||||
void play(void); // Play the queue from the beginning
|
void play(void); // Play the queue from the beginning
|
||||||
void play(int rowId); // Play the queue from the given rowId
|
void play(int rowId); // Play the queue from the given rowId
|
||||||
|
void select(int rowId); // Select the given rowId
|
||||||
void playNext(void); // Play the next track
|
void playNext(void); // Play the next track
|
||||||
void playPrevious(void); // Play the previous track
|
void playPrevious(void); // Play the previous track
|
||||||
|
|
||||||
@@ -59,7 +60,10 @@ class PlayQueue : public Wt::WTableView
|
|||||||
void moveSelectedDown(void);
|
void moveSelectedDown(void);
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
Wt::Signal< boost::filesystem::path >& playTrack() { return _sigTrackPlay; }
|
// Emitted when a song has to be played
|
||||||
|
Wt::Signal< boost::filesystem::path, int >& playTrack() { return _sigTrackPlay; }
|
||||||
|
// Emitted when the list has changed
|
||||||
|
Wt::Signal< void >& tracksUpdated() { return _sigTracksUpdated; }
|
||||||
|
|
||||||
// Slots
|
// Slots
|
||||||
void handlePlaybackComplete(void);
|
void handlePlaybackComplete(void);
|
||||||
@@ -72,7 +76,8 @@ class PlayQueue : public Wt::WTableView
|
|||||||
void setPlayingTrackPos(int newRowPos);
|
void setPlayingTrackPos(int newRowPos);
|
||||||
void renumber(int firstId, int lastId);
|
void renumber(int firstId, int lastId);
|
||||||
|
|
||||||
Wt::Signal< boost::filesystem::path > _sigTrackPlay;
|
Wt::Signal< boost::filesystem::path, int > _sigTrackPlay;
|
||||||
|
Wt::Signal< void > _sigTracksUpdated;
|
||||||
|
|
||||||
Database::Handler& _db;
|
Database::Handler& _db;
|
||||||
|
|
||||||
|
|||||||
@@ -59,12 +59,17 @@ _sessionData(sessionData)
|
|||||||
hLayout->addWidget(menu);
|
hLayout->addWidget(menu);
|
||||||
hLayout->addWidget(contents, 1);
|
hLayout->addWidget(contents, 1);
|
||||||
|
|
||||||
Wt::Dbo::Transaction transaction( sessionData.getDatabaseHandler().getSession());
|
std::string userId;
|
||||||
|
bool userIsAdmin;
|
||||||
::Database::User::pointer user = sessionData.getDatabaseHandler().getCurrentUser();
|
{
|
||||||
|
Wt::Dbo::Transaction transaction( sessionData.getDatabaseHandler().getSession());
|
||||||
|
::Database::User::pointer user = sessionData.getDatabaseHandler().getCurrentUser();
|
||||||
|
userId = Database::User::getId(user);
|
||||||
|
userIsAdmin = user->isAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
menu->addItem("Audio", new AudioFormView(sessionData));
|
menu->addItem("Audio", new AudioFormView(sessionData));
|
||||||
if (user->isAdmin())
|
if (userIsAdmin)
|
||||||
{
|
{
|
||||||
MediaDirectories* mediaDirectory = new MediaDirectories(sessionData);
|
MediaDirectories* mediaDirectory = new MediaDirectories(sessionData);
|
||||||
mediaDirectory->changed().connect(this, &Settings::handleDatabaseDirectoriesChanged);
|
mediaDirectory->changed().connect(this, &Settings::handleDatabaseDirectoriesChanged);
|
||||||
@@ -78,7 +83,7 @@ _sessionData(sessionData)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
menu->addItem("Account", new AccountFormView(sessionData, Database::User::getId(user)));
|
menu->addItem("Account", new AccountFormView(sessionData, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user