[UI] Added information on the current media being played

This commit is contained in:
emeric
2015-06-22 13:10:24 +02:00
parent 9d53d7f758
commit 794de2fda8
7 changed files with 150 additions and 136 deletions
+91 -47
View File
@@ -24,6 +24,10 @@
#include <Wt/WHBoxLayout> #include <Wt/WHBoxLayout>
#include <Wt/WVBoxLayout> #include <Wt/WVBoxLayout>
#include "logger/Logger.hpp"
#include "LmsApplication.hpp"
#include "AudioMediaPlayer.hpp" #include "AudioMediaPlayer.hpp"
namespace UserInterface { namespace UserInterface {
@@ -36,75 +40,91 @@ AudioMediaPlayer::getBestEncoding()
return Wt::WMediaPlayer::MP3; return Wt::WMediaPlayer::MP3;
} }
AudioMediaPlayer::AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent) AudioMediaPlayer::AudioMediaPlayer(Wt::WContainerWidget *parent)
: Wt::WContainerWidget(parent), : Wt::WContainerWidget(parent),
_mediaResource(nullptr), _mediaResource(nullptr)
_encoding(encoding)
{ {
this->setStyleClass("mediaplayer"); this->setStyleClass("mediaplayer");
this->setHeight(90);
Wt::WVBoxLayout* mainLayout = new Wt::WVBoxLayout(); Wt::WVBoxLayout* mainLayout = new Wt::WVBoxLayout();
this->setLayout(mainLayout); this->setLayout(mainLayout);
/* TODO add media info here // Determine the encoding to be used
{
Wt::Dbo::Transaction transaction(DboSession());
switch (CurrentUser()->getAudioEncoding())
{
case Database::AudioEncoding::MP3: _encoding = Wt::WMediaPlayer::MP3; break;
case Database::AudioEncoding::WEBMA: _encoding = Wt::WMediaPlayer::WEBMA; break;
case Database::AudioEncoding::OGA: _encoding = Wt::WMediaPlayer::OGA; break;
case Database::AudioEncoding::FLA: _encoding = Wt::WMediaPlayer::FLA; break;
case Database::AudioEncoding::AUTO:
default:
_encoding = getBestEncoding();
}
}
LMS_LOG(MOD_UI, SEV_INFO) << "Audio player using encoding " << _encoding;
// Current Media info // Current Media info
Wt::WHBoxLayout *currentMediaLayout = new Wt::WHBoxLayout(); Wt::WHBoxLayout *currentMediaLayout = new Wt::WHBoxLayout();
mainLayout->addLayout(currentMediaLayout); mainLayout->addLayout(currentMediaLayout, 1);
currentMediaLayout->addWidget( _mediaCover = new Wt::WImage()); currentMediaLayout->addWidget( _mediaCover = new Wt::WImage());
_mediaCover->setImageLink( Wt::WLink("images/unknown-cover.jpg") ); _mediaCover->setImageLink( LmsApplication::instance()->getCoverResource()->getUnkownTrackUrl(72));
_mediaCover->setStyleClass("mediaplayer-current-cover");
Wt::WVBoxLayout* mediaInfoLayout = new Wt::WVBoxLayout(); Wt::WVBoxLayout* mediaInfoLayout = new Wt::WVBoxLayout();
currentMediaLayout->addLayout(mediaInfoLayout, 1); currentMediaLayout->addLayout(mediaInfoLayout, 1);
mediaInfoLayout->addWidget( _mediaTitle = new Wt::WText()); mediaInfoLayout->addWidget( _mediaTitle = new Wt::WText("---"));
mediaInfoLayout->addWidget( _mediaArtistRelease = new Wt::WText()); mediaInfoLayout->addWidget( _mediaArtistRelease = new Wt::WText("---"));
*/ _mediaTitle->setStyleClass("mediaplayer-current-track vertical-align");
_mediaArtistRelease->setStyleClass("mediaplayer-current-artist vertical-align");
// Time control // Time control
Wt::WHBoxLayout *sliderLayout = new Wt::WHBoxLayout(); Wt::WHBoxLayout *sliderLayout = new Wt::WHBoxLayout();
mainLayout->addLayout(sliderLayout); mainLayout->addLayout(sliderLayout);
sliderLayout->addWidget(_curTime = new Wt::WText("00:00:00")); sliderLayout->addWidget(_curTime = new Wt::WText("00:00:00"));
_curTime->setLineHeight(30);
sliderLayout->addWidget(_timeSlider = new Wt::WSlider( ), 1); sliderLayout->addWidget(_timeSlider = new Wt::WSlider( ), 1);
sliderLayout->addWidget(_duration = new Wt::WText("00:00:00")); sliderLayout->addWidget(_duration = new Wt::WText("00:00:00"));
_duration->setLineHeight(30); _timeSlider->setHeight(26); // Default is too big (50)
_curTime->setStyleClass("vertical-align");
_duration->setStyleClass("vertical-align");
// Controls // Controls
Wt::WHBoxLayout *controlsLayout = new Wt::WHBoxLayout(); Wt::WHBoxLayout *controlsLayout = new Wt::WHBoxLayout();
mainLayout->addLayout(controlsLayout); mainLayout->addLayout(controlsLayout);
Wt::WContainerWidget *btnContainer = new Wt::WContainerWidget();
// Do not allow button to wrap
btnContainer->setMinimumSize(155, Wt::WLength::Auto);
Wt::WTemplate *t = new Wt::WTemplate(Wt::WString::tr("mediaplayer-controls"), btnContainer);
Wt::WPushButton *prevBtn = new Wt::WPushButton("<<"); Wt::WPushButton *prevBtn = new Wt::WPushButton("<<");
t->bindWidget("prev", prevBtn); controlsLayout->addWidget(prevBtn);
prevBtn->setStyleClass("mediaplayer-controls"); prevBtn->setStyleClass("mediaplayer-btn-controls");
Wt::WContainerWidget *btnContainer = new Wt::WContainerWidget();;
_playBtn = new Wt::WPushButton("Play"); _playBtn = new Wt::WPushButton("Play");
t->bindWidget("play", _playBtn); btnContainer->addWidget(_playBtn);
_playBtn->setWidth(70); _playBtn->setWidth(70);
_playBtn->setStyleClass("mediaplayer-controls"); _playBtn->setStyleClass("mediaplayer-btn-controls");
_pauseBtn = new Wt::WPushButton("Pause"); _pauseBtn = new Wt::WPushButton("Pause");
t->bindWidget("pause", _pauseBtn); btnContainer->addWidget(_pauseBtn);
_pauseBtn->setWidth(70); _pauseBtn->setWidth(70);
_pauseBtn->setStyleClass("mediaplayer-controls"); _pauseBtn->setStyleClass("mediaplayer-btn-controls");
Wt::WPushButton *nextBtn = new Wt::WPushButton(">>");
t->bindWidget("next", nextBtn);
nextBtn->setStyleClass("mediaplayer-controls");
controlsLayout->addWidget(btnContainer); controlsLayout->addWidget(btnContainer);
Wt::WPushButton *nextBtn = new Wt::WPushButton(">>");
controlsLayout->addWidget(nextBtn);
nextBtn->setStyleClass("mediaplayer-btn-controls");
_volumeSlider = new Wt::WSlider(); _volumeSlider = new Wt::WSlider();
_volumeSlider->setRange(0,100); _volumeSlider->setRange(0,100);
_volumeSlider->setWidth(60); _volumeSlider->setWidth(60); // Default is too big (150)
_volumeSlider->setMinimumSize(60, Wt::WLength::Auto); _volumeSlider->setHeight(26); // Default is too big (50)
_volumeSlider->setMinimumSize(50, Wt::WLength::Auto);
controlsLayout->addWidget(_volumeSlider, 1); controlsLayout->addWidget(_volumeSlider, 1);
Wt::WPushButton *loop = new Wt::WPushButton("Loop"); Wt::WPushButton *loop = new Wt::WPushButton("Loop");
@@ -149,10 +169,8 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WCo
_volumeSlider->sliderMoved().connect(this, &AudioMediaPlayer::handleVolumeSliderMoved); _volumeSlider->sliderMoved().connect(this, &AudioMediaPlayer::handleVolumeSliderMoved);
} }
void void
AudioMediaPlayer::loadPlayer(void) AudioMediaPlayer::loadPlayer(void)
{ {
@@ -168,19 +186,57 @@ AudioMediaPlayer::loadPlayer(void)
} }
void void
AudioMediaPlayer::load(const Transcode::Parameters& parameters) AudioMediaPlayer::load(Database::Track::id_type trackId)
{ {
std::size_t bitrate = 0;
boost::filesystem::path trackPath;
{
Wt::Dbo::Transaction transaction(DboSession());
Database::Track::pointer track = Database::Track::getById(DboSession(), trackId);
bitrate = CurrentUser()->getAudioBitrate();
trackPath = track->getPath();
_mediaTitle->setText ( Wt::WString::fromUTF8(track->getName()) );
_mediaArtistRelease->setText ( Wt::WString::fromUTF8(track->getArtistName()) + " - " + Wt::WString::fromUTF8(track->getReleaseName()) );
_mediaCover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 72)));
}
Transcode::Format::Encoding encoding;
switch (_encoding)
{
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
case Wt::WMediaPlayer::FLA: encoding = Transcode::Format::FLA; break;
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
case Wt::WMediaPlayer::WEBMA: encoding = Transcode::Format::WEBMA; break;
default:
encoding = Transcode::Format::MP3;
}
_timeSlider->setDisabled(false); _timeSlider->setDisabled(false);
_currentParameters = std::make_shared<Transcode::Parameters>( parameters ); try
{
Transcode::Parameters parameters(trackPath, Transcode::Format::get(encoding));
parameters.setBitrate(Transcode::Stream::Audio, bitrate);
_currentParameters = std::make_shared<Transcode::Parameters>( parameters );
}
catch(std::exception &e)
{
LMS_LOG(MOD_UI, SEV_ERROR) << "Cannot load input file '" << trackPath << "'";
return;
}
loadPlayer(); loadPlayer();
_timeSlider->setRange(0, parameters.getInputMediaFile().getDuration().total_seconds() ); _timeSlider->setRange(0, _currentParameters->getInputMediaFile().getDuration().total_seconds() );
_timeSlider->setValue(0); _timeSlider->setValue(0);
_duration->setText( boost::posix_time::to_simple_string( parameters.getInputMediaFile().getDuration() )); _duration->setText( boost::posix_time::to_simple_string( _currentParameters->getInputMediaFile().getDuration() ));
// Auto play
_mediaPlayer->play(); _mediaPlayer->play();
} }
@@ -203,18 +259,6 @@ AudioMediaPlayer::handleTrackEnded(void)
_playbackEnded.emit(); _playbackEnded.emit();
} }
void
AudioMediaPlayer::handleValueChanged(double value)
{
// TODO
}
void
AudioMediaPlayer::handleSliderMoved(int value)
{
;
}
void void
AudioMediaPlayer::handleTimeUpdated(void) AudioMediaPlayer::handleTimeUpdated(void)
{ {
+5 -2
View File
@@ -29,6 +29,8 @@
#include <Wt/WText> #include <Wt/WText>
#include <Wt/WImage> #include <Wt/WImage>
#include "database/Types.hpp"
#include "transcode/Parameters.hpp" #include "transcode/Parameters.hpp"
#include "resource/AvConvTranscodeStreamResource.hpp" #include "resource/AvConvTranscodeStreamResource.hpp"
#include "resource/CoverResource.hpp" #include "resource/CoverResource.hpp"
@@ -41,9 +43,10 @@ class AudioMediaPlayer : public Wt::WContainerWidget
public: public:
static Wt::WMediaPlayer::Encoding getBestEncoding(); static Wt::WMediaPlayer::Encoding getBestEncoding();
AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0); AudioMediaPlayer(Wt::WContainerWidget *parent = 0);
void load(const Transcode::Parameters& parameters); // Load Media to be played
void load(Database::Track::id_type trackId);
// Accessors // Accessors
Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; } Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; }
+9 -52
View File
@@ -120,21 +120,7 @@ _playQueue(nullptr)
Wt::WVBoxLayout* playQueueLayout = new Wt::WVBoxLayout(); Wt::WVBoxLayout* playQueueLayout = new Wt::WVBoxLayout();
playQueueContainer->setLayout(playQueueLayout); playQueueContainer->setLayout(playQueueLayout);
// Determine the encoding to be used _mediaPlayer = new AudioMediaPlayer();
Wt::WMediaPlayer::Encoding encoding;
switch (CurrentUser()->getAudioEncoding())
{
case Database::AudioEncoding::MP3: encoding = Wt::WMediaPlayer::MP3; break;
case Database::AudioEncoding::WEBMA: encoding = Wt::WMediaPlayer::WEBMA; break;
case Database::AudioEncoding::OGA: encoding = Wt::WMediaPlayer::OGA; break;
case Database::AudioEncoding::FLA: encoding = Wt::WMediaPlayer::FLA; break;
case Database::AudioEncoding::AUTO:
default:
encoding = AudioMediaPlayer::getBestEncoding();
}
LMS_LOG(MOD_UI, SEV_INFO) << "Audio player using encoding " << encoding;
_mediaPlayer = new AudioMediaPlayer(encoding);
playQueueLayout->addWidget(_mediaPlayer); playQueueLayout->addWidget(_mediaPlayer);
playQueueLayout->addWidget( _playQueue, 1); playQueueLayout->addWidget( _playQueue, 1);
@@ -192,7 +178,7 @@ _playQueue(nullptr)
mainLayout->setRowStretch(1, 1); mainLayout->setRowStretch(1, 1);
mainLayout->setRowResizable(0, true, Wt::WLength(250, Wt::WLength::Pixel)); mainLayout->setRowResizable(0, true, Wt::WLength(250, Wt::WLength::Pixel));
mainLayout->setColumnResizable(0, true, Wt::WLength(400, Wt::WLength::Pixel)); mainLayout->setColumnResizable(0, true);
// Double click on track // Double click on track
// Set the selected tracks to the play queue // Set the selected tracks to the play queue
@@ -499,45 +485,16 @@ Audio::playSelectedTracks(PlayQueueAddType addType)
} }
void void
Audio::playTrack(boost::filesystem::path p, int pos) Audio::playTrack(Database::Track::id_type trackId, int pos)
{ {
LMS_LOG(MOD_UI, SEV_DEBUG) << "play track '" << p << "'";
try {
std::size_t bitrate = 0;
// Get user preferences
{
Wt::Dbo::Transaction transaction(DboSession());
bitrate = CurrentUser()->getAudioBitrate();
CurrentUser().modify()->setCurPlayingTrackPos(pos);
}
Transcode::InputMediaFile inputFile(p);
// Determine the output format using the encoding of the player
Transcode::Format::Encoding encoding;
switch (_mediaPlayer->getEncoding())
{
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
case Wt::WMediaPlayer::FLA: encoding = Transcode::Format::FLA; break;
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
case Wt::WMediaPlayer::WEBMA: encoding = Transcode::Format::WEBMA; break;
default:
encoding = Transcode::Format::MP3;
}
Transcode::Parameters parameters(inputFile, Transcode::Format::get(encoding));
parameters.setBitrate(Transcode::Stream::Audio, bitrate);
_mediaPlayer->load( parameters );
}
catch( std::exception &e)
{ {
LMS_LOG(MOD_UI, SEV_ERROR) << "Caught exception while loading '" << p << "': " << e.what(); Wt::Dbo::Transaction transaction(DboSession());
// Update user current track position
CurrentUser().modify()->setCurPlayingTrackPos(pos);
} }
_mediaPlayer->load(trackId);
} }
} // namespace Desktop } // namespace Desktop
+1 -1
View File
@@ -53,7 +53,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, int pos); void playTrack(Database::Track::id_type id, int pos);
enum PlayQueueAddType enum PlayQueueAddType
{ {
+11 -22
View File
@@ -340,8 +340,7 @@ PlayQueue::play()
{ {
_trackSelector->setPos(0); _trackSelector->setPos(0);
if (!readTrack(_trackSelector->getCurrent())) readTrack(_trackSelector->getCurrent());
playNext();
} }
void void
@@ -350,8 +349,7 @@ PlayQueue::play(int rowId)
// Update the track selector to use the requested track as current position // Update the track selector to use the requested track as current position
_trackSelector->setPosByRowId(rowId); _trackSelector->setPosByRowId(rowId);
if (!readTrack(_trackSelector->getCurrent())) readTrack(_trackSelector->getCurrent());
playNext();
} }
void void
@@ -389,6 +387,7 @@ PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
else else
coverUrl = LmsApplication::instance()->getCoverResource()->getUnkownTrackUrl(64); coverUrl = LmsApplication::instance()->getCoverResource()->getUnkownTrackUrl(64);
_model->setData(dataRow, COLUMN_ID_COVER, coverUrl, Wt::DecorationRole); _model->setData(dataRow, COLUMN_ID_COVER, coverUrl, Wt::DecorationRole);
_model->setData(dataRow, COLUMN_ID_COVER, "playqueue-cover", Wt::StyleClassRole);
TrackInfo trackInfo; TrackInfo trackInfo;
trackInfo.track = Wt::WString::fromUTF8(track->getName()); trackInfo.track = Wt::WString::fromUTF8(track->getName());
@@ -432,10 +431,9 @@ PlayQueue::playNext(void)
if (pos == trackPosInvalid) if (pos == trackPosInvalid)
break; break;
if (readTrack(pos)) readTrack(pos);
break;
--nbTries; break;
} }
} }
@@ -450,34 +448,25 @@ PlayQueue::playPrevious(void)
if (pos == trackPosInvalid) if (pos == trackPosInvalid)
break; break;
if (readTrack(pos)) readTrack(pos);
break; break;
--nbTries;
} }
} }
bool bool
PlayQueue::readTrack(int rowPos) PlayQueue::readTrack(int rowPos)
{ {
Wt::Dbo::Transaction transaction(DboSession());
LMS_LOG(MOD_UI, SEV_DEBUG) << "Reading track at pos " << rowPos; LMS_LOG(MOD_UI, SEV_DEBUG) << "Reading track at pos " << rowPos;
Database::Track::id_type trackId = boost::any_cast<Database::Track::id_type>(_model->data(rowPos, COLUMN_ID_TRACK_ID, Wt::UserRole)); Database::Track::id_type trackId = boost::any_cast<Database::Track::id_type>(_model->data(rowPos, COLUMN_ID_TRACK_ID, Wt::UserRole));
Database::Track::pointer track = Database::Track::getById(DboSession(), trackId); setPlayingTrackPos(rowPos);
if (track)
{
setPlayingTrackPos(rowPos);
_sigTrackPlay.emit(track->getPath(), rowPos); _sigTrackPlay.emit(trackId, rowPos);
this->scrollTo( _model->index(_trackSelector->getCurrent(), 0)); this->scrollTo( _model->index(_trackSelector->getCurrent(), 0));
return true; return true;
}
else
return false;
} }
void void
+2 -2
View File
@@ -61,7 +61,7 @@ class PlayQueue : public Wt::WTableView
// Signals // Signals
// Emitted when a song has to be played // Emitted when a song has to be played
Wt::Signal< boost::filesystem::path, int >& playTrack() { return _sigTrackPlay; } Wt::Signal< Database::Track::id_type, int >& playTrack() { return _sigTrackPlay; }
// Emitted when the list has changed // Emitted when the list has changed
Wt::Signal< void >& tracksUpdated() { return _sigTracksUpdated; } Wt::Signal< void >& tracksUpdated() { return _sigTracksUpdated; }
@@ -76,7 +76,7 @@ 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, int > _sigTrackPlay; Wt::Signal< Database::Track::id_type, int > _sigTrackPlay;
Wt::Signal< void > _sigTracksUpdated; Wt::Signal< void > _sigTracksUpdated;
Wt::WStandardItemModel* _model; Wt::WStandardItemModel* _model;
+31 -10
View File
@@ -14,15 +14,6 @@ div.contents {
padding: 0px 12px 6px; padding: 0px 12px 6px;
} }
.playqueue {
background-color: #EEE;
border-radius: 10px;
}
.playqueue-playing {
background-color: #4A42CA;
}
.Wt-tableview .playqueue-playing { .Wt-tableview .playqueue-playing {
color: #FFF; color: #FFF;
} }
@@ -35,6 +26,15 @@ div.contents {
background-color: #4A42CA; background-color: #4A42CA;
} }
.playqueue {
background-color: #EEE;
border-radius: 10px;
}
.playqueue-playing {
background-color: #4A42CA;
}
.playqueue-track { .playqueue-track {
margin-top: 12px; margin-top: 12px;
line-height: normal; line-height: normal;
@@ -46,15 +46,36 @@ div.contents {
font-style: italic; font-style: italic;
} }
.playqueue-cover {
width: 64px;
height: 64px;
}
.mediaplayer { .mediaplayer {
background-color: #CCC; background-color: #CCC;
border-radius: 10px; border-radius: 10px;
min-width: 360px;
} }
.mediaplayer-controls { .mediaplayer-btn-controls {
font-weight: bold; font-weight: bold;
} }
.mediaplayer-current-cover {
width: 72px;
height: 72px;
border-radius: 8px;
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.5);
}
.mediaplayer-current-track {
font-weight: bold;
}
.mediaplayer-current-artist {
font-style: italic;
}
.mobile-search-title { .mobile-search-title {
font-weight: bold; font-weight: bold;
height: 32px; height: 32px;