diff --git a/approot/mediaplayer.xml b/approot/mediaplayer.xml
index 0d445ca6..15ab6bb4 100644
--- a/approot/mediaplayer.xml
+++ b/approot/mediaplayer.xml
@@ -2,37 +2,18 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${previous} ${play-pause} ${next}
- ${cover}
- ${current-time} ${total-time} ${shuffle} ${repeat}
- ${}${artist-name}${}
- ${}${release-name}${}
- ${track-name}
+
+
+
+ ...
+
+
+ 00:00
+ 00:00
+
+
+
diff --git a/docroot/js/mediaplayer.js b/docroot/js/mediaplayer.js
index 8a2ab650..69570ad8 100644
--- a/docroot/js/mediaplayer.js
+++ b/docroot/js/mediaplayer.js
@@ -1 +1,81 @@
-/* TEST */
+// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
+
+var LMS = LMS || {};
+
+LMS.mediaplayer = function () {
+
+ var _root = {};
+ var _elems = {};
+
+ var _updateControls = function() {
+ if (_elems.audio.paused) {
+ _elems.play.style.display = "block";
+ _elems.pause.style.display = "none";
+ }
+ else {
+ _elems.pause.style.display = "block";
+ _elems.play.style.display = "none";
+ }
+ }
+
+ var init = function(root) {
+ _root = root;
+
+ _elems.audio = document.getElementById("lms-mp-audio");
+ _elems.play = document.getElementById("lms-mp-play");
+ _elems.pause = document.getElementById("lms-mp-pause");
+ _elems.previous = document.getElementById("lms-mp-previous");
+ _elems.next = document.getElementById("lms-mp-next");
+ _elems.title = document.getElementById("lms-mp-title");
+ _elems.artist = document.getElementById("lms-mp-artist");
+ _elems.release = document.getElementById("lms-mp-release");
+ _elems.duration = document.getElementById("lms-mp-duration");
+
+ _elems.play.addEventListener("click", function() {
+ _elems.audio.play();
+ });
+ _elems.pause.addEventListener("click", function() {
+ _elems.audio.pause();
+ });
+
+ _elems.previous.addEventListener("click", function() {
+ Wt.emit(_root, "playPrevious");
+ });
+ _elems.next.addEventListener("click", function() {
+ Wt.emit(_root, "playNext");
+ });
+
+ _elems.audio.addEventListener("play", _updateControls);
+ _elems.audio.addEventListener("playing", _updateControls);
+ _elems.audio.addEventListener("pause", _updateControls);
+
+ _elems.audio.addEventListener("ended", function() {
+ Wt.emit(_root, "playbackEnded");
+ });
+ }
+
+ var loadTrack = function(params, autoplay) {
+ console.log("Loading track '" + params.name + "', release = '" + params.release + "', artist = '" + params.artist + "', resource = '" + params.resource + "', imgResource = '" + params.imgResource);
+
+ _elems.title.innerHTML = params.name;
+ _elems.artist.innerHTML = params.artist;
+ _elems.release.innerHTML = params.release;
+ _elems.audio.src = params.resource;
+ _elems.duration.innerHTML = params.duration;
+
+ if (autoplay)
+ _elems.audio.play();
+ }
+
+ var stop = function() {
+ _elems.audio.pause();
+ }
+
+ return {
+ init: init,
+ loadTrack: loadTrack,
+ stop: stop,
+ };
+}();
+
+// @license-end
diff --git a/src/ui/MediaPlayer.cpp b/src/ui/MediaPlayer.cpp
index fa9a2003..62423135 100644
--- a/src/ui/MediaPlayer.cpp
+++ b/src/ui/MediaPlayer.cpp
@@ -16,10 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see .
*/
-#include
-#include
-#include
-#include
+#include
#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
diff --git a/src/ui/MediaPlayer.hpp b/src/ui/MediaPlayer.hpp
index 8b36d8eb..80d7d74d 100644
--- a/src/ui/MediaPlayer.hpp
+++ b/src/ui/MediaPlayer.hpp
@@ -19,15 +19,14 @@
#pragma once
-#include
-#include
-#include
+#include
+#include
#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 playbackEnded;
- Wt::Signal playPrevious;
- Wt::Signal playNext;
+ Wt::JSignal playbackEnded;
+ Wt::JSignal playPrevious;
+ Wt::JSignal playNext;
private:
- Wt::WAudio* _audio;
+
};
} // namespace UserInterface
diff --git a/src/ui/resource/TranscodeResource.cpp b/src/ui/resource/TranscodeResource.cpp
index 428a68d2..6d9203f9 100644
--- a/src/ui/resource/TranscodeResource.cpp
+++ b/src/ui/resource/TranscodeResource.cpp
@@ -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 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;
diff --git a/src/ui/resource/TranscodeResource.hpp b/src/ui/resource/TranscodeResource.hpp
index a13f4e9b..51f8ecc8 100644
--- a/src/ui/resource/TranscodeResource.hpp
+++ b/src/ui/resource/TranscodeResource.hpp
@@ -21,8 +21,6 @@
#include
-#include
-
#include
#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 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);