From 217fdf9cbaf62ab03fd7a09044719320e0d149ec Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Mon, 21 Oct 2024 08:39:45 -0400 Subject: [PATCH] Uploading banks and presets fails. --- src/PiPedalModel.cpp | 2 +- src/PluginPreset.cpp | 71 +++++++++++++++++++++++++++++++++++++++++ src/PluginPreset.hpp | 5 +++ src/PresetBundle.cpp | 10 +++--- src/Storage.cpp | 61 +++++++++++++++++++++++++++++++++++ src/Storage.hpp | 1 + src/WebServerConfig.cpp | 3 +- 7 files changed, 146 insertions(+), 7 deletions(-) diff --git a/src/PiPedalModel.cpp b/src/PiPedalModel.cpp index 8f7f1a3..6cbe83f 100644 --- a/src/PiPedalModel.cpp +++ b/src/PiPedalModel.cpp @@ -844,7 +844,7 @@ void PiPedalModel::UploadPluginPresets(const PluginPresets &pluginPresets) throw PiPedalException("Invalid plugin presets."); } std::lock_guard guard{mutex}; - storage.SavePluginPresets(pluginPresets.pluginUri_, pluginPresets); + storage.MergePluginPresets(pluginPresets.pluginUri_, pluginPresets); FirePluginPresetsChanged(pluginPresets.pluginUri_); } int64_t PiPedalModel::UploadPreset(const BankFile &bankFile, int64_t uploadAfter) diff --git a/src/PluginPreset.cpp b/src/PluginPreset.cpp index e41166b..2d34e47 100644 --- a/src/PluginPreset.cpp +++ b/src/PluginPreset.cpp @@ -2,6 +2,77 @@ using namespace pipedal; + +static std::string GetUnversionedLabel(const std::string label) +{ + size_t pos = label.length(); + if (pos != 0 && label.at(pos-1) == ')') + { + --pos; + while (true) + { + if (pos == 0) + { + return label; // not versioned. return the original. + } + --pos; + char c = label[pos]; + if (c >= '0' && c <= '9') + { + continue; // eat the number. + } + else if (c == '(') + { + return label.substr(0,pos); + + } else { + return label; // failure. return the unmodified original + } + } + } + return label; +} + +bool PluginPreset::equals(const PluginPreset&other) const +{ + // everything EXCEPT instanceId (since preset may be from another PluginPresets collection) + return label_ == other.label_ && + lilvPresetUri_ == other.lilvPresetUri_ && + controlValues_ == other.controlValues_ && + state_ == other.state_; +} + +void PluginPresets::MergePreset(const PluginPreset&preset) +{ + int existingPresetIndex = Find(preset.label_); + if (existingPresetIndex != -1) + { + if (this->presets_[existingPresetIndex].equals(preset)) + { + // an exact duplicate. discard the new preset. + return; + } + std::string baseLabel = GetUnversionedLabel(preset.label_); + + for (int i = 1; i < 1000; ++i) + { + std::string newLabel = SS(baseLabel << "(" << i << ")"); + if (Find(newLabel) == -1) + { + PluginPreset versionedPreset = preset; + versionedPreset.label_ = newLabel; + MergePreset(versionedPreset); + return; + } + } + // A thousand duplicates?! Heck. just add a duplicate label. :-/ + } + this->presets_.push_back(preset); + this->presets_.back().instanceId_ = this->nextInstanceId_++; + +} + + JSON_MAP_BEGIN(PluginUiPreset) JSON_MAP_REFERENCE(PluginUiPreset,label) JSON_MAP_REFERENCE(PluginUiPreset,instanceId) diff --git a/src/PluginPreset.hpp b/src/PluginPreset.hpp index e27dec1..d53906e 100644 --- a/src/PluginPreset.hpp +++ b/src/PluginPreset.hpp @@ -111,6 +111,8 @@ public: return preset; } + bool equals(const PluginPreset&other) const; + uint64_t instanceId_; std::string label_; std::string lilvPresetUri_; @@ -158,6 +160,9 @@ public: return -1; } + void MergePreset(const PluginPreset&preset); + + DECLARE_JSON_MAP(PluginPresets); }; diff --git a/src/PresetBundle.cpp b/src/PresetBundle.cpp index f7e6904..27ae4da 100644 --- a/src/PresetBundle.cpp +++ b/src/PresetBundle.cpp @@ -214,17 +214,17 @@ public: { this->pluginUploadDirectory = model.GetPluginUploadDirectory(); zipFile = ZipFileReader::Create(path); - auto s = zipFile->GetFileInputStream("pluginPresets.json"); + auto s = zipFile->GetFileInputStream("bankFile.json"); json_reader reader(s); - reader.read(&pluginPresets); + reader.read(&bankFile); } void LoadPluginPresetFile(PiPedalModel &model, const std::filesystem::path &path) { this->pluginUploadDirectory = model.GetPluginUploadDirectory(); zipFile = ZipFileReader::Create(path); - auto s = zipFile->GetFileInputStream("bankFile.json"); + auto s = zipFile->GetFileInputStream("pluginPresets.json"); json_reader reader(s); - reader.read(&bankFile); + reader.read(&pluginPresets); } virtual ~PresetBundleReaderImpl() noexcept; @@ -296,7 +296,7 @@ PresetBundleReader::ptr PresetBundleReader::LoadPresetsFile(PiPedalModel &model, PresetBundleReader::ptr PresetBundleReader::LoadPluginPresetsFile(PiPedalModel &model, const std::filesystem::path &filePath) { std::unique_ptr result = std::make_unique(); - result->LoadPluginPresetsFile(model, filePath); + result->LoadPluginPresetFile(model, filePath); return result; } diff --git a/src/Storage.cpp b/src/Storage.cpp index 92f49cc..fbea14f 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -1107,6 +1107,67 @@ std::filesystem::path Storage::GetPluginPresetPath(const std::string &pluginUri) } throw PiPedalArgumentException("Plugin preset file not found."); } + +void Storage::MergePluginPresets(const std::string &pluginUri, const PluginPresets &presets) +{ + std::string name; + std::filesystem::path path; + bool presetAdded = false; + PluginPresets existingPresets; + if (!HasPluginPresets(pluginUri)) + { + name = SS(pluginPresetIndex.nextInstanceId_ << ".json"); + path = GetPluginPresetsDirectory() / name; + presetAdded = true; + } + else + { + path = GetPluginPresetPath(pluginUri); + try { + std::ifstream f(path); + if (f.is_open()) + { + json_reader reader(f); + reader.read(&existingPresets); + } + } catch (const std::exception &e) + { + Lv2Log::error(SS("Storage::MergePluginPresets: Can't reading existing plugin presets." << e.what())); + } + } + for (const PluginPreset &preset: presets.presets_) + { + + existingPresets.MergePreset(preset); + } + auto tempPath = path.string() + ".$$$"; + { + pipedal::ofstream_synced os; + os.open(tempPath, std::ios_base::trunc); + if (os.fail()) + { + throw PiPedalException(SS("Can't write to " << path)); + } + json_writer writer(os, true); + writer.write(existingPresets); + } + if (std::filesystem::exists(path)) + { + std::filesystem::remove(path); + } + std::filesystem::rename(tempPath, path); + + if (presetAdded) + { + pluginPresetIndex.entries_.push_back( + PluginPresetIndexEntry( + pluginUri, name)); + pluginPresetIndex.nextInstanceId_++; + this->pluginPresetIndexChanged = true; + SavePluginPresetIndex(); + } +} + void Storage::SavePluginPresets(const std::string &pluginUri, const PluginPresets &presets) { std::string name; diff --git a/src/Storage.hpp b/src/Storage.hpp index b129852..e00da98 100644 --- a/src/Storage.hpp +++ b/src/Storage.hpp @@ -187,6 +187,7 @@ private: public: bool HasPluginPresets(const std::string&pluginUri) const; void SavePluginPresets(const std::string&pluginUri, const PluginPresets&presets); + void MergePluginPresets(const std::string&pluginUri, const PluginPresets&presets); PluginPresets GetPluginPresets(const std::string&pluginUri) const; const PluginPresetIndex& GetPluginPresetIndex(); diff --git a/src/WebServerConfig.cpp b/src/WebServerConfig.cpp index e453a5e..e516139 100644 --- a/src/WebServerConfig.cpp +++ b/src/WebServerConfig.cpp @@ -37,7 +37,7 @@ #define OLD_PRESET_EXTENSION ".piPreset" #define PRESET_EXTENSION ".piPreset" #define OLD_BANK_EXTENSION ".piBank" -#define BANK_EXTENSION ".piBankBundle" +#define BANK_EXTENSION ".piBank" #define PLUGIN_PRESETS_EXTENSION ".piPluginPresets" static const std::filesystem::path WEB_TEMP_DIR{"/var/pipedal/web_temp"}; @@ -598,6 +598,7 @@ public: } catch (const std::exception &e) { + Lv2Log::error(SS("Error uploading file: " << e.what()) ); if (strcmp(e.what(), "Not found") == 0) { ec = boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory);