diff --git a/approot/templates.xml b/approot/templates.xml index ff40519c..27fc5b8a 100644 --- a/approot/templates.xml +++ b/approot/templates.xml @@ -490,7 +490,7 @@ - + diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp index cc99db01..faa87640 100644 --- a/src/ui/LmsApplication.cpp +++ b/src/ui/LmsApplication.cpp @@ -194,11 +194,9 @@ LmsApplication::handleAuthEvent(void) this->root()->setOverflow(Wt::WContainerWidget::OverflowHidden); setConfirmCloseMessage("Closing LMS. Are you sure?"); - // Handle internal paths - // Create a Vertical layout: top is the nav bar, bottom is the contents Wt::WVBoxLayout *layout = new Wt::WVBoxLayout(this->root()); - // Create a navigation bar with a link to a web page. + Wt::WNavigationBar *navigation = new Wt::WNavigationBar(); navigation->setTitle("LMS", "https://github.com/epoupon/lms"); navigation->setResponsive(true); @@ -219,19 +217,20 @@ LmsApplication::handleAuthEvent(void) searchEdit->setWidth(150); // TODO add a span with a search icon - Audio *audio; + menu->setInternalPathEnabled(); + menu->setInternalBasePath("/"); + Audio *audio; if (agentIsMobile()) audio = new Mobile::Audio(); else audio = new Desktop::Audio(); - menu->addItem("Audio", audio); + menu->addItem("Audio", audio)->setPathComponent("audio");; #if defined HAVE_VIDEO - menu->addItem("Video", new VideoWidget()); + menu->addItem("Video", new VideoWidget())->setPathComponent("video"); #endif - menu->addItem("Settings", new Settings::Settings()); - + menu->addItem("Settings", new Settings::Settings())->setPathComponent("settings"); Wt::WPopupMenu *popup = new Wt::WPopupMenu(); popup->addItem("Logout"); diff --git a/src/ui/audio/mobile/MobileAudio.cpp b/src/ui/audio/mobile/MobileAudio.cpp index c37c9fcc..c9e3fdbb 100644 --- a/src/ui/audio/mobile/MobileAudio.cpp +++ b/src/ui/audio/mobile/MobileAudio.cpp @@ -55,18 +55,6 @@ enum WidgetIdx using namespace Database; -static void playTrack(AudioPlayer *audioPlayer, Database::Track::id_type trackId) -{ - LMS_LOG(UI, DEBUG) << "Playing track id " << trackId; - - Wt::Dbo::Transaction transaction(DboSession()); - - Track::pointer track = Track::getById(DboSession(), trackId); - - if (track) - audioPlayer->loadTrack(track.id()); -} - void Audio::search(std::string text) { @@ -83,12 +71,12 @@ Audio::Audio(Wt::WContainerWidget *parent) Wt::WStackedWidget *stack = new Wt::WStackedWidget(this); // Same order as WidgetIdxXXX - stack->addWidget(new PreviewSearchView()); + stack->addWidget(new PreviewSearchView(_playQueueEvents)); stack->addWidget(new ArtistSearchView()); stack->addWidget(new ReleaseSearchView()); - stack->addWidget(new TrackSearchView()); + stack->addWidget(new TrackSearchView(_playQueueEvents)); stack->addWidget(new ArtistView()); - stack->addWidget(new ReleaseView()); + stack->addWidget(new ReleaseView(_playQueueEvents)); wApp->internalPathChanged().connect(std::bind([=] (std::string path) { @@ -117,6 +105,11 @@ Audio::Audio(Wt::WContainerWidget *parent) AudioPlayer* audioPlayer = new AudioPlayer(); footer->bindWidget("player", audioPlayer); + // Connect the events to the player + _playQueueEvents.trackPlay.connect(std::bind([=] (Database::Track::id_type id) + { + audioPlayer->loadTrack(id); + }, std::placeholders::_1)); } } // namespace Mobile diff --git a/src/ui/audio/mobile/MobileAudio.hpp b/src/ui/audio/mobile/MobileAudio.hpp index 1f8ea20d..c49b24ae 100644 --- a/src/ui/audio/mobile/MobileAudio.hpp +++ b/src/ui/audio/mobile/MobileAudio.hpp @@ -17,13 +17,15 @@ * along with LMS. If not, see . */ -#ifndef UI_AUDIO_MOBILE_HPP -#define UI_AUDIO_MOBILE_HPP +#pragma once #include #include "audio/Audio.hpp" +#include "MobilePlayQueueEvents.hpp" + + namespace UserInterface { namespace Mobile { @@ -35,9 +37,11 @@ class Audio : public UserInterface::Audio void search(std::string text); private: + + PlayQueueEvents _playQueueEvents; + }; } // namespace Mobile } // namespace UserInterface -#endif diff --git a/src/ui/audio/mobile/MobilePlayQueueEvents.hpp b/src/ui/audio/mobile/MobilePlayQueueEvents.hpp new file mode 100644 index 00000000..9fb80bf4 --- /dev/null +++ b/src/ui/audio/mobile/MobilePlayQueueEvents.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include +#include "database/Types.hpp" + +namespace UserInterface { +namespace Mobile { + +struct PlayQueueEvents +{ + Wt::Signal trackPlay; +}; + + +} // namespace Mobile +} // namespace UserInterface diff --git a/src/ui/audio/mobile/PreviewSearchView.cpp b/src/ui/audio/mobile/PreviewSearchView.cpp index 2385b8c9..38cb7a33 100644 --- a/src/ui/audio/mobile/PreviewSearchView.cpp +++ b/src/ui/audio/mobile/PreviewSearchView.cpp @@ -36,13 +36,13 @@ namespace Mobile { using namespace Database; -PreviewSearchView::PreviewSearchView(Wt::WContainerWidget* parent) +PreviewSearchView::PreviewSearchView(PlayQueueEvents& events, Wt::WContainerWidget* parent) { const std::string pathPrefix = "/audio/search/preview"; ArtistSearch* artistSearch = new ArtistSearch("Artists", this); ReleaseSearch* releaseSearch = new ReleaseSearch(this); - TrackSearch* trackSearch = new TrackSearch(this); + TrackSearch* trackSearch = new TrackSearch(events, this); artistSearch->showMore().connect(std::bind([=] { diff --git a/src/ui/audio/mobile/PreviewSearchView.hpp b/src/ui/audio/mobile/PreviewSearchView.hpp index bdcc079f..fab0b4e9 100644 --- a/src/ui/audio/mobile/PreviewSearchView.hpp +++ b/src/ui/audio/mobile/PreviewSearchView.hpp @@ -21,6 +21,8 @@ #include +#include "MobilePlayQueueEvents.hpp" + namespace UserInterface { namespace Mobile { @@ -28,7 +30,7 @@ class PreviewSearchView : public Wt::WContainerWidget { public: - PreviewSearchView(Wt::WContainerWidget* parent = 0); + PreviewSearchView(PlayQueueEvents& events, Wt::WContainerWidget* parent = 0); }; diff --git a/src/ui/audio/mobile/ReleaseSearch.hpp b/src/ui/audio/mobile/ReleaseSearch.hpp index e2a7586e..3e82eb57 100644 --- a/src/ui/audio/mobile/ReleaseSearch.hpp +++ b/src/ui/audio/mobile/ReleaseSearch.hpp @@ -20,7 +20,6 @@ #pragma once #include -#include #include #include "database/SearchFilter.hpp" diff --git a/src/ui/audio/mobile/ReleaseView.cpp b/src/ui/audio/mobile/ReleaseView.cpp index a74bcd16..7557e8ac 100644 --- a/src/ui/audio/mobile/ReleaseView.cpp +++ b/src/ui/audio/mobile/ReleaseView.cpp @@ -33,8 +33,9 @@ namespace Mobile { using namespace Database; -ReleaseView::ReleaseView(Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent) +ReleaseView::ReleaseView(PlayQueueEvents& events, Wt::WContainerWidget *parent) +: Wt::WContainerWidget(parent), + _events(events) { Wt::WTemplate* wrapper = new Wt::WTemplate(this); wrapper->setTemplateText(Wt::WString::tr("wa-trackview-wrapper")); @@ -97,23 +98,6 @@ ReleaseView::search(SearchFilter filter, size_t nb) addResults(nb); } -static -std::vector -getTracks(SearchFilter filter, size_t offset, size_t nb, bool &moreResults) -{ - std::vector tracks = Track::getByFilter(DboSession(), filter, offset, nb + 1); - - if (tracks.size() == nb + 1) - { - moreResults = true; - tracks.pop_back(); - } - else - moreResults = false; - - return tracks; -} - static Wt::WString getArtistNameFromRelease(Release::pointer release) { @@ -132,7 +116,7 @@ ReleaseView::addResults(size_t nb) Wt::Dbo::Transaction transaction(DboSession()); bool moreResults; - std::vector tracks = getTracks(_filter, _nbTracks, nb, moreResults); + std::vector tracks = Track::getByFilter(DboSession(), _filter, _nbTracks, nb, moreResults); for (Track::pointer track : tracks) { @@ -150,7 +134,7 @@ ReleaseView::addResults(size_t nb) Wt::WImage *cover = new Wt::WImage(); cover->setStyleClass ("center-block img-responsive"); // TODO move to CSS? - cover->setImageLink(Wt::WLink (LmsApp->getImageResource()->getReleaseUrl(release.id(), 512))); + cover->setImageLink(Wt::WLink (SessionImageResource()->getReleaseUrl(release.id(), 512))); releaseContainer->bindWidget("cover", cover); releaseContainer->bindString("artist-name", getArtistNameFromRelease(release), Wt::PlainText); @@ -191,16 +175,13 @@ ReleaseView::addResults(size_t nb) trackRes->bindString("track-name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText); // TODO, display artist name for compilation releases? - std::string format = track->getDuration().total_seconds() < 3600 ? "%M:%S" : "%H:%M:%S"; - trackRes->bindString("time", durationToString(track->getDuration(), format), Wt::PlainText); - Wt::WText *playBtn = new Wt::WText("Play", Wt::PlainText); playBtn->setStyleClass("center-block"); // TODO move to CSS? playBtn->clicked().connect(std::bind([=] { - _sigTrackPlay.emit(track.id()); + _events.trackPlay.emit(track.id()); })); - trackRes->bindWidget("btn", playBtn); + trackRes->bindWidget("play-btn", playBtn); _nbTracks++; } diff --git a/src/ui/audio/mobile/ReleaseView.hpp b/src/ui/audio/mobile/ReleaseView.hpp index c2553793..bb590702 100644 --- a/src/ui/audio/mobile/ReleaseView.hpp +++ b/src/ui/audio/mobile/ReleaseView.hpp @@ -22,6 +22,8 @@ #include #include +#include "MobilePlayQueueEvents.hpp" + namespace UserInterface { namespace Mobile { @@ -31,22 +33,21 @@ class ReleaseView : public Wt::WContainerWidget static Wt::WLink getLink(Database::Release::id_type id); - ReleaseView(Wt::WContainerWidget *parent = 0); + ReleaseView(PlayQueueEvents& events, Wt::WContainerWidget *parent = 0); void search(Database::SearchFilter filter, size_t nb); // Slots - Wt::Signal& trackPlay() { return _sigTrackPlay;} Wt::Signal& moreTracksSelected() { return _sigMoreTracksSelected;} private: - Wt::Signal _sigTrackPlay; Wt::Signal _sigMoreTracksSelected; void clear(void); void addResults(size_t nb); + PlayQueueEvents& _events; Wt::WTemplate* _showMore; Database::SearchFilter _filter; diff --git a/src/ui/audio/mobile/TrackSearch.cpp b/src/ui/audio/mobile/TrackSearch.cpp index ce0ecc8f..504ca3b9 100644 --- a/src/ui/audio/mobile/TrackSearch.cpp +++ b/src/ui/audio/mobile/TrackSearch.cpp @@ -33,8 +33,9 @@ namespace Mobile { using namespace Database; -TrackSearch::TrackSearch(Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent) +TrackSearch::TrackSearch(PlayQueueEvents& events, Wt::WContainerWidget *parent) +: Wt::WContainerWidget(parent), + _events(events) { Wt::WTemplate* t = new Wt::WTemplate(this); t->setTemplateText(Wt::WString::tr("wa-track-search")); @@ -97,7 +98,7 @@ TrackSearch::addResults(size_t nb) Wt::WText *playBtn = new Wt::WText("Play", Wt::PlainText); playBtn->setStyleClass("center-block"); // TODO move to CSS? playBtn->clicked().connect(std::bind([=] { - _sigTrackPlay.emit(track.id()); + _events.trackPlay.emit(track.id()); })); res->bindWidget("btn", playBtn); diff --git a/src/ui/audio/mobile/TrackSearch.hpp b/src/ui/audio/mobile/TrackSearch.hpp index 8fe7fe3b..0a98d886 100644 --- a/src/ui/audio/mobile/TrackSearch.hpp +++ b/src/ui/audio/mobile/TrackSearch.hpp @@ -25,6 +25,8 @@ #include "database/SearchFilter.hpp" #include "database/Types.hpp" +#include "MobilePlayQueueEvents.hpp" + namespace UserInterface { namespace Mobile { @@ -32,22 +34,21 @@ class TrackSearch : public Wt::WContainerWidget { public: - TrackSearch(Wt::WContainerWidget *parent = 0); + TrackSearch(PlayQueueEvents& events, Wt::WContainerWidget *parent = 0); void addResults(size_t nb); void search(Database::SearchFilter filter, size_t nb); // Slots Wt::Signal& showMore() { return _sigShowMore;} - Wt::Signal& trackPlay() { return _sigTrackPlay;} private: Wt::Signal _sigShowMore; - Wt::Signal _sigTrackPlay; void clear(void); + PlayQueueEvents& _events; Wt::WTemplate* _showMore; Database::SearchFilter _filter; Wt::WContainerWidget* _contents; diff --git a/src/ui/audio/mobile/TrackSearchView.cpp b/src/ui/audio/mobile/TrackSearchView.cpp index 3141d561..c7138452 100644 --- a/src/ui/audio/mobile/TrackSearchView.cpp +++ b/src/ui/audio/mobile/TrackSearchView.cpp @@ -34,9 +34,9 @@ namespace Mobile { using namespace Database; -TrackSearchView::TrackSearchView(Wt::WContainerWidget* parent) +TrackSearchView::TrackSearchView(PlayQueueEvents& events, Wt::WContainerWidget* parent) { - TrackSearch* trackSearch = new TrackSearch(this); + TrackSearch* trackSearch = new TrackSearch(events, this); trackSearch->showMore().connect(std::bind([=] { trackSearch->addResults(SEARCH_NB_ITEMS); })); diff --git a/src/ui/audio/mobile/TrackSearchView.hpp b/src/ui/audio/mobile/TrackSearchView.hpp index 67f560b8..602d9c56 100644 --- a/src/ui/audio/mobile/TrackSearchView.hpp +++ b/src/ui/audio/mobile/TrackSearchView.hpp @@ -20,6 +20,7 @@ #pragma once #include +#include namespace UserInterface { namespace Mobile { @@ -28,7 +29,7 @@ class TrackSearchView : public Wt::WContainerWidget { public: - TrackSearchView(Wt::WContainerWidget* parent = 0); + TrackSearchView(PlayQueueEvents& events, Wt::WContainerWidget* parent = 0); }; diff --git a/src/ui/settings/Settings.cpp b/src/ui/settings/Settings.cpp index c2e8d727..84e38fd3 100644 --- a/src/ui/settings/Settings.cpp +++ b/src/ui/settings/Settings.cpp @@ -55,6 +55,8 @@ Settings::Settings(Wt::WContainerWidget* parent) Wt::WMenu *menu = new Wt::WMenu(contents, Wt::Vertical); menu->setStyleClass("nav nav-pills nav-stacked submenu"); menu->setWidth(150); + menu->setInternalPathEnabled(); + menu->setInternalBasePath("/settings/"); hLayout->addWidget(menu); hLayout->addWidget(contents, 1); @@ -68,22 +70,22 @@ Settings::Settings(Wt::WContainerWidget* parent) userIsAdmin = CurrentUser()->isAdmin(); } - menu->addItem("Audio", new AudioFormView()); + menu->addItem("Audio", new AudioFormView())->setPathComponent("audio"); if (userIsAdmin) { - MediaDirectories* mediaDirectory = new MediaDirectories(); - mediaDirectory->changed().connect(this, &Settings::handleDatabaseDirectoriesChanged); - menu->addItem("Media Folders", mediaDirectory); + MediaDirectories* mediaDirectories = new MediaDirectories(); + mediaDirectories->changed().connect(this, &Settings::handleDatabaseDirectoriesChanged); + menu->addItem("Media Folders", mediaDirectories)->setPathComponent("mediadirectories"); DatabaseFormView* databaseFormView = new DatabaseFormView(); databaseFormView->changed().connect(this, &Settings::restartDatabaseUpdateService); - menu->addItem("Database", databaseFormView); + menu->addItem("Database", databaseFormView)->setPathComponent("database"); - menu->addItem("Users", new Users()); + menu->addItem("Users", new Users())->setPathComponent("users"); } else { - menu->addItem("Account", new AccountFormView(userId)); + menu->addItem("Account", new AccountFormView(userId))->setPathComponent("account"); } }