Added some logic in the playqueue (play next / play previous handling)
This commit is contained in:
@@ -340,6 +340,23 @@ LmsApplication::handleAuthEvent(void)
|
||||
auto player = new MediaPlayer();
|
||||
main->bindWidget("player", player);
|
||||
|
||||
// Events from MediaPlayer
|
||||
player->playNext.connect(std::bind([=]
|
||||
{
|
||||
playqueue->playNext();
|
||||
}));
|
||||
player->playPrevious.connect(std::bind([=]
|
||||
{
|
||||
playqueue->playPrevious();
|
||||
}));
|
||||
player->playbackEnded.connect(std::bind([=]
|
||||
{
|
||||
playqueue->playNext();
|
||||
}));
|
||||
|
||||
// Events from the PlayQueue
|
||||
playqueue->playTrack.connect(player, &MediaPlayer::playTrack);
|
||||
|
||||
// Events from MediaScanner
|
||||
if (CurrentUser()->isAdmin())
|
||||
{
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <Wt/WTemplate>
|
||||
#include <Wt/WText>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
|
||||
#include "MediaPlayer.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
@@ -35,9 +37,17 @@ MediaPlayer::MediaPlayer(Wt::WContainerWidget* parent)
|
||||
|
||||
auto prevBtn = new Wt::WText(Wt::WString::tr("btn-mediaplayer-prev"), Wt::XHTMLText);
|
||||
player->bindWidget("previous", prevBtn);
|
||||
prevBtn->clicked().connect(std::bind([=]
|
||||
{
|
||||
playPrevious.emit();
|
||||
}));
|
||||
|
||||
auto nextBtn = new Wt::WText(Wt::WString::tr("btn-mediaplayer-next"), Wt::XHTMLText);
|
||||
player->bindWidget("next", nextBtn);
|
||||
nextBtn->clicked().connect(std::bind([=]
|
||||
{
|
||||
playNext.emit();
|
||||
}));
|
||||
|
||||
auto shuffleBtn = new Wt::WText(Wt::WString::tr("btn-mediaplayer-shuffle"), Wt::XHTMLText);
|
||||
player->bindWidget("shuffle", shuffleBtn);
|
||||
@@ -53,7 +63,12 @@ MediaPlayer::MediaPlayer(Wt::WContainerWidget* parent)
|
||||
|
||||
auto trackName = new Wt::WText("---");
|
||||
player->bindWidget("track-name", trackName);
|
||||
}
|
||||
|
||||
void
|
||||
MediaPlayer::playTrack(Database::Track::id_type id)
|
||||
{
|
||||
LMS_LOG(UI, DEBUG) << "Playing track ID = " << id;
|
||||
}
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
@@ -19,14 +19,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Wt/WSignal>
|
||||
#include <Wt/WContainerWidget>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
class MediaPlayer : public Wt::WContainerWidget
|
||||
{
|
||||
public:
|
||||
MediaPlayer(Wt::WContainerWidget* parent = 0);
|
||||
|
||||
void playTrack(Database::Track::id_type);
|
||||
|
||||
// Signals
|
||||
Wt::Signal<void> playbackEnded;
|
||||
Wt::Signal<void> playPrevious;
|
||||
Wt::Signal<void> playNext;
|
||||
|
||||
};
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
@@ -75,6 +75,8 @@ PlayQueue::PlayQueue(Wt::WContainerWidget* parent)
|
||||
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
|
||||
if (!playlist)
|
||||
playlist = Database::Playlist::create(DboSession(), currentPlayQueueName, false, CurrentUser());
|
||||
|
||||
_trackPos = CurrentUser()->getCurPlayingTrackPos();
|
||||
}
|
||||
|
||||
_showMore->clicked().connect(std::bind([=]
|
||||
@@ -86,6 +88,63 @@ PlayQueue::PlayQueue(Wt::WContainerWidget* parent)
|
||||
addSome();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::stop()
|
||||
{
|
||||
updateCurrentTrack(false);
|
||||
_trackPos.reset();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::play(std::size_t pos)
|
||||
{
|
||||
updateCurrentTrack(false);
|
||||
|
||||
Database::Track::id_type trackId;
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(DboSession());
|
||||
|
||||
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
|
||||
|
||||
// If out of range, stop playing
|
||||
if (pos >= playlist->getCount())
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
_trackPos = pos;
|
||||
trackId = playlist->getEntry(*_trackPos)->getTrack().id();
|
||||
updateCurrentTrack(true);
|
||||
}
|
||||
|
||||
playTrack.emit(trackId);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playPrevious()
|
||||
{
|
||||
if (!_trackPos)
|
||||
return;
|
||||
|
||||
if (*_trackPos == 0)
|
||||
stop();
|
||||
else
|
||||
play(*_trackPos - 1);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::playNext()
|
||||
{
|
||||
if (!_trackPos)
|
||||
{
|
||||
play(0);
|
||||
return;
|
||||
}
|
||||
|
||||
play(*_trackPos + 1);
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::updateInfo()
|
||||
{
|
||||
@@ -95,6 +154,22 @@ PlayQueue::updateInfo()
|
||||
_nbTracks->setText(Wt::WString::tr("Lms.PlayQueue.nb-tracks").arg(playlist->getCount()));
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::updateCurrentTrack(bool selected)
|
||||
{
|
||||
if (!_trackPos || *_trackPos >= static_cast<std::size_t>(_entriesContainer->count()))
|
||||
return;
|
||||
|
||||
auto track = _entriesContainer->widget(*_trackPos);
|
||||
if (track)
|
||||
{
|
||||
if (selected)
|
||||
track->addStyleClass("Lms-playqueue-selected");
|
||||
else
|
||||
track->removeStyleClass("Lms-playqueue-selected");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::addTracks(const std::vector<Database::Track::pointer>& tracks)
|
||||
{
|
||||
@@ -169,7 +244,12 @@ PlayQueue::addSome()
|
||||
|
||||
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.play"), Wt::XHTMLText);
|
||||
entry->bindWidget("play-btn", playBtn);
|
||||
// TODO
|
||||
playBtn->clicked().connect(std::bind([=]
|
||||
{
|
||||
auto pos = _entriesContainer->indexOf(entry);
|
||||
if (pos >= 0)
|
||||
play(pos);
|
||||
}));
|
||||
|
||||
auto delBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.delete"), Wt::XHTMLText);
|
||||
entry->bindWidget("del-btn", delBtn);
|
||||
@@ -183,6 +263,13 @@ PlayQueue::addSome()
|
||||
entryToRemove.remove();
|
||||
}
|
||||
|
||||
if (_trackPos)
|
||||
{
|
||||
auto pos = _entriesContainer->indexOf(entry);
|
||||
if (pos > 0 && *_trackPos >= static_cast<std::size_t>(pos))
|
||||
(*_trackPos)--;
|
||||
}
|
||||
|
||||
_entriesContainer->removeWidget(entry);
|
||||
|
||||
updateInfo();
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Wt/WContainerWidget>
|
||||
#include <Wt/WSignal>
|
||||
#include <Wt/WTemplate>
|
||||
#include <Wt/WText>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
@@ -35,13 +38,27 @@ class PlayQueue : public Wt::WContainerWidget
|
||||
void addTracks(const std::vector<Database::Track::pointer>& tracks);
|
||||
void playTracks(const std::vector<Database::Track::pointer>& tracks);
|
||||
|
||||
// play the next track in the queue
|
||||
void playNext();
|
||||
|
||||
// play the previous track in the queue
|
||||
void playPrevious();
|
||||
|
||||
// Signal emitted when a track is to be played
|
||||
Wt::Signal<Database::Track::id_type> playTrack;
|
||||
|
||||
private:
|
||||
void addSome();
|
||||
void updateInfo();
|
||||
void updateCurrentTrack(bool selected);
|
||||
|
||||
void play(std::size_t pos);
|
||||
void stop();
|
||||
|
||||
Wt::WContainerWidget* _entriesContainer;
|
||||
Wt::WTemplate* _showMore;
|
||||
Wt::WText* _nbTracks;
|
||||
boost::optional<std::size_t> _trackPos; // current track position, if set
|
||||
};
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
Reference in New Issue
Block a user