From feb52c3ed9c86e19da833e7be9a98201a90d5db0 Mon Sep 17 00:00:00 2001 From: emeric Date: Tue, 22 Dec 2015 15:02:21 +0100 Subject: [PATCH] [UI/MOBILE] Changed the audio player. Still WIP --- approot/templates.xml | 29 +-- docroot/images/unknown-cover.jpg | Bin src/Makefile.am | 3 +- src/av/AvTranscoder.cpp | 19 -- src/av/AvTranscoder.hpp | 2 - src/database/User.cpp | 1 - src/database/User.hpp | 1 - src/ui/LmsApplication.cpp | 13 + src/ui/LmsApplication.hpp | 6 + src/ui/audio/AudioPlayer.cpp | 228 ++++++++++++++++++ ...leAudioMediaPlayer.hpp => AudioPlayer.hpp} | 38 +-- src/ui/audio/desktop/AudioMediaPlayer.cpp | 3 - src/ui/audio/mobile/MobileAudio.cpp | 55 +---- .../audio/mobile/MobileAudioMediaPlayer.cpp | 110 --------- src/ui/common/InputRange.cpp | 49 ++++ src/ui/common/InputRange.hpp | 37 +++ src/ui/resource/TranscodeResource.cpp | 23 +- src/ui/settings/SettingsAudioFormView.cpp | 1 - 18 files changed, 372 insertions(+), 246 deletions(-) mode change 100755 => 100644 docroot/images/unknown-cover.jpg create mode 100644 src/ui/audio/AudioPlayer.cpp rename src/ui/audio/{mobile/MobileAudioMediaPlayer.hpp => AudioPlayer.hpp} (50%) delete mode 100644 src/ui/audio/mobile/MobileAudioMediaPlayer.cpp create mode 100644 src/ui/common/InputRange.cpp create mode 100644 src/ui/common/InputRange.hpp diff --git a/approot/templates.xml b/approot/templates.xml index e346dfe4..e7a8985f 100644 --- a/approot/templates.xml +++ b/approot/templates.xml @@ -419,31 +419,6 @@ - -
-
-
-
- -
-
-
-
-
-
@@ -541,4 +516,8 @@ + + ${shuffle} ${repeat} ${playlist} ${prev} ${play-pause} ${next} ${cover} ${artist} ${track} ${release} ${curtime} ${seekbar} ${duration} ${volume} + + diff --git a/docroot/images/unknown-cover.jpg b/docroot/images/unknown-cover.jpg old mode 100755 new mode 100644 diff --git a/src/Makefile.am b/src/Makefile.am index f70f3293..7cc1077c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,6 +24,7 @@ lms_SOURCES = \ $(srcdir)/service/DatabaseUpdateService.cpp \ $(srcdir)/ui/LmsApplication.cpp \ $(srcdir)/ui/auth/LmsAuth.cpp \ + $(srcdir)/ui/audio/AudioPlayer.cpp \ $(srcdir)/ui/audio/desktop/DesktopAudio.cpp \ $(srcdir)/ui/audio/desktop/AudioMediaPlayer.cpp \ $(srcdir)/ui/audio/desktop/FilterChain.cpp \ @@ -33,11 +34,11 @@ lms_SOURCES = \ $(srcdir)/ui/audio/desktop/TrackView.cpp \ $(srcdir)/ui/audio/mobile/ArtistSearch.cpp \ $(srcdir)/ui/audio/mobile/MobileAudio.cpp \ - $(srcdir)/ui/audio/mobile/MobileAudioMediaPlayer.cpp \ $(srcdir)/ui/audio/mobile/ReleaseSearch.cpp \ $(srcdir)/ui/audio/mobile/TrackReleaseView.cpp \ $(srcdir)/ui/audio/mobile/TrackSearch.cpp \ $(srcdir)/ui/common/DirectoryValidator.cpp \ + $(srcdir)/ui/common/InputRange.cpp \ $(srcdir)/ui/common/LineEdit.cpp \ $(srcdir)/ui/resource/AvConvTranscodeStreamResource.cpp \ $(srcdir)/ui/resource/CoverResource.cpp \ diff --git a/src/av/AvTranscoder.cpp b/src/av/AvTranscoder.cpp index 94e0a4e2..67ee92b6 100644 --- a/src/av/AvTranscoder.cpp +++ b/src/av/AvTranscoder.cpp @@ -264,25 +264,6 @@ Transcoder::start() args.push_back("m4v"); break; - case Encoding::FLV: - args.push_back("-acodec"); - args.push_back("libmp3lame"); - args.push_back("-ac"); - args.push_back("2"); - args.push_back("-ar"); - args.push_back("44100"); - args.push_back("-vcodec"); - args.push_back("libx264"); - args.push_back("-f"); - args.push_back("flv"); - break; - - case Encoding::FLA: - args.push_back("-acodec"); - args.push_back("libmp3lame"); - args.push_back("-f"); - args.push_back("flv"); - break; default: return false; } diff --git a/src/av/AvTranscoder.hpp b/src/av/AvTranscoder.hpp index 7289715a..5706ea94 100644 --- a/src/av/AvTranscoder.hpp +++ b/src/av/AvTranscoder.hpp @@ -40,8 +40,6 @@ enum class Encoding MP3, WEBMA, WEBMV, - FLA, - FLV, M4A, M4V, }; diff --git a/src/database/User.cpp b/src/database/User.cpp index 21aa8310..d25410c3 100644 --- a/src/database/User.cpp +++ b/src/database/User.cpp @@ -55,7 +55,6 @@ User::audioEncodings = AudioEncoding::MP3, AudioEncoding::OGA, AudioEncoding::WEBMA, - AudioEncoding::FLA, }; const std::vector diff --git a/src/database/User.hpp b/src/database/User.hpp index 2450aa1f..0bf1138a 100644 --- a/src/database/User.hpp +++ b/src/database/User.hpp @@ -39,7 +39,6 @@ enum class AudioEncoding MP3, OGA, WEBMA, - FLA, }; enum class VideoEncoding diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp index 0011ed78..cdf5c7e7 100644 --- a/src/ui/LmsApplication.cpp +++ b/src/ui/LmsApplication.cpp @@ -100,6 +100,7 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti setTheme(bootstrapTheme); useStyleSheet("css/lms.css"); + useStyleSheet("resources/font-awesome/css/font-awesome.min.css"); // Add a resource bundle messageResourceBundle().use(appRoot() + "templates"); @@ -142,6 +143,16 @@ Database::User::pointer CurrentUser() return DbHandler().getCurrentUser(); } +CoverResource* SessionCoverResource() +{ + return LmsApplication::instance()->getCoverResource(); +} + +TranscodeResource* SessionTranscodeResource() +{ + return LmsApplication::instance()->getTranscodeResource(); +} + void LmsApplication::createFirstConnectionUI() { @@ -155,6 +166,8 @@ void LmsApplication::createLmsUI() { _coverResource = new CoverResource(_db, root()); + _transcodeResource = new TranscodeResource(_db, root()); + DbHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent); LmsAuth *authWidget = new LmsAuth(); diff --git a/src/ui/LmsApplication.hpp b/src/ui/LmsApplication.hpp index b2946991..447c1db3 100644 --- a/src/ui/LmsApplication.hpp +++ b/src/ui/LmsApplication.hpp @@ -27,6 +27,7 @@ #include "database/DatabaseHandler.hpp" #include "resource/CoverResource.hpp" +#include "resource/TranscodeResource.hpp" namespace UserInterface { @@ -40,6 +41,7 @@ class LmsApplication : public Wt::WApplication // Session application data CoverResource* getCoverResource() { return _coverResource; } + TranscodeResource* getTranscodeResource() { return _transcodeResource; } Database::Handler& getDbHandler() { return _db;} private: @@ -50,6 +52,7 @@ class LmsApplication : public Wt::WApplication Database::Handler _db; CoverResource* _coverResource; + TranscodeResource* _transcodeResource; }; // Helpers to get session data @@ -59,6 +62,9 @@ Wt::Dbo::Session& DboSession(); const Wt::Auth::User& CurrentAuthUser(); Database::User::pointer CurrentUser(); +CoverResource *SessionCoverResource(); +TranscodeResource *SessionTranscodeResource(); + } // namespace UserInterface #endif diff --git a/src/ui/audio/AudioPlayer.cpp b/src/ui/audio/AudioPlayer.cpp new file mode 100644 index 00000000..9b3d6196 --- /dev/null +++ b/src/ui/audio/AudioPlayer.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2015 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + + +#include +#include +#include +#include +#include + +#include "common/InputRange.hpp" + +#include "LmsApplication.hpp" + +#include "AudioPlayer.hpp" + +namespace UserInterface { + +void +AudioPlayer::loadTrack(Database::Track::id_type trackId) +{ + Wt::Dbo::Transaction transaction(DboSession()); + + Database::Track::pointer track = Database::Track::getById(DboSession(), trackId); + if (!track) + { + std::cerr << "no track for this id!" << std::endl; + return; + } + + _trackName->setText(Wt::WString::fromUTF8(track->getName())); + _artistName->setText( Wt::WString::fromUTF8(track->getArtist()->getName())); + _releaseName->setText( Wt::WString::fromUTF8(track->getRelease()->getName())); + _cover->setImageLink(SessionCoverResource()->getTrackUrl(trackId, 64)); + _trackDuration->setText( boost::posix_time::to_simple_string( track->getDuration() )); + + // Analyse track, select the best media stream + Av::MediaFile mediaFile(track->getPath()); + + if (!mediaFile.open() || !mediaFile.scan()) + { + std::cerr << "cannot open file '" << track->getPath() << std::endl; + return; + } + + + int audioBestStreamId = mediaFile.getBestStreamId(Av::Stream::Type::Audio); + std::vector streams; + if (audioBestStreamId != -1) + streams.push_back(audioBestStreamId); + + this->doJavaScript("\ + document.lms.audio.state = \"loaded\";\ + document.lms.audio.seekbar.min = " + std::to_string(0) + ";\ + document.lms.audio.seekbar.max = " + std::to_string(track->getDuration().total_seconds()) + ";\ + document.lms.audio.seekbar.value = 0;\ + document.lms.audio.seekbar.disabled = false;\ + document.lms.audio.offset = 0;\ + document.lms.audio.curTime = 0;\ + "); + + //TODO, try to load everything in JS in order to prevent the WriteError bug? + _audio->pause(); + _audio->clearSources(); + //TODOencoding + _audio->addSource(SessionTranscodeResource()->getUrl(trackId, Av::Encoding::MP3, 0, streams)); + _audio->play(); +} + +AudioPlayer::AudioPlayer(Wt::WContainerWidget *parent) +: Wt::WContainerWidget(parent) +{ + Wt::WTemplate *t = new Wt::WTemplate(this); + t->setTemplateText(Wt::WString::tr("wa-audio-player")); + + _audio = new Wt::WAudio(this); + + _cover = new Wt::WImage(); + t->bindWidget("cover", _cover); + _cover->setImageLink(SessionCoverResource()->getUnknownTrackUrl(64)); + + InputRange *seekbar = new InputRange(); + t->bindWidget("seekbar", seekbar); + + _trackName = new Wt::WText(); + t->bindWidget("track", _trackName); + + _artistName = new Wt::WText(); + t->bindWidget("artist", _artistName); + + _releaseName = new Wt::WText(); + t->bindWidget("release", _releaseName); + + InputRange *volumeSlider = new InputRange(); + t->bindWidget("volume", volumeSlider); + + Wt::WPushButton *playlistBtn = new Wt::WPushButton("", Wt::XHTMLText); + t->bindWidget("playlist", playlistBtn); + + Wt::WPushButton *repeatBtn = new Wt::WPushButton("", Wt::XHTMLText); + t->bindWidget("repeat", repeatBtn); + + Wt::WPushButton *shuffleBtn = new Wt::WPushButton("", Wt::XHTMLText); + t->bindWidget("shuffle", shuffleBtn); + + Wt::WPushButton *prevBtn = new Wt::WPushButton("", Wt::XHTMLText); + t->bindWidget("prev", prevBtn); + + Wt::WPushButton *nextBtn = new Wt::WPushButton("", Wt::XHTMLText); + t->bindWidget("next", nextBtn); + + Wt::WPushButton *playPauseBtn = new Wt::WPushButton("", Wt::XHTMLText); + t->bindWidget("play-pause", playPauseBtn); + + Wt::WText *trackCurrentTime = new Wt::WText("00:00"); + t->bindWidget("curtime", trackCurrentTime); + + _trackDuration = new Wt::WText("00:00"); + t->bindWidget("duration", _trackDuration); + + this->doJavaScript( + "\ + document.lms = {};\ + document.lms.audio = {};\ + document.lms.audio.audio = " + _audio->jsRef() + ";\ + document.lms.audio.seekbar = " + seekbar->jsRef() +";\ + document.lms.audio.volumeSlider = " + volumeSlider->jsRef() + ";\ + document.lms.audio.curTimeText = " + trackCurrentTime->jsRef() + ";\ + document.lms.audio.playPause = " + playPauseBtn->jsRef() + ";\ + \ + document.lms.audio.offset = 0;\ + document.lms.audio.curTime = 0;\ + document.lms.audio.state = \"init\";\ + document.lms.audio.volume = 1;\ + \ + document.lms.audio.seekbar.value = 0;\ + document.lms.audio.seekbar.disabled = true;\ + \ + document.lms.audio.volumeSlider.min = 0;\ + document.lms.audio.volumeSlider.max = 100;\ + document.lms.audio.volumeSlider.value = 100;\ + \ + function updateUI() {\ + document.lms.audio.curTimeText.innerHTML = document.lms.audio.curTime;\ + document.lms.audio.seekbar.value = document.lms.audio.curTime;\ + }\ + \ + var mouseDown = 0;\ + function seekMouseDown(e) {\ + ++mouseDown;\ + }\ + function seekMouseUp(e) {\ + --mouseDown;\ + }\ + \ + function seeking(e) {\ + if (document.lms.audio.state == \"init\")\ + return;\ + \ + document.lms.audio.curTimeText.innerHTML = document.lms.audio.seekbar.value;\ + }\ + \ + function seek(e) {\ + if (document.lms.audio.state == \"init\")\ + return;\ + \ + document.lms.audio.audio.pause(); \ + document.lms.audio.offset = parseInt(document.lms.audio.seekbar.value);\ + document.lms.audio.curTime = document.lms.audio.seekbar.value;\ + var audioSource = document.lms.audio.audio.getElementsByTagName(\"source\")[0];\ + var src = audioSource.src;\ + src = src.slice(0, src.lastIndexOf(\"=\") + 1);\ + audioSource.src = src + document.lms.audio.seekbar.value;\ + document.lms.audio.audio.load(); \ + document.lms.audio.audio.play(); \ + document.lms.audio.curTimeText.innerHTML = ~~document.lms.audio.curTime + \" \";\ + }\ + \ + function volumeChanged() {\ + document.lms.audio.audio.volume = document.lms.audio.volumeSlider.value / 100;\ + }\ + \ + function updateCurTime() {\ + document.lms.audio.curTime = document.lms.audio.offset + ~~document.lms.audio.audio.currentTime; \ + if (mouseDown == 0)\ + updateUI();\ + } \ + \ + function playPause() {\ + if (document.lms.audio.state == \"init\") \ + return;\ + \ + if (document.lms.audio.audio.paused)\ + document.lms.audio.audio.play();\ + else\ + document.lms.audio.audio.pause();\ + \ + }\ + \ + document.lms.audio.audio.addEventListener('timeupdate', updateCurTime); \ + document.lms.audio.seekbar.addEventListener('change', seek);\ + document.lms.audio.seekbar.addEventListener('input', seeking);\ + document.lms.audio.seekbar.addEventListener('mousedown', seekMouseDown);\ + document.lms.audio.seekbar.addEventListener('mouseup', seekMouseUp);\ + document.lms.audio.volumeSlider.addEventListener('input', volumeChanged);\ + document.lms.audio.playPause.addEventListener('click', playPause);\ + " + ); +} + + +} // namespaceUserInterface diff --git a/src/ui/audio/mobile/MobileAudioMediaPlayer.hpp b/src/ui/audio/AudioPlayer.hpp similarity index 50% rename from src/ui/audio/mobile/MobileAudioMediaPlayer.hpp rename to src/ui/audio/AudioPlayer.hpp index cf970073..f202e93e 100644 --- a/src/ui/audio/mobile/MobileAudioMediaPlayer.hpp +++ b/src/ui/audio/AudioPlayer.hpp @@ -17,43 +17,31 @@ * along with LMS. If not, see . */ -#ifndef UI_AUDIO_MOBILE_MEDIA_PLAYER_HPP -#define UI_AUDIO_MOBILE_MEDIA_PLAYER_HPP +#pragma once -#include -#include -#include - -#include "database/DatabaseHandler.hpp" -#include "av/AvTranscoder.hpp" +#include "common/InputRange.hpp" +#include "database/Types.hpp" namespace UserInterface { -namespace Mobile { -class AudioMediaPlayer : public Wt::WContainerWidget +class AudioPlayer : public Wt::WContainerWidget { public: - static Wt::WMediaPlayer::Encoding getBestEncoding(); + AudioPlayer(Wt::WContainerWidget *parent = 0); - AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0); + void loadTrack(Database::Track::id_type trackId); - void play(Database::Track::id_type trackId, Av::TranscodeParameters parameters); - - Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; } + // Slots private: - Wt::WMediaPlayer* _player; - Wt::WMediaPlayer::Encoding _encoding; - - Wt::WImage* _cover; - Wt::WText* _track; - Wt::WText* _artistRelease; - + Wt::WAudio* _audio; + Wt::WText* _trackDuration; + Wt::WText* _trackName; + Wt::WText* _artistName; + Wt::WText* _releaseName; + Wt::WImage* _cover; }; } // namespace UserInterface -} // namespace Mobile - -#endif diff --git a/src/ui/audio/desktop/AudioMediaPlayer.cpp b/src/ui/audio/desktop/AudioMediaPlayer.cpp index 39462fdb..42d9e6cb 100644 --- a/src/ui/audio/desktop/AudioMediaPlayer.cpp +++ b/src/ui/audio/desktop/AudioMediaPlayer.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,6 @@ AudioMediaPlayer::AudioMediaPlayer(Wt::WContainerWidget *parent) 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(); @@ -237,7 +235,6 @@ AudioMediaPlayer::load(Database::Track::id_type trackId) switch (_encoding) { case Wt::WMediaPlayer::MP3: encoding = Av::Encoding::MP3; break; - case Wt::WMediaPlayer::FLA: encoding = Av::Encoding::FLA; break; case Wt::WMediaPlayer::OGA: encoding = Av::Encoding::OGA; break; case Wt::WMediaPlayer::WEBMA: encoding = Av::Encoding::WEBMA; break; default: diff --git a/src/ui/audio/mobile/MobileAudio.cpp b/src/ui/audio/mobile/MobileAudio.cpp index 750f0973..2a4eb065 100644 --- a/src/ui/audio/mobile/MobileAudio.cpp +++ b/src/ui/audio/mobile/MobileAudio.cpp @@ -27,14 +27,13 @@ #include "logger/Logger.hpp" #include "utils/Utils.hpp" +#include "audio/AudioPlayer.hpp" #include "LmsApplication.hpp" #include "ArtistSearch.hpp" #include "ReleaseSearch.hpp" #include "TrackSearch.hpp" - #include "TrackReleaseView.hpp" -#include "MobileAudioMediaPlayer.hpp" #include "MobileAudio.hpp" @@ -45,36 +44,16 @@ namespace Mobile { using namespace Database; -static void playTrack(AudioMediaPlayer *mediaPlayer, Database::Track::id_type trackId) +static void playTrack(AudioPlayer *audioPlayer, Database::Track::id_type trackId) { LMS_LOG(UI, DEBUG) << "Playing track id " << trackId; - // TODO reduce transaction scope here + Wt::Dbo::Transaction transaction(DboSession()); Track::pointer track = Track::getById(DboSession(), trackId); if (track) - { - Av::TranscodeParameters parameters; - - // Determine the output format using the encoding of the player - Av::Encoding encoding; - switch(mediaPlayer->getEncoding()) - { - case Wt::WMediaPlayer::MP3: encoding = Av::Encoding::MP3; break; - case Wt::WMediaPlayer::FLA: encoding = Av::Encoding::FLA; break; - case Wt::WMediaPlayer::OGA: encoding = Av::Encoding::OGA; break; - case Wt::WMediaPlayer::WEBMA: encoding = Av::Encoding::WEBMA; break; - default: - encoding = Av::Encoding::MP3; - } - parameters.setEncoding(encoding); - - // TODO compute parameters using user's profile - parameters.setBitrate(Av::Stream::Type::Audio, 96000); - - mediaPlayer->play(track.id(), parameters); - } + audioPlayer->loadTrack(track.id()); } Audio::Audio(Wt::WContainerWidget *parent) @@ -103,26 +82,8 @@ Audio::Audio(Wt::WContainerWidget *parent) Wt::WTemplate* footer = new Wt::WTemplate(this); footer->setTemplateText(Wt::WString::tr("mobile-audio-footer")); - // Determine the encoding to be used - Wt::WMediaPlayer::Encoding encoding; - - { - Wt::Dbo::Transaction transaction (DboSession()); - - switch (CurrentUser()->getAudioEncoding()) - { - case AudioEncoding::MP3: encoding = Wt::WMediaPlayer::MP3; break; - case AudioEncoding::WEBMA: encoding = Wt::WMediaPlayer::WEBMA; break; - case AudioEncoding::OGA: encoding = Wt::WMediaPlayer::OGA; break; - case AudioEncoding::FLA: encoding = Wt::WMediaPlayer::FLA; break; - case AudioEncoding::AUTO: - default: - encoding = AudioMediaPlayer::getBestEncoding(); - } - } - - AudioMediaPlayer* mediaPlayer = new AudioMediaPlayer(encoding); - footer->bindWidget("player", mediaPlayer); + AudioPlayer* audioPlayer = new AudioPlayer(); + footer->bindWidget("player", audioPlayer); edit->changed().connect(std::bind([=] () { @@ -188,12 +149,12 @@ Audio::Audio(Wt::WContainerWidget *parent) trackSearch->trackPlay().connect(std::bind([=] (Track::id_type id) { - playTrack(mediaPlayer, id); + playTrack(audioPlayer, id); }, std::placeholders::_1)); trackReleaseView->trackPlay().connect(std::bind([=] (Track::id_type id) { - playTrack(mediaPlayer, id); + playTrack(audioPlayer, id); }, std::placeholders::_1)); // Initially, populate the widgets using an empty search diff --git a/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp b/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp deleted file mode 100644 index 2127567d..00000000 --- a/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2015 Emeric Poupon - * - * This file is part of LMS. - * - * LMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LMS. If not, see . - */ - -#include -#include -#include -#include -#include - -#include "LmsApplication.hpp" - -#include "MobileAudioMediaPlayer.hpp" - -#include "resource/AvConvTranscodeStreamResource.hpp" - -namespace UserInterface { -namespace Mobile { - -Wt::WMediaPlayer::Encoding -AudioMediaPlayer::getBestEncoding() -{ - // MP3 seems to be better supported everywhere - return Wt::WMediaPlayer::MP3; -} - -AudioMediaPlayer::AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent) -: - Wt::WContainerWidget(parent), -_player(nullptr), -_encoding(encoding) -{ - Wt::WTemplate* container = new Wt::WTemplate(this); - container->setTemplateText(Wt::WString::tr("mobile-audio-player")); - - Wt::WPushButton *play = new Wt::WPushButton("Play"); - play->setStyleClass("btn-sm"); - play->setWidth(52); - container->bindWidget("play", play); - - Wt::WPushButton *pause = new Wt::WPushButton("Pause"); - pause->setStyleClass("btn-sm"); - pause->setWidth(52); - container->bindWidget("pause", pause); - - _track = new Wt::WText("", Wt::PlainText); - _track->setStyleClass("mobile-track"); - container->bindWidget("track", _track); - - _artistRelease = new Wt::WText("", Wt::PlainText); - _artistRelease->setStyleClass("mobile-artist"); - container->bindWidget("artist", _artistRelease); - - _cover = new Wt::WImage(); - container->bindWidget("cover", _cover); - _cover->setStyleClass("mobile-audio-player-cover"); - - - _player = new Wt::WMediaPlayer(Wt::WMediaPlayer::Audio, this); - _player->addSource( _encoding, "" ); - _player->setControlsWidget( 0 ); - _player->setButton(Wt::WMediaPlayer::Play, play); - _player->setButton(Wt::WMediaPlayer::Pause, pause); - -} - -void -AudioMediaPlayer::play(Database::Track::id_type trackId, Av::TranscodeParameters parameters) -{ - boost::filesystem::path path; - - { - Wt::Dbo::Transaction transaction(DboSession()); - - Database::Track::pointer track = Database::Track::getById(DboSession(), trackId); - - _track->setText( Wt::WString::fromUTF8(track->getName() )); - _artistRelease->setText( Wt::WString::fromUTF8(track->getArtist()->getName()) ); - path = track->getPath(); - } - - // FIXME memleak here - AvConvTranscodeStreamResource *resource = new AvConvTranscodeStreamResource( path, parameters, this ); - - _player->clearSources(); - _player->addSource( _encoding, Wt::WLink(resource)); - - _player->play(); - - _cover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 48))); - -} - -} // namespace UserInterface -} // namespace Mobile diff --git a/src/ui/common/InputRange.cpp b/src/ui/common/InputRange.cpp new file mode 100644 index 00000000..3ff0da7b --- /dev/null +++ b/src/ui/common/InputRange.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include + +#if WT_VERSION < 0X03030500 +#include +#endif + +#include "InputRange.hpp" + +InputRange::InputRange(Wt::WContainerWidget *parent) +: Wt::WWebWidget(parent) +{ + //TODO woraround for older Wt versions +#if WT_VERSION >= 0X03030500 + setHtmlTagName("input"); + setAttributeValue("type", "range"); +#else + Wt::WTemplate *t = new Wt::WTemplate("", parent); +#endif +} + + +std::string +InputRange::jsRef(void) const +{ +#if WT_VERSION >= 0X03030500 + return Wt::WWebWidget::jsRef(); +#else + return this->jsRef() + ".getElementsByTagName(\"input\")[0]"; +#endif +} diff --git a/src/ui/common/InputRange.hpp b/src/ui/common/InputRange.hpp new file mode 100644 index 00000000..7f03abb4 --- /dev/null +++ b/src/ui/common/InputRange.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include +#include + +class InputRange : public Wt::WWebWidget +{ + public: + InputRange(Wt::WContainerWidget *parent = 0); + + Wt::DomElementType domElementType() const + { + return Wt::DomElement_INPUT; + } + + std::string jsRef() const; +}; + diff --git a/src/ui/resource/TranscodeResource.cpp b/src/ui/resource/TranscodeResource.cpp index 3573bfbc..16478a5f 100644 --- a/src/ui/resource/TranscodeResource.cpp +++ b/src/ui/resource/TranscodeResource.cpp @@ -71,11 +71,11 @@ TranscodeResource::handleRequest(const Wt::Http::Request& request, Wt::Http::ResponseContinuation *continuation = request.continuation(); if (continuation) { - LMS_LOG(UI, DEBUG) << "Continuation!"; + LMS_LOG(UI, DEBUG) << "Continuation! " << continuation ; transcoder = boost::any_cast >(continuation->data()); if (!transcoder) { - LMS_LOG(UI, DEBUG) << "No transcoder set -> abort!"; + LMS_LOG(UI, ERROR) << "No transcoder set -> abort!"; return; } } @@ -101,18 +101,23 @@ TranscodeResource::handleRequest(const Wt::Http::Request& request, Database::User::pointer user = _db.getCurrentUser(); Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId); - if (!track/* || !user */) + if (!track) { - LMS_LOG(UI, ERROR) << "Missing track or user"; + LMS_LOG(UI, ERROR) << "Missing track"; + return; + } + + if (!user) + { + LMS_LOG(UI, ERROR) << "Missing user"; return; } Av::TranscodeParameters parameters; - // TODO parameters.setOffset(boost::posix_time::seconds(std::stol(*offsetStr))); parameters.setEncoding(Av::encoding_from_int(std::stol(*encodingStr))); - parameters.setBitrate(Av::Stream::Type::Audio, 96000); + parameters.setBitrate(Av::Stream::Type::Audio, user->getAudioBitrate() ); for (std::string strStream: streams) { LMS_LOG(UI, DEBUG) << "Added stream " << std::stol(strStream); @@ -135,18 +140,14 @@ TranscodeResource::handleRequest(const Wt::Http::Request& request, LMS_LOG(UI, DEBUG) << "Transcoder started"; } - LMS_LOG(UI, DEBUG) << "processing data?"; - if (!transcoder->isComplete()) { std::vector data; data.reserve(_bufferSize); - LMS_LOG(UI, DEBUG) << "Processing data from transcoder..."; + LMS_LOG(UI, DEBUG) << "Reading data from transcoder"; transcoder->process(data, _bufferSize); - LMS_LOG(UI, DEBUG) << "Processing data from transcoder DONE"; - // Give the client all the output data response.out().write(reinterpret_cast(&data[0]), data.size()); LMS_LOG(UI, DEBUG) << "Written " << data.size() << " bytes! complete = " << std::boolalpha << transcoder->isComplete(); diff --git a/src/ui/settings/SettingsAudioFormView.cpp b/src/ui/settings/SettingsAudioFormView.cpp index d92312f0..1af1fc18 100644 --- a/src/ui/settings/SettingsAudioFormView.cpp +++ b/src/ui/settings/SettingsAudioFormView.cpp @@ -41,7 +41,6 @@ std::string encodingToString(Database::AudioEncoding encoding) case Database::AudioEncoding::MP3: return "MP3"; case Database::AudioEncoding::OGA: return "OGG"; case Database::AudioEncoding::WEBMA: return "WebM"; - case Database::AudioEncoding::FLA: return "Flash"; } return "?";