From c69fde01d4d07cadb195c7febc32be8a875bc4de Mon Sep 17 00:00:00 2001 From: Maciej Gibowicz Date: Sun, 19 Sep 2021 16:08:30 +0200 Subject: [PATCH] [EGD-6630] Integration file indexer with music player The list of music tracks is retrieved from the database, where they are indexed beforehand, instead of being searched in real time in the file system. --- .../ApplicationMusicPlayer.cpp | 4 +- .../models/SongsModel.cpp | 135 +++++++-------- .../models/SongsModel.hpp | 13 +- .../models/SongsModelInterface.hpp | 9 +- .../models/SongsRepository.cpp | 61 ++++--- .../models/SongsRepository.hpp | 27 +-- .../tests/CMakeLists.txt | 1 - .../tests/MockSongsRepository.hpp | 6 +- .../tests/unittest_songrepository.cpp | 154 ------------------ .../tests/unittest_songsmodel.cpp | 15 +- .../windows/MusicPlayerAllSongsWindow.cpp | 3 - module-db/Interface/MultimediaFilesRecord.cpp | 10 +- .../QueryMultimediaFilesGetLimited.cpp | 24 ++- .../QueryMultimediaFilesGetLimited.hpp | 15 +- 14 files changed, 173 insertions(+), 304 deletions(-) delete mode 100644 module-apps/application-music-player/tests/unittest_songrepository.cpp diff --git a/module-apps/application-music-player/ApplicationMusicPlayer.cpp b/module-apps/application-music-player/ApplicationMusicPlayer.cpp index d082eeddde68ae8fded51dc16f9b70c0856cc9f2..283d5a7c18969a7435b38e8b23bc68e51fea0c3b 100644 --- a/module-apps/application-music-player/ApplicationMusicPlayer.cpp +++ b/module-apps/application-music-player/ApplicationMusicPlayer.cpp @@ -46,8 +46,8 @@ namespace app bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications); auto tagsFetcher = std::make_unique(this); - auto songsRepository = std::make_unique(std::move(tagsFetcher)); - priv->songsModel = std::make_unique(std::move(songsRepository)); + auto songsRepository = std::make_unique(this, std::move(tagsFetcher)); + priv->songsModel = std::make_unique(this, std::move(songsRepository)); auto audioOperations = std::make_unique(this); priv->songsPresenter = std::make_unique(priv->songsModel, std::move(audioOperations)); diff --git a/module-apps/application-music-player/models/SongsModel.cpp b/module-apps/application-music-player/models/SongsModel.cpp index 3921b7b25135f3b6b616e5bd5071017cbd1c025d..97690cee6ab5df0b11dd1e1d38c9fd92058a93db 100644 --- a/module-apps/application-music-player/models/SongsModel.cpp +++ b/module-apps/application-music-player/models/SongsModel.cpp @@ -12,13 +12,19 @@ namespace app::music_player { - SongsModel::SongsModel(std::shared_ptr songsRepository) - : songsRepository{std::move(songsRepository)} + SongsListItemProvider::SongsListItemProvider(ApplicationCommon *app) : DatabaseModel(app) + {} + + SongsModelInterface::SongsModelInterface(ApplicationCommon *app) : SongsListItemProvider(app) + {} + + SongsModel::SongsModel(app::ApplicationCommon *app, std::shared_ptr songsRepository) + : SongsModelInterface(app), songsRepository{std::move(songsRepository)} {} auto SongsModel::requestRecordsCount() -> unsigned int { - return internalData.size(); + return recordsCount; } auto SongsModel::getMinimalItemSpaceRequired() const -> unsigned int @@ -28,48 +34,65 @@ namespace app::music_player void SongsModel::requestRecords(const uint32_t offset, const uint32_t limit) { - setupModel(offset, limit); - list->onProviderDataUpdate(); + songsRepository->getMusicFilesList( + offset, + limit, + [this](const std::vector &records, + unsigned int repoRecordsCount) { return onMusicListRetrieved(records, repoRecordsCount); }); } auto SongsModel::getItem(gui::Order order) -> gui::ListItem * { - return getRecord(order); - } + std::shared_ptr song = getRecord(order); + if (!song) { + return nullptr; + } - void SongsModel::createData(OnShortReleaseCallback shortReleaseCallback, - OnLongPressCallback longPressCallback, - OnSetBottomBarTemporaryCallback bottomBarTemporaryMode, - OnRestoreBottomBarTemporaryCallback bottomBarRestoreFromTemporaryMode) - { - songsRepository->scanMusicFilesList(); - auto songsList = songsRepository->getMusicFilesList(); - for (const auto &song : songsList) { - auto item = new gui::SongItem(song.artist, - song.title, - utils::time::Duration(song.total_duration_s).str(), - bottomBarTemporaryMode, - bottomBarRestoreFromTemporaryMode); - - item->activatedCallback = [=](gui::Item &) { - shortReleaseCallback(song.filePath); + auto item = new gui::SongItem(song->tags.album.artist, + song->tags.title, + utils::time::Duration(song->audioProperties.songLength).str(), + bottomBarTemporaryMode, + bottomBarRestoreFromTemporaryMode); + + if (songContext.filePath == song->fileInfo.path) { + item->setState(songContext.isPlaying() ? gui::SongItem::ItemState::Playing + : (songContext.isPaused() ? gui::SongItem::ItemState::Paused + : gui::SongItem::ItemState::None)); + } + else { + item->setState(gui::SongItem::ItemState::None); + } + + item->activatedCallback = [this, song](gui::Item &) { + if (shortReleaseCallback != nullptr) { + shortReleaseCallback(song->fileInfo.path); return true; - }; + } + return false; + }; - item->inputCallback = [longPressCallback](gui::Item &, const gui::InputEvent &event) { - if (event.isLongRelease(gui::KeyCode::KEY_ENTER)) { + item->inputCallback = [=](gui::Item &, const gui::InputEvent &event) { + if (event.isLongRelease(gui::KeyCode::KEY_ENTER)) { + if (longPressCallback != nullptr) { longPressCallback(); return true; } - return false; - }; + } + return false; + }; - internalData.push_back(item); - } + return item; + } - for (auto &item : internalData) { - item->deleteByList = false; - } + void SongsModel::createData(OnShortReleaseCallback shortReleaseCallback, + OnLongPressCallback longPressCallback, + OnSetBottomBarTemporaryCallback bottomBarTemporaryMode, + OnRestoreBottomBarTemporaryCallback bottomBarRestoreFromTemporaryMode) + { + this->shortReleaseCallback = shortReleaseCallback; + this->longPressCallback = longPressCallback; + this->bottomBarTemporaryMode = bottomBarTemporaryMode; + this->bottomBarRestoreFromTemporaryMode = bottomBarRestoreFromTemporaryMode; } bool SongsModel::isSongPlaying() const noexcept @@ -80,7 +103,6 @@ namespace app::music_player void SongsModel::setCurrentSongState(SongState songState) noexcept { songContext.currentSongState = songState; - updateCurrentItemState(); } std::optional SongsModel::getCurrentFileToken() const noexcept @@ -112,50 +134,35 @@ namespace app::music_player void SongsModel::setCurrentSongContext(SongContext context) { using namespace gui; - clearCurrentItemState(); - songContext = context; - - updateCurrentItemState(); } void SongsModel::clearCurrentSongContext() { - clearCurrentItemState(); songContext.clear(); } - void SongsModel::clearCurrentItemState() + void SongsModel::clearData() { - using namespace gui; - const auto songIndex = getCurrentIndex(); - if (songIndex < internalData.size()) { - internalData[songIndex]->setState(SongItem::ItemState::None); - } + list->reset(); } - void SongsModel::updateCurrentItemState() + [[nodiscard]] bool SongsModel::updateRecords(std::vector records) { - using namespace gui; - const auto songIndex = getCurrentIndex(); - if (songIndex >= internalData.size()) { - return; - } - - if (songContext.isPlaying()) { - internalData[songIndex]->setState(SongItem::ItemState::Playing); - } - else if (songContext.isPaused()) { - internalData[songIndex]->setState(SongItem::ItemState::Paused); - } - else { - internalData[songIndex]->setState(SongItem::ItemState::None); - } + DatabaseModel::updateRecords(std::move(records)); + list->onProviderDataUpdate(); + return true; } - void SongsModel::clearData() + bool SongsModel::onMusicListRetrieved(const std::vector &records, + unsigned int repoRecordsCount) { - list->reset(); - eraseInternalData(); + if (recordsCount != repoRecordsCount) { + recordsCount = repoRecordsCount; + list->reSendLastRebuildRequest(); + return false; + } + return updateRecords(records); } + } // namespace app::music_player diff --git a/module-apps/application-music-player/models/SongsModel.hpp b/module-apps/application-music-player/models/SongsModel.hpp index b8e05657ec82c2e8bfd41abc7d919f6b44f8fd7f..d8dd948399e9cd266cb295337937eefd96cf8391 100644 --- a/module-apps/application-music-player/models/SongsModel.hpp +++ b/module-apps/application-music-player/models/SongsModel.hpp @@ -16,7 +16,7 @@ namespace app::music_player class SongsModel : public SongsModelInterface { public: - explicit SongsModel(std::shared_ptr songsRepository); + SongsModel(app::ApplicationCommon *app, std::shared_ptr songsRepository); void createData(OnShortReleaseCallback shortReleaseCallback, OnLongPressCallback longPressCallback, @@ -46,10 +46,17 @@ namespace app::music_player void clearData() override; private: - void clearCurrentItemState(); - void updateCurrentItemState(); + bool onMusicListRetrieved(const std::vector &records, + unsigned int repoRecordsCount); + [[nodiscard]] bool updateRecords(std::vector records) override; + SongContext songContext; + OnShortReleaseCallback shortReleaseCallback{nullptr}; + OnLongPressCallback longPressCallback{nullptr}; + OnSetBottomBarTemporaryCallback bottomBarTemporaryMode{nullptr}; + OnRestoreBottomBarTemporaryCallback bottomBarRestoreFromTemporaryMode{nullptr}; + std::shared_ptr songsRepository; }; } // namespace app::music_player diff --git a/module-apps/application-music-player/models/SongsModelInterface.hpp b/module-apps/application-music-player/models/SongsModelInterface.hpp index 04a403e06134ea404df374420b2d51ea16a751b7..f6d5fcf536f192f7d399e64d61feafa20e96ba83 100644 --- a/module-apps/application-music-player/models/SongsModelInterface.hpp +++ b/module-apps/application-music-player/models/SongsModelInterface.hpp @@ -6,20 +6,22 @@ #include "SongContext.hpp" #include #include -#include #include #include +#include +#include namespace app::music_player { - class SongsListItemProvider : public app::InternalModel, public gui::ListItemProvider + class SongsListItemProvider : public app::DatabaseModel, + public gui::ListItemProvider { public: using OnShortReleaseCallback = std::function; using OnLongPressCallback = std::function; using OnSetBottomBarTemporaryCallback = std::function; using OnRestoreBottomBarTemporaryCallback = std::function; - + explicit SongsListItemProvider(app::ApplicationCommon *app); virtual ~SongsListItemProvider() noexcept = default; virtual void createData(OnShortReleaseCallback shortReleaseCallback, @@ -33,6 +35,7 @@ namespace app::music_player class SongsModelInterface : public SongsListItemProvider { public: + explicit SongsModelInterface(app::ApplicationCommon *app); virtual ~SongsModelInterface() noexcept = default; virtual bool isSongPlaying() const noexcept = 0; diff --git a/module-apps/application-music-player/models/SongsRepository.cpp b/module-apps/application-music-player/models/SongsRepository.cpp index 73f7a5005e9cc2be0f37dde30b2c3ccd2907c06e..1c0e3d3eb4442b8cafe840e60bd384fa5c885d75 100644 --- a/module-apps/application-music-player/models/SongsRepository.cpp +++ b/module-apps/application-music-player/models/SongsRepository.cpp @@ -9,7 +9,7 @@ #include #include