diff --git a/src/Makefile.am b/src/Makefile.am index 3a3aa96d..4fe9107b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,6 @@ lms_SOURCES = \ $(srcdir)/ui/audio/mobile/TrackSearch.cpp \ $(srcdir)/ui/common/DirectoryValidator.cpp \ $(srcdir)/ui/common/LineEdit.cpp \ - $(srcdir)/ui/common/SessionData.cpp \ $(srcdir)/ui/resource/AvConvTranscodeStreamResource.cpp \ $(srcdir)/ui/resource/CoverResource.cpp \ $(srcdir)/ui/video/VideoWidget.cpp \ diff --git a/src/database/User.cpp b/src/database/User.cpp index 66f955d3..21aa8310 100644 --- a/src/database/User.cpp +++ b/src/database/User.cpp @@ -23,7 +23,7 @@ namespace Database { // must be ordered const std::vector - User::audioBitrates = +User::audioBitrates = { 64000, 96000, @@ -38,7 +38,7 @@ const std::vector const std::vector - User::videoBitrates = +User::videoBitrates = { 256000, 512000, @@ -47,12 +47,32 @@ const std::vector 4096000, 8192000 }; + +const std::vector +User::audioEncodings = +{ + AudioEncoding::AUTO, + AudioEncoding::MP3, + AudioEncoding::OGA, + AudioEncoding::WEBMA, + AudioEncoding::FLA, +}; + +const std::vector +User::videoEncodings = +{ + VideoEncoding::AUTO, +}; + User::User() : _maxAudioBitrate(maxAudioBitrate), _maxVideoBitrate(maxVideoBitrate), _isAdmin(false), _audioBitrate(defaultAudioBitrate), -_videoBitrate(defaultVideoBitrate) +_audioEncoding(AudioEncoding::AUTO), +_videoBitrate(defaultVideoBitrate), +_videoEncoding(VideoEncoding::AUTO), +_curPlayingTrackPos(0) { } diff --git a/src/database/User.hpp b/src/database/User.hpp index 3d5bbac9..2450aa1f 100644 --- a/src/database/User.hpp +++ b/src/database/User.hpp @@ -32,14 +32,34 @@ typedef Wt::Auth::Dbo::AuthInfo AuthInfo; class Playlist; -class User { +// User selectable audio formats +enum class AudioEncoding +{ + AUTO, + MP3, + OGA, + WEBMA, + FLA, +}; + +enum class VideoEncoding +{ + AUTO, +}; + +class User +{ public: + static const std::size_t MaxNameLength = 15; - // list of commonly used bitrates + // list of audio/video parameters static const std::vector audioBitrates; + static const std::vector audioEncodings; + static const std::vector videoBitrates; + static const std::vector videoEncodings; User(); @@ -53,16 +73,22 @@ class User { // write void setAdmin(bool admin) { _isAdmin = admin; } void setAudioBitrate(std::size_t bitrate); + void setAudioEncoding(AudioEncoding encoding) { _audioEncoding = encoding; } void setVideoBitrate(std::size_t bitrate); + void setVideoEncoding(VideoEncoding encoding) { _videoEncoding = encoding; } void setMaxAudioBitrate(std::size_t bitrate); void setMaxVideoBitrate(std::size_t bitrate); + void setCurPlayingTrackPos(std::size_t pos) { _curPlayingTrackPos = pos; } // read bool isAdmin() const {return _isAdmin;} std::size_t getAudioBitrate() const; + AudioEncoding getAudioEncoding() const { return _audioEncoding;} std::size_t getVideoBitrate() const; + VideoEncoding getVideoEncoding() const { return _videoEncoding;} std::size_t getMaxAudioBitrate() const; std::size_t getMaxVideoBitrate() const; + std::size_t getCurPlayingTrackPos() const { return _curPlayingTrackPos; } template void persist(Action& a) @@ -71,7 +97,11 @@ class User { Wt::Dbo::field(a, _maxVideoBitrate, "max_video_bitrate"); Wt::Dbo::field(a, _isAdmin, "admin"); Wt::Dbo::field(a, _audioBitrate, "audio_bitrate"); + Wt::Dbo::field(a, _audioEncoding, "audio_encoding"); Wt::Dbo::field(a, _videoBitrate, "video_bitrate"); + Wt::Dbo::field(a, _videoEncoding, "video_encoding"); + // User's dynamic data + Wt::Dbo::field(a, _curPlayingTrackPos, "cur_playing_track_pos"); Wt::Dbo::hasMany(a, _playlists, Wt::Dbo::ManyToOne, "user"); } @@ -90,7 +120,12 @@ class User { // User defined settings int _audioBitrate; + AudioEncoding _audioEncoding; int _videoBitrate; + VideoEncoding _videoEncoding; + + // User's dynamic data + int _curPlayingTrackPos; // Current track position in queue Wt::Dbo::collection< Wt::Dbo::ptr > _playlists; diff --git a/src/transcode/AvConvTranscoder.cpp b/src/transcode/AvConvTranscoder.cpp index 1b4dd815..aa9cc467 100644 --- a/src/transcode/AvConvTranscoder.cpp +++ b/src/transcode/AvConvTranscoder.cpp @@ -135,7 +135,7 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters) oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libvpx -threads 4 -f webm"; break; case Format::M4A: - oss << " -acodec aac -f mp4"; + oss << " -acodec aac -f mp4 -strict experimental"; break; case Format::M4V: oss << " -acodec aac -strict experimental -ac 2 -ar 44100 -vcodec libx264 -f m4v"; @@ -143,6 +143,9 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters) case Format::FLV: oss << " -acodec libmp3lame -ac 2 -ar 44100 -vcodec libx264 -f flv"; break; + case Format::FLA: + oss << " -acodec libmp3lame -f flv"; + break; default: assert(0); } diff --git a/src/transcode/Format.cpp b/src/transcode/Format.cpp index 8e35ff20..2e9c5a5a 100644 --- a/src/transcode/Format.cpp +++ b/src/transcode/Format.cpp @@ -33,6 +33,7 @@ const std::vector Format::_supportedFormats {Format::MP3, Format::Audio, "audio/mpeg", "MP3"}, {Format::WEBMA, Format::Audio, "audio/webm", "WebM"}, {Format::WEBMV, Format::Video, "video/webm", "WebM"}, + {Format::FLA, Format::Audio, "audio/x-flv", "Flash Audio"}, {Format::FLV, Format::Video, "video/x-flv", "Flash Video"}, {Format::M4A, Format::Audio, "audio/mp4", "MP4"}, {Format::M4V, Format::Video, "video/mp4", "MP4"}, diff --git a/src/transcode/Format.hpp b/src/transcode/Format.hpp index 96a07e3e..a2885cf6 100644 --- a/src/transcode/Format.hpp +++ b/src/transcode/Format.hpp @@ -38,6 +38,7 @@ class Format MP3, WEBMA, WEBMV, + FLA, FLV, M4A, M4V, diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp index 7aaaebc1..9798d26a 100644 --- a/src/ui/LmsApplication.cpp +++ b/src/ui/LmsApplication.cpp @@ -56,6 +56,7 @@ bool agentIsMobile() || env.userAgent().find("Tablet") != std::string::npos // Workaround for firefox ); } + } @@ -71,6 +72,12 @@ LmsApplication::create(const Wt::WEnvironment& env, boost::filesystem::path dbPa return new LmsApplication(env, dbPath); } +LmsApplication* +LmsApplication::instance() +{ + return reinterpret_cast(Wt::WApplication::instance()); +} + /* * The env argument contains information about the new session, and * the initial request. It must be passed to the Wt::WApplication @@ -79,7 +86,8 @@ LmsApplication::create(const Wt::WEnvironment& env, boost::filesystem::path dbPa */ LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::path dbPath) : Wt::WApplication(env), - _sessionData(dbPath) + _db(dbPath), + _coverResource(nullptr) { Wt::WBootstrapTheme *bootstrapTheme = new Wt::WBootstrapTheme(this); @@ -96,9 +104,9 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::p bool firstConnection; { - Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - firstConnection = (Database::User::getAll(_sessionData.getDatabaseHandler().getSession()).size() == 0); + firstConnection = (Database::User::getAll(DboSession()).size() == 0); } // If here is no account in the database, launch the first connection wizard @@ -109,22 +117,41 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::p } +Database::Handler& DbHandler() +{ + return LmsApplication::instance()->getDbHandler(); +} +Wt::Dbo::Session& DboSession() +{ + return DbHandler().getSession(); +} + +const Wt::Auth::User& CurrentAuthUser() +{ + return DbHandler().getLogin().user(); +} + +Database::User::pointer CurrentUser() +{ + return DbHandler().getCurrentUser(); +} + void LmsApplication::createFirstConnectionUI() { // Hack, use the auth widget builtin strings builtinLocalizedStrings().useBuiltin(skeletons::AuthStrings_xml1); - root()->addWidget( new Settings::FirstConnectionFormView(_sessionData)); + root()->addWidget( new Settings::FirstConnectionFormView()); } void LmsApplication::createLmsUI() { + _coverResource = new CoverResource(_db, root()); + DbHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent); - _sessionData.getDatabaseHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent); - - LmsAuth *authWidget = new LmsAuth(_sessionData.getDatabaseHandler()); + LmsAuth *authWidget = new LmsAuth(); authWidget->model()->addPasswordAuth(&Database::Handler::getPasswordService()); authWidget->setRegistrationEnabled(false); @@ -138,11 +165,9 @@ LmsApplication::createLmsUI() void LmsApplication::handleAuthEvent(void) { - if (_sessionData.getDatabaseHandler().getLogin().loggedIn()) + if (DbHandler().getLogin().loggedIn()) { - Wt::Auth::User user(_sessionData.getDatabaseHandler().getLogin().user()); - - LMS_LOG(MOD_UI, SEV_NOTICE) << "User '" << user.identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().agent() << ", session = " << Wt::WApplication::instance()->sessionId(); + LMS_LOG(MOD_UI, SEV_NOTICE) << "User '" << CurrentAuthUser().identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().agent() << ", session = " << Wt::WApplication::instance()->sessionId(); this->root()->setOverflow(Wt::WContainerWidget::OverflowHidden); @@ -162,20 +187,18 @@ LmsApplication::handleAuthEvent(void) Wt::WMenu *leftMenu = new Wt::WMenu(contentsStack); navigation->addMenu(leftMenu); - const Wt::WEnvironment& env = Wt::WApplication::instance()->environment(); - Audio *audio; if (agentIsMobile()) - audio = new Mobile::Audio(_sessionData.getDatabaseHandler()); + audio = new Mobile::Audio(); else - audio = new Desktop::Audio(_sessionData); + audio = new Desktop::Audio(); - VideoWidget *videoWidget = new VideoWidget(_sessionData); + VideoWidget *videoWidget = new VideoWidget(); leftMenu->addItem("Audio", audio); leftMenu->addItem("Video", videoWidget); - leftMenu->addItem("Settings", new Settings::Settings(_sessionData)); + leftMenu->addItem("Settings", new Settings::Settings()); // Setup a Right-aligned menu. Wt::WMenu *rightMenu = new Wt::WMenu(); @@ -185,14 +208,14 @@ LmsApplication::handleAuthEvent(void) Wt::WPopupMenu *popup = new Wt::WPopupMenu(); popup->addItem("Logout"); - Wt::WMenuItem *item = new Wt::WMenuItem( user.identity(Wt::Auth::Identity::LoginName) ); + Wt::WMenuItem *item = new Wt::WMenuItem( CurrentAuthUser().identity(Wt::Auth::Identity::LoginName) ); item->setMenu(popup); rightMenu->addItem(item); popup->itemSelected().connect(std::bind([=] (Wt::WMenuItem* item) { if (item && item->text() == "Logout") - _sessionData.getDatabaseHandler().getLogin().logout(); + DbHandler().getLogin().logout(); }, std::placeholders::_1)); // Add a Search control. diff --git a/src/ui/LmsApplication.hpp b/src/ui/LmsApplication.hpp index f1f814d0..3a559953 100644 --- a/src/ui/LmsApplication.hpp +++ b/src/ui/LmsApplication.hpp @@ -20,31 +20,42 @@ #ifndef LMS_APPLICATION_HPP #define LMS_APPLICATION_HPP +#include #include -#include "common/SessionData.hpp" +#include "database/DatabaseHandler.hpp" +#include "resource/CoverResource.hpp" namespace UserInterface { - class LmsApplication : public Wt::WApplication { public: - static Wt::WApplication *create(const Wt::WEnvironment& env, boost::filesystem::path dbPath); + static LmsApplication* instance(); LmsApplication(const Wt::WEnvironment& env, boost::filesystem::path dbPath); + // Session application data + CoverResource* getCoverResource() { return _coverResource; } + Database::Handler& getDbHandler() { return _db;} + private: void handleAuthEvent(void); void createFirstConnectionUI(); void createLmsUI(); - SessionData _sessionData; - + Database::Handler _db; + CoverResource* _coverResource; }; +// Helpers to get session data +Database::Handler& DbHandler(); +Wt::Dbo::Session& DboSession(); + +const Wt::Auth::User& CurrentAuthUser(); +Database::User::pointer CurrentUser(); } // namespace UserInterface diff --git a/src/ui/approot/templates.xml b/src/ui/approot/templates.xml index c4f1bf71..b55f513b 100644 --- a/src/ui/approot/templates.xml +++ b/src/ui/approot/templates.xml @@ -229,6 +229,17 @@
${bitrate-info}
+ +
+ +
+ ${encoding} +
+
+ ${encoding-info} +
@@ -327,7 +338,7 @@
-
${text}
+
${text}
@@ -341,7 +352,9 @@
-
${name}
+
+
${name}
+
@@ -376,9 +389,34 @@
+ + + + -
-
${player}
+
+
+
+
+ +
+
+
diff --git a/src/ui/audio/desktop/AudioMediaPlayer.cpp b/src/ui/audio/desktop/AudioMediaPlayer.cpp index e0ee418d..ebdc6fb3 100644 --- a/src/ui/audio/desktop/AudioMediaPlayer.cpp +++ b/src/ui/audio/desktop/AudioMediaPlayer.cpp @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include "AudioMediaPlayer.hpp" @@ -32,19 +30,16 @@ namespace UserInterface { namespace Desktop { Wt::WMediaPlayer::Encoding -AudioMediaPlayer::getEncoding() +AudioMediaPlayer::getBestEncoding() { - const Wt::WEnvironment& env = Wt::WApplication::instance()->environment(); - - if (env.agentIsIE()) - return Wt::WMediaPlayer::MP3; - else - return Wt::WMediaPlayer::OGA; + // MP3 seems to be better supported everywhere + return Wt::WMediaPlayer::MP3; } -AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent) +AudioMediaPlayer::AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent) : Wt::WContainerWidget(parent), - _mediaResource(nullptr) + _mediaResource(nullptr), + _encoding(encoding) { this->setStyleClass("mediaplayer"); this->setHeight(90); @@ -52,6 +47,21 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent) Wt::WVBoxLayout* mainLayout = new Wt::WVBoxLayout(); this->setLayout(mainLayout); + /* TODO add media info here + // Current Media info + Wt::WHBoxLayout *currentMediaLayout = new Wt::WHBoxLayout(); + mainLayout->addLayout(currentMediaLayout); + + currentMediaLayout->addWidget( _mediaCover = new Wt::WImage()); + _mediaCover->setImageLink( Wt::WLink("images/unknown-cover.jpg") ); + + Wt::WVBoxLayout* mediaInfoLayout = new Wt::WVBoxLayout(); + currentMediaLayout->addLayout(mediaInfoLayout, 1); + + mediaInfoLayout->addWidget( _mediaTitle = new Wt::WText()); + mediaInfoLayout->addWidget( _mediaArtistRelease = new Wt::WText()); + */ + // Time control Wt::WHBoxLayout *sliderLayout = new Wt::WHBoxLayout(); mainLayout->addLayout(sliderLayout); @@ -61,6 +71,7 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent) sliderLayout->addWidget(_duration = new Wt::WText("00:00:00")); _duration->setLineHeight(30); + // Controls Wt::WHBoxLayout *controlsLayout = new Wt::WHBoxLayout(); mainLayout->addLayout(controlsLayout); @@ -68,7 +79,6 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent) 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("<<"); @@ -112,7 +122,7 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent) controlsLayout->addWidget(shuffle); _mediaPlayer = new Wt::WMediaPlayer( Wt::WMediaPlayer::Audio, btnContainer ); - _mediaPlayer->addSource( getEncoding(), "" ); + _mediaPlayer->addSource( _encoding, "" ); _mediaPlayer->ended().connect(this, &AudioMediaPlayer::handleTrackEnded); _mediaPlayer->setControlsWidget( 0 ); @@ -148,15 +158,13 @@ AudioMediaPlayer::loadPlayer(void) { _mediaPlayer->clearSources(); - _mediaInternalLink.setResource( nullptr ); if (_mediaResource) delete _mediaResource; assert( _currentParameters ); _mediaResource = new AvConvTranscodeStreamResource( *_currentParameters, this ); - _mediaInternalLink.setResource( _mediaResource ); - _mediaPlayer->addSource( getEncoding(), _mediaInternalLink ); + _mediaPlayer->addSource( getEncoding(), Wt::WLink(_mediaResource)); } void diff --git a/src/ui/audio/desktop/AudioMediaPlayer.hpp b/src/ui/audio/desktop/AudioMediaPlayer.hpp index 2f6a00fd..1c319e43 100644 --- a/src/ui/audio/desktop/AudioMediaPlayer.hpp +++ b/src/ui/audio/desktop/AudioMediaPlayer.hpp @@ -26,11 +26,12 @@ #include #include #include -#include #include +#include #include "transcode/Parameters.hpp" #include "resource/AvConvTranscodeStreamResource.hpp" +#include "resource/CoverResource.hpp" namespace UserInterface { namespace Desktop { @@ -38,14 +39,15 @@ namespace Desktop { class AudioMediaPlayer : public Wt::WContainerWidget { public: + static Wt::WMediaPlayer::Encoding getBestEncoding(); - // Encoding is set based on environment - static Wt::WMediaPlayer::Encoding getEncoding(); - - AudioMediaPlayer( Wt::WContainerWidget *parent = 0); + AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0); void load(const Transcode::Parameters& parameters); + // Accessors + Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; } + // Signal slots Wt::Signal& playbackEnded() {return _playbackEnded;} Wt::Signal& playNext() {return _playNext;} @@ -53,6 +55,7 @@ class AudioMediaPlayer : public Wt::WContainerWidget Wt::Signal& shuffle() {return _shuffle;} Wt::Signal& loop() {return _loop;} + private: void handlePlayOffset(int offsetSecs); @@ -76,7 +79,12 @@ class AudioMediaPlayer : public Wt::WContainerWidget // Core Wt::WMediaPlayer* _mediaPlayer; AvConvTranscodeStreamResource* _mediaResource; - Wt::WLink _mediaInternalLink; + Wt::WMediaPlayer::Encoding _encoding; + + // Media info + Wt::WImage* _mediaCover; + Wt::WText* _mediaTitle; + Wt::WText* _mediaArtistRelease; // Controls std::shared_ptr _currentParameters; diff --git a/src/ui/audio/desktop/DesktopAudio.cpp b/src/ui/audio/desktop/DesktopAudio.cpp index b1e7d103..9e538875 100644 --- a/src/ui/audio/desktop/DesktopAudio.cpp +++ b/src/ui/audio/desktop/DesktopAudio.cpp @@ -32,6 +32,7 @@ #include #include "logger/Logger.hpp" +#include "LmsApplication.hpp" #include "TableFilter.hpp" #include "KeywordSearchFilter.hpp" @@ -51,9 +52,12 @@ void WPopupMenuClear(Wt::WPopupMenu* menu) namespace UserInterface { namespace Desktop { -Audio::Audio(SessionData& sessionData, Wt::WContainerWidget* parent) +// Special playlist generated each time the playque gets changed +// Restored at the beginning of the session +static const std::string CurrentQueuePlaylistName = "__current__"; + +Audio::Audio(Wt::WContainerWidget* parent) : UserInterface::Audio(parent), -_db(sessionData.getDatabaseHandler()), _mediaPlayer(nullptr), _trackView(nullptr), _playQueue(nullptr) @@ -65,15 +69,15 @@ _playQueue(nullptr) // Filters Wt::WHBoxLayout *filterLayout = new Wt::WHBoxLayout(); - TableFilterGenre *filterGenre = new TableFilterGenre(_db); + TableFilterGenre *filterGenre = new TableFilterGenre(); filterLayout->addWidget(filterGenre); _filterChain.addFilter(filterGenre); - TableFilterArtist *filterArtist = new TableFilterArtist(_db); + TableFilterArtist *filterArtist = new TableFilterArtist(); filterLayout->addWidget(filterArtist); _filterChain.addFilter(filterArtist); - TableFilterRelease *filterRelease = new TableFilterRelease(_db); + TableFilterRelease *filterRelease = new TableFilterRelease(); filterLayout->addWidget(filterRelease); _filterChain.addFilter(filterRelease); @@ -84,7 +88,7 @@ _playQueue(nullptr) Wt::WVBoxLayout* trackLayout = new Wt::WVBoxLayout(); - _trackView = new TrackView(_db); + _trackView = new TrackView(); trackLayout->addWidget(_trackView, 1); Wt::WHBoxLayout* trackControls = new Wt::WHBoxLayout(); @@ -105,18 +109,32 @@ _playQueue(nullptr) _filterChain.addFilter(_trackView); - _playQueue = new PlayQueue(_db); + _playQueue = new PlayQueue(); // Playlist/PlayQueue { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); Wt::WContainerWidget* playQueueContainer = new Wt::WContainerWidget(); playQueueContainer->setStyleClass("playqueue"); Wt::WVBoxLayout* playQueueLayout = new Wt::WVBoxLayout(); playQueueContainer->setLayout(playQueueLayout); - _mediaPlayer = new AudioMediaPlayer(); + // Determine the encoding to be used + 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( _playQueue, 1); @@ -165,6 +183,11 @@ _playQueue(nullptr) playQueueLayout->addLayout(playlistControls); mainLayout->addWidget(playQueueContainer, 0, 0, 2, 1); + + // Load the last known queue + playlistLoadToPlayqueue(CurrentQueuePlaylistName); + // Select the last known playing track + _playQueue->select(CurrentUser()->getCurPlayingTrackPos()); } mainLayout->setRowStretch(1, 1); @@ -197,6 +220,13 @@ _playQueue(nullptr) _mediaPlayer->shuffle().connect(boost::bind(&PlayQueue::setShuffle, _playQueue, _1)); _mediaPlayer->loop().connect(boost::bind(&PlayQueue::setLoop,_playQueue, _1)); + _playQueue->tracksUpdated().connect(std::bind([=] () { + LMS_LOG(MOD_UI, SEV_INFO) << "Playqueue updated!"; + + playlistSaveFromPlayqueue(CurrentQueuePlaylistName); + })); + + playlistRefreshMenus(); } @@ -250,14 +280,10 @@ Audio::playlistShowSaveNewDialog() void Audio::playlistShowSaveDialog(std::string playlistName) { - Wt::Dbo::Transaction transaction(_db.getSession()); - - Database::User::pointer user = _db.getCurrentUser(); - if (!user) - return; + Wt::Dbo::Transaction transaction(DboSession()); // Actually create the dialog only if the given list already exists - if (Database::Playlist::get(_db.getSession(), playlistName, user)) + if (Database::Playlist::get(DboSession(), playlistName, CurrentUser())) { Wt::WMessageBox *messageBox = new Wt::WMessageBox ("Overwrite playlist", @@ -287,20 +313,16 @@ Audio::playlistSaveFromPlayqueue(std::string playlistName) { LMS_LOG(MOD_UI, SEV_INFO) << "Saving playqueue to playlist '" << playlistName << "'"; - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - Database::User::pointer user = _db.getCurrentUser(); - if (!user) - return; - - Database::Playlist::pointer playlist = Database::Playlist::get(_db.getSession(), playlistName, user); + Database::Playlist::pointer playlist = Database::Playlist::get(DboSession(), playlistName, CurrentUser()); if (playlist) { LMS_LOG(MOD_UI, SEV_INFO) << "Erasing playlist '" << playlistName << "'"; playlist.remove(); } - playlist = Database::Playlist::create(_db.getSession(), playlistName, false, user); + playlist = Database::Playlist::create(DboSession(), playlistName, false, CurrentUser()); std::vector trackIds; _playQueue->getTracks(trackIds); @@ -308,10 +330,10 @@ Audio::playlistSaveFromPlayqueue(std::string playlistName) int pos = 0; BOOST_FOREACH(Database::Track::id_type trackId, trackIds) { - Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId); + Database::Track::pointer track = Database::Track::getById(DboSession(), trackId); if (track) - Database::PlaylistEntry::create(_db.getSession(), track, playlist, pos++); + Database::PlaylistEntry::create(DboSession(), track, playlist, pos++); } LMS_LOG(MOD_UI, SEV_INFO) << "Saving playqueue to playlist '" << playlistName << "' done. Contains " << pos << " entries"; @@ -322,17 +344,17 @@ Audio::playlistLoadToPlayqueue(std::string playlistName) { LMS_LOG(MOD_UI, SEV_DEBUG) << "Loading playlist '" << playlistName << "' to playqueue"; - Wt::Dbo::Transaction transaction(_db.getSession()); + std::vector entries; - Database::User::pointer user = _db.getCurrentUser(); - if (!user) - return; + { + Wt::Dbo::Transaction transaction(DboSession()); - Database::Playlist::pointer playlist = Database::Playlist::get(_db.getSession(), playlistName, user); - if (!playlist) - return; + Database::Playlist::pointer playlist = Database::Playlist::get(DboSession(), playlistName, CurrentUser()); + if (!playlist) + return; - std::vector entries = Database::PlaylistEntry::getEntries(_db.getSession(), playlist); + entries = Database::PlaylistEntry::getEntries(DboSession(), playlist); + } _playQueue->clear(); _playQueue->addTracks(entries); @@ -355,12 +377,9 @@ Audio::playlistShowDeleteDialog(std::string name) messageBox->buttonClicked().connect(std::bind([=] () { if (messageBox->buttonResult() == Wt::Yes) { - Wt::Dbo::Transaction transaction(_db.getSession()); - Database::User::pointer user = _db.getCurrentUser(); - if (!user) - return; + Wt::Dbo::Transaction transaction(DboSession()); - Database::Playlist::pointer playlist = Database::Playlist::get(_db.getSession(), name, user); + Database::Playlist::pointer playlist = Database::Playlist::get(DboSession(), name, CurrentUser()); if (playlist) playlist.remove(); @@ -376,11 +395,7 @@ Audio::playlistShowDeleteDialog(std::string name) void Audio::playlistRefreshMenus() { - Wt::Dbo::Transaction transaction(_db.getSession()); - - Database::User::pointer user = _db.getCurrentUser(); - if (!user) - return; + Wt::Dbo::Transaction transaction(DboSession()); // Clear playlists in each menu LMS_LOG(MOD_UI, SEV_DEBUG) << "Save item count: " << _popupMenuSave->count(); @@ -395,10 +410,13 @@ Audio::playlistRefreshMenus() })); _popupMenuSave->addSeparator(); - std::vector playlists = Database::Playlist::get(_db.getSession(), user); + std::vector playlists = Database::Playlist::get(DboSession(), CurrentUser()); BOOST_FOREACH(Database::Playlist::pointer playlist, playlists) { + if (playlist->getName() == CurrentQueuePlaylistName) + continue; + // Add playlists in each menu _popupMenuDelete->addItem(playlist->getName())->triggered().connect(std::bind([=] () { @@ -481,7 +499,7 @@ Audio::playSelectedTracks(PlayQueueAddType addType) } void -Audio::playTrack(boost::filesystem::path p) +Audio::playTrack(boost::filesystem::path p, int pos) { LMS_LOG(MOD_UI, SEV_DEBUG) << "play track '" << p << "'"; try { @@ -490,26 +508,22 @@ Audio::playTrack(boost::filesystem::path p) // Get user preferences { - Wt::Dbo::Transaction transaction(_db.getSession()); - Database::User::pointer user = _db.getCurrentUser(); - if (user) - bitrate = user->getAudioBitrate(); - else - { - LMS_LOG(MOD_UI, SEV_ERROR) << "Can't play: user does not exists!"; - return; // TODO logout? - } + 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(AudioMediaPlayer::getEncoding()) + switch (_mediaPlayer->getEncoding()) { case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break; - case Wt::WMediaPlayer::M4A: encoding = Transcode::Format::M4A; 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; } diff --git a/src/ui/audio/desktop/DesktopAudio.hpp b/src/ui/audio/desktop/DesktopAudio.hpp index 19b70f5f..7b5a2d75 100644 --- a/src/ui/audio/desktop/DesktopAudio.hpp +++ b/src/ui/audio/desktop/DesktopAudio.hpp @@ -24,8 +24,6 @@ #include -#include "common/SessionData.hpp" - #include "AudioMediaPlayer.hpp" #include "TrackView.hpp" #include "PlayQueue.hpp" @@ -42,7 +40,7 @@ class Audio : public UserInterface::Audio public: - Audio(SessionData& sessionData, Wt::WContainerWidget* parent = 0); + Audio(Wt::WContainerWidget* parent = 0); void search(std::string searchText); @@ -55,7 +53,7 @@ class Audio : public UserInterface::Audio void playlistShowDeleteDialog(std::string name); void playlistRefreshMenus(); - void playTrack(boost::filesystem::path p); + void playTrack(boost::filesystem::path p, int pos); enum PlayQueueAddType { @@ -68,8 +66,6 @@ class Audio : public UserInterface::Audio void handlePlaylistSelected(Wt::WString name); - Database::Handler& _db; - AudioMediaPlayer* _mediaPlayer; TrackView* _trackView; PlayQueue* _playQueue; diff --git a/src/ui/audio/desktop/PlayQueue.cpp b/src/ui/audio/desktop/PlayQueue.cpp index 8d600fc0..3d592d83 100644 --- a/src/ui/audio/desktop/PlayQueue.cpp +++ b/src/ui/audio/desktop/PlayQueue.cpp @@ -22,16 +22,14 @@ #include #include -#include #include #include #include #include -#include "resource/CoverResource.hpp" - #include "logger/Logger.hpp" +#include "LmsApplication.hpp" #include "PlayQueue.hpp" static const int TrackInfoRole = Wt::UserRole; @@ -272,9 +270,8 @@ class PlayQueueItemDelegate : public Wt::WItemDelegate }; -PlayQueue::PlayQueue(Database::Handler& db, Wt::WContainerWidget* parent) +PlayQueue::PlayQueue(Wt::WContainerWidget* parent) : Wt::WTableView(parent), -_db(db), _curPlayedTrackPos(trackPosInvalid), _trackSelector(new TrackSelector()) { @@ -316,7 +313,6 @@ _trackSelector(new TrackSelector()) }, std::placeholders::_1, std::placeholders::_2)); - _coverResource = new CoverResource(db, 64); } void @@ -358,15 +354,26 @@ PlayQueue::play(int rowId) playNext(); } +void +PlayQueue::select(int rowId) +{ + // Update the track selector to use the requested track as current position + _trackSelector->setPosByRowId(rowId); + + Wt::WTableView::select(_model->index(_trackSelector->getCurrent(), 0)); + + this->scrollTo( _model->index(_trackSelector->getCurrent(), 0)); +} + void PlayQueue::addTracks(const std::vector& trackIds) { // Add tracks to model - Wt::Dbo::Transaction transaction(_db.getSession()); - + // BOOST_FOREACH(Database::Track::id_type trackId, trackIds) { - Database::Track::pointer track (Database::Track::getById(_db.getSession(), trackId)); + Wt::Dbo::Transaction transaction(DboSession()); + Database::Track::pointer track (Database::Track::getById(DboSession(), trackId)); if (track) { @@ -378,9 +385,9 @@ PlayQueue::addTracks(const std::vector& trackIds) std::string coverUrl; if (track->hasCover()) - coverUrl = _coverResource->getTrackUrl(track.id()); + coverUrl = LmsApplication::instance()->getCoverResource()->getTrackUrl(track.id(), 64); else - coverUrl = "images/unknown-cover.jpg"; + coverUrl = LmsApplication::instance()->getCoverResource()->getUnkownTrackUrl(64); _model->setData(dataRow, COLUMN_ID_COVER, coverUrl, Wt::DecorationRole); TrackInfo trackInfo; @@ -392,6 +399,8 @@ PlayQueue::addTracks(const std::vector& trackIds) } _trackSelector->setSize( _model->rowCount() ); + + _sigTracksUpdated.emit(); } void @@ -402,6 +411,8 @@ PlayQueue::clear(void) // Reset play id _curPlayedTrackPos = trackPosInvalid; _trackSelector->setSize( 0 ); + + _sigTracksUpdated.emit(); } void @@ -449,17 +460,17 @@ PlayQueue::playPrevious(void) bool PlayQueue::readTrack(int rowPos) { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); LMS_LOG(MOD_UI, SEV_DEBUG) << "Reading track at pos " << rowPos; Database::Track::id_type trackId = boost::any_cast(_model->data(rowPos, COLUMN_ID_TRACK_ID, Wt::UserRole)); - Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId); + Database::Track::pointer track = Database::Track::getById(DboSession(), trackId); if (track) { setPlayingTrackPos(rowPos); - _sigTrackPlay.emit(track->getPath()); + _sigTrackPlay.emit(track->getPath(), rowPos); this->scrollTo( _model->index(_trackSelector->getCurrent(), 0)); @@ -505,6 +516,7 @@ PlayQueue::delSelected(void) _trackSelector->setSize(_model->rowCount()); renumber(minId, _model->rowCount() - 1); + _sigTracksUpdated.emit(); } void @@ -512,6 +524,7 @@ PlayQueue::delAll(void) { _model->removeRows(0, _model->rowCount()); _trackSelector->setSize(0); + _sigTracksUpdated.emit(); } void @@ -552,6 +565,8 @@ PlayQueue::moveSelectedUp(void) this->setSelectedIndexes( newIndexSet ); renumber(minId, maxId); + + _sigTracksUpdated.emit(); } @@ -593,6 +608,8 @@ PlayQueue::moveSelectedDown(void) this->setSelectedIndexes( newIndexSet ); renumber(minId, maxId); + + _sigTracksUpdated.emit(); } void diff --git a/src/ui/audio/desktop/PlayQueue.hpp b/src/ui/audio/desktop/PlayQueue.hpp index 9d150a41..ed055c7f 100644 --- a/src/ui/audio/desktop/PlayQueue.hpp +++ b/src/ui/audio/desktop/PlayQueue.hpp @@ -23,7 +23,7 @@ #include #include -#include "database/DatabaseHandler.hpp" +#include "database/Types.hpp" #include "resource/CoverResource.hpp" @@ -36,7 +36,7 @@ class TrackSelector; class PlayQueue : public Wt::WTableView { public: - PlayQueue(Database::Handler& db, Wt::WContainerWidget* parent = 0); + PlayQueue(Wt::WContainerWidget* parent = 0); void addTracks(const std::vector& trackIds); void getTracks(std::vector& trackIds) const; @@ -49,6 +49,7 @@ class PlayQueue : public Wt::WTableView // Play functions void play(void); // Play the queue from the beginning void play(int rowId); // Play the queue from the given rowId + void select(int rowId); // Select the given rowId void playNext(void); // Play the next track void playPrevious(void); // Play the previous track @@ -59,7 +60,10 @@ class PlayQueue : public Wt::WTableView void moveSelectedDown(void); // Signals - Wt::Signal< boost::filesystem::path >& playTrack() { return _sigTrackPlay; } + // Emitted when a song has to be played + Wt::Signal< boost::filesystem::path, int >& playTrack() { return _sigTrackPlay; } + // Emitted when the list has changed + Wt::Signal< void >& tracksUpdated() { return _sigTracksUpdated; } // Slots void handlePlaybackComplete(void); @@ -72,16 +76,13 @@ class PlayQueue : public Wt::WTableView void setPlayingTrackPos(int newRowPos); void renumber(int firstId, int lastId); - Wt::Signal< boost::filesystem::path > _sigTrackPlay; - - Database::Handler& _db; + Wt::Signal< boost::filesystem::path, int > _sigTrackPlay; + Wt::Signal< void > _sigTracksUpdated; Wt::WStandardItemModel* _model; PlayQueueItemDelegate* _itemDelegate; - CoverResource* _coverResource; - int _curPlayedTrackPos; std::unique_ptr _trackSelector; diff --git a/src/ui/audio/desktop/TableFilter.cpp b/src/ui/audio/desktop/TableFilter.cpp index 6b8f1010..664960d7 100644 --- a/src/ui/audio/desktop/TableFilter.cpp +++ b/src/ui/audio/desktop/TableFilter.cpp @@ -22,9 +22,9 @@ #include #include "database/Types.hpp" - #include "logger/Logger.hpp" +#include "LmsApplication.hpp" #include "TableFilter.hpp" namespace UserInterface { @@ -32,15 +32,14 @@ namespace Desktop { using namespace Database; -TableFilterGenre::TableFilterGenre(Database::Handler& db, Wt::WContainerWidget* parent) -: Wt::WTableView( parent ), Filter(), -_db(db) +TableFilterGenre::TableFilterGenre(Wt::WContainerWidget* parent) +: Wt::WTableView( parent ), Filter() { const std::vector columnNames = {"Genre", "Tracks"}; SearchFilter filter; - Genre::updateGenreQueryModel(_db.getSession(), _queryModel, filter, columnNames); + Genre::updateGenreQueryModel(DboSession(), _queryModel, filter, columnNames); this->setSelectionMode(Wt::ExtendedSelection); this->setSortingEnabled(true); @@ -83,7 +82,7 @@ TableFilterGenre::layoutSizeChanged (int width, int height) void TableFilterGenre::refresh(SearchFilter& filter) { - Genre::updateGenreQueryModel(_db.getSession(), _queryModel, filter); + Genre::updateGenreQueryModel(DboSession(), _queryModel, filter); } // Get constraint created by this filter @@ -103,15 +102,14 @@ TableFilterGenre::getConstraint(SearchFilter& filter) } } -TableFilterArtist::TableFilterArtist(Database::Handler& db, Wt::WContainerWidget* parent) -: Wt::WTableView( parent ), Filter(), -_db(db) +TableFilterArtist::TableFilterArtist(Wt::WContainerWidget* parent) +: Wt::WTableView( parent ), Filter() { const std::vector columnNames = {"Artist", "Releases", "Tracks"}; SearchFilter filter; - Track::updateArtistQueryModel(_db.getSession(), _queryModel, filter, columnNames); + Track::updateArtistQueryModel(DboSession(), _queryModel, filter, columnNames); this->setSelectionMode(Wt::ExtendedSelection); this->setSortingEnabled(true); @@ -155,7 +153,7 @@ TableFilterArtist::layoutSizeChanged (int width, int height) void TableFilterArtist::refresh(SearchFilter& filter) { - Track::updateArtistQueryModel(_db.getSession(), _queryModel, filter); + Track::updateArtistQueryModel(DboSession(), _queryModel, filter); } // Get constraint created by this filter @@ -175,15 +173,14 @@ TableFilterArtist::getConstraint(SearchFilter& filter) } } -TableFilterRelease::TableFilterRelease(Database::Handler& db, Wt::WContainerWidget* parent) -: Wt::WTableView( parent ), Filter(), -_db(db) +TableFilterRelease::TableFilterRelease(Wt::WContainerWidget* parent) +: Wt::WTableView( parent ), Filter() { const std::vector columnNames = {"Release", "Date", "Tracks"}; SearchFilter filter; - Track::updateReleaseQueryModel(_db.getSession(), _queryModel, filter, columnNames); + Track::updateReleaseQueryModel(DboSession(), _queryModel, filter, columnNames); this->setSelectionMode(Wt::ExtendedSelection); this->setSortingEnabled(true); @@ -234,7 +231,7 @@ TableFilterRelease::layoutSizeChanged (int width, int height) void TableFilterRelease::refresh(SearchFilter& filter) { - Track::updateReleaseQueryModel(_db.getSession(), _queryModel, filter); + Track::updateReleaseQueryModel(DboSession(), _queryModel, filter); } // Get constraint created by this filter diff --git a/src/ui/audio/desktop/TableFilter.hpp b/src/ui/audio/desktop/TableFilter.hpp index d5bc6024..ca4b8d2d 100644 --- a/src/ui/audio/desktop/TableFilter.hpp +++ b/src/ui/audio/desktop/TableFilter.hpp @@ -25,7 +25,7 @@ #include #include "Filter.hpp" -#include "database/DatabaseHandler.hpp" +#include "database/Types.hpp" namespace UserInterface { namespace Desktop { @@ -33,7 +33,7 @@ namespace Desktop { class TableFilterGenre : public Wt::WTableView, public Filter { public: - TableFilterGenre(Database::Handler& db, Wt::WContainerWidget* parent = 0); + TableFilterGenre(Wt::WContainerWidget* parent = 0); // Set constraints on this filter void refresh(Database::SearchFilter& filter); @@ -51,8 +51,6 @@ class TableFilterGenre : public Wt::WTableView, public Filter SigDoubleClicked _sigDoubleClicked; - Database::Handler& _db; - // Name, track count Wt::Dbo::QueryModel _queryModel; }; @@ -60,7 +58,7 @@ class TableFilterGenre : public Wt::WTableView, public Filter class TableFilterArtist : public Wt::WTableView, public Filter { public: - TableFilterArtist(Database::Handler& db, Wt::WContainerWidget* parent = 0); + TableFilterArtist(Wt::WContainerWidget* parent = 0); // Set constraints on this filter void refresh(Database::SearchFilter& filter); @@ -78,8 +76,6 @@ class TableFilterArtist : public Wt::WTableView, public Filter SigDoubleClicked _sigDoubleClicked; - Database::Handler& _db; - // Name, track count Wt::Dbo::QueryModel _queryModel; }; @@ -87,7 +83,7 @@ class TableFilterArtist : public Wt::WTableView, public Filter class TableFilterRelease : public Wt::WTableView, public Filter { public: - TableFilterRelease(Database::Handler& db, Wt::WContainerWidget* parent = 0); + TableFilterRelease(Wt::WContainerWidget* parent = 0); // Set constraints on this filter void refresh(Database::SearchFilter& filter); @@ -105,8 +101,6 @@ class TableFilterRelease : public Wt::WTableView, public Filter SigDoubleClicked _sigDoubleClicked; - Database::Handler& _db; - // Name, track count Wt::Dbo::QueryModel _queryModel; }; diff --git a/src/ui/audio/desktop/TrackView.cpp b/src/ui/audio/desktop/TrackView.cpp index 63c611b6..3ceaf7f9 100644 --- a/src/ui/audio/desktop/TrackView.cpp +++ b/src/ui/audio/desktop/TrackView.cpp @@ -25,14 +25,14 @@ #include "logger/Logger.hpp" +#include "LmsApplication.hpp" #include "TrackView.hpp" namespace UserInterface { namespace Desktop { -TrackView::TrackView( Database::Handler& db, Wt::WContainerWidget* parent) -: Wt::WTableView( parent ), -_db(db) +TrackView::TrackView(Wt::WContainerWidget* parent) +: Wt::WTableView( parent ) { static const std::vector columnNames = @@ -50,7 +50,7 @@ _db(db) Database::SearchFilter filter; - Database::Track::updateTracksQueryModel(_db.getSession(), _queryModel, filter, columnNames); + Database::Track::updateTracksQueryModel(DboSession(), _queryModel, filter, columnNames); _queryModel.setBatchSize(300); @@ -111,7 +111,7 @@ _db(db) void TrackView::refresh(Database::SearchFilter& filter) { - Database::Track::updateTracksQueryModel(_db.getSession(), _queryModel, filter); + Database::Track::updateTracksQueryModel(DboSession(), _queryModel, filter); } void diff --git a/src/ui/audio/desktop/TrackView.hpp b/src/ui/audio/desktop/TrackView.hpp index 77819bc8..494cd965 100644 --- a/src/ui/audio/desktop/TrackView.hpp +++ b/src/ui/audio/desktop/TrackView.hpp @@ -34,7 +34,7 @@ class TrackView : public Wt::WTableView, public Filter { public: - TrackView( Database::Handler& db, Wt::WContainerWidget* parent = 0); + TrackView(Wt::WContainerWidget* parent = 0); // Filter interface // Set constraints created by parent filters @@ -62,8 +62,6 @@ class TrackView : public Wt::WTableView, public Filter SigTrackDoubleClicked _sigTrackDoubleClicked; - Database::Handler& _db; - typedef Database::Track::pointer ResultType; Wt::Dbo::QueryModel< ResultType > _queryModel; Wt::WTableView* _tableView; diff --git a/src/ui/audio/mobile/ArtistSearch.cpp b/src/ui/audio/mobile/ArtistSearch.cpp index bbdb4d40..3428bb07 100644 --- a/src/ui/audio/mobile/ArtistSearch.cpp +++ b/src/ui/audio/mobile/ArtistSearch.cpp @@ -21,14 +21,15 @@ #include #include +#include "LmsApplication.hpp" + #include "ArtistSearch.hpp" namespace UserInterface { namespace Mobile { -ArtistSearch::ArtistSearch(Database::Handler& db, Wt::WContainerWidget *parent) +ArtistSearch::ArtistSearch(Wt::WContainerWidget *parent) : Wt::WContainerWidget(parent), -_db(db), _resCount(0) { Wt::WTemplate *title = new Wt::WTemplate(this); @@ -60,10 +61,10 @@ ArtistSearch::addResults(Database::SearchFilter filter, std::size_t nb) std::vector artists; { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Request one more to see if more results are to be expected - artists = Database::Track::getArtists(_db.getSession(), filter, _resCount, nb + 1); + artists = Database::Track::getArtists(DboSession(), filter, _resCount, nb + 1); } bool expectMoreResults; diff --git a/src/ui/audio/mobile/ArtistSearch.hpp b/src/ui/audio/mobile/ArtistSearch.hpp index 937b89bb..f5e30f93 100644 --- a/src/ui/audio/mobile/ArtistSearch.hpp +++ b/src/ui/audio/mobile/ArtistSearch.hpp @@ -23,7 +23,7 @@ #include #include -#include "database/DatabaseHandler.hpp" +#include "database/Types.hpp" namespace UserInterface { namespace Mobile { @@ -32,7 +32,7 @@ class ArtistSearch : public Wt::WContainerWidget { public: - ArtistSearch(Database::Handler& db, Wt::WContainerWidget *parent = 0); + ArtistSearch(Wt::WContainerWidget *parent = 0); void search(Database::SearchFilter filter, std::size_t nb); @@ -48,7 +48,6 @@ class ArtistSearch : public Wt::WContainerWidget void clear(void); void addResults(Database::SearchFilter filter, size_t nb); - Database::Handler& _db; std::size_t _resCount; }; diff --git a/src/ui/audio/mobile/MobileAudio.cpp b/src/ui/audio/mobile/MobileAudio.cpp index c5d5c87b..04bd79e7 100644 --- a/src/ui/audio/mobile/MobileAudio.cpp +++ b/src/ui/audio/mobile/MobileAudio.cpp @@ -24,10 +24,11 @@ #include #include #include -#include #include #include +#include "LmsApplication.hpp" + #include "MobileAudio.hpp" #include "ArtistSearch.hpp" @@ -40,12 +41,12 @@ namespace UserInterface { namespace Mobile { -Audio::Audio(Database::Handler& db, Wt::WContainerWidget *parent) -: UserInterface::Audio(parent), -_db(db) +Audio::Audio(Wt::WContainerWidget *parent) +: UserInterface::Audio(parent) { // Root div has to be a "container" - this->setStyleClass("container"); + this->setStyleClass("container-fluid"); + this->setPadding(60, Wt::Bottom); Wt::WTemplate* search = new Wt::WTemplate(this); search->setTemplateText(Wt::WString::tr("mobile-search")); @@ -56,15 +57,33 @@ _db(db) search->bindWidget("search", edit); search->setMargin(10); - ArtistSearch* artistSearch = new ArtistSearch(_db, this); - ReleaseSearch* releaseSearch = new ReleaseSearch(_db, this); - TrackSearch* trackSearch = new TrackSearch(_db, this); + ArtistSearch* artistSearch = new ArtistSearch(this); + ReleaseSearch* releaseSearch = new ReleaseSearch(this); + TrackSearch* trackSearch = new TrackSearch(this); - Wt::WTemplate* playerTemplate = new Wt::WTemplate(this); - playerTemplate->setTemplateText(Wt::WString::tr("mobile-audio-player")); + Wt::WTemplate* footer = new Wt::WTemplate(this); + footer->setTemplateText(Wt::WString::tr("mobile-audio-footer")); - AudioMediaPlayer* mediaPlayer = new AudioMediaPlayer(); - playerTemplate->bindWidget("player", mediaPlayer); + // Determine the encoding to be used + Wt::WMediaPlayer::Encoding encoding; + + { + 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 = AudioMediaPlayer::getBestEncoding(); + } + } + + AudioMediaPlayer* mediaPlayer = new AudioMediaPlayer(encoding); + footer->bindWidget("player", mediaPlayer); edit->changed().connect(std::bind([=] () { std::string text = edit->text().toUTF8(); @@ -169,19 +188,21 @@ _db(db) trackSearch->trackPlay().connect(std::bind([=] (Database::Track::id_type id) { LMS_LOG(MOD_UI, SEV_DEBUG) << "Playing track id " << id; - Wt::Dbo::Transaction transaction(_db.getSession()); + // TODO reduce transaction scope here + Wt::Dbo::Transaction transaction(DboSession()); - Database::Track::pointer track = Database::Track::getById(_db.getSession(), id); + Database::Track::pointer track = Database::Track::getById(DboSession(), id); if (track) { // Determine the output format using the encoding of the player Transcode::Format::Encoding encoding; - switch(AudioMediaPlayer::getEncoding()) + switch(mediaPlayer->getEncoding()) { case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break; - case Wt::WMediaPlayer::M4A: encoding = Transcode::Format::M4A; 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; } @@ -190,7 +211,7 @@ _db(db) Transcode::Parameters parameters(inputFile, Transcode::Format::get(encoding)); parameters.setBitrate(Transcode::Stream::Audio, 96000); - mediaPlayer->play(parameters); + mediaPlayer->play(track.id(), parameters); } } , std::placeholders::_1)); diff --git a/src/ui/audio/mobile/MobileAudio.hpp b/src/ui/audio/mobile/MobileAudio.hpp index 143159ad..e10a3a57 100644 --- a/src/ui/audio/mobile/MobileAudio.hpp +++ b/src/ui/audio/mobile/MobileAudio.hpp @@ -22,8 +22,6 @@ #include -#include "database/DatabaseHandler.hpp" - #include "audio/Audio.hpp" namespace UserInterface { @@ -32,13 +30,12 @@ namespace Mobile { class Audio : public UserInterface::Audio { public: - Audio(Database::Handler& db, Wt::WContainerWidget *parent = 0); + Audio(Wt::WContainerWidget *parent = 0); void search(std::string text) {} private: - Database::Handler& _db; }; } // namespace Mobile diff --git a/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp b/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp index d459a8bc..47c2ff0a 100644 --- a/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp +++ b/src/ui/audio/mobile/MobileAudioMediaPlayer.cpp @@ -19,6 +19,11 @@ #include #include +#include +#include +#include + +#include "LmsApplication.hpp" #include "MobileAudioMediaPlayer.hpp" @@ -28,32 +33,73 @@ namespace UserInterface { namespace Mobile { Wt::WMediaPlayer::Encoding -AudioMediaPlayer::getEncoding() +AudioMediaPlayer::getBestEncoding() { - const Wt::WEnvironment& env = Wt::WApplication::instance()->environment(); - - if (env.agentIsIE()) - return Wt::WMediaPlayer::MP3; - else - return Wt::WMediaPlayer::OGA; + // MP3 seems to be better supported everywhere + return Wt::WMediaPlayer::MP3; } -AudioMediaPlayer::AudioMediaPlayer(Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent) +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( getEncoding(), "" ); + _player->addSource( _encoding, "" ); + _player->setControlsWidget( 0 ); + _player->setButton(Wt::WMediaPlayer::Play, play); + _player->setButton(Wt::WMediaPlayer::Pause, pause); + } void -AudioMediaPlayer::play(const Transcode::Parameters& parameters) +AudioMediaPlayer::play(Database::Track::id_type trackId, const Transcode::Parameters& parameters) { + // FIXME memleak here AvConvTranscodeStreamResource *resource = new AvConvTranscodeStreamResource( parameters, this ); _player->clearSources(); - _player->addSource( getEncoding(), Wt::WLink(resource)); + _player->addSource( _encoding, Wt::WLink(resource)); _player->play(); + + _cover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 48))); + + { + 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->getArtistName()) ); + } } } // namespace UserInterface diff --git a/src/ui/audio/mobile/MobileAudioMediaPlayer.hpp b/src/ui/audio/mobile/MobileAudioMediaPlayer.hpp index bcc77753..1b9ab86e 100644 --- a/src/ui/audio/mobile/MobileAudioMediaPlayer.hpp +++ b/src/ui/audio/mobile/MobileAudioMediaPlayer.hpp @@ -22,7 +22,9 @@ #include #include +#include +#include "database/DatabaseHandler.hpp" #include "transcode/Parameters.hpp" namespace UserInterface { @@ -32,15 +34,22 @@ class AudioMediaPlayer : public Wt::WContainerWidget { public: - static Wt::WMediaPlayer::Encoding getEncoding(); + static Wt::WMediaPlayer::Encoding getBestEncoding(); - AudioMediaPlayer(Wt::WContainerWidget *parent = 0); + AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0); - void play(const Transcode::Parameters& parameters); + void play(Database::Track::id_type trackId, const Transcode::Parameters& parameters); + + Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; } private: - Wt::WMediaPlayer *_player; + Wt::WMediaPlayer* _player; + Wt::WMediaPlayer::Encoding _encoding; + + Wt::WImage* _cover; + Wt::WText* _track; + Wt::WText* _artistRelease; }; diff --git a/src/ui/audio/mobile/ReleaseSearch.cpp b/src/ui/audio/mobile/ReleaseSearch.cpp index 0e2d39ac..4f4375f9 100644 --- a/src/ui/audio/mobile/ReleaseSearch.cpp +++ b/src/ui/audio/mobile/ReleaseSearch.cpp @@ -23,23 +23,21 @@ #include #include "logger/Logger.hpp" +#include "LmsApplication.hpp" #include "ReleaseSearch.hpp" namespace UserInterface { namespace Mobile { -ReleaseSearch::ReleaseSearch(Database::Handler& db, Wt::WContainerWidget *parent) +ReleaseSearch::ReleaseSearch(Wt::WContainerWidget *parent) : Wt::WContainerWidget(parent), -_db(db), _resCount(0) { Wt::WTemplate* title = new Wt::WTemplate(this); title->setTemplateText(Wt::WString::tr("mobile-search-title")); title->bindWidget("text", new Wt::WText("Releases", Wt::PlainText)); - - _coverResource = new CoverResource(db, 56); } void @@ -65,10 +63,10 @@ ReleaseSearch::addResults(Database::SearchFilter filter, size_t nb) std::vector releases; { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Request one more to see if more results are to be expected - releases = Database::Track::getReleases(_db.getSession(), filter, _resCount, nb + 1); + releases = Database::Track::getReleases(DboSession(), filter, _resCount, nb + 1); } bool expectMoreResults; @@ -87,7 +85,7 @@ ReleaseSearch::addResults(Database::SearchFilter filter, size_t nb) Wt::WImage *cover = new Wt::WImage(); cover->setStyleClass("center-block"); - cover->setImageLink( Wt::WLink( _coverResource->getReleaseUrl(release))); + cover->setImageLink( Wt::WLink( LmsApplication::instance()->getCoverResource()->getReleaseUrl(release, 56))); releaseWidget->bindWidget("cover", cover); releaseWidget->bindWidget("name", new Wt::WText(Wt::WString::fromUTF8(release), Wt::PlainText)); diff --git a/src/ui/audio/mobile/ReleaseSearch.hpp b/src/ui/audio/mobile/ReleaseSearch.hpp index 97f6e4bb..591ae161 100644 --- a/src/ui/audio/mobile/ReleaseSearch.hpp +++ b/src/ui/audio/mobile/ReleaseSearch.hpp @@ -25,10 +25,6 @@ #include #include -#include "resource/CoverResource.hpp" - -#include "database/DatabaseHandler.hpp" - namespace UserInterface { namespace Mobile { @@ -36,7 +32,7 @@ class ReleaseSearch : public Wt::WContainerWidget { public: - ReleaseSearch(Database::Handler& db, Wt::WContainerWidget *parent = 0); + ReleaseSearch(Wt::WContainerWidget *parent = 0); void search(Database::SearchFilter filter, size_t nb); @@ -52,10 +48,6 @@ class ReleaseSearch : public Wt::WContainerWidget void clear(void); void addResults(Database::SearchFilter filter, size_t nb); - Database::Handler& _db; - - CoverResource* _coverResource; - std::size_t _resCount; }; diff --git a/src/ui/audio/mobile/TrackSearch.cpp b/src/ui/audio/mobile/TrackSearch.cpp index c6c5c46d..0a5e4f28 100644 --- a/src/ui/audio/mobile/TrackSearch.cpp +++ b/src/ui/audio/mobile/TrackSearch.cpp @@ -23,15 +23,15 @@ #include #include "logger/Logger.hpp" +#include "LmsApplication.hpp" #include "TrackSearch.hpp" namespace UserInterface { namespace Mobile { -TrackSearch::TrackSearch(Database::Handler& db, Wt::WContainerWidget *parent) +TrackSearch::TrackSearch(Wt::WContainerWidget *parent) : Wt::WContainerWidget(parent), -_db(db), _resCount(0) { Wt::WTemplate* title = new Wt::WTemplate(this); @@ -39,7 +39,6 @@ _resCount(0) title->bindWidget("text", new Wt::WText("Tracks", Wt::PlainText)); - _coverResource = new CoverResource(db, 56); } void @@ -61,9 +60,9 @@ TrackSearch::search(Database::SearchFilter filter, size_t max) void TrackSearch::addResults(Database::SearchFilter filter, size_t nb) { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - std::vector< Database::Track::pointer > tracks = Database::Track::getTracks(_db.getSession(), filter, _resCount, nb + 1); + std::vector< Database::Track::pointer > tracks = Database::Track::getTracks(DboSession(), filter, _resCount, nb + 1); bool expectMoreResults; if (tracks.size() == nb + 1) @@ -81,7 +80,7 @@ TrackSearch::addResults(Database::SearchFilter filter, size_t nb) Wt::WImage *cover = new Wt::WImage(); cover->setStyleClass("center-block"); - cover->setImageLink( Wt::WLink (_coverResource->getTrackUrl(track.id())) ); + cover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(track.id(), 56)) ); trackWidget->bindWidget("cover", cover); // Track Name (bold) diff --git a/src/ui/audio/mobile/TrackSearch.hpp b/src/ui/audio/mobile/TrackSearch.hpp index 16076df2..6cf3b317 100644 --- a/src/ui/audio/mobile/TrackSearch.hpp +++ b/src/ui/audio/mobile/TrackSearch.hpp @@ -27,8 +27,6 @@ #include "resource/CoverResource.hpp" -#include "database/DatabaseHandler.hpp" - namespace UserInterface { namespace Mobile { @@ -36,7 +34,7 @@ class TrackSearch : public Wt::WContainerWidget { public: - TrackSearch(Database::Handler& db, Wt::WContainerWidget *parent = 0); + TrackSearch(Wt::WContainerWidget *parent = 0); void search(Database::SearchFilter filter, size_t nb); @@ -52,10 +50,6 @@ class TrackSearch : public Wt::WContainerWidget void clear(void); void addResults(Database::SearchFilter filter, size_t nb); - Database::Handler& _db; - - CoverResource* _coverResource; - std::size_t _resCount; }; diff --git a/src/ui/auth/LmsAuth.cpp b/src/ui/auth/LmsAuth.cpp index 565dbab9..eb3a8559 100644 --- a/src/ui/auth/LmsAuth.cpp +++ b/src/ui/auth/LmsAuth.cpp @@ -17,15 +17,16 @@ * along with LMS. If not, see . */ - #include "LmsAuth.hpp" +#include "LmsApplication.hpp" + namespace UserInterface { -LmsAuth::LmsAuth(Database::Handler& db) -: Wt::Auth::AuthWidget(db.getAuthService(), - db.getUserDatabase(), - db.getLogin()) +LmsAuth::LmsAuth() +: Wt::Auth::AuthWidget(DbHandler().getAuthService(), + DbHandler().getUserDatabase(), + DbHandler().getLogin()) { // Root div has to be a container this->setStyleClass("container"); diff --git a/src/ui/auth/LmsAuth.hpp b/src/ui/auth/LmsAuth.hpp index 1e601fd5..bcf8fc7f 100644 --- a/src/ui/auth/LmsAuth.hpp +++ b/src/ui/auth/LmsAuth.hpp @@ -26,15 +26,13 @@ #include #include -#include "database/DatabaseHandler.hpp" - namespace UserInterface { class LmsAuth : public Wt::Auth::AuthWidget { public: - LmsAuth(Database::Handler& db); + LmsAuth(); // LoggedInView is delegated to LmsHome void createLoggedInView () ; diff --git a/src/ui/common/SessionData.cpp b/src/ui/common/SessionData.cpp deleted file mode 100644 index 7ef47a12..00000000 --- a/src/ui/common/SessionData.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 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 "SessionData.hpp" - -namespace UserInterface { - -SessionData::SessionData(boost::filesystem::path dbPath) -: _db(dbPath) -{ -} - -} // namespace UserInterface - diff --git a/src/ui/common/SessionData.hpp b/src/ui/common/SessionData.hpp deleted file mode 100644 index eeba7dde..00000000 --- a/src/ui/common/SessionData.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 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 . - */ - -#ifndef UI_SESSION_DATA_HPP -#define UI_SESSION_DATA_HPP - -#include - -#include "database/DatabaseHandler.hpp" - -namespace UserInterface { - -class SessionData -{ - public: - - SessionData(boost::filesystem::path dbPath); - - Database::Handler& getDatabaseHandler() { return _db;} - const Database::Handler& getDatabaseHandler() const { return _db;} - - private: - - Database::Handler _db; - -}; - -} // namespace UserInterface - -#endif - diff --git a/src/ui/docroot/css/lms.css b/src/ui/docroot/css/lms.css index 68c40fa1..d8888a55 100644 --- a/src/ui/docroot/css/lms.css +++ b/src/ui/docroot/css/lms.css @@ -58,6 +58,7 @@ div.contents { .mobile-search-title { font-weight: bold; height: 32px; + line-height: 32px; background-color: grey; color: white; text-align: center; @@ -96,3 +97,13 @@ div.contents { align-items: center; } +.mobile-audio-footer { + background-color: #f5f5f5; + height: 60px; +} + +.mobile-audio-player-cover { + width: 48px; + height: 48px; +} + diff --git a/src/ui/resource/CoverResource.cpp b/src/ui/resource/CoverResource.cpp index 33f917fa..06e32f62 100644 --- a/src/ui/resource/CoverResource.cpp +++ b/src/ui/resource/CoverResource.cpp @@ -30,26 +30,12 @@ namespace UserInterface { -CoverResource::CoverResource(Database::Handler& db, std::size_t size, Wt::WObject *parent) +const std::string CoverResource::unknownCoverPath = "/images/unknown-cover.jpg"; + +CoverResource::CoverResource(Database::Handler& db, Wt::WObject *parent) : Wt::WResource(parent), -_db(db), -_size(size) +_db(db) { - // Load default cover art - - std::vector data; - - { - std::ifstream ist(Wt::WApplication::instance()->docRoot() + "/images/unknown-cover.jpg"); - char c; - while(ist.get(c)) - data.push_back(c); - } - - _defaultCover.setData(data); - _defaultCover.setMimeType("image/jpeg"); - - _defaultCover.scale(size); } CoverResource:: ~CoverResource() @@ -57,16 +43,59 @@ CoverResource:: ~CoverResource() beingDeleted(); } -std::string -CoverResource::getReleaseUrl(std::string releaseName) +const CoverArt::CoverArt& +CoverResource::getDefaultCover(std::size_t size) { - return url() + "&release=" + releaseName; + auto itCover = _defaultCovers.find(size); + if (itCover == _defaultCovers.end()) + { + // Load default cover art for this size + + CoverArt::CoverArt defaultCover; + + std::vector data; + { + std::ifstream ist(Wt::WApplication::instance()->docRoot() + unknownCoverPath); + char c; + while(ist.get(c)) + data.push_back(c); + } + + defaultCover.setData(data); + defaultCover.setMimeType("image/jpeg"); + defaultCover.scale(size); + + auto res = _defaultCovers.insert(std::make_pair(size, defaultCover)); + itCover = res.first; + } + + return itCover->second; } std::string -CoverResource::getTrackUrl(Database::Track::id_type trackId) +CoverResource::getReleaseUrl(std::string releaseName, std::size_t size) const { - return url()+ "&trackid=" + std::to_string(trackId); + return url() + "&release=" + releaseName + "&size=" + std::to_string(size); +} + +std::string +CoverResource::getTrackUrl(Database::Track::id_type trackId, std::size_t size) const +{ + return url()+ "&trackid=" + std::to_string(trackId) + "&size=" + std::to_string(size); +} + +std::string +CoverResource::getUnkownTrackUrl(size_t size) const +{ + return Wt::WApplication::instance()->docRoot() + unknownCoverPath + "&size=" + std::to_string(size); +} + +void +CoverResource::putCover(Wt::Http::Response& response, const CoverArt::CoverArt& cover) +{ + response.setMimeType( cover.getMimeType() ); + BOOST_FOREACH(unsigned char c, cover.getData()) + response.out().put( c ); } void @@ -75,15 +104,24 @@ CoverResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons // Get the id of the track const std::string *trackIdStr = request.getParameter("trackid"); + const std::string *sizeStr = request.getParameter("size"); const std::string *releaseStr = request.getParameter("release"); std::vector covers; + // Mandatory parameter size + if (!sizeStr) + return; + + std::size_t size = std::stol(*sizeStr); + if (size > maxSize) + return; + if (trackIdStr) { Database::Track::id_type trackId = std::stol(*trackIdStr); std::string path; - bool hasCover = false;; + bool hasCover = false; { // transactions are not thread safe @@ -94,15 +132,13 @@ CoverResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId); if (track) { - hasCover = track->hasCover();; + hasCover = track->hasCover(); path = track->getPath(); } } if (hasCover) - { covers = CoverArt::Grabber::getFromTrack(path); - } } else if (releaseStr) { @@ -115,22 +151,15 @@ CoverResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons BOOST_FOREACH(CoverArt::CoverArt& cover, covers) { - if (cover.scale(_size)) + if (cover.scale(size)) { - response.setMimeType( cover.getMimeType() ); - - BOOST_FOREACH(unsigned char c, cover.getData()) - response.out().put( c ); - + putCover(response, cover); return; } } // If no cover found, just send default one - response.setMimeType( _defaultCover.getMimeType() ); - BOOST_FOREACH(unsigned char c, _defaultCover.getData()) - response.out().put( c ); - + putCover(response, getDefaultCover(size)); } } // namespace UserInterface diff --git a/src/ui/resource/CoverResource.hpp b/src/ui/resource/CoverResource.hpp index c1625718..bdfeaeea 100644 --- a/src/ui/resource/CoverResource.hpp +++ b/src/ui/resource/CoverResource.hpp @@ -22,9 +22,6 @@ #include -#include -#include - #include #include "database/DatabaseHandler.hpp" @@ -32,25 +29,34 @@ namespace UserInterface { + class CoverResource : public Wt::WResource { public: - CoverResource(Database::Handler& db, - std::size_t size, // size * size pixels - Wt::WObject *parent = 0); + static const std::string unknownCoverPath; + static const std::size_t maxSize = 512; + + CoverResource(Database::Handler& db, Wt::WObject *parent = 0); ~CoverResource(); - std::string getReleaseUrl(std::string releaseName); - std::string getTrackUrl(Database::Track::id_type trackId); + std::string getReleaseUrl(std::string releaseName, size_t size) const; + std::string getTrackUrl(Database::Track::id_type trackId, size_t size) const; + std::string getUnkownTrackUrl(size_t size) const; void handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response); private: + const CoverArt::CoverArt& getDefaultCover(std::size_t size); + void putCover(Wt::Http::Response& response, const CoverArt::CoverArt& cover); + std::mutex _mutex; Database::Handler& _db; - std::size_t _size; - CoverArt::CoverArt _defaultCover; + + // Default cover for different sizes + std::map _defaultCovers; + + // TODO construct a cache for covers? }; } // namespace UserInterface diff --git a/src/ui/settings/Settings.cpp b/src/ui/settings/Settings.cpp index 4ccc57e1..3e6a462e 100644 --- a/src/ui/settings/Settings.cpp +++ b/src/ui/settings/Settings.cpp @@ -30,18 +30,18 @@ #include "SettingsUsers.hpp" #include "logger/Logger.hpp" - #include "service/ServiceManager.hpp" #include "service/DatabaseUpdateService.hpp" +#include "LmsApplication.hpp" + #include "Settings.hpp" namespace UserInterface { namespace Settings { -Settings::Settings(SessionData& sessionData, Wt::WContainerWidget* parent) -: Wt::WContainerWidget(parent), -_sessionData(sessionData) +Settings::Settings(Wt::WContainerWidget* parent) +: Wt::WContainerWidget(parent) { Wt::WHBoxLayout* hLayout = new Wt::WHBoxLayout(this); @@ -59,29 +59,31 @@ _sessionData(sessionData) hLayout->addWidget(menu); hLayout->addWidget(contents, 1); - Wt::Dbo::Transaction transaction( sessionData.getDatabaseHandler().getSession()); - - ::Database::User::pointer user = sessionData.getDatabaseHandler().getCurrentUser(); - - // Must be logged in here - assert(user); - - menu->addItem("Audio", new AudioFormView(sessionData, Database::User::getId(user))); - if (user->isAdmin()) + std::string userId; + bool userIsAdmin; { - MediaDirectories* mediaDirectory = new MediaDirectories(sessionData); + Wt::Dbo::Transaction transaction(DboSession()); + + userId = Database::User::getId(CurrentUser()); + userIsAdmin = CurrentUser()->isAdmin(); + } + + menu->addItem("Audio", new AudioFormView()); + if (userIsAdmin) + { + MediaDirectories* mediaDirectory = new MediaDirectories(); mediaDirectory->changed().connect(this, &Settings::handleDatabaseDirectoriesChanged); menu->addItem("Media Folders", mediaDirectory); - DatabaseFormView* databaseFormView = new DatabaseFormView(sessionData); + DatabaseFormView* databaseFormView = new DatabaseFormView(); databaseFormView->changed().connect(this, &Settings::restartDatabaseUpdateService); menu->addItem("Database Update", databaseFormView); - menu->addItem("Users", new Users(sessionData)); + menu->addItem("Users", new Users()); } else { - menu->addItem("Account", new AccountFormView(sessionData, Database::User::getId(user))); + menu->addItem("Account", new AccountFormView(userId)); } } @@ -92,8 +94,8 @@ Settings::handleDatabaseDirectoriesChanged() LMS_LOG(MOD_UI, SEV_NOTICE) << "Media directories have changed: requesting imediate scan"; // On directory add or delete, request an immediate scan { - Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); - Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession()).modify()->setManualScanRequested(true); + Wt::Dbo::Transaction transaction(DboSession()); + Database::MediaDirectorySettings::get(DboSession()).modify()->setManualScanRequested(true); } restartDatabaseUpdateService(); diff --git a/src/ui/settings/Settings.hpp b/src/ui/settings/Settings.hpp index 46958c33..2c6f0f76 100644 --- a/src/ui/settings/Settings.hpp +++ b/src/ui/settings/Settings.hpp @@ -19,15 +19,13 @@ #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { class Settings : public Wt::WContainerWidget { public: - Settings(SessionData& sessionData, Wt::WContainerWidget* parent = 0); + Settings(Wt::WContainerWidget* parent = 0); private: @@ -35,8 +33,6 @@ class Settings : public Wt::WContainerWidget void restartDatabaseUpdateService(void); - SessionData& _sessionData; - }; } // namespace Settings diff --git a/src/ui/settings/SettingsAccountFormView.cpp b/src/ui/settings/SettingsAccountFormView.cpp index 1c87496e..12f2b4a6 100644 --- a/src/ui/settings/SettingsAccountFormView.cpp +++ b/src/ui/settings/SettingsAccountFormView.cpp @@ -29,6 +29,7 @@ #include "logger/Logger.hpp" #include "common/Validators.hpp" +#include "LmsApplication.hpp" #include "SettingsAccountFormView.hpp" @@ -45,9 +46,8 @@ class AccountFormModel : public Wt::WFormModel static const Field PasswordField; static const Field PasswordConfirmField; - AccountFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0) + AccountFormModel(std::string userId, Wt::WObject *parent = 0) : Wt::WFormModel(parent), - _db(sessionData.getDatabaseHandler()), _userId(userId) { addField(NameField); @@ -64,10 +64,10 @@ class AccountFormModel : public Wt::WFormModel void loadData() { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - Wt::Auth::User authUser = _db.getUserDatabase().findWithId( _userId ); - Database::User::pointer user = _db.getUser(authUser); + Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId( _userId ); + Database::User::pointer user = DbHandler().getUser(authUser); if (user && authUser.isValid()) { @@ -85,11 +85,11 @@ class AccountFormModel : public Wt::WFormModel { // DBO transaction active here try { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Update user - Wt::Auth::User authUser = _db.getUserDatabase().findWithId(_userId); - Database::User::pointer user = _db.getUser( authUser ); + Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId(_userId); + Database::User::pointer user = DbHandler().getUser( authUser ); // user may have been deleted by someone else if (!authUser.isValid()) { @@ -131,9 +131,9 @@ class AccountFormModel : public Wt::WFormModel if (field == NameField) { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Must be unique since used as LoginIdentity - Wt::Auth::User user = _db.getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field)); + Wt::Auth::User user = DbHandler().getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field)); if (user.isValid() && user.id() != _userId) error = "Already exists"; else @@ -178,7 +178,6 @@ class AccountFormModel : public Wt::WFormModel private: - Database::Handler& _db; std::string _userId; }; @@ -187,11 +186,11 @@ const Wt::WFormModel::Field AccountFormModel::EmailField = "email"; const Wt::WFormModel::Field AccountFormModel::PasswordField = "password"; const Wt::WFormModel::Field AccountFormModel::PasswordConfirmField = "password-confirm"; -AccountFormView::AccountFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent) +AccountFormView::AccountFormView(std::string userId, Wt::WContainerWidget *parent) : Wt::WTemplateFormView(parent) { - _model = new AccountFormModel(sessionData, userId, this); + _model = new AccountFormModel(userId, this); setTemplateText(tr("userAccountForm-template")); addFunction("id", &WTemplate::Functions::id); diff --git a/src/ui/settings/SettingsAccountFormView.hpp b/src/ui/settings/SettingsAccountFormView.hpp index 1583bedd..ebe02e5e 100644 --- a/src/ui/settings/SettingsAccountFormView.hpp +++ b/src/ui/settings/SettingsAccountFormView.hpp @@ -24,8 +24,6 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { @@ -34,7 +32,7 @@ class AccountFormModel; class AccountFormView : public Wt::WTemplateFormView { public: - AccountFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0); + AccountFormView(std::string userId, Wt::WContainerWidget *parent = 0); private: void processCancel(); // reload from DB diff --git a/src/ui/settings/SettingsAudioFormView.cpp b/src/ui/settings/SettingsAudioFormView.cpp index 806e2884..0f6392c4 100644 --- a/src/ui/settings/SettingsAudioFormView.cpp +++ b/src/ui/settings/SettingsAudioFormView.cpp @@ -27,9 +27,27 @@ #include "logger/Logger.hpp" #include "common/Validators.hpp" +#include "LmsApplication.hpp" #include "SettingsAudioFormView.hpp" +namespace { +std::string encodingToString(Database::AudioEncoding encoding) +{ + + switch (encoding) + { + case Database::AudioEncoding::AUTO: return "Automatic"; + 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 "?"; +} +} + namespace UserInterface { namespace Settings { @@ -39,49 +57,46 @@ class AudioFormModel : public Wt::WFormModel // Associate each field with a unique string literal. static const Field BitrateField; + static const Field EncodingField; - AudioFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0) - : Wt::WFormModel(parent), - _db(sessionData.getDatabaseHandler()), - _userId(userId) + AudioFormModel(Wt::WObject *parent = 0) + : Wt::WFormModel(parent) { initializeModels(); addField(BitrateField); + addField(EncodingField, "Session must be reloaded to apply this setting"); setValidator(BitrateField, new Wt::WValidator(true)); // mandatory + setValidator(EncodingField, new Wt::WValidator(true)); // mandatory // populate the model with initial data loadData(); } Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; } + Wt::WAbstractItemModel *encodingModel() { return _encodingModel; } void loadData() { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - Database::User::pointer user = Database::User::getById( _db.getSession(), _userId); - - if (user) - setValue(BitrateField, std::min(user->getMaxAudioBitrate(), user->getAudioBitrate()) / 1000); // in kps - else - setValue(BitrateField, Wt::WString()); + setValue(BitrateField, std::min(CurrentUser()->getMaxAudioBitrate(), CurrentUser()->getAudioBitrate()) / 1000); // in kps + int encodingRow = getAudioEncodingRow( CurrentUser()->getAudioEncoding()); + setValue(EncodingField, getAudioEncodingString(encodingRow)); } bool saveData(Wt::WString& error) { // DBO transaction active here try { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - Database::User::pointer user = Database::User::getById( _db.getSession(), _userId); // user may have been deleted by someone else - if (user) - { - user.modify()->setAudioBitrate( Wt::asNumber(value(BitrateField)) * 1000); // in kbps - } + CurrentUser().modify()->setAudioBitrate( Wt::asNumber(value(BitrateField)) * 1000); // in kbps + int encodingRow = getAudioEncodingRow( boost::any_cast(value((EncodingField)))); + CurrentUser().modify()->setAudioEncoding( getAudioEncodingValue(encodingRow)); } catch(Wt::Dbo::Exception& exception) { @@ -92,33 +107,74 @@ class AudioFormModel : public Wt::WFormModel return true; } + int getAudioEncodingRow( Database::AudioEncoding encoding) + { + for (int i = 0; i < _encodingModel->rowCount(); ++i) + { + if (getAudioEncodingValue(i) == encoding) + return i; + } + return -1; + } + + int getAudioEncodingRow( Wt::WString encoding) + { + for (int i = 0; i < _encodingModel->rowCount(); ++i) + { + if (getAudioEncodingString(i) == encoding) + return i; + } + return -1; + } + + Database::AudioEncoding getAudioEncodingValue(int row) + { + return boost::any_cast + (_encodingModel->data(_encodingModel->index(row, 0), Wt::UserRole)); + } + + Wt::WString getAudioEncodingString(int row) + { + return boost::any_cast + (_encodingModel->data(_encodingModel->index(row, 0), Wt::DisplayRole)); + } + + private: void initializeModels() { - Wt::Dbo::Transaction transaction(_db.getSession()); - - Database::User::pointer user = Database::User::getById(_db.getSession(), _userId); + Wt::Dbo::Transaction transaction(DboSession()); _bitrateModel = new Wt::WStringListModel(this); BOOST_FOREACH(std::size_t bitrate, Database::User::audioBitrates) { - if (user && bitrate <= user->getMaxAudioBitrate()) + if (bitrate <= CurrentUser()->getMaxAudioBitrate()) _bitrateModel->addString( Wt::WString("{1}").arg( bitrate / 1000 ) ); // in kbps } + + _encodingModel = new Wt::WStringListModel(this); + int row = 0; + BOOST_FOREACH(Database::AudioEncoding encoding, Database::User::audioEncodings) + { + _encodingModel->addString(encodingToString(encoding)); + _encodingModel->setData(row, 0, encoding, Wt::UserRole); + row++; + } } - Database::Handler& _db; std::string _userId; Wt::WStringListModel* _bitrateModel; + Wt::WStringListModel* _encodingModel; }; const Wt::WFormModel::Field AudioFormModel::BitrateField = "bitrate"; +const Wt::WFormModel::Field AudioFormModel::EncodingField = "encoding"; -AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent) +AudioFormView::AudioFormView(Wt::WContainerWidget *parent) : Wt::WTemplateFormView(parent) { - _model = new AudioFormModel(sessionData, userId, this); + _model = new AudioFormModel(this); setTemplateText(tr("audioForm-template")); addFunction("id", &WTemplate::Functions::id); @@ -136,6 +192,12 @@ AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::W bitrateCB->setModel(_model->bitrateModel()); bitrateCB->changed().connect(_applyInfo, &Wt::WWidget::hide); + // Encoding + Wt::WComboBox *encodingCB = new Wt::WComboBox(); + setFormWidget(AudioFormModel::EncodingField, encodingCB); + encodingCB->setModel(_model->encodingModel()); + encodingCB->changed().connect(_applyInfo, &Wt::WWidget::hide); + // Title & Buttons bindString("title", "Audio settings"); @@ -148,9 +210,7 @@ AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::W bindWidget("cancel-button", cancelButton); cancelButton->clicked().connect(this, &AudioFormView::processCancel); - updateView(_model); - } void diff --git a/src/ui/settings/SettingsAudioFormView.hpp b/src/ui/settings/SettingsAudioFormView.hpp index d51ab8a0..deed1ea6 100644 --- a/src/ui/settings/SettingsAudioFormView.hpp +++ b/src/ui/settings/SettingsAudioFormView.hpp @@ -24,8 +24,6 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { @@ -34,7 +32,7 @@ class AudioFormModel; class AudioFormView : public Wt::WTemplateFormView { public: - AudioFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0); + AudioFormView(Wt::WContainerWidget *parent = 0); private: void processCancel(); // reload from DB diff --git a/src/ui/settings/SettingsDatabaseFormView.cpp b/src/ui/settings/SettingsDatabaseFormView.cpp index 96e8a7eb..5bb668ab 100644 --- a/src/ui/settings/SettingsDatabaseFormView.cpp +++ b/src/ui/settings/SettingsDatabaseFormView.cpp @@ -30,6 +30,7 @@ #include "database/MediaDirectory.hpp" #include "common/DirectoryValidator.hpp" +#include "LmsApplication.hpp" #include "SettingsDatabaseFormView.hpp" @@ -43,9 +44,8 @@ class DatabaseFormModel : public Wt::WFormModel static const Field UpdatePeriodField; static const Field UpdateStartTimeField; - DatabaseFormModel(SessionData& sessionData, Wt::WObject *parent = 0) - : Wt::WFormModel(parent), - _sessionData(sessionData) + DatabaseFormModel(Wt::WObject *parent = 0) + : Wt::WFormModel(parent) { initializeModels(); @@ -64,10 +64,10 @@ class DatabaseFormModel : public Wt::WFormModel void loadData() { - Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Get refresh settings - ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession()); + ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(DboSession()); int periodRow = getUpdatePeriodModelRow( settings->getUpdatePeriod() ); if (periodRow != -1) @@ -81,10 +81,9 @@ class DatabaseFormModel : public Wt::WFormModel void saveData() { - Wt::Dbo::Session& session( _sessionData.getDatabaseHandler().getSession()); - Wt::Dbo::Transaction transaction(session); + Wt::Dbo::Transaction transaction(DboSession()); - ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession() ); + ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(DboSession()); int periodRow = getUpdatePeriodModelRow( boost::any_cast(value(UpdatePeriodField))); assert(periodRow != -1); @@ -99,10 +98,9 @@ class DatabaseFormModel : public Wt::WFormModel bool setImmediateScan(Wt::WString& error) { try { - Wt::Dbo::Session& session( _sessionData.getDatabaseHandler().getSession()); - Wt::Dbo::Transaction transaction(session); + Wt::Dbo::Transaction transaction( DboSession()); - ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession() ); + ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(DboSession() ); settings.modify()->setManualScanRequested( true ); } @@ -231,7 +229,6 @@ class DatabaseFormModel : public Wt::WFormModel } - SessionData& _sessionData; Wt::WStringListModel* _updatePeriodModel; Wt::WStringListModel* _updateStartTimeModel; @@ -241,10 +238,10 @@ const Wt::WFormModel::Field DatabaseFormModel::UpdatePeriodField = "update-peri const Wt::WFormModel::Field DatabaseFormModel::UpdateStartTimeField = "update-start-time"; -DatabaseFormView::DatabaseFormView(SessionData& sessionData, Wt::WContainerWidget *parent) +DatabaseFormView::DatabaseFormView(Wt::WContainerWidget *parent) : Wt::WTemplateFormView(parent) { - _model = new DatabaseFormModel(sessionData, this); + _model = new DatabaseFormModel(this); setTemplateText(tr("databaseForm-template")); addFunction("id", &WTemplate::Functions::id); diff --git a/src/ui/settings/SettingsDatabaseFormView.hpp b/src/ui/settings/SettingsDatabaseFormView.hpp index 69f75e2c..23585fdb 100644 --- a/src/ui/settings/SettingsDatabaseFormView.hpp +++ b/src/ui/settings/SettingsDatabaseFormView.hpp @@ -25,8 +25,6 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { @@ -35,7 +33,7 @@ class DatabaseFormModel; class DatabaseFormView : public Wt::WTemplateFormView { public: - DatabaseFormView(SessionData& sessionData, Wt::WContainerWidget *parent = 0); + DatabaseFormView(Wt::WContainerWidget *parent = 0); Wt::Signal& changed() { return _sigChanged; } diff --git a/src/ui/settings/SettingsFirstConnectionFormView.cpp b/src/ui/settings/SettingsFirstConnectionFormView.cpp index b5ff5988..44748796 100644 --- a/src/ui/settings/SettingsFirstConnectionFormView.cpp +++ b/src/ui/settings/SettingsFirstConnectionFormView.cpp @@ -27,6 +27,7 @@ #include "logger/Logger.hpp" #include "common/Validators.hpp" +#include "LmsApplication.hpp" #include "SettingsFirstConnectionFormView.hpp" @@ -43,9 +44,8 @@ class FirstConnectionFormModel : public Wt::WFormModel static const Field PasswordField; static const Field PasswordConfirmField; - FirstConnectionFormModel(SessionData& sessionData, Wt::WObject *parent = 0) - : Wt::WFormModel(parent), - _db(sessionData.getDatabaseHandler()) + FirstConnectionFormModel(Wt::WObject *parent = 0) + : Wt::WFormModel(parent) { addField(NameField); addField(EmailField); @@ -61,11 +61,11 @@ class FirstConnectionFormModel : public Wt::WFormModel { // DBO transaction active here try { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Check if a user already exist // If it's the case, just do nothing - if (Database::User::getAll(_db.getSession()).size() > 0) + if (!Database::User::getAll(DboSession()).empty()) { LMS_LOG(MOD_UI, SEV_ERROR) << "Admin user already created"; error = Wt::WString("Admin user already created!"); @@ -73,8 +73,8 @@ class FirstConnectionFormModel : public Wt::WFormModel } // Create user - Wt::Auth::User authUser = _db.getUserDatabase().registerNew(); - Database::User::pointer user = _db.getUser(authUser); + Wt::Auth::User authUser = DbHandler().getUserDatabase().registerNew(); + Database::User::pointer user = DbHandler().getUser(authUser); // Account authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(NameField)); @@ -139,7 +139,6 @@ class FirstConnectionFormModel : public Wt::WFormModel private: - Database::Handler& _db; }; const Wt::WFormModel::Field FirstConnectionFormModel::NameField = "name"; @@ -147,11 +146,11 @@ const Wt::WFormModel::Field FirstConnectionFormModel::EmailField = "email"; const Wt::WFormModel::Field FirstConnectionFormModel::PasswordField = "password"; const Wt::WFormModel::Field FirstConnectionFormModel::PasswordConfirmField = "password-confirm"; -FirstConnectionFormView::FirstConnectionFormView(SessionData& sessionData, Wt::WContainerWidget *parent) +FirstConnectionFormView::FirstConnectionFormView(Wt::WContainerWidget *parent) : Wt::WTemplateFormView(parent) { - _model = new FirstConnectionFormModel(sessionData, this); + _model = new FirstConnectionFormModel(this); setTemplateText(tr("firstConnectionForm-template")); addFunction("id", &WTemplate::Functions::id); diff --git a/src/ui/settings/SettingsFirstConnectionFormView.hpp b/src/ui/settings/SettingsFirstConnectionFormView.hpp index 043437a6..1761c192 100644 --- a/src/ui/settings/SettingsFirstConnectionFormView.hpp +++ b/src/ui/settings/SettingsFirstConnectionFormView.hpp @@ -25,8 +25,6 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { @@ -35,7 +33,7 @@ class FirstConnectionFormModel; class FirstConnectionFormView : public Wt::WTemplateFormView { public: - FirstConnectionFormView(SessionData& sessionData, Wt::WContainerWidget *parent = 0); + FirstConnectionFormView(Wt::WContainerWidget *parent = 0); private: diff --git a/src/ui/settings/SettingsMediaDirectories.cpp b/src/ui/settings/SettingsMediaDirectories.cpp index 0e113b84..d9b75a20 100644 --- a/src/ui/settings/SettingsMediaDirectories.cpp +++ b/src/ui/settings/SettingsMediaDirectories.cpp @@ -24,6 +24,8 @@ #include "database/MediaDirectory.hpp" +#include "LmsApplication.hpp" + #include "SettingsMediaDirectoryFormView.hpp" #include "SettingsMediaDirectories.hpp" @@ -31,9 +33,8 @@ namespace UserInterface { namespace Settings { -MediaDirectories::MediaDirectories(SessionData& sessionData, Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent), -_db(sessionData.getDatabaseHandler()) +MediaDirectories::MediaDirectories(Wt::WContainerWidget *parent) +: Wt::WContainerWidget(parent) { // Stack two widgets: _stack = new Wt::WStackedWidget(this); @@ -72,9 +73,9 @@ MediaDirectories::refresh(void) for (int i = _table->rowCount() - 1; i > 0; --i) _table->deleteRow(i); - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - std::vector mediaDirectories = Database::MediaDirectory::getAll(_db.getSession()); + std::vector mediaDirectories = Database::MediaDirectory::getAll(DboSession()); std::size_t id = 1; BOOST_FOREACH(Database::MediaDirectory::pointer mediaDirectory, mediaDirectories) @@ -114,10 +115,10 @@ MediaDirectories::handleDelMediaDirectory(boost::filesystem::path p, Database::M if (messageBox->buttonResult() == Wt::Yes) { { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Delete the media diretory - Database::MediaDirectory::pointer mediaDirectory = Database::MediaDirectory::get(_db.getSession(), p, type); + Database::MediaDirectory::pointer mediaDirectory = Database::MediaDirectory::get(DboSession(), p, type); if (mediaDirectory) mediaDirectory.remove(); } @@ -140,7 +141,7 @@ MediaDirectories::handleCreateMediaDirectory(void) { assert(_stack->count() == 1); - MediaDirectoryFormView* formView = new MediaDirectoryFormView(_db, _stack); + MediaDirectoryFormView* formView = new MediaDirectoryFormView(_stack); formView->completed().connect(this, &MediaDirectories::handleMediaDirectoryFormCompleted); _stack->setCurrentIndex(1); diff --git a/src/ui/settings/SettingsMediaDirectories.hpp b/src/ui/settings/SettingsMediaDirectories.hpp index 5811230f..4fb2bdf8 100644 --- a/src/ui/settings/SettingsMediaDirectories.hpp +++ b/src/ui/settings/SettingsMediaDirectories.hpp @@ -27,15 +27,13 @@ #include "database/MediaDirectory.hpp" -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { class MediaDirectories : public Wt::WContainerWidget { public: - MediaDirectories(SessionData& sessioNData, Wt::WContainerWidget *parent = 0); + MediaDirectories(Wt::WContainerWidget *parent = 0); void refresh(); @@ -50,8 +48,6 @@ class MediaDirectories : public Wt::WContainerWidget void handleDelMediaDirectory(boost::filesystem::path p, Database::MediaDirectory::Type type); void handleCreateMediaDirectory(void); - Database::Handler& _db; - Wt::WStackedWidget* _stack; Wt::WTable* _table; }; diff --git a/src/ui/settings/SettingsMediaDirectoryFormView.cpp b/src/ui/settings/SettingsMediaDirectoryFormView.cpp index 4bce3d49..b6efe99e 100644 --- a/src/ui/settings/SettingsMediaDirectoryFormView.cpp +++ b/src/ui/settings/SettingsMediaDirectoryFormView.cpp @@ -29,7 +29,7 @@ #include "database/MediaDirectory.hpp" #include "common/DirectoryValidator.hpp" - +#include "LmsApplication.hpp" #include "SettingsMediaDirectoryFormView.hpp" @@ -45,9 +45,8 @@ class MediaDirectoryFormModel : public Wt::WFormModel static const Field PathField; static const Field TypeField; - MediaDirectoryFormModel(Database::Handler& db, Wt::WObject *parent = 0) - : Wt::WFormModel(parent), - _db(db) + MediaDirectoryFormModel(Wt::WObject *parent = 0) + : Wt::WFormModel(parent) { initializeModels(); @@ -66,18 +65,18 @@ class MediaDirectoryFormModel : public Wt::WFormModel bool saveData(Wt::WString& error) { try { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); Database::MediaDirectory::Type type = (valueText(TypeField) == "Audio") ? Database::MediaDirectory::Audio : Database::MediaDirectory::Video; - if (Database::MediaDirectory::get(_db.getSession(), valueText(PathField).toUTF8(), type)) + if (Database::MediaDirectory::get(DboSession(), valueText(PathField).toUTF8(), type)) { error = "This Path/Type already exists!"; return false; } - Database::MediaDirectory::create(_db.getSession(), valueText(PathField).toUTF8(), type); + Database::MediaDirectory::create(DboSession(), valueText(PathField).toUTF8(), type); } catch(Wt::Dbo::Exception& exception) @@ -97,7 +96,6 @@ class MediaDirectoryFormModel : public Wt::WFormModel _typeModel->addString("Video"); } - Database::Handler& _db; std::string _userId; Wt::WStringListModel* _typeModel; }; @@ -105,11 +103,11 @@ class MediaDirectoryFormModel : public Wt::WFormModel const Wt::WFormModel::Field MediaDirectoryFormModel::PathField = "path"; const Wt::WFormModel::Field MediaDirectoryFormModel::TypeField = "type"; -MediaDirectoryFormView::MediaDirectoryFormView(Database::Handler& db, Wt::WContainerWidget *parent) +MediaDirectoryFormView::MediaDirectoryFormView(Wt::WContainerWidget *parent) : Wt::WTemplateFormView(parent) { - _model = new MediaDirectoryFormModel(db, this); + _model = new MediaDirectoryFormModel(this); setTemplateText(tr("mediaDirectoryForm-template")); addFunction("id", &WTemplate::Functions::id); diff --git a/src/ui/settings/SettingsMediaDirectoryFormView.hpp b/src/ui/settings/SettingsMediaDirectoryFormView.hpp index efd75490..29554c74 100644 --- a/src/ui/settings/SettingsMediaDirectoryFormView.hpp +++ b/src/ui/settings/SettingsMediaDirectoryFormView.hpp @@ -25,8 +25,6 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { @@ -35,7 +33,7 @@ class MediaDirectoryFormModel; class MediaDirectoryFormView : public Wt::WTemplateFormView { public: - MediaDirectoryFormView(Database::Handler& db, Wt::WContainerWidget *parent = 0); + MediaDirectoryFormView(Wt::WContainerWidget *parent = 0); // Signal emitted once the form is completed Wt::Signal& completed() { return _sigCompleted; } diff --git a/src/ui/settings/SettingsUserFormView.cpp b/src/ui/settings/SettingsUserFormView.cpp index d56f054c..0ff6c4ba 100644 --- a/src/ui/settings/SettingsUserFormView.cpp +++ b/src/ui/settings/SettingsUserFormView.cpp @@ -30,6 +30,7 @@ #include "logger/Logger.hpp" #include "common/Validators.hpp" +#include "LmsApplication.hpp" #include "SettingsUserFormView.hpp" @@ -50,9 +51,8 @@ class UserFormModel : public Wt::WFormModel static const Field AudioBitrateLimitField; static const Field VideoBitrateLimitField; - UserFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0) + UserFormModel(std::string userId, Wt::WObject *parent = 0) : Wt::WFormModel(parent), - _db(sessionData.getDatabaseHandler()), _userId(userId) { initializeModels(); @@ -88,12 +88,12 @@ class UserFormModel : public Wt::WFormModel if (!userId.empty()) { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - Wt::Auth::User authUser = _db.getUserDatabase().findWithId( userId ); - Database::User::pointer user = _db.getUser(authUser); + Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId( userId ); + Database::User::pointer user = DbHandler().getUser(authUser); - Wt::Auth::User currentUser = _db.getLogin().user(); + Wt::Auth::User currentUser = CurrentAuthUser(); if (user && authUser.isValid()) { @@ -130,13 +130,13 @@ class UserFormModel : public Wt::WFormModel bool saveData() { try { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); if (_userId.empty()) { // Create user - Wt::Auth::User authUser = _db.getUserDatabase().registerNew(); - Database::User::pointer user = _db.getUser(authUser); + Wt::Auth::User authUser = DbHandler().getUserDatabase().registerNew(); + Database::User::pointer user = DbHandler().getUser(authUser); // Account authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(NameField)); @@ -163,8 +163,8 @@ class UserFormModel : public Wt::WFormModel else { // Update user - Wt::Auth::User authUser = _db.getUserDatabase().findWithId(_userId); - Database::User::pointer user = _db.getUser( authUser ); + Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId(_userId); + Database::User::pointer user = DbHandler().getUser( authUser ); // user may have been deleted by someone else if (!authUser.isValid()) { @@ -219,9 +219,9 @@ class UserFormModel : public Wt::WFormModel if (field == NameField) { - Wt::Dbo::Transaction transaction(_db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Must be unique since used as LoginIdentity - Wt::Auth::User user = _db.getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field)); + Wt::Auth::User user = DbHandler().getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field)); if (user.isValid() && user.id() != _userId) error = "Already exists"; else @@ -280,7 +280,6 @@ class UserFormModel : public Wt::WFormModel } - Database::Handler& _db; std::string _userId; Wt::WStringListModel* _audioBitrateModel; Wt::WStringListModel* _videoBitrateModel; @@ -295,11 +294,11 @@ const Wt::WFormModel::Field UserFormModel::AudioBitrateLimitField = "audio-bitra const Wt::WFormModel::Field UserFormModel::VideoBitrateLimitField = "video-bitrate-limit"; -UserFormView::UserFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent) +UserFormView::UserFormView(std::string userId, Wt::WContainerWidget *parent) : Wt::WTemplateFormView(parent) { - _model = new UserFormModel(sessionData, userId, this); + _model = new UserFormModel(userId, this); setTemplateText(tr("userForm-template")); addFunction("id", &WTemplate::Functions::id); @@ -344,9 +343,8 @@ UserFormView::UserFormView(SessionData& sessionData, std::string userId, Wt::WCo title = Wt::WString("Create user"); } else { - Database::Handler &db = sessionData.getDatabaseHandler(); - Wt::Dbo::Transaction transaction (db.getSession()); - Wt::Auth::User authUser = db.getUserDatabase().findWithId( userId ); + Wt::Dbo::Transaction transaction (DboSession()); + Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId( userId ); Wt::WString userName; if (authUser.isValid()) diff --git a/src/ui/settings/SettingsUserFormView.hpp b/src/ui/settings/SettingsUserFormView.hpp index 100006b5..1e495784 100644 --- a/src/ui/settings/SettingsUserFormView.hpp +++ b/src/ui/settings/SettingsUserFormView.hpp @@ -24,8 +24,6 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { @@ -35,7 +33,7 @@ class UserFormView : public Wt::WTemplateFormView { public: - UserFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0); + UserFormView(std::string userId, Wt::WContainerWidget *parent = 0); // Signal emitted once the form is completed Wt::Signal& completed() { return _sigCompleted; } diff --git a/src/ui/settings/SettingsUsers.cpp b/src/ui/settings/SettingsUsers.cpp index fa36f063..98c4dc64 100644 --- a/src/ui/settings/SettingsUsers.cpp +++ b/src/ui/settings/SettingsUsers.cpp @@ -28,15 +28,15 @@ #include "logger/Logger.hpp" #include "SettingsUserFormView.hpp" +#include "LmsApplication.hpp" #include "SettingsUsers.hpp" namespace UserInterface { namespace Settings { -Users::Users(SessionData& sessionData, Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent), -_sessionData(sessionData) +Users::Users(Wt::WContainerWidget *parent) +: Wt::WContainerWidget(parent) { // Stack two widgets: _stack = new Wt::WStackedWidget(this); @@ -76,13 +76,11 @@ Users::refresh(void) for (int i = _table->rowCount() - 1; i > 0; --i) _table->deleteRow(i); - Database::Handler& db = _sessionData.getDatabaseHandler(); + Wt::Dbo::Transaction transaction(DboSession()); - Wt::Dbo::Transaction transaction(db.getSession()); + const Wt::Auth::User& currentUser = CurrentAuthUser(); - const Wt::Auth::User& currentUser = db.getLogin().user(); - - std::vector users = Database::User::getAll(db.getSession()); + std::vector users = Database::User::getAll(DboSession()); std::size_t userIndex = 1; for (std::size_t i = 0; i < users.size(); ++i) @@ -94,7 +92,7 @@ Users::refresh(void) // Hack try/catch here since it may fail! try { - authUser = db.getUserDatabase().findWithId( userId ); + authUser = DbHandler().getUserDatabase().findWithId( userId ); } catch(Wt::Dbo::Exception& e) { @@ -152,16 +150,14 @@ Users::handleDelUser(Wt::WString loginNameIdentity, std::string id) messageBox->buttonClicked().connect(std::bind([=] () { if (messageBox->buttonResult() == Wt::Yes) { - Database::Handler& db = _sessionData.getDatabaseHandler(); - - Wt::Dbo::Transaction transaction(db.getSession()); + Wt::Dbo::Transaction transaction(DboSession()); // Delete the user - Wt::Auth::User authUser = db.getUserDatabase().findWithId( id ); + Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId( id ); - db.getUserDatabase().deleteUser( authUser ); + DbHandler().getUserDatabase().deleteUser( authUser ); - Database::User::pointer user = Database::User::getById(db.getSession(), id); + Database::User::pointer user = Database::User::getById(DboSession(), id); if (user) user.remove(); @@ -180,7 +176,7 @@ Users::handleCreateUser(std::string id) { assert(_stack->count() == 1); - UserFormView* userFormView = new UserFormView(_sessionData, id, _stack); + UserFormView* userFormView = new UserFormView(id, _stack); userFormView->completed().connect(this, &Users::handleUserFormCompleted); _stack->setCurrentIndex(1); diff --git a/src/ui/settings/SettingsUsers.hpp b/src/ui/settings/SettingsUsers.hpp index de0b1d27..4f67f672 100644 --- a/src/ui/settings/SettingsUsers.hpp +++ b/src/ui/settings/SettingsUsers.hpp @@ -24,15 +24,13 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { namespace Settings { class Users : public Wt::WContainerWidget { public: - Users(SessionData& sessioNData, Wt::WContainerWidget *parent = 0); + Users(Wt::WContainerWidget *parent = 0); void refresh(); @@ -43,8 +41,6 @@ class Users : public Wt::WContainerWidget void handleDelUser(Wt::WString loginNameIdentity, std::string id); void handleCreateUser(std::string id); // set the id in order to edit the user - SessionData& _sessionData; - Wt::WStackedWidget* _stack; Wt::WTable* _table; }; diff --git a/src/ui/video/VideoDatabaseWidget.cpp b/src/ui/video/VideoDatabaseWidget.cpp index b8e31456..54ec0020 100644 --- a/src/ui/video/VideoDatabaseWidget.cpp +++ b/src/ui/video/VideoDatabaseWidget.cpp @@ -27,13 +27,14 @@ #include "transcode/Parameters.hpp" +#include "LmsApplication.hpp" + #include "VideoDatabaseWidget.hpp" namespace UserInterface { -VideoDatabaseWidget::VideoDatabaseWidget(Database::Handler& db, Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent), - _db(db) +VideoDatabaseWidget::VideoDatabaseWidget(Wt::WContainerWidget *parent) +: Wt::WContainerWidget(parent) { _table = new Wt::WTable( this ); _table->setHeaderCount(1); @@ -98,10 +99,10 @@ VideoDatabaseWidget::updateView(boost::filesystem::path directory, size_t depth) // If directory is not valid, add the root Media Directories if (depth == 0) { - Wt::Dbo::Transaction transaction ( _db.getSession() ); + Wt::Dbo::Transaction transaction ( DboSession() ); std::vector dirs - = Database::MediaDirectory::getByType(_db.getSession(), Database::MediaDirectory::Video); + = Database::MediaDirectory::getByType(DboSession(), Database::MediaDirectory::Video); BOOST_FOREACH(Database::MediaDirectory::pointer dir, dirs) { @@ -128,9 +129,9 @@ VideoDatabaseWidget::updateView(boost::filesystem::path directory, size_t depth) addDirectory( path.filename().string(), path, depth + 1); else if (boost::filesystem::is_regular(path) ) { - Wt::Dbo::Transaction transaction ( _db.getSession() ); + Wt::Dbo::Transaction transaction ( DboSession() ); - Database::Video::pointer video = Database::Video::getByPath( _db.getSession(), path); + Database::Video::pointer video = Database::Video::getByPath( DboSession(), path); if (video) addVideo( video->getName(), video->getDuration(), path); } diff --git a/src/ui/video/VideoDatabaseWidget.hpp b/src/ui/video/VideoDatabaseWidget.hpp index d778c429..8ab399d4 100644 --- a/src/ui/video/VideoDatabaseWidget.hpp +++ b/src/ui/video/VideoDatabaseWidget.hpp @@ -23,14 +23,12 @@ #include #include -#include "common/SessionData.hpp" - namespace UserInterface { class VideoDatabaseWidget : public Wt::WContainerWidget { public: - VideoDatabaseWidget( Database::Handler& db, Wt::WContainerWidget *parent = 0); + VideoDatabaseWidget(Wt::WContainerWidget *parent = 0); // Signals Wt::Signal< boost::filesystem::path >& playVideo() { return _playVideo; } @@ -43,8 +41,6 @@ class VideoDatabaseWidget : public Wt::WContainerWidget void updateView(boost::filesystem::path directory, size_t depth); - Database::Handler& _db; - Wt::Signal< boost::filesystem::path > _playVideo; Wt::WTable* _table; diff --git a/src/ui/video/VideoMediaPlayerWidget.cpp b/src/ui/video/VideoMediaPlayerWidget.cpp index 2f031393..9a70011f 100644 --- a/src/ui/video/VideoMediaPlayerWidget.cpp +++ b/src/ui/video/VideoMediaPlayerWidget.cpp @@ -38,6 +38,7 @@ convert(Transcode::Format format) case Transcode::Format::MP3: return Wt::WMediaPlayer::MP3; case Transcode::Format::WEBMA: return Wt::WMediaPlayer::WEBMA; case Transcode::Format::WEBMV: return Wt::WMediaPlayer::WEBMV; + case Transcode::Format::FLA: return Wt::WMediaPlayer::FLA; case Transcode::Format::FLV: return Wt::WMediaPlayer::FLV; case Transcode::Format::M4A: return Wt::WMediaPlayer::M4A; case Transcode::Format::M4V: return Wt::WMediaPlayer::M4V; diff --git a/src/ui/video/VideoWidget.cpp b/src/ui/video/VideoWidget.cpp index 16ff470f..31ebeebc 100644 --- a/src/ui/video/VideoWidget.cpp +++ b/src/ui/video/VideoWidget.cpp @@ -22,16 +22,17 @@ #include "logger/Logger.hpp" +#include "LmsApplication.hpp" + #include "VideoWidget.hpp" namespace UserInterface { -VideoWidget::VideoWidget(SessionData& sessionData, Wt::WContainerWidget* parent ) -: Wt::WContainerWidget(parent), -_sessionData(sessionData) +VideoWidget::VideoWidget(Wt::WContainerWidget* parent ) +: Wt::WContainerWidget(parent) { - _videoDbWidget = new VideoDatabaseWidget(_sessionData.getDatabaseHandler(), this); + _videoDbWidget = new VideoDatabaseWidget(this); _videoDbWidget->playVideo().connect(this, &VideoWidget::playVideo); @@ -56,19 +57,10 @@ VideoWidget::playVideo(boost::filesystem::path p) // Get user preferences { - Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); + Wt::Dbo::Transaction transaction(DboSession()); - Database::User::pointer user = _sessionData.getDatabaseHandler().getCurrentUser(); - if (user) - { - audioBitrate = user->getMaxAudioBitrate(); - videoBitrate = user->getMaxVideoBitrate(); - } - else - { - LMS_LOG(MOD_UI, SEV_ERROR) << "Can't play video: user does not exists!"; - return; // TODO logout? - } + audioBitrate = CurrentUser()->getMaxAudioBitrate(); + videoBitrate = CurrentUser()->getMaxVideoBitrate(); } LMS_LOG(MOD_UI, SEV_DEBUG) << "Max bitrate set to " << videoBitrate << "/" << audioBitrate; diff --git a/src/ui/video/VideoWidget.hpp b/src/ui/video/VideoWidget.hpp index b7720d2a..68b2109a 100644 --- a/src/ui/video/VideoWidget.hpp +++ b/src/ui/video/VideoWidget.hpp @@ -24,8 +24,6 @@ #include -#include "common/SessionData.hpp" - #include "video/VideoMediaPlayerWidget.hpp" #include "video/VideoDatabaseWidget.hpp" @@ -35,7 +33,7 @@ class VideoWidget : public Wt::WContainerWidget { public: - VideoWidget(SessionData& sessionData, Wt::WContainerWidget* parent = 0); + VideoWidget(Wt::WContainerWidget* parent = 0); void search(const std::string& searchText); @@ -44,8 +42,6 @@ class VideoWidget : public Wt::WContainerWidget void backToList(void); void playVideo(boost::filesystem::path p); - SessionData& _sessionData; - VideoDatabaseWidget* _videoDbWidget; VideoMediaPlayerWidget* _mediaPlayer;