db.h (6964B)
1 #pragma once 2 3 #include <functional> 4 #include <map> 5 #include <list> 6 #include <shared_mutex> 7 8 #include "patch.h" 9 #include "patchdbtypes.h" 10 #include "search.h" 11 12 #include "jobqueue.h" 13 14 #include "juce_core/juce_core.h" 15 16 namespace pluginLib 17 { 18 enum class ExportType : uint8_t; 19 class FileType; 20 } 21 22 namespace pluginLib::patchDB 23 { 24 struct SearchRequest; 25 struct Patch; 26 struct DataSource; 27 28 class DB 29 { 30 public: 31 using DataSourceLoadedCallback = std::function<void(bool,DataSourceNodePtr)>; 32 33 DB(juce::File _dir); 34 virtual ~DB(); 35 36 void uiProcess(); 37 38 DataSourceNodePtr addDataSource(const DataSource& _ds, const DataSourceLoadedCallback& = [](bool, std::shared_ptr<DataSourceNode>) {}); 39 void removeDataSource(const DataSource& _ds, bool _save = true); 40 void refreshDataSource(const DataSourceNodePtr& _ds); 41 void renameDataSource(const DataSourceNodePtr& _ds, const std::string& _newName); 42 DataSourceNodePtr getDataSource(const DataSource& _ds); 43 std::set<DataSourceNodePtr> getDataSourcesOfSourceType(SourceType _type); 44 45 void getDataSources(std::vector<DataSourceNodePtr>& _dataSources) 46 { 47 std::shared_lock lock(m_dataSourcesMutex); 48 _dataSources.reserve(m_dataSources.size()); 49 for (const auto& it : m_dataSources) 50 _dataSources.push_back(it.second); 51 } 52 53 bool setTagColor(TagType _type, const Tag& _tag, Color _color); 54 Color getTagColor(TagType _type, const Tag& _tag) const; 55 Color getPatchColor(const PatchPtr& _patch, const TypedTags& _tagsToIgnore) const; 56 57 bool addTag(TagType _type, const Tag& _tag); 58 bool removeTag(TagType _type, const Tag& _tag); 59 60 void getTags(TagType _type, std::set<Tag>& _tags); 61 bool modifyTags(const std::vector<PatchPtr>& _patches, const TypedTags& _tags); 62 bool renamePatch(const PatchPtr& _patch, const std::string& _name); 63 bool replacePatch(const PatchPtr& _existing, const PatchPtr& _new); 64 65 SearchHandle search(SearchRequest&& _request); 66 SearchHandle search(SearchRequest&& _request, SearchCallback&& _callback); 67 SearchHandle findDatasourceForPatch(const PatchPtr& _patch, SearchCallback&& _callback); 68 69 void cancelSearch(uint32_t _handle); 70 std::shared_ptr<Search> getSearch(SearchHandle _handle); 71 std::shared_ptr<Search> getSearch(const DataSource& _dataSource); 72 73 void copyPatchesTo(const DataSourceNodePtr& _ds, const std::vector<PatchPtr>& _patches, int _insertRow = -1, 74 const std::function<void(const std::vector<PatchPtr>&)>& _successCallback = {}); 75 void removePatches(const DataSourceNodePtr& _ds, const std::vector<PatchPtr>& _patches); 76 bool movePatchesTo(uint32_t _position, const std::vector<PatchPtr>& _patches); 77 78 static bool isValid(const PatchPtr& _patch); 79 80 PatchPtr requestPatchForPart(uint32_t _part, uint64_t _userData = 0); 81 virtual bool requestPatchForPart(Data& _data, uint32_t _part, uint64_t _userData) = 0; 82 83 bool isLoading() const { return m_loading; } 84 bool isScanning() const { return !m_loader.empty(); } 85 86 bool writePatchesToFile(const juce::File& _file, const std::vector<PatchPtr>& _patches); 87 88 static void assign(const PatchPtr& _patch, const PatchModificationsPtr& _mods); 89 90 static std::string createValidFilename(const std::string& _name); 91 92 protected: 93 DataSourceNodePtr addDataSource(const DataSource& _ds, bool _save, const DataSourceLoadedCallback& = [](bool , std::shared_ptr<DataSourceNode>) {}); 94 95 public: 96 virtual bool loadData(DataList& _results, const DataSourceNodePtr& _ds); 97 virtual bool loadData(DataList& _results, const DataSource& _ds); 98 99 virtual bool loadRomData(DataList& _results, uint32_t _bank, uint32_t _program) = 0; 100 virtual bool loadFile(DataList& _results, const std::string& _file); 101 virtual bool loadLocalStorage(DataList& _results, const DataSource& _ds); 102 virtual bool loadFolder(const DataSourceNodePtr& _folder); 103 virtual PatchPtr initializePatch(Data&& _sysex, const std::string& _defaultPatchName) = 0; 104 virtual Data applyModifications(const PatchPtr& _patch, const FileType& _fileType, ExportType _exportType) const = 0; 105 virtual bool parseFileData(DataList& _results, const Data& _data); 106 virtual bool equals(const PatchPtr& _a, const PatchPtr& _b) const 107 { 108 return _a == _b || _a->hash == _b->hash; 109 } 110 virtual void processDirty(const Dirty& _dirty) const = 0; 111 112 protected: 113 virtual void onLoadFinished() {} 114 115 virtual void startLoaderThread(const juce::File& _migrateFromDir = {}); 116 void stopLoaderThread(); 117 118 void runOnLoaderThread(std::function<void()>&& _func); 119 void runOnUiThread(const std::function<void()>& _func); 120 121 private: 122 void addDataSource(const DataSourceNodePtr& _ds); 123 124 bool addPatches(const std::vector<PatchPtr>& _patches); 125 bool removePatch(const PatchPtr& _patch); 126 127 bool internalAddTag(TagType _type, const Tag& _tag); 128 bool internalRemoveTag(TagType _type, const Tag& _tag); 129 130 bool executeSearch(Search& _search); 131 void updateSearches(const std::vector<PatchPtr>& _patches); 132 bool removePatchesFromSearches(const std::vector<PatchPtr>& _keys); 133 134 void preservePatchModifications(const PatchPtr& _patch); 135 void preservePatchModifications(const std::vector<PatchPtr>& _patches); 136 137 bool createConsecutiveProgramNumbers(const DataSourceNodePtr& _ds) const; 138 139 Color getTagColorInternal(TagType _type, const Tag& _tag) const; 140 141 bool loadJson(); 142 bool loadPatchModifications(const DataSourceNodePtr& _ds, const std::vector<PatchPtr>& _patches); 143 static bool loadPatchModifications(std::map<PatchKey, PatchModificationsPtr>& _patchModifications, const juce::var& _parentNode, const DataSourceNodePtr& _dataSource = nullptr); 144 145 bool deleteFile(const juce::File& _file); 146 147 bool saveJson(); 148 bool saveJson(const DataSourceNodePtr& _ds); 149 bool saveJson(const juce::File& _target, juce::DynamicObject* _src); 150 151 public: 152 juce::File getJsonFile(const DataSource& _ds) const; 153 juce::File getLocalStorageFile(const DataSource& _ds) const; 154 155 private: 156 bool saveLocalStorage(); 157 158 void pushError(std::string _string); 159 160 bool loadCache(); 161 void saveCache(); 162 juce::File getCacheFile() const; 163 juce::File getJsonFile() const; 164 165 // IO 166 const juce::File m_settingsDir; 167 168 // loader 169 JobQueue m_loader; 170 171 // ui 172 std::mutex m_uiMutex; 173 std::list<std::function<void()>> m_uiFuncs; 174 Dirty m_dirty; 175 176 // data 177 std::shared_mutex m_dataSourcesMutex; 178 std::map<DataSource, DataSourceNodePtr> m_dataSources; // we need a key to find duplicates, but at the same time we need pointers to do the parent relation 179 180 mutable std::shared_mutex m_patchesMutex; 181 std::unordered_map<TagType, std::set<Tag>> m_tags; 182 std::unordered_map<TagType, std::unordered_map<Tag, uint32_t>> m_tagColors; 183 std::map<PatchKey, PatchModificationsPtr> m_patchModifications; 184 185 // search 186 std::shared_mutex m_searchesMutex; 187 std::unordered_map<uint32_t, std::shared_ptr<Search>> m_searches; 188 std::unordered_set<SearchHandle> m_cancelledSearches; 189 uint32_t m_nextSearchHandle = 0; 190 191 // state 192 bool m_loading = true; 193 bool m_cacheDirty = false; 194 }; 195 }