From 29193bc26924d716156cb373c9582838bd80a00a Mon Sep 17 00:00:00 2001 From: Robin Davies Date: Thu, 10 Oct 2024 20:51:18 -0400 Subject: [PATCH] Snapshot bugs. --- react/src/Pedalboard.tsx | 1 + src/AudioHost.cpp | 6 +- src/Lv2Effect.hpp | 5 +- src/Pedalboard.cpp | 119 ++++++++++++++++++++++++++++----------- src/Pedalboard.hpp | 6 +- src/PiPedalModel.cpp | 31 +++++----- src/SplitEffect.cpp | 1 + src/SplitEffect.hpp | 1 - todo.txt | 2 + 9 files changed, 121 insertions(+), 51 deletions(-) diff --git a/react/src/Pedalboard.tsx b/react/src/Pedalboard.tsx index 414d060..f1d6faf 100644 --- a/react/src/Pedalboard.tsx +++ b/react/src/Pedalboard.tsx @@ -206,6 +206,7 @@ export class PedalboardItem implements Deserializable { export class SnapshotValue { deserialize(input: any): SnapshotValue { + this.isEnabled = input.isEnabled; this.instanceId = input.instanceId; this.controlValues = ControlValue.deserializeArray(input.controlValues); this.lv2State = input.lv2state; diff --git a/src/AudioHost.cpp b/src/AudioHost.cpp index 0e559b4..f909380 100644 --- a/src/AudioHost.cpp +++ b/src/AudioHost.cpp @@ -135,7 +135,7 @@ namespace pipedal { auto maxInputControl = effect->GetMaxInputControl(); inputControlValues.resize(maxInputControl); - + this->enabled = true; for (uint64_t i = 0; i < maxInputControl; ++i) { bool isInputControl = effect->IsInputControl(i); @@ -150,6 +150,7 @@ namespace pipedal } if (snapshotValue) { + this->enabled = snapshotValue->isEnabled_; for (auto &controlValue : snapshotValue->controlValues_) { auto index = effect->GetControlIndex(controlValue.key()); @@ -202,6 +203,8 @@ namespace pipedal } void ApplyValues(IEffect *effect) { + + effect->SetBypass(this->enabled); if (effect != pEffect) { throw std::runtime_error("Wrong effect"); @@ -226,6 +229,7 @@ namespace pipedal private: IEffect *pEffect; Lv2PluginState lv2State; + bool enabled; std::vector inputControlValues; std::vector pathPatchProperties; }; diff --git a/src/Lv2Effect.hpp b/src/Lv2Effect.hpp index 2fed630..a85e5ae 100644 --- a/src/Lv2Effect.hpp +++ b/src/Lv2Effect.hpp @@ -293,7 +293,10 @@ namespace pipedal virtual float GetOutputControlValue(int portIndex) const { - return controlValues[portIndex]; + if (portIndex >= 0 && portIndex < controlValues.size()) { + return controlValues[portIndex]; + } + return 0; } virtual void SetBypass(bool bypass) diff --git a/src/Pedalboard.cpp b/src/Pedalboard.cpp index 5349a96..77a334a 100644 --- a/src/Pedalboard.cpp +++ b/src/Pedalboard.cpp @@ -20,6 +20,9 @@ #include "pch.h" #include "Pedalboard.hpp" #include "AtomConverter.hpp" +#include "PluginHost.hpp" +#include "AtomConverter.hpp" +#include "SplitEffect.hpp" using namespace pipedal; @@ -87,6 +90,19 @@ ControlValue* PedalboardItem::GetControlValue(const std::string&symbol) return nullptr; } + +bool PedalboardItem::SetControlValue(const std::string&symbol, float value) +{ + ControlValue*controlValue = GetControlValue(symbol); + if (controlValue == nullptr) return false; + if (controlValue->value() != value) + { + controlValue->value(value); + return true; + } + return false; +} + const ControlValue* PedalboardItem::GetControlValue(const std::string&symbol) const { for (size_t i = 0; i < this->controlValues().size(); ++i) @@ -117,14 +133,7 @@ bool Pedalboard::SetControlValue(int64_t pedalItemId, const std::string &symbol, { PedalboardItem*item = GetItem(pedalItemId); if (!item) return false; - ControlValue*controlValue = item->GetControlValue(symbol); - if (controlValue == nullptr) return false; - if (controlValue->value() != value) - { - controlValue->value(value); - return true; - } - return false; + return item->SetControlValue(symbol,value); } @@ -190,12 +199,12 @@ bool IsPedalboardSplitItem(const PedalboardItem*self, const std::vectoruri() == SPLIT_PEDALBOARD_ITEM_URI; } -bool Pedalboard::ApplySnapshot(int64_t snapshotIndex) +bool Pedalboard::ApplySnapshot(int64_t snapshotIndex, PluginHost&pluginHost) { if (snapshotIndex < 0 || snapshotIndex >= this->snapshots_.size() || - this->snapshots_[snapshotIndex] == nullptr || - this->selectedSnapshot() == snapshotIndex) + this->snapshots_[snapshotIndex] == nullptr + ) { return false; } @@ -210,15 +219,47 @@ bool Pedalboard::ApplySnapshot(int64_t snapshotIndex) auto plugins = this->GetAllPlugins(); for (PedalboardItem *pedalboardItem: plugins) { - SnapshotValue*snapshotValue = indexedValues[pedalboardItem->instanceId()]; - if (snapshotValue) + if (!pedalboardItem->isEmpty()) { - pedalboardItem->ApplySnapshotValue(snapshotValue); + SnapshotValue*snapshotValue = indexedValues[pedalboardItem->instanceId()]; + if (snapshotValue) + { + pedalboardItem->ApplySnapshotValue(snapshotValue); + } else { + pedalboardItem->ApplyDefaultValues(pluginHost); + } } } return true; } +void PedalboardItem::ApplyDefaultValues(PluginHost&pluginHost) +{ + if (isEmpty()) return; + auto pluginInfo = pluginHost.GetPluginInfo(this->uri()); + if (!pluginInfo) + { + if (this->isSplit()) + { + pluginInfo = GetSplitterPluginInfo(); + } + } + this->isEnabled(true); + if (pluginInfo) + { + for (auto &port: pluginInfo->ports()) + { + this->SetControlValue(port->symbol(),port->default_value()); + } + // a cheat. this isn't actually true, but close enough. + for (auto &pathProperty: this->pathProperties_) + { + pathProperties_[pathProperty.first] = AtomConverter::EmptyPathstring(); + } + } +} + + void PedalboardItem::ApplySnapshotValue(SnapshotValue*snapshotValue) { std::map cumulativeValues; @@ -240,6 +281,16 @@ void PedalboardItem::ApplySnapshotValue(SnapshotValue*snapshotValue) this->lv2State(snapshotValue->lv2State_); this->stateUpdateCount(this->stateUpdateCount()+1); } + for (auto&property: snapshotValue->pathProperties_) + { + if (property.second == "null") + { + this->pathProperties_[property.first] = AtomConverter::EmptyPathstring(); + + } else { + this->pathProperties_[property.first] = property.second; + } + } this->isEnabled(snapshotValue->isEnabled_); } @@ -278,17 +329,19 @@ bool PedalboardItem::IsStructurallyIdentical(const PedalboardItem&other) const } if (this->isSplit()) // so is the other by virtue of idential uris. { - auto myValue = this->GetControlValue("splitType"); - auto otherValue = other.GetControlValue("splitType"); - if (myValue == nullptr || otherValue == nullptr) // actually an error. - { - return false; - } - // split type changes potentially trigger buffer allocation changes, - // so different split types are not structurally identical. - if (myValue->value() != otherValue->value()) { - return false; - } + // provisionally, it seems ok to change the split type. + // auto myValue = this->GetControlValue("splitType"); + // auto otherValue = other.GetControlValue("splitType"); + // if (myValue == nullptr || otherValue == nullptr) // actually an error. + // { + // return false; + // } + + // // split type changes potentially trigger buffer allocation changes, + // // so different split types are not structurally identical. + // if (myValue->value() != otherValue->value()) { + // return false; + // } if (topChain().size() != other.topChain().size()) { return false; @@ -407,17 +460,19 @@ Snapshot Pedalboard::MakeSnapshotFromCurrentSettings(const Pedalboard &previousP { Snapshot snapshot; // name and color don't matter. this is strictly for loading purposes. - for (auto &item : this->items()) + auto items = this->GetAllPlugins(); + for (auto item : items) { - item.AddToSnapshotFromCurrentSettings(snapshot); + item->AddToSnapshotFromCurrentSettings(snapshot); } // a neccesary precondition: the previous pedalboard must have identical structure, // so we can just - size_t index = 0; - for (auto&item: previousPedalboard.items_) - { - item.AddResetsForMissingProperties(snapshot,&index); - } + // auto items = this->GetAllPlugins(); + + // for (auto&item: previousPedalboard.items_) + // { + // item.AddResetsForMissingProperties(snapshot,&index); + // } return snapshot; } diff --git a/src/Pedalboard.hpp b/src/Pedalboard.hpp index 7e67f67..9ae3565 100644 --- a/src/Pedalboard.hpp +++ b/src/Pedalboard.hpp @@ -28,6 +28,7 @@ namespace pipedal { class SnapshotValue; class Snapshot; + class PluginHost; #define SPLIT_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Split" #define EMPTY_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Empty" @@ -102,10 +103,13 @@ public: public: ControlValue*GetControlValue(const std::string&symbol); const ControlValue*GetControlValue(const std::string&symbol) const; + bool SetControlValue(const std::string&key, float value); + bool IsStructurallyIdentical(const PedalboardItem&other) const; void ApplySnapshotValue(SnapshotValue*snapshotValue); + void ApplyDefaultValues(PluginHost&pluginHost); bool hasLv2State() const { return lv2State_.isValid_ != 0; } @@ -203,7 +207,7 @@ public: std::vectorGetAllPlugins(); bool HasItem(int64_t pedalItemid) const { return GetItem(pedalItemid) != nullptr; } - bool ApplySnapshot(int64_t snapshotIndex); + bool ApplySnapshot(int64_t snapshotIndex, PluginHost &pluginHost); GETTER_SETTER_REF(name) GETTER_SETTER_VEC(items) diff --git a/src/PiPedalModel.cpp b/src/PiPedalModel.cpp index e1d46e3..8860bfe 100644 --- a/src/PiPedalModel.cpp +++ b/src/PiPedalModel.cpp @@ -535,23 +535,17 @@ void PiPedalModel::SetPedalboard(int64_t clientId, Pedalboard &pedalboard) void PiPedalModel::SetSnapshot(int64_t selectedSnapshot) { std::lock_guard lock(mutex); - if (this->pedalboard.ApplySnapshot(selectedSnapshot)) + if (this->pedalboard.ApplySnapshot(selectedSnapshot, pluginHost)) { - this->pedalboard.SetCurrentSnapshotModified(false); - this->FireSnapshotModified(selectedSnapshot,false); - if (this->audioHost) - { - if (this->previousPedalboardLoaded && this->pedalboard.IsStructureIdentical(this->previousPedalboard)) - { - this->audioHost->LoadSnapshot(*(this->pedalboard.snapshots()[selectedSnapshot]), this->pluginHost); // no longer own it. - } else { - LoadCurrentPedalboard(); - } - - } - SetPresetChanged(-1, true, false); this->pedalboard.selectedSnapshot(selectedSnapshot); - FirePedalboardChanged(-1, false); + for (auto snapshot: this->pedalboard.snapshots()) + { + if (snapshot) + { + snapshot->isModified_ = false; + } + } + FirePedalboardChanged(-1, true); } } @@ -567,6 +561,13 @@ void PiPedalModel::SetSnapshots(std::vector> &snapshot if (selectedSnapshot != -1) { this->pedalboard.selectedSnapshot(selectedSnapshot); + for (auto &snapshot: pedalboard.snapshots()) + { + if (snapshot) + { + snapshot->isModified_ = false; + } + } } this->FirePedalboardChanged(-1, false); // notify clients (but don't change the running pedalboard, because it's still the same) diff --git a/src/SplitEffect.cpp b/src/SplitEffect.cpp index cf06c7e..2f2dcc7 100644 --- a/src/SplitEffect.cpp +++ b/src/SplitEffect.cpp @@ -182,6 +182,7 @@ SplitEffect::SplitEffect( Lv2PluginInfo::ptr puginInfo = g_splitterPluginInfo; + defaultInputControlValues.resize(MAX_INPUT_CONTROL); for (auto&port: puginInfo->ports()) { if (port->is_control_port() && port->is_input()) diff --git a/src/SplitEffect.hpp b/src/SplitEffect.hpp index e408a0e..b85fdc2 100644 --- a/src/SplitEffect.hpp +++ b/src/SplitEffect.hpp @@ -358,7 +358,6 @@ namespace pipedal virtual void SetBypass(bool enabled) { - throw PiPedalArgumentException("Not implmented. Should not have been called."); } virtual float GetOutputControlValue(int index) const { diff --git a/todo.txt b/todo.txt index 667d9de..ffdaf18 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,5 @@ +Loading shields need to be of Modal type. + MOD fileTypes - audioloop: Audio Loops, meant to be used for looper-style plugins