~aleteoryx/muditaos

ref: 06d16390c21c37457bc875e841bb12039d1123d7 muditaos/module-apps/apps-common/models/SongsRepository.hpp -rw-r--r-- 6.4 KiB
06d16390 — Lefucjusz [MOS-1021] Fix blocked passcode behavior 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) 2017-2023, 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>

#include <cstddef>

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