JS implementation of the player

This commit is contained in:
emeric
2018-03-26 23:35:51 +02:00
parent 7eb250fdff
commit f272394992
6 changed files with 127 additions and 100 deletions
+26 -55
View File
@@ -16,10 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WImage>
#include <Wt/WSlider>
#include <Wt/WTemplate>
#include <Wt/WText>
#include <boost/algorithm/string/replace.hpp>
#include "av/AvInfo.hpp"
#include "utils/Logger.hpp"
@@ -33,50 +30,17 @@
namespace UserInterface {
MediaPlayer::MediaPlayer(Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent)
: Wt::WTemplate(Wt::WString::tr("template-mediaplayer"), parent),
playbackEnded(this, "playbackEnded"),
playPrevious(this, "playPrevious"),
playNext(this, "playNext")
{
_audio = new Wt::WAudio(this);
_audio->setOptions(Wt::WAudio::Autoplay);
_audio->setPreloadMode(Wt::WAudio::PreloadNone);
wApp->doJavaScript("LMS.mediaplayer.init(" + jsRef() + ")");
}
_audio->ended().connect(std::bind([=] ()
{
playbackEnded.emit();
}));
auto player = new Wt::WTemplate(Wt::WString::tr("template-mediaplayer"), this);
auto playPauseBtn = new Wt::WText(Wt::WString::tr("btn-mediaplayer-play"), Wt::XHTMLText);
player->bindWidget("play-pause", playPauseBtn);
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);
auto repeatBtn = new Wt::WText(Wt::WString::tr("btn-mediaplayer-repeat"), Wt::XHTMLText);
player->bindWidget("repeat", repeatBtn);
player->bindString("current-time", "00:00");
player->bindString("total-time", "00:00");
auto cover = new Wt::WImage();
player->bindWidget("cover", cover);
auto trackName = new Wt::WText("---");
player->bindWidget("track-name", trackName);
static std::string escape(const std::string& str)
{
return boost::replace_all_copy(str, "\"", "\\\"");
}
void
@@ -86,32 +50,39 @@ MediaPlayer::playTrack(Database::Track::id_type trackId)
Wt::Dbo::Transaction transaction(DboSession());
auto track = Database::Track::getById(DboSession(), trackId);
transaction.commit();
// Analyse track, select the best media stream
try
{
Av::MediaFile mediaFile(track->getPath());
auto streamId = mediaFile.getBestStream();
auto resource = LmsApp->getTranscodeResource()->getUrl(trackId, Av::Encoding::MP3, boost::posix_time::seconds(0));
_audio->pause();
_audio->clearSources();
_audio->addSource(LmsApp->getTranscodeResource()->getUrl(trackId, Av::Encoding::MP3, boost::posix_time::seconds(0), streamId));
_audio->setPreloadMode(Wt::WAudio::PreloadNone);
_audio->play();
std::ostringstream oss;
oss
<< "var params = {"
<< " name: \"" << escape(track->getName()) + "\","
<< " release: " << (track->getRelease() ? "\"" + escape(track->getRelease()->getName()) + "\"" : "undefined" ) << ","
<< " artist: " << (track->getArtist() ? "\"" + escape(track->getArtist()->getName()) + "\"" : "undefined" ) << ","
<< " resource: \"" << resource << "\","
<< " duration: " << track->getDuration().total_seconds() << ","
<< "};";
oss << "LMS.mediaplayer.loadTrack(params, true)"; // true to autoplay
LMS_LOG(UI, DEBUG) << "Runing js = '" << oss.str() << "'";
wApp->doJavaScript(oss.str());
}
catch (Av::MediaFileException& e)
{
LMS_LOG(UI, ERROR) << "MediaFileException: " << e.what();
stop();
}
}
void
MediaPlayer::stop()
{
_audio->pause();
wApp->doJavaScript("LMS.mediaplayer.stop()");
}
} // namespace UserInterface
+7 -8
View File
@@ -19,15 +19,14 @@
#pragma once
#include <Wt/WSignal>
#include <Wt/WAudio>
#include <Wt/WContainerWidget>
#include <Wt/WJavaScript>
#include <Wt/WTemplate>
#include "database/Types.hpp"
namespace UserInterface {
class MediaPlayer : public Wt::WContainerWidget
class MediaPlayer : public Wt::WTemplate
{
public:
MediaPlayer(Wt::WContainerWidget* parent = 0);
@@ -36,12 +35,12 @@ class MediaPlayer : public Wt::WContainerWidget
void playTrack(Database::Track::id_type);
// Signals
Wt::Signal<void> playbackEnded;
Wt::Signal<void> playPrevious;
Wt::Signal<void> playNext;
Wt::JSignal<void> playbackEnded;
Wt::JSignal<void> playPrevious;
Wt::JSignal<void> playNext;
private:
Wt::WAudio* _audio;
};
} // namespace UserInterface
+1 -3
View File
@@ -41,11 +41,9 @@ TranscodeResource:: ~TranscodeResource()
}
std::string
TranscodeResource::getUrl(Database::Track::id_type trackId, Av::Encoding encoding, boost::posix_time::time_duration offset, boost::optional<std::size_t> streamId) const
TranscodeResource::getUrl(Database::Track::id_type trackId, Av::Encoding encoding, boost::posix_time::time_duration offset) const
{
std::string res = url()+ "&trackid=" + std::to_string(trackId) + "&encoding=" + std::to_string(Av::encoding_to_int(encoding));
if (streamId)
res += "&stream=" + std::to_string(*streamId);
res += "&offset=" + std::to_string(offset.seconds());
return res;
+1 -3
View File
@@ -21,8 +21,6 @@
#include <mutex>
#include <boost/optional.hpp>
#include <Wt/WResource>
#include "av/AvTranscoder.hpp"
@@ -37,7 +35,7 @@ class TranscodeResource : public Wt::WResource
TranscodeResource(Database::Handler& db, Wt::WObject *parent);
~TranscodeResource();
std::string getUrl(Database::Track::id_type trackId, Av::Encoding encoding, boost::posix_time::time_duration offset, boost::optional<size_t> stream = boost::none) const;
std::string getUrl(Database::Track::id_type trackId, Av::Encoding encoding, boost::posix_time::time_duration offset) const;
void handleRequest(const Wt::Http::Request& request,
Wt::Http::Response& response);