Snapshot bugs.

This commit is contained in:
Robin Davies
2024-10-10 20:51:18 -04:00
parent c9e38723e7
commit 29193bc269
9 changed files with 121 additions and 51 deletions
+1
View File
@@ -206,6 +206,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
export class SnapshotValue { export class SnapshotValue {
deserialize(input: any): SnapshotValue { deserialize(input: any): SnapshotValue {
this.isEnabled = input.isEnabled;
this.instanceId = input.instanceId; this.instanceId = input.instanceId;
this.controlValues = ControlValue.deserializeArray(input.controlValues); this.controlValues = ControlValue.deserializeArray(input.controlValues);
this.lv2State = input.lv2state; this.lv2State = input.lv2state;
+5 -1
View File
@@ -135,7 +135,7 @@ namespace pipedal
{ {
auto maxInputControl = effect->GetMaxInputControl(); auto maxInputControl = effect->GetMaxInputControl();
inputControlValues.resize(maxInputControl); inputControlValues.resize(maxInputControl);
this->enabled = true;
for (uint64_t i = 0; i < maxInputControl; ++i) for (uint64_t i = 0; i < maxInputControl; ++i)
{ {
bool isInputControl = effect->IsInputControl(i); bool isInputControl = effect->IsInputControl(i);
@@ -150,6 +150,7 @@ namespace pipedal
} }
if (snapshotValue) if (snapshotValue)
{ {
this->enabled = snapshotValue->isEnabled_;
for (auto &controlValue : snapshotValue->controlValues_) for (auto &controlValue : snapshotValue->controlValues_)
{ {
auto index = effect->GetControlIndex(controlValue.key()); auto index = effect->GetControlIndex(controlValue.key());
@@ -202,6 +203,8 @@ namespace pipedal
} }
void ApplyValues(IEffect *effect) void ApplyValues(IEffect *effect)
{ {
effect->SetBypass(this->enabled);
if (effect != pEffect) if (effect != pEffect)
{ {
throw std::runtime_error("Wrong effect"); throw std::runtime_error("Wrong effect");
@@ -226,6 +229,7 @@ namespace pipedal
private: private:
IEffect *pEffect; IEffect *pEffect;
Lv2PluginState lv2State; Lv2PluginState lv2State;
bool enabled;
std::vector<InputControlEntry> inputControlValues; std::vector<InputControlEntry> inputControlValues;
std::vector<PathPatchProperty> pathPatchProperties; std::vector<PathPatchProperty> pathPatchProperties;
}; };
+4 -1
View File
@@ -293,7 +293,10 @@ namespace pipedal
virtual float GetOutputControlValue(int portIndex) const 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) virtual void SetBypass(bool bypass)
+87 -32
View File
@@ -20,6 +20,9 @@
#include "pch.h" #include "pch.h"
#include "Pedalboard.hpp" #include "Pedalboard.hpp"
#include "AtomConverter.hpp" #include "AtomConverter.hpp"
#include "PluginHost.hpp"
#include "AtomConverter.hpp"
#include "SplitEffect.hpp"
using namespace pipedal; using namespace pipedal;
@@ -87,6 +90,19 @@ ControlValue* PedalboardItem::GetControlValue(const std::string&symbol)
return nullptr; 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 const ControlValue* PedalboardItem::GetControlValue(const std::string&symbol) const
{ {
for (size_t i = 0; i < this->controlValues().size(); ++i) 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); PedalboardItem*item = GetItem(pedalItemId);
if (!item) return false; if (!item) return false;
ControlValue*controlValue = item->GetControlValue(symbol); return item->SetControlValue(symbol,value);
if (controlValue == nullptr) return false;
if (controlValue->value() != value)
{
controlValue->value(value);
return true;
}
return false;
} }
@@ -190,12 +199,12 @@ bool IsPedalboardSplitItem(const PedalboardItem*self, const std::vector<Pedalboa
return self->uri() == SPLIT_PEDALBOARD_ITEM_URI; return self->uri() == SPLIT_PEDALBOARD_ITEM_URI;
} }
bool Pedalboard::ApplySnapshot(int64_t snapshotIndex) bool Pedalboard::ApplySnapshot(int64_t snapshotIndex, PluginHost&pluginHost)
{ {
if (snapshotIndex < 0 || if (snapshotIndex < 0 ||
snapshotIndex >= this->snapshots_.size() || snapshotIndex >= this->snapshots_.size() ||
this->snapshots_[snapshotIndex] == nullptr || this->snapshots_[snapshotIndex] == nullptr
this->selectedSnapshot() == snapshotIndex) )
{ {
return false; return false;
} }
@@ -210,15 +219,47 @@ bool Pedalboard::ApplySnapshot(int64_t snapshotIndex)
auto plugins = this->GetAllPlugins(); auto plugins = this->GetAllPlugins();
for (PedalboardItem *pedalboardItem: plugins) for (PedalboardItem *pedalboardItem: plugins)
{ {
SnapshotValue*snapshotValue = indexedValues[pedalboardItem->instanceId()]; if (!pedalboardItem->isEmpty())
if (snapshotValue)
{ {
pedalboardItem->ApplySnapshotValue(snapshotValue); SnapshotValue*snapshotValue = indexedValues[pedalboardItem->instanceId()];
if (snapshotValue)
{
pedalboardItem->ApplySnapshotValue(snapshotValue);
} else {
pedalboardItem->ApplyDefaultValues(pluginHost);
}
} }
} }
return true; 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) void PedalboardItem::ApplySnapshotValue(SnapshotValue*snapshotValue)
{ {
std::map<std::string,float> cumulativeValues; std::map<std::string,float> cumulativeValues;
@@ -240,6 +281,16 @@ void PedalboardItem::ApplySnapshotValue(SnapshotValue*snapshotValue)
this->lv2State(snapshotValue->lv2State_); this->lv2State(snapshotValue->lv2State_);
this->stateUpdateCount(this->stateUpdateCount()+1); 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_); 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. if (this->isSplit()) // so is the other by virtue of idential uris.
{ {
auto myValue = this->GetControlValue("splitType"); // provisionally, it seems ok to change the split type.
auto otherValue = other.GetControlValue("splitType"); // auto myValue = this->GetControlValue("splitType");
if (myValue == nullptr || otherValue == nullptr) // actually an error. // auto otherValue = other.GetControlValue("splitType");
{ // if (myValue == nullptr || otherValue == nullptr) // actually an error.
return false; // {
} // return false;
// split type changes potentially trigger buffer allocation changes, // }
// so different split types are not structurally identical.
if (myValue->value() != otherValue->value()) { // // split type changes potentially trigger buffer allocation changes,
return false; // // so different split types are not structurally identical.
} // if (myValue->value() != otherValue->value()) {
// return false;
// }
if (topChain().size() != other.topChain().size()) if (topChain().size() != other.topChain().size())
{ {
return false; return false;
@@ -407,17 +460,19 @@ Snapshot Pedalboard::MakeSnapshotFromCurrentSettings(const Pedalboard &previousP
{ {
Snapshot snapshot; Snapshot snapshot;
// name and color don't matter. this is strictly for loading purposes. // 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, // a neccesary precondition: the previous pedalboard must have identical structure,
// so we can just // so we can just
size_t index = 0; // auto items = this->GetAllPlugins();
for (auto&item: previousPedalboard.items_)
{ // for (auto&item: previousPedalboard.items_)
item.AddResetsForMissingProperties(snapshot,&index); // {
} // item.AddResetsForMissingProperties(snapshot,&index);
// }
return snapshot; return snapshot;
} }
+5 -1
View File
@@ -28,6 +28,7 @@
namespace pipedal { namespace pipedal {
class SnapshotValue; class SnapshotValue;
class Snapshot; class Snapshot;
class PluginHost;
#define SPLIT_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Split" #define SPLIT_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Split"
#define EMPTY_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Empty" #define EMPTY_PEDALBOARD_ITEM_URI "uri://two-play/pipedal/pedalboard#Empty"
@@ -102,10 +103,13 @@ public:
public: public:
ControlValue*GetControlValue(const std::string&symbol); ControlValue*GetControlValue(const std::string&symbol);
const ControlValue*GetControlValue(const std::string&symbol) const; const ControlValue*GetControlValue(const std::string&symbol) const;
bool SetControlValue(const std::string&key, float value);
bool IsStructurallyIdentical(const PedalboardItem&other) const; bool IsStructurallyIdentical(const PedalboardItem&other) const;
void ApplySnapshotValue(SnapshotValue*snapshotValue); void ApplySnapshotValue(SnapshotValue*snapshotValue);
void ApplyDefaultValues(PluginHost&pluginHost);
bool hasLv2State() const { bool hasLv2State() const {
return lv2State_.isValid_ != 0; return lv2State_.isValid_ != 0;
} }
@@ -203,7 +207,7 @@ public:
std::vector<PedalboardItem*>GetAllPlugins(); std::vector<PedalboardItem*>GetAllPlugins();
bool HasItem(int64_t pedalItemid) const { return GetItem(pedalItemid) != nullptr; } 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_REF(name)
GETTER_SETTER_VEC(items) GETTER_SETTER_VEC(items)
+16 -15
View File
@@ -535,23 +535,17 @@ void PiPedalModel::SetPedalboard(int64_t clientId, Pedalboard &pedalboard)
void PiPedalModel::SetSnapshot(int64_t selectedSnapshot) void PiPedalModel::SetSnapshot(int64_t selectedSnapshot)
{ {
std::lock_guard<std::recursive_mutex> lock(mutex); std::lock_guard<std::recursive_mutex> 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); 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<std::shared_ptr<Snapshot>> &snapshot
if (selectedSnapshot != -1) if (selectedSnapshot != -1)
{ {
this->pedalboard.selectedSnapshot(selectedSnapshot); 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) this->FirePedalboardChanged(-1, false); // notify clients (but don't change the running pedalboard, because it's still the same)
+1
View File
@@ -182,6 +182,7 @@ SplitEffect::SplitEffect(
Lv2PluginInfo::ptr puginInfo = g_splitterPluginInfo; Lv2PluginInfo::ptr puginInfo = g_splitterPluginInfo;
defaultInputControlValues.resize(MAX_INPUT_CONTROL);
for (auto&port: puginInfo->ports()) for (auto&port: puginInfo->ports())
{ {
if (port->is_control_port() && port->is_input()) if (port->is_control_port() && port->is_input())
-1
View File
@@ -358,7 +358,6 @@ namespace pipedal
virtual void SetBypass(bool enabled) virtual void SetBypass(bool enabled)
{ {
throw PiPedalArgumentException("Not implmented. Should not have been called.");
} }
virtual float GetOutputControlValue(int index) const { virtual float GetOutputControlValue(int index) const {
+2
View File
@@ -1,3 +1,5 @@
Loading shields need to be of Modal type.
MOD fileTypes MOD fileTypes
- audioloop: Audio Loops, meant to be used for looper-style plugins - audioloop: Audio Loops, meant to be used for looper-style plugins