mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-01-06 04:49:04 -05:00
138 lines
6.4 KiB
C++
138 lines
6.4 KiB
C++
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#pragma once
|
|
|
|
#include <apps-common/ApplicationCommon.hpp>
|
|
#include <tags_fetcher/TagsFetcher.hpp>
|
|
#include <module-db/Interface/MultimediaFilesRecord.hpp>
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace app::music
|
|
{
|
|
struct FilesCache
|
|
{
|
|
std::vector<db::multimedia_files::MultimediaFilesRecord> records{};
|
|
std::uint32_t recordsOffset{0};
|
|
std::uint32_t recordsCount{0};
|
|
};
|
|
|
|
class AbstractTagsFetcher
|
|
{
|
|
public:
|
|
virtual ~AbstractTagsFetcher() noexcept = default;
|
|
|
|
virtual std::optional<tags::fetcher::Tags> getFileTags(const std::string &filePath) const = 0;
|
|
};
|
|
|
|
class ServiceAudioTagsFetcher : public AbstractTagsFetcher
|
|
{
|
|
public:
|
|
explicit ServiceAudioTagsFetcher(ApplicationCommon *application);
|
|
|
|
std::optional<tags::fetcher::Tags> getFileTags(const std::string &filePath) const final;
|
|
|
|
private:
|
|
ApplicationCommon *application = nullptr;
|
|
};
|
|
|
|
class AbstractSongsRepository
|
|
{
|
|
public:
|
|
using OnGetMusicFilesListCallback =
|
|
std::function<bool(const std::vector<db::multimedia_files::MultimediaFilesRecord> &, unsigned int)>;
|
|
|
|
virtual ~AbstractSongsRepository() noexcept = default;
|
|
|
|
virtual void initCache() = 0;
|
|
virtual void getMusicFilesList(uint32_t offset,
|
|
uint32_t limit,
|
|
const OnGetMusicFilesListCallback &callback) = 0;
|
|
virtual void getMusicFilesListByPaths(std::uint32_t offset,
|
|
std::uint32_t limit,
|
|
const OnGetMusicFilesListCallback &callback) = 0;
|
|
virtual std::string getNextFilePath(const std::string &filePath) const = 0;
|
|
virtual std::string getPreviousFilePath(const std::string &filePath) const = 0;
|
|
virtual std::optional<db::multimedia_files::MultimediaFilesRecord> getRecord(
|
|
const std::string &filePath) const = 0;
|
|
virtual void updateRepository(const std::string &filePath) = 0;
|
|
};
|
|
|
|
class SongsRepository : public AbstractSongsRepository, public app::AsyncCallbackReceiver
|
|
{
|
|
public:
|
|
SongsRepository(ApplicationCommon *application,
|
|
std::unique_ptr<AbstractTagsFetcher> tagsFetcher,
|
|
const std::vector<std::string> &pathPrefixes);
|
|
|
|
void initCache() override;
|
|
void getMusicFilesList(uint32_t offset, uint32_t limit, const OnGetMusicFilesListCallback &callback) override;
|
|
void getMusicFilesListByPaths(std::uint32_t offset,
|
|
std::uint32_t limit,
|
|
const OnGetMusicFilesListCallback &callback) override;
|
|
std::string getNextFilePath(const std::string &filePath) const override;
|
|
std::string getPreviousFilePath(const std::string &filePath) const override;
|
|
std::optional<db::multimedia_files::MultimediaFilesRecord> getRecord(
|
|
const std::string &filePath) const override;
|
|
|
|
/// If the currently playing track is not included in the musicFilesCache then we request new data of the size
|
|
/// of the cache otherwise if the index number of the currently playing track exceeds the upper or lower
|
|
/// cacheThreshold, then we request the next records. See doc/SongsRepository.md for more information.
|
|
void updateRepository(const std::string &filePath) override;
|
|
|
|
private:
|
|
using OnUpdateMusicFilesListCallback = std::function<bool(
|
|
const std::vector<db::multimedia_files::MultimediaFilesRecord> &, unsigned int, std::uint32_t)>;
|
|
|
|
ApplicationCommon *application;
|
|
|
|
std::unique_ptr<AbstractTagsFetcher> tagsFetcher;
|
|
|
|
std::vector<std::string> pathPrefixes;
|
|
|
|
/// collection of music files displayed in the list view
|
|
FilesCache musicFilesViewCache;
|
|
/// collection of music files currently playing
|
|
FilesCache musicFilesModelCache;
|
|
|
|
std::size_t getCachedFileIndex(const std::string &filePath) const;
|
|
std::uint32_t calculateOffset();
|
|
|
|
/// Try to fetch list view's entry by the file name
|
|
std::optional<db::multimedia_files::MultimediaFilesRecord> getCachedViewEntryByFilePath(
|
|
const std::string &filePath) const;
|
|
|
|
/// overwrite the musicFiles view cache with new data from the given index
|
|
void updateMusicFilesList(std::uint32_t offset,
|
|
std::uint32_t limit,
|
|
const OnUpdateMusicFilesListCallback &callback);
|
|
|
|
/// overwrite musicFiles model cache with new data from zero index
|
|
bool initCacheCallback(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
|
|
unsigned int repoRecordsCount);
|
|
/// overwrite the musicFiles model cache with new data from the given index
|
|
bool newDataCallback(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
|
|
unsigned int repoRecordsCount,
|
|
std::uint32_t offset);
|
|
/// adding new data to the musicFiles model cache at the end of the list, with the first records being deleted
|
|
/// so that the cache size is not changed
|
|
bool newBackDataCallback(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
|
|
unsigned int repoRecordsCount,
|
|
std::uint32_t offset);
|
|
/// adding new data to the musicFiles model cache to the top of the list, but the last records are removed so
|
|
/// that the cache size is not changed
|
|
bool newFrontDataCallback(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
|
|
unsigned int repoRecordsCount,
|
|
std::uint32_t offset);
|
|
|
|
void getMusicFilesList(const std::vector<std::string> &paths,
|
|
std::uint32_t offset,
|
|
std::uint32_t limit,
|
|
const OnGetMusicFilesListCallback &callback);
|
|
};
|
|
} // namespace app::music
|