gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit d7bae530977046a658238dd74c694022c76231a2
parent cad1d21630d87502da4b91495978a193f3e5fff3
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Sat, 27 Apr 2024 15:17:55 +0200

fix unhandled exception while reading patch manager cache

Diffstat:
Msource/jucePluginLib/patchdb/db.cpp | 286+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 147 insertions(+), 139 deletions(-)

diff --git a/source/jucePluginLib/patchdb/db.cpp b/source/jucePluginLib/patchdb/db.cpp @@ -1690,194 +1690,202 @@ namespace pluginLib::patchDB if(!synthLib::readFile(data, m_cacheFileName.getFullPathName().toStdString())) return false; - synthLib::BinaryStream inStream(data); - - auto stream = inStream.tryReadChunk(chunks::g_patchManager); - - if(!stream) - return false; + try + { + synthLib::BinaryStream inStream(data); - std::unique_lock lockDS(m_dataSourcesMutex); - std::unique_lock lockP(m_patchesMutex); + auto stream = inStream.tryReadChunk(chunks::g_patchManager); - std::map<DataSource, DataSourceNodePtr> resultDataSources; - std::unordered_map<TagType, std::set<Tag>> resultTags; - std::unordered_map<TagType, std::unordered_map<Tag, uint32_t>> resultTagColors; - std::map<PatchKey, PatchModificationsPtr> resultPatchModifications; + if(!stream) + return false; - if(auto s = stream.tryReadChunk(chunks::g_patchManagerDataSources, 1)) - { - const auto numDatasources = s.read<uint32_t>(); + std::unique_lock lockDS(m_dataSourcesMutex); + std::unique_lock lockP(m_patchesMutex); - std::vector<DataSource> dataSources; - dataSources.reserve(numDatasources); + std::map<DataSource, DataSourceNodePtr> resultDataSources; + std::unordered_map<TagType, std::set<Tag>> resultTags; + std::unordered_map<TagType, std::unordered_map<Tag, uint32_t>> resultTagColors; + std::map<PatchKey, PatchModificationsPtr> resultPatchModifications; - for(uint32_t i=0; i<numDatasources; ++i) + if(auto s = stream.tryReadChunk(chunks::g_patchManagerDataSources, 1)) { - DataSource& ds = dataSources.emplace_back(); - if(!ds.read(s)) - return false; - } + const auto numDatasources = s.read<uint32_t>(); - // read tree information - std::map<uint32_t, uint32_t> childToParentMap; - const auto childToParentCount = s.read<uint32_t>(); - for(uint32_t i=0; i<childToParentCount; ++i) - { - const auto child = s.read<uint32_t>(); - const auto parent = s.read<uint32_t>(); - childToParentMap.insert({child, parent}); - } + std::vector<DataSource> dataSources; + dataSources.reserve(numDatasources); - std::vector<DataSourceNodePtr> nodes; - nodes.resize(dataSources.size()); + for(uint32_t i=0; i<numDatasources; ++i) + { + DataSource& ds = dataSources.emplace_back(); + if(!ds.read(s)) + return false; + } - // create root nodes first - for(uint32_t i=0; i<dataSources.size(); ++i) - { - if(childToParentMap.find(i) != childToParentMap.end()) - continue; + // read tree information + std::map<uint32_t, uint32_t> childToParentMap; + const auto childToParentCount = s.read<uint32_t>(); + for(uint32_t i=0; i<childToParentCount; ++i) + { + const auto child = s.read<uint32_t>(); + const auto parent = s.read<uint32_t>(); + childToParentMap.insert({child, parent}); + } - const auto& ds = dataSources[i]; - const auto node = std::make_shared<DataSourceNode>(ds); - nodes[i] = node; - resultDataSources.insert({ds, node}); - } + std::vector<DataSourceNodePtr> nodes; + nodes.resize(dataSources.size()); - // now iteratively create children until there are none left - while(!childToParentMap.empty()) - { - for(auto it = childToParentMap.begin(); it != childToParentMap.end();) + // create root nodes first + for(uint32_t i=0; i<dataSources.size(); ++i) { - const auto childId = it->first; - const auto parentId = it->second; - - const auto& parent = nodes[parentId]; - if(!parent) - { - ++it; + if(childToParentMap.find(i) != childToParentMap.end()) continue; - } - const auto& ds = dataSources[childId]; + const auto& ds = dataSources[i]; const auto node = std::make_shared<DataSourceNode>(ds); - node->setParent(parent); - nodes[childId] = node; + nodes[i] = node; resultDataSources.insert({ds, node}); + } + + // now iteratively create children until there are none left + while(!childToParentMap.empty()) + { + for(auto it = childToParentMap.begin(); it != childToParentMap.end();) + { + const auto childId = it->first; + const auto parentId = it->second; - it = childToParentMap.erase(it); + const auto& parent = nodes[parentId]; + if(!parent) + { + ++it; + continue; + } + + const auto& ds = dataSources[childId]; + const auto node = std::make_shared<DataSourceNode>(ds); + node->setParent(parent); + nodes[childId] = node; + resultDataSources.insert({ds, node}); + + it = childToParentMap.erase(it); + } } - } - // now as we have the datasources created as nodes, patches need to know the datasource nodes they are part of - for (const auto& it : resultDataSources) - { - for(auto& patch : it.second->patches) - patch->source = it.second->weak_from_this(); + // now as we have the datasources created as nodes, patches need to know the datasource nodes they are part of + for (const auto& it : resultDataSources) + { + for(auto& patch : it.second->patches) + patch->source = it.second->weak_from_this(); + } } - } - else - return false; - - if(auto s = stream.tryReadChunk(chunks::g_patchManagerTags, 1)) - { - const auto tagTypeCount = s.read<uint32_t>(); + else + return false; - for(uint32_t i=0; i<tagTypeCount; ++i) + if(auto s = stream.tryReadChunk(chunks::g_patchManagerTags, 1)) { - const auto tagType = static_cast<TagType>(s.read<uint8_t>()); - const auto tagCount = s.read<uint32_t>(); + const auto tagTypeCount = s.read<uint32_t>(); - std::set<Tag> tags; - for(uint32_t t=0; t<tagCount; ++t) - tags.insert(s.readString()); + for(uint32_t i=0; i<tagTypeCount; ++i) + { + const auto tagType = static_cast<TagType>(s.read<uint8_t>()); + const auto tagCount = s.read<uint32_t>(); - resultTags.insert({tagType, tags}); - } - } - else - return false; + std::set<Tag> tags; + for(uint32_t t=0; t<tagCount; ++t) + tags.insert(s.readString()); - if(auto s = stream.tryReadChunk(chunks::g_patchManagerTagColors, 1)) - { - const auto tagTypeCount = s.read<uint32_t>(); + resultTags.insert({tagType, tags}); + } + } + else + return false; - for(uint32_t i=0; i<tagTypeCount; ++i) + if(auto s = stream.tryReadChunk(chunks::g_patchManagerTagColors, 1)) { - const auto tagType = static_cast<TagType>(s.read<uint8_t>()); - std::unordered_map<Tag, Color> tagToColor; + const auto tagTypeCount = s.read<uint32_t>(); - const auto count = s.read<uint32_t>(); - for(uint32_t c=0; c<count; ++c) + for(uint32_t i=0; i<tagTypeCount; ++i) { - const auto tag = s.readString(); - const auto color = s.read<Color>(); - tagToColor.insert({tag, color}); + const auto tagType = static_cast<TagType>(s.read<uint8_t>()); + std::unordered_map<Tag, Color> tagToColor; + + const auto count = s.read<uint32_t>(); + for(uint32_t c=0; c<count; ++c) + { + const auto tag = s.readString(); + const auto color = s.read<Color>(); + tagToColor.insert({tag, color}); + } + resultTagColors.insert({tagType, tagToColor}); } - resultTagColors.insert({tagType, tagToColor}); } - } - else - return false; - - if(auto s = stream.tryReadChunk(chunks::g_patchManagerPatchModifications, 1)) - { - const auto count = s.read<uint32_t>(); + else + return false; - for(uint32_t i=0; i<count; ++i) + if(auto s = stream.tryReadChunk(chunks::g_patchManagerPatchModifications, 1)) { - auto key = PatchKey::fromString(s.readString()); + const auto count = s.read<uint32_t>(); - const auto itDS = resultDataSources.find(*key.source); - if(itDS != resultDataSources.end()) - key.source = itDS->second; + for(uint32_t i=0; i<count; ++i) + { + auto key = PatchKey::fromString(s.readString()); - auto mods = std::make_shared<PatchModifications>(); - if(!mods->read(s)) - return false; + const auto itDS = resultDataSources.find(*key.source); + if(itDS != resultDataSources.end()) + key.source = itDS->second; - resultPatchModifications.insert({key, mods}); + auto mods = std::make_shared<PatchModifications>(); + if(!mods->read(s)) + return false; - for (const auto& it : resultDataSources) - { - for (const auto& patch : it.second->patches) + resultPatchModifications.insert({key, mods}); + + for (const auto& it : resultDataSources) { - if(*patch != key) - continue; + for (const auto& patch : it.second->patches) + { + if(*patch != key) + continue; - patch->modifications = mods; - mods->patch = patch; + patch->modifications = mods; + mods->patch = patch; + } } } } - } - else - return false; + else + return false; - m_dataSources = resultDataSources; - m_tags = resultTags; - m_tagColors = resultTagColors; - m_patchModifications = resultPatchModifications; + m_dataSources = resultDataSources; + m_tags = resultTags; + m_tagColors = resultTagColors; + m_patchModifications = resultPatchModifications; - for (const auto& it: resultDataSources) - { - const auto& patches = it.second->patches; - updateSearches({patches.begin(), patches.end()}); - } + for (const auto& it: resultDataSources) + { + const auto& patches = it.second->patches; + updateSearches({patches.begin(), patches.end()}); + } - { - std::unique_lock lockUi(m_uiMutex); + { + std::unique_lock lockUi(m_uiMutex); - m_dirty.dataSources = true; - m_dirty.patches = true; + m_dirty.dataSources = true; + m_dirty.patches = true; - for (const auto& it : m_tags) - m_dirty.tags.insert(it.first); - } + for (const auto& it : m_tags) + m_dirty.tags.insert(it.first); + } - m_cacheDirty = false; + m_cacheDirty = false; - return true; + return true; + } + catch(const std::range_error& e) + { + LOG("Failed to read patch manager cache, " << e.what()); + return false; + } } void DB::saveCache()