Side-chains
This commit is contained in:
@@ -54,7 +54,9 @@ namespace pipedal {
|
|||||||
|
|
||||||
virtual int GetNumberOfInputAudioBuffers() const = 0; // may be different if plugin has zero inputs.
|
virtual int GetNumberOfInputAudioBuffers() const = 0; // may be different if plugin has zero inputs.
|
||||||
virtual int GetNumberOfOutputAudioBuffers() const = 0; // may be different if plugin has zero inputs.
|
virtual int GetNumberOfOutputAudioBuffers() const = 0; // may be different if plugin has zero inputs.
|
||||||
|
virtual int GetNumberOfSidechainAudioBuffers() const { return 0; }
|
||||||
virtual float *GetAudioInputBuffer(int index) const = 0;
|
virtual float *GetAudioInputBuffer(int index) const = 0;
|
||||||
|
virtual float *GetAudioSidechainBuffer(int index) const { throw std::runtime_error("Not implemented"); }
|
||||||
virtual float *GetAudioOutputBuffer(int index) const = 0;
|
virtual float *GetAudioOutputBuffer(int index) const = 0;
|
||||||
virtual void ResetAtomBuffers() = 0;
|
virtual void ResetAtomBuffers() = 0;
|
||||||
|
|
||||||
@@ -65,6 +67,7 @@ namespace pipedal {
|
|||||||
|
|
||||||
virtual void SetAudioInputBuffer(int index, float *buffer) = 0;
|
virtual void SetAudioInputBuffer(int index, float *buffer) = 0;
|
||||||
virtual void SetAudioOutputBuffer(int index, float*buffer) = 0;
|
virtual void SetAudioOutputBuffer(int index, float*buffer) = 0;
|
||||||
|
virtual void SetAudioSidechainBuffer(int index, float *buffer) { throw std::runtime_error("Not implemented");}
|
||||||
|
|
||||||
virtual void Activate() = 0;
|
virtual void Activate() = 0;
|
||||||
|
|
||||||
|
|||||||
+78
-5
@@ -384,7 +384,12 @@ void Lv2Effect::PreparePortIndices()
|
|||||||
{
|
{
|
||||||
if (port->is_input())
|
if (port->is_input())
|
||||||
{
|
{
|
||||||
this->inputAudioPortIndices.push_back(portIndex);
|
if (port->is_sidechain())
|
||||||
|
{
|
||||||
|
this->inputSidechainPortIndices.push_back(portIndex);
|
||||||
|
} else {
|
||||||
|
this->inputAudioPortIndices.push_back(portIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -432,6 +437,7 @@ void Lv2Effect::PreparePortIndices()
|
|||||||
this->maxInputControlPort = maxInputControlPort;
|
this->maxInputControlPort = maxInputControlPort;
|
||||||
|
|
||||||
inputAudioBuffers.resize(inputAudioPortIndices.size());
|
inputAudioBuffers.resize(inputAudioPortIndices.size());
|
||||||
|
inputSidechainBuffers.resize(inputSidechainPortIndices.size());
|
||||||
outputAudioBuffers.resize(outputAudioPortIndices.size());
|
outputAudioBuffers.resize(outputAudioPortIndices.size());
|
||||||
inputAtomBuffers.resize(inputAtomPortIndices.size());
|
inputAtomBuffers.resize(inputAtomPortIndices.size());
|
||||||
outputAtomBuffers.resize(outputAtomPortIndices.size());
|
outputAtomBuffers.resize(outputAtomPortIndices.size());
|
||||||
@@ -439,9 +445,7 @@ void Lv2Effect::PreparePortIndices()
|
|||||||
if (RequiresBufferStaging())
|
if (RequiresBufferStaging())
|
||||||
{
|
{
|
||||||
EnableBufferStaging(
|
EnableBufferStaging(
|
||||||
GetStagedBufferSize(),
|
GetStagedBufferSize());
|
||||||
this->GetNumberOfInputAudioBuffers(),
|
|
||||||
this->GetNumberOfOutputAudioBuffers());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,6 +477,7 @@ void Lv2Effect::PrepareNoInputEffect(int numberOfInputs, size_t maxBufferSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
|
void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
|
||||||
{
|
{
|
||||||
this->inputAudioBuffers.at(index) = buffer;
|
this->inputAudioBuffers.at(index) = buffer;
|
||||||
@@ -512,6 +517,32 @@ void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Lv2Effect::SetAudioSidechainBuffer(int index, float *buffer)
|
||||||
|
{
|
||||||
|
this->inputSidechainBuffers.at(index) = buffer;
|
||||||
|
|
||||||
|
if (borrowedEffect)
|
||||||
|
{
|
||||||
|
// Already running on the realtime thread,
|
||||||
|
// so don't update the audio ports until the effect gets placed on the realtime thread.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stagingBufferSize != 0)
|
||||||
|
{
|
||||||
|
int pluginIndex = this->inputSidechainPortIndices.at(index);
|
||||||
|
if (index >= sidechainStagingBufferPointers.size())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid input staging buffer index.");
|
||||||
|
}
|
||||||
|
lilv_instance_connect_port(this->pInstance, pluginIndex, sidechainStagingBufferPointers.at(index));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pluginIndex = this->inputSidechainPortIndices.at(index);
|
||||||
|
lilv_instance_connect_port(this->pInstance, pluginIndex, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Lv2Effect::SetAudioInputBuffer(float *left)
|
void Lv2Effect::SetAudioInputBuffer(float *left)
|
||||||
{
|
{
|
||||||
@@ -664,6 +695,14 @@ void Lv2Effect::UpdateAudioPorts()
|
|||||||
lilv_instance_connect_port(pInstance, portIndex, outputStagingBufferPointers.at(i));
|
lilv_instance_connect_port(pInstance, portIndex, outputStagingBufferPointers.at(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < this->inputSidechainPortIndices.size(); ++i)
|
||||||
|
{
|
||||||
|
int portIndex = this->inputSidechainPortIndices.at(i);
|
||||||
|
if (sidechainStagingBufferPointers.at(i) != nullptr)
|
||||||
|
{
|
||||||
|
lilv_instance_connect_port(pInstance, portIndex, sidechainStagingBufferPointers.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
for (size_t i = 0; i < this->inputAtomPortIndices.size(); ++i)
|
for (size_t i = 0; i < this->inputAtomPortIndices.size(); ++i)
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@@ -710,6 +749,15 @@ void Lv2Effect::UpdateAudioPorts()
|
|||||||
lilv_instance_connect_port(pInstance, portIndex, GetAudioOutputBuffer(i));
|
lilv_instance_connect_port(pInstance, portIndex, GetAudioOutputBuffer(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < this->inputSidechainPortIndices.size(); ++i)
|
||||||
|
{
|
||||||
|
int portIndex = this->inputSidechainPortIndices.at(i);
|
||||||
|
if (GetAudioSidechainBuffer(i) != nullptr)
|
||||||
|
{
|
||||||
|
lilv_instance_connect_port(pInstance, portIndex, GetAudioSidechainBuffer(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < this->inputAtomPortIndices.size(); ++i)
|
for (size_t i = 0; i < this->inputAtomPortIndices.size(); ++i)
|
||||||
{
|
{
|
||||||
auto atomInputBuffer = this->GetAtomInputBuffer(i);
|
auto atomInputBuffer = this->GetAtomInputBuffer(i);
|
||||||
@@ -877,6 +925,16 @@ size_t Lv2Effect::stageToInput(size_t inputSampleOffset, size_t samples)
|
|||||||
pOutput[i] = pInput[i];
|
pOutput[i] = pInput[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (size_t nSidechain = 0; nSidechain < this->inputSidechainBuffers.size(); ++nSidechain)
|
||||||
|
{
|
||||||
|
float *restrict pInput = this->inputSidechainBuffers[nSidechain] + inputSampleOffset;
|
||||||
|
float *restrict pOutput = this->sidechainStagingBufferPointers.at(nSidechain) + this->stagingInputIx;
|
||||||
|
for (size_t i = 0; i < thisTime; ++i)
|
||||||
|
{
|
||||||
|
pOutput[i] = pInput[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
this->stagingInputIx += thisTime;
|
this->stagingInputIx += thisTime;
|
||||||
inputSampleOffset += thisTime;
|
inputSampleOffset += thisTime;
|
||||||
|
|
||||||
@@ -1487,8 +1545,11 @@ void Lv2Effect::SetPathPatchProperty(const std::string &propertyUri, const std::
|
|||||||
mainThreadPathProperties[propertyUri] = jsonAtom;
|
mainThreadPathProperties[propertyUri] = jsonAtom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lv2Effect::EnableBufferStaging(size_t bufferSize, size_t nInputs, size_t nOutputs)
|
void Lv2Effect::EnableBufferStaging(size_t bufferSize )
|
||||||
{
|
{
|
||||||
|
size_t nInputs = this->GetNumberOfInputAudioBuffers();
|
||||||
|
size_t nSidechainInputs = this->GetNumberOfSidechainAudioBuffers();
|
||||||
|
size_t nOutputs = this->GetNumberOfOutputAudioBuffers();
|
||||||
|
|
||||||
stagingBufferSize = bufferSize;
|
stagingBufferSize = bufferSize;
|
||||||
stagingOutputIx = bufferSize;
|
stagingOutputIx = bufferSize;
|
||||||
@@ -1520,6 +1581,12 @@ void Lv2Effect::EnableBufferStaging(size_t bufferSize, size_t nInputs, size_t nO
|
|||||||
inputStagingBuffers[i][bufferSize] = 99.9f; // guard entry
|
inputStagingBuffers[i][bufferSize] = 99.9f; // guard entry
|
||||||
inputStagingBufferPointers.at(i) = inputStagingBuffers.at(i).data();
|
inputStagingBufferPointers.at(i) = inputStagingBuffers.at(i).data();
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < nSidechainInputs; ++i)
|
||||||
|
{
|
||||||
|
sidechainStagingBuffers.at(i).resize(bufferSize + 1);
|
||||||
|
sidechainStagingBuffers[i][bufferSize] = 99.9f; // guard entry
|
||||||
|
sidechainStagingBufferPointers.at(i) = sidechainStagingBuffers.at(i).data();
|
||||||
|
}
|
||||||
for (size_t i = 0; i < nOutputs; ++i)
|
for (size_t i = 0; i < nOutputs; ++i)
|
||||||
{
|
{
|
||||||
outputStagingBuffers.at(i).resize(bufferSize + 1);
|
outputStagingBuffers.at(i).resize(bufferSize + 1);
|
||||||
@@ -1571,6 +1638,12 @@ float *Lv2Effect::GetAudioInputBuffer(int index) const
|
|||||||
throw std::range_error("Lv2Effect::GetAudioInputBuffer");
|
throw std::range_error("Lv2Effect::GetAudioInputBuffer");
|
||||||
return this->inputAudioBuffers.at(index);
|
return this->inputAudioBuffers.at(index);
|
||||||
}
|
}
|
||||||
|
float *Lv2Effect::GetAudioSidechainBuffer(int index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= this->inputSidechainBuffers.size())
|
||||||
|
throw std::range_error("Lv2Effect::GetAudioSidechainBuffer");
|
||||||
|
return this->inputSidechainBuffers.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
float *Lv2Effect::GetAudioOutputBuffer(int index) const
|
float *Lv2Effect::GetAudioOutputBuffer(int index) const
|
||||||
{
|
{
|
||||||
|
|||||||
+20
-11
@@ -81,6 +81,8 @@ namespace pipedal
|
|||||||
std::vector<int> inputAudioPortIndices;
|
std::vector<int> inputAudioPortIndices;
|
||||||
std::vector<int> outputAudioPortIndices;
|
std::vector<int> outputAudioPortIndices;
|
||||||
|
|
||||||
|
std::vector<int> inputSidechainPortIndices;
|
||||||
|
|
||||||
std::vector<int> inputAtomPortIndices;
|
std::vector<int> inputAtomPortIndices;
|
||||||
std::vector<int> outputAtomPortIndices;
|
std::vector<int> outputAtomPortIndices;
|
||||||
|
|
||||||
@@ -90,6 +92,7 @@ namespace pipedal
|
|||||||
std::vector<int> midiInputIndices;
|
std::vector<int> midiInputIndices;
|
||||||
|
|
||||||
std::vector<float *> inputAudioBuffers;
|
std::vector<float *> inputAudioBuffers;
|
||||||
|
std::vector<float *> inputSidechainBuffers;
|
||||||
std::vector<float *> outputAudioBuffers;
|
std::vector<float *> outputAudioBuffers;
|
||||||
|
|
||||||
std::vector<char *> inputAtomBuffers;
|
std::vector<char *> inputAtomBuffers;
|
||||||
@@ -212,7 +215,7 @@ namespace pipedal
|
|||||||
|
|
||||||
bool borrowedEffect = false;
|
bool borrowedEffect = false;
|
||||||
bool activated = false;
|
bool activated = false;
|
||||||
void EnableBufferStaging(size_t bufferSize, size_t nInputs, size_t nOutputs);
|
void EnableBufferStaging(size_t bufferSize);
|
||||||
void CheckStagingBufferSentries();
|
void CheckStagingBufferSentries();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -262,8 +265,10 @@ namespace pipedal
|
|||||||
size_t stagingInputIx = 0;
|
size_t stagingInputIx = 0;
|
||||||
size_t stagingOutputIx = 0;
|
size_t stagingOutputIx = 0;
|
||||||
std::vector<std::vector<float>> inputStagingBuffers;
|
std::vector<std::vector<float>> inputStagingBuffers;
|
||||||
|
std::vector<std::vector<float>> sidechainStagingBuffers;
|
||||||
std::vector<std::vector<float>> outputStagingBuffers;
|
std::vector<std::vector<float>> outputStagingBuffers;
|
||||||
std::vector<float*> inputStagingBufferPointers;
|
std::vector<float*> inputStagingBufferPointers;
|
||||||
|
std::vector<float*> sidechainStagingBufferPointers;
|
||||||
std::vector<float*> outputStagingBufferPointers;
|
std::vector<float*> outputStagingBufferPointers;
|
||||||
|
|
||||||
std::vector<uint8_t> stagedInputAtomBuffer;
|
std::vector<uint8_t> stagedInputAtomBuffer;
|
||||||
@@ -297,22 +302,26 @@ namespace pipedal
|
|||||||
|
|
||||||
virtual void ResetAtomBuffers();
|
virtual void ResetAtomBuffers();
|
||||||
virtual uint64_t GetInstanceId() const { return instanceId; }
|
virtual uint64_t GetInstanceId() const { return instanceId; }
|
||||||
virtual int GetNumberOfInputAudioPorts() const { return inputAudioPortIndices.size(); }
|
virtual int GetNumberOfInputAudioPorts() const override { return inputAudioPortIndices.size(); }
|
||||||
virtual int GetNumberOfOutputAudioPorts() const { return outputAudioPortIndices.size(); }
|
virtual int GetNumberOfOutputAudioPorts() const override { return outputAudioPortIndices.size(); }
|
||||||
|
|
||||||
virtual int GetNumberOfInputAtomPorts() const { return inputAtomPortIndices.size(); }
|
virtual int GetNumberOfInputAtomPorts() const { return inputAtomPortIndices.size(); }
|
||||||
|
|
||||||
virtual int GetNumberOfOutputAtomPorts() const { return outputAtomPortIndices.size(); }
|
virtual int GetNumberOfOutputAtomPorts() const { return outputAtomPortIndices.size(); }
|
||||||
virtual int GetNumberOfMidiInputPorts() const { return inputMidiPortIndices.size(); }
|
virtual int GetNumberOfMidiInputPorts() const { return inputMidiPortIndices.size(); }
|
||||||
virtual int GetNumberOfMidiOutputPorts() const { return outputMidiPortIndices.size(); }
|
virtual int GetNumberOfMidiOutputPorts() const { return outputMidiPortIndices.size(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual int GetNumberOfInputAudioBuffers() const { return this->inputAudioBuffers.size(); }
|
virtual int GetNumberOfInputAudioBuffers() const override { return this->inputAudioBuffers.size(); }
|
||||||
virtual int GetNumberOfOutputAudioBuffers() const {return this->outputAudioBuffers.size(); }
|
virtual int GetNumberOfSidechainAudioBuffers() const override { return this->inputSidechainBuffers.size(); }
|
||||||
|
virtual int GetNumberOfOutputAudioBuffers() const override {return this->outputAudioBuffers.size(); }
|
||||||
|
|
||||||
virtual void SetAudioInputBuffer(int index, float *buffer);
|
virtual void SetAudioInputBuffer(int index, float *buffer) override;
|
||||||
virtual float *GetAudioInputBuffer(int index) const;
|
virtual float *GetAudioInputBuffer(int index) const override;
|
||||||
|
|
||||||
|
virtual void SetAudioSidechainBuffer(int index, float *buffer) override;
|
||||||
|
virtual float *GetAudioSidechainBuffer(int index) const override;
|
||||||
|
|
||||||
|
|
||||||
virtual void SetAudioInputBuffer(float *buffer);
|
virtual void SetAudioInputBuffer(float *buffer);
|
||||||
|
|||||||
+54
-1
@@ -176,6 +176,60 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
|||||||
auto bufferR = inputBuffers[1];
|
auto bufferR = inputBuffers[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Connect sidechain buffers.
|
||||||
|
|
||||||
|
if (pLv2Effect->GetNumberOfSidechainAudioBuffers() != 0)
|
||||||
|
{
|
||||||
|
if (item.sideChainInputId() == -2) // -2 means "use pedalboard inputs".
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pLv2Effect->GetNumberOfSidechainAudioBuffers(); ++i)
|
||||||
|
{
|
||||||
|
if (i < this->pedalboardInputBuffers.size())
|
||||||
|
{
|
||||||
|
pLv2Effect->SetAudioSidechainBuffer(i, this->pedalboardInputBuffers[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just use the first output buffer for all sidechain inputs.
|
||||||
|
pLv2Effect->SetAudioSidechainBuffer(i, this->pedalboardInputBuffers[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (item.sideChainInputId() != -1) {
|
||||||
|
IEffect *pSideChainInput = GetEffect(item.sideChainInputId());
|
||||||
|
|
||||||
|
if (pSideChainInput)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pLv2Effect->GetNumberOfSidechainAudioBuffers(); ++i)
|
||||||
|
{
|
||||||
|
if (i < pSideChainInput->GetNumberOfOutputAudioBuffers())
|
||||||
|
{
|
||||||
|
pLv2Effect->SetAudioSidechainBuffer(i, pSideChainInput->GetAudioOutputBuffer(i));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just use the first output buffer for all sidechain inputs.
|
||||||
|
pLv2Effect->SetAudioSidechainBuffer(i, pSideChainInput->GetAudioOutputBuffer(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Internal error: Sidechain input IEffect not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No sidechain input. Feed zero buffer to all sidechain audio ports..
|
||||||
|
for (size_t i = 0; i < pLv2Effect->GetNumberOfSidechainAudioBuffers(); ++i)
|
||||||
|
{
|
||||||
|
|
||||||
|
// just use one buffer for all plugins
|
||||||
|
if (!this->pedalboardSidechainBuffer)
|
||||||
|
{
|
||||||
|
this->pedalboardSidechainBuffer = CreateNewAudioBuffer();
|
||||||
|
}
|
||||||
|
pLv2Effect->SetAudioSidechainBuffer(i, this->pedalboardSidechainBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check to see whether we need buffer staging.
|
// check to see whether we need buffer staging.
|
||||||
bool requiresBufferStaging = false;
|
bool requiresBufferStaging = false;
|
||||||
@@ -194,7 +248,6 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!requiresBufferStaging)
|
if (!requiresBufferStaging)
|
||||||
{
|
{
|
||||||
this->processActions.push_back(
|
this->processActions.push_back(
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace pipedal
|
|||||||
BufferPool bufferPool;
|
BufferPool bufferPool;
|
||||||
std::vector<float *> pedalboardInputBuffers;
|
std::vector<float *> pedalboardInputBuffers;
|
||||||
std::vector<float *> pedalboardOutputBuffers;
|
std::vector<float *> pedalboardOutputBuffers;
|
||||||
|
float *pedalboardSidechainBuffer = nullptr;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<IEffect>> effects;
|
std::vector<std::shared_ptr<IEffect>> effects;
|
||||||
std::vector<IEffect *> realtimeEffects;
|
std::vector<IEffect *> realtimeEffects;
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ JSON_MAP_BEGIN(PedalboardItem)
|
|||||||
JSON_MAP_REFERENCE(PedalboardItem,title)
|
JSON_MAP_REFERENCE(PedalboardItem,title)
|
||||||
JSON_MAP_REFERENCE(PedalboardItem,useModUi)
|
JSON_MAP_REFERENCE(PedalboardItem,useModUi)
|
||||||
JSON_MAP_REFERENCE(PedalboardItem,iconColor)
|
JSON_MAP_REFERENCE(PedalboardItem,iconColor)
|
||||||
|
JSON_MAP_REFERENCE(PedalboardItem,sideChainInputId)
|
||||||
JSON_MAP_END()
|
JSON_MAP_END()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ public:
|
|||||||
std::string title_;
|
std::string title_;
|
||||||
bool useModUi_ = false;
|
bool useModUi_ = false;
|
||||||
std::string iconColor_;
|
std::string iconColor_;
|
||||||
|
int64_t sideChainInputId_ = -1;
|
||||||
|
|
||||||
// non persistent state.
|
// non persistent state.
|
||||||
PropertyMap patchProperties;
|
PropertyMap patchProperties;
|
||||||
@@ -138,6 +139,7 @@ public:
|
|||||||
GETTER_SETTER_REF(title)
|
GETTER_SETTER_REF(title)
|
||||||
GETTER_SETTER_REF(iconColor)
|
GETTER_SETTER_REF(iconColor)
|
||||||
GETTER_SETTER(useModUi)
|
GETTER_SETTER(useModUi)
|
||||||
|
GETTER_SETTER(sideChainInputId)
|
||||||
|
|
||||||
Lv2PluginState&lv2State() { return lv2State_; } // non-const version.
|
Lv2PluginState&lv2State() { return lv2State_; } // non-const version.
|
||||||
GETTER_SETTER_REF(lilvPresetUri)
|
GETTER_SETTER_REF(lilvPresetUri)
|
||||||
|
|||||||
@@ -2428,7 +2428,7 @@ void PiPedalModel::OnNotifyPathPatchPropertyReceived(
|
|||||||
auto i = pedalboardItem->pathProperties_.find(pathPatchPropertyUri);
|
auto i = pedalboardItem->pathProperties_.find(pathPatchPropertyUri);
|
||||||
if (i != pedalboardItem->pathProperties_.end())
|
if (i != pedalboardItem->pathProperties_.end())
|
||||||
{
|
{
|
||||||
std::string abstractAtomString = storage.ToAbstractPathJson(atomString);
|
std::string abstractAtomString = storage.ToAbstractPathFromJson(atomString);
|
||||||
pedalboardItem->pathProperties_[pathPatchPropertyUri] = abstractAtomString;
|
pedalboardItem->pathProperties_[pathPatchPropertyUri] = abstractAtomString;
|
||||||
|
|
||||||
std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
|
std::vector<IPiPedalModelSubscriber::ptr> t{subscribers.begin(), subscribers.end()};
|
||||||
|
|||||||
+111
-7
@@ -121,6 +121,7 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
|
|||||||
enumeration_property_uri = lilv_new_uri(pWorld, LV2_CORE__enumeration);
|
enumeration_property_uri = lilv_new_uri(pWorld, LV2_CORE__enumeration);
|
||||||
core__toggled = lilv_new_uri(pWorld, LV2_CORE__toggled);
|
core__toggled = lilv_new_uri(pWorld, LV2_CORE__toggled);
|
||||||
core__connectionOptional = lilv_new_uri(pWorld, LV2_CORE__connectionOptional);
|
core__connectionOptional = lilv_new_uri(pWorld, LV2_CORE__connectionOptional);
|
||||||
|
core__isSideChain = lilv_new_uri(pWorld, LV2_CORE_PREFIX "isSideChain"); // missing in lv2.h
|
||||||
portprops__not_on_gui_property_uri = lilv_new_uri(pWorld, LV2_PORT_PROPS__notOnGUI);
|
portprops__not_on_gui_property_uri = lilv_new_uri(pWorld, LV2_PORT_PROPS__notOnGUI);
|
||||||
portprops__trigger = lilv_new_uri(pWorld, LV2_PORT_PROPS__trigger);
|
portprops__trigger = lilv_new_uri(pWorld, LV2_PORT_PROPS__trigger);
|
||||||
midi__event = lilv_new_uri(pWorld, LV2_MIDI__MidiEvent);
|
midi__event = lilv_new_uri(pWorld, LV2_MIDI__MidiEvent);
|
||||||
@@ -134,6 +135,7 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
|
|||||||
|
|
||||||
atom__bufferType = lilv_new_uri(pWorld, LV2_ATOM__bufferType);
|
atom__bufferType = lilv_new_uri(pWorld, LV2_ATOM__bufferType);
|
||||||
atom__Path = lilv_new_uri(pWorld, LV2_ATOM__Path);
|
atom__Path = lilv_new_uri(pWorld, LV2_ATOM__Path);
|
||||||
|
atom__String = lilv_new_uri(pWorld, LV2_ATOM__String);
|
||||||
presets__preset = lilv_new_uri(pWorld, LV2_PRESETS__Preset);
|
presets__preset = lilv_new_uri(pWorld, LV2_PRESETS__Preset);
|
||||||
state__state = lilv_new_uri(pWorld, LV2_STATE__state);
|
state__state = lilv_new_uri(pWorld, LV2_STATE__state);
|
||||||
rdfs__label = lilv_new_uri(pWorld, LILV_NS_RDFS "label");
|
rdfs__label = lilv_new_uri(pWorld, LILV_NS_RDFS "label");
|
||||||
@@ -214,6 +216,7 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
|
|||||||
buf_size__maxBlockLength = lilv_new_uri(pWorld, LV2_BUF_SIZE__maxBlockLength);
|
buf_size__maxBlockLength = lilv_new_uri(pWorld, LV2_BUF_SIZE__maxBlockLength);
|
||||||
buf_size__fixedBlockLength = lilv_new_uri(pWorld, LV2_BUF_SIZE__fixedBlockLength);
|
buf_size__fixedBlockLength = lilv_new_uri(pWorld, LV2_BUF_SIZE__fixedBlockLength);
|
||||||
buf_size__coarseBlockLength = lilv_new_uri(pWorld, LV2_BUF_SIZE__coarseBlockLength);
|
buf_size__coarseBlockLength = lilv_new_uri(pWorld, LV2_BUF_SIZE__coarseBlockLength);
|
||||||
|
port_groups__sideChainOf = lilv_new_uri(pWorld, LV2_PORT_GROUPS__sideChainOf);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -794,7 +797,12 @@ Lv2PluginInfo::FindWritablePathProperties(PluginHost *lv2Host, const LilvPlugin
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsupportedPatchProperty = true;
|
if (lilv_world_ask(pWorld, propertyUri, lv2Host->lilvUris->rdfs__range, lv2Host->lilvUris->atom__String))
|
||||||
|
{
|
||||||
|
|
||||||
|
} else {
|
||||||
|
unsupportedPatchProperty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -945,6 +953,60 @@ Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvP
|
|||||||
|
|
||||||
|
|
||||||
std::sort(ports_.begin(), ports_.end(), ports_sort_compare);
|
std::sort(ports_.begin(), ports_.end(), ports_sort_compare);
|
||||||
|
|
||||||
|
|
||||||
|
// Check the portgroup for audio inputs to see if they are sidechains.
|
||||||
|
std::string last_sidechain_title;
|
||||||
|
for (auto&port: this->ports_)
|
||||||
|
{
|
||||||
|
if (port->is_audio_port() && port->is_input()) {
|
||||||
|
if (!port->port_group().empty())
|
||||||
|
{
|
||||||
|
for (auto &pg: this->port_groups_)
|
||||||
|
{
|
||||||
|
if (pg->uri() == port->port_group())
|
||||||
|
{
|
||||||
|
if (!pg->sideChainOf().empty())
|
||||||
|
{
|
||||||
|
port->is_sidechain(true);
|
||||||
|
audio_sidechain_title_ = pg->name();
|
||||||
|
if (last_sidechain_title.empty()) {
|
||||||
|
last_sidechain_title = pg->name();
|
||||||
|
}
|
||||||
|
else if (last_sidechain_title != pg->name()) {
|
||||||
|
// multiple sidechain titles!
|
||||||
|
isValid = false;
|
||||||
|
Lv2Log::debug("Plugin %s (%s) has multiple sidechain titles (%s and %s).",
|
||||||
|
this->name_.c_str(),
|
||||||
|
this->uri_.c_str(),
|
||||||
|
last_sidechain_title.c_str(),
|
||||||
|
pg->name().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (port->is_sidechain()) {
|
||||||
|
// port is marked as sidechain, but has no port group.
|
||||||
|
if (last_sidechain_title.empty())
|
||||||
|
{
|
||||||
|
last_sidechain_title = port->name();
|
||||||
|
this->audio_sidechain_title_ = port->name();
|
||||||
|
}
|
||||||
|
else if (last_sidechain_title != port->name()) {
|
||||||
|
isValid = false;
|
||||||
|
Lv2Log::debug("Plugin %s (%s) has multiple sidechain ports, but no portgroup. (%s)",
|
||||||
|
this->name_.c_str(),
|
||||||
|
this->uri_.c_str(),
|
||||||
|
port->name().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch patch properties.
|
// Fetch patch properties.
|
||||||
{
|
{
|
||||||
AutoLilvNodes patchWritables = lilv_world_find_nodes(pWorld, plugUri, lv2Host->lilvUris->patch__writable, nullptr);
|
AutoLilvNodes patchWritables = lilv_world_find_nodes(pWorld, plugUri, lv2Host->lilvUris->patch__writable, nullptr);
|
||||||
@@ -1034,17 +1096,28 @@ Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvP
|
|||||||
}
|
}
|
||||||
|
|
||||||
int nInputs = 0;
|
int nInputs = 0;
|
||||||
|
int nSideChains = 0;
|
||||||
for (size_t i = 0; i < ports_.size(); ++i)
|
for (size_t i = 0; i < ports_.size(); ++i)
|
||||||
{
|
{
|
||||||
auto port = ports_[i];
|
auto port = ports_[i];
|
||||||
if (port->is_audio_port() && port->is_input())
|
if (port->is_audio_port() && port->is_input())
|
||||||
{
|
{
|
||||||
if (nInputs >= 2 && !port->connection_optional())
|
if (!port->is_sidechain()) {
|
||||||
{
|
if (nInputs >= 2)
|
||||||
isValid = false;
|
{
|
||||||
break;
|
isValid = false;
|
||||||
|
Lv2Log::debug("Plugin %s (%s) has more than 2 audio inputs.", this->name_.c_str(), this->uri_.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++nInputs;
|
||||||
|
} else {
|
||||||
|
if (nSideChains >= 2) {
|
||||||
|
Lv2Log::debug("Plugin %s (%s) has more than 2 audio sidechain inputs.", this->name_.c_str(), this->uri_.c_str());
|
||||||
|
isValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++nSideChains;
|
||||||
}
|
}
|
||||||
++nInputs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int nOutputs = 0;
|
int nOutputs = 0;
|
||||||
@@ -1199,6 +1272,7 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
|
|||||||
this->not_on_gui_ = lilv_port_has_property(plugin, pPort, host->lilvUris->portprops__not_on_gui_property_uri);
|
this->not_on_gui_ = lilv_port_has_property(plugin, pPort, host->lilvUris->portprops__not_on_gui_property_uri);
|
||||||
this->connection_optional_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__connectionOptional);
|
this->connection_optional_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__connectionOptional);
|
||||||
this->trigger_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->portprops__trigger);
|
this->trigger_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->portprops__trigger);
|
||||||
|
this->is_sidechain_ = lilv_port_has_property(plugin,pPort,host->lilvUris->core__isSideChain);
|
||||||
|
|
||||||
AutoLilvNode port_ledColor = lilv_port_get(plugin, pPort, host->lilvUris->pipedalUI__ledColor);
|
AutoLilvNode port_ledColor = lilv_port_get(plugin, pPort, host->lilvUris->pipedalUI__ledColor);
|
||||||
if (port_ledColor)
|
if (port_ledColor)
|
||||||
@@ -1402,7 +1476,12 @@ Lv2PluginUiInfo::Lv2PluginUiInfo(PluginHost *pHost, const Lv2PluginInfo *plugin)
|
|||||||
}
|
}
|
||||||
else if (port->is_audio_port())
|
else if (port->is_audio_port())
|
||||||
{
|
{
|
||||||
++audio_inputs_;
|
if (port->is_sidechain()) {
|
||||||
|
// sidechain outputs don't count.
|
||||||
|
++audio_side_chain_inputs_;
|
||||||
|
} else {
|
||||||
|
++audio_inputs_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (port->is_output())
|
else if (port->is_output())
|
||||||
@@ -1918,12 +1997,29 @@ Lv2PortGroup::Lv2PortGroup(PluginHost *lv2Host, const std::string &groupUri)
|
|||||||
{
|
{
|
||||||
LilvWorld *pWorld = lv2Host->pWorld;
|
LilvWorld *pWorld = lv2Host->pWorld;
|
||||||
|
|
||||||
|
// Enumerate all Lilv nodes for groupUri that have an 'a' predicate
|
||||||
|
|
||||||
this->uri_ = groupUri;
|
this->uri_ = groupUri;
|
||||||
AutoLilvNode uri = lilv_new_uri(pWorld, groupUri.c_str());
|
AutoLilvNode uri = lilv_new_uri(pWorld, groupUri.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
AutoLilvNode aPredicate = lilv_new_uri(pWorld, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
||||||
|
|
||||||
|
AutoLilvNodes types = lilv_world_find_nodes(pWorld, uri, aPredicate, nullptr);
|
||||||
|
LILV_FOREACH(nodes, iNode, types)
|
||||||
|
{
|
||||||
|
AutoLilvNode typeNode = lilv_nodes_get(types, iNode);
|
||||||
|
std::string typeUri = nodeAsString(typeNode);
|
||||||
|
this->isA_.push_back(std::move(typeUri));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AutoLilvNode symbolNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__symbol, nullptr);
|
AutoLilvNode symbolNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__symbol, nullptr);
|
||||||
symbol_ = nodeAsString(symbolNode);
|
symbol_ = nodeAsString(symbolNode);
|
||||||
AutoLilvNode nameNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__name, nullptr);
|
AutoLilvNode nameNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->lv2core__name, nullptr);
|
||||||
name_ = nodeAsString(nameNode);
|
name_ = nodeAsString(nameNode);
|
||||||
|
AutoLilvNode sideChainOfNode = lilv_world_get(pWorld, uri, lv2Host->lilvUris->port_groups__sideChainOf, nullptr);
|
||||||
|
sideChainOf_ = nodeAsString(sideChainOfNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lv2PluginInfo::isSplit() const
|
bool Lv2PluginInfo::isSplit() const
|
||||||
@@ -2187,6 +2283,7 @@ json_map::storage_type<Lv2PortInfo> Lv2PortInfo::jmap{
|
|||||||
|
|
||||||
json_map::reference("is_input", &Lv2PortInfo::is_input_),
|
json_map::reference("is_input", &Lv2PortInfo::is_input_),
|
||||||
json_map::reference("is_output", &Lv2PortInfo::is_output_),
|
json_map::reference("is_output", &Lv2PortInfo::is_output_),
|
||||||
|
json_map::reference("is_sidechain", &Lv2PortInfo::is_sidechain_),
|
||||||
|
|
||||||
json_map::reference("is_control_port", &Lv2PortInfo::is_control_port_),
|
json_map::reference("is_control_port", &Lv2PortInfo::is_control_port_),
|
||||||
json_map::reference("is_audio_port", &Lv2PortInfo::is_audio_port_),
|
json_map::reference("is_audio_port", &Lv2PortInfo::is_audio_port_),
|
||||||
@@ -2226,7 +2323,11 @@ json_map::storage_type<Lv2PortInfo> Lv2PortInfo::jmap{
|
|||||||
|
|
||||||
|
|
||||||
json_map::storage_type<Lv2PortGroup> Lv2PortGroup::jmap{{
|
json_map::storage_type<Lv2PortGroup> Lv2PortGroup::jmap{{
|
||||||
|
MAP_REF(Lv2PortGroup, isA),
|
||||||
MAP_REF(Lv2PortGroup, uri),
|
MAP_REF(Lv2PortGroup, uri),
|
||||||
|
MAP_REF(Lv2PortGroup, name),
|
||||||
|
MAP_REF(Lv2PortGroup, symbol),
|
||||||
|
MAP_REF(Lv2PortGroup, sideChainOf),
|
||||||
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -2281,6 +2382,7 @@ json_map::storage_type<Lv2PluginUiPort> Lv2PluginUiPort::jmap{{
|
|||||||
json_map::reference("name", &Lv2PluginUiPort::name_),
|
json_map::reference("name", &Lv2PluginUiPort::name_),
|
||||||
MAP_REF(Lv2PluginUiPort, index),
|
MAP_REF(Lv2PluginUiPort, index),
|
||||||
MAP_REF(Lv2PluginUiPort, is_input),
|
MAP_REF(Lv2PluginUiPort, is_input),
|
||||||
|
MAP_REF(Lv2PluginUiPort, is_sidechain),
|
||||||
MAP_REF(Lv2PluginUiPort, min_value),
|
MAP_REF(Lv2PluginUiPort, min_value),
|
||||||
MAP_REF(Lv2PluginUiPort, max_value),
|
MAP_REF(Lv2PluginUiPort, max_value),
|
||||||
MAP_REF(Lv2PluginUiPort, default_value),
|
MAP_REF(Lv2PluginUiPort, default_value),
|
||||||
@@ -2324,7 +2426,9 @@ json_map::storage_type<Lv2PluginUiInfo>
|
|||||||
json_map::reference("author_name", &Lv2PluginUiInfo::author_name_),
|
json_map::reference("author_name", &Lv2PluginUiInfo::author_name_),
|
||||||
json_map::reference("author_homepage", &Lv2PluginUiInfo::author_homepage_),
|
json_map::reference("author_homepage", &Lv2PluginUiInfo::author_homepage_),
|
||||||
json_map::reference("audio_inputs", &Lv2PluginUiInfo::audio_inputs_),
|
json_map::reference("audio_inputs", &Lv2PluginUiInfo::audio_inputs_),
|
||||||
|
json_map::reference("audio_side_chain_inputs", &Lv2PluginUiInfo::audio_side_chain_inputs_),
|
||||||
json_map::reference("audio_outputs", &Lv2PluginUiInfo::audio_outputs_),
|
json_map::reference("audio_outputs", &Lv2PluginUiInfo::audio_outputs_),
|
||||||
|
json_map::reference("audio_side_chain_title", &Lv2PluginUiInfo::audio_side_chain_title_),
|
||||||
json_map::reference("description", &Lv2PluginUiInfo::description_),
|
json_map::reference("description", &Lv2PluginUiInfo::description_),
|
||||||
json_map::reference("has_midi_input", &Lv2PluginUiInfo::has_midi_input_),
|
json_map::reference("has_midi_input", &Lv2PluginUiInfo::has_midi_input_),
|
||||||
json_map::reference("has_midi_output", &Lv2PluginUiInfo::has_midi_output_),
|
json_map::reference("has_midi_output", &Lv2PluginUiInfo::has_midi_output_),
|
||||||
|
|||||||
+61
-49
@@ -33,7 +33,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include "ModGui.hpp"
|
#include "ModGui.hpp"
|
||||||
|
|
||||||
//#include "lv2.h"
|
// #include "lv2.h"
|
||||||
#include "Units.hpp"
|
#include "Units.hpp"
|
||||||
#include "PluginPreset.hpp"
|
#include "PluginPreset.hpp"
|
||||||
|
|
||||||
@@ -206,6 +206,7 @@ namespace pipedal
|
|||||||
|
|
||||||
bool is_control_port_ = false;
|
bool is_control_port_ = false;
|
||||||
bool is_audio_port_ = false;
|
bool is_audio_port_ = false;
|
||||||
|
bool is_sidechain_ = false;
|
||||||
bool is_atom_port_ = false;
|
bool is_atom_port_ = false;
|
||||||
bool is_cv_port_ = false;
|
bool is_cv_port_ = false;
|
||||||
bool connection_optional_ = false;
|
bool connection_optional_ = false;
|
||||||
@@ -287,6 +288,7 @@ namespace pipedal
|
|||||||
LV2_PROPERTY_GETSET_SCALAR(is_output);
|
LV2_PROPERTY_GETSET_SCALAR(is_output);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(is_control_port);
|
LV2_PROPERTY_GETSET_SCALAR(is_control_port);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(is_audio_port);
|
LV2_PROPERTY_GETSET_SCALAR(is_audio_port);
|
||||||
|
LV2_PROPERTY_GETSET_SCALAR(is_sidechain);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(is_atom_port);
|
LV2_PROPERTY_GETSET_SCALAR(is_atom_port);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(connection_optional);
|
LV2_PROPERTY_GETSET_SCALAR(connection_optional);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(is_cv_port);
|
LV2_PROPERTY_GETSET_SCALAR(is_cv_port);
|
||||||
@@ -321,7 +323,6 @@ namespace pipedal
|
|||||||
return Lv2BufferType::Unknown;
|
return Lv2BufferType::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Lv2PortInfo() {}
|
Lv2PortInfo() {}
|
||||||
~Lv2PortInfo() = default;
|
~Lv2PortInfo() = default;
|
||||||
@@ -330,7 +331,8 @@ namespace pipedal
|
|||||||
static json_map::storage_type<Lv2PortInfo> jmap;
|
static json_map::storage_type<Lv2PortInfo> jmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Lv2PatchPropertyInfo {
|
class Lv2PatchPropertyInfo
|
||||||
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string uri_;
|
std::string uri_;
|
||||||
@@ -343,9 +345,10 @@ namespace pipedal
|
|||||||
std::string shortName_;
|
std::string shortName_;
|
||||||
std::vector<std::string> fileTypes_;
|
std::vector<std::string> fileTypes_;
|
||||||
std::vector<std::string> supportedExtensions_;
|
std::vector<std::string> supportedExtensions_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Lv2PatchPropertyInfo() {}
|
Lv2PatchPropertyInfo() {}
|
||||||
Lv2PatchPropertyInfo(PluginHost *pluginHost, const LilvNode *propertyUri);
|
Lv2PatchPropertyInfo(PluginHost *pluginHost, const LilvNode *propertyUri);
|
||||||
|
|
||||||
LV2_PROPERTY_GETSET(uri);
|
LV2_PROPERTY_GETSET(uri);
|
||||||
LV2_PROPERTY_GETSET(writable);
|
LV2_PROPERTY_GETSET(writable);
|
||||||
@@ -359,21 +362,24 @@ namespace pipedal
|
|||||||
LV2_PROPERTY_GETSET(supportedExtensions);
|
LV2_PROPERTY_GETSET(supportedExtensions);
|
||||||
|
|
||||||
DECLARE_JSON_MAP(Lv2PatchPropertyInfo);
|
DECLARE_JSON_MAP(Lv2PatchPropertyInfo);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Lv2PortGroup
|
class Lv2PortGroup
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
std::vector<std::string> isA_;
|
||||||
std::string uri_;
|
std::string uri_;
|
||||||
std::string symbol_;
|
std::string symbol_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
std::string sideChainOf_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
LV2_PROPERTY_GETSET(isA);
|
||||||
LV2_PROPERTY_GETSET(uri);
|
LV2_PROPERTY_GETSET(uri);
|
||||||
LV2_PROPERTY_GETSET(symbol);
|
LV2_PROPERTY_GETSET(symbol);
|
||||||
LV2_PROPERTY_GETSET(name);
|
LV2_PROPERTY_GETSET(name);
|
||||||
|
LV2_PROPERTY_GETSET(sideChainOf);
|
||||||
|
|
||||||
Lv2PortGroup() {}
|
Lv2PortGroup() {}
|
||||||
Lv2PortGroup(PluginHost *lv2Host, const std::string &groupUri);
|
Lv2PortGroup(PluginHost *lv2Host, const std::string &groupUri);
|
||||||
|
|
||||||
@@ -389,10 +395,11 @@ namespace pipedal
|
|||||||
using ptr = std::shared_ptr<Lv2PluginInfo>;
|
using ptr = std::shared_ptr<Lv2PluginInfo>;
|
||||||
Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvPlugin *);
|
Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvPlugin *);
|
||||||
Lv2PluginInfo() {}
|
Lv2PluginInfo() {}
|
||||||
bool isSplit() const ;
|
bool isSplit() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FindWritablePathPropertiesResult {
|
struct FindWritablePathPropertiesResult
|
||||||
|
{
|
||||||
std::shared_ptr<PiPedalUI> pipedalUi;
|
std::shared_ptr<PiPedalUI> pipedalUi;
|
||||||
bool hasUnsupportedPatchProperties = false;
|
bool hasUnsupportedPatchProperties = false;
|
||||||
};
|
};
|
||||||
@@ -406,7 +413,7 @@ namespace pipedal
|
|||||||
std::string name_;
|
std::string name_;
|
||||||
std::string plugin_class_;
|
std::string plugin_class_;
|
||||||
std::string brand_;
|
std::string brand_;
|
||||||
std::string label_;
|
std::string label_;
|
||||||
std::vector<std::string> supported_features_;
|
std::vector<std::string> supported_features_;
|
||||||
std::vector<std::string> required_features_;
|
std::vector<std::string> required_features_;
|
||||||
std::vector<std::string> optional_features_;
|
std::vector<std::string> optional_features_;
|
||||||
@@ -420,9 +427,9 @@ namespace pipedal
|
|||||||
std::vector<std::shared_ptr<Lv2PortInfo>> ports_;
|
std::vector<std::shared_ptr<Lv2PortInfo>> ports_;
|
||||||
std::vector<std::shared_ptr<Lv2PortGroup>> port_groups_;
|
std::vector<std::shared_ptr<Lv2PortGroup>> port_groups_;
|
||||||
std::vector<Lv2PatchPropertyInfo> patchProperties_;
|
std::vector<Lv2PatchPropertyInfo> patchProperties_;
|
||||||
|
std::string audio_sidechain_title_;
|
||||||
bool hasDefaultState_;
|
bool hasDefaultState_;
|
||||||
|
|
||||||
bool is_valid_ = false;
|
bool is_valid_ = false;
|
||||||
PiPedalUI::ptr piPedalUI_;
|
PiPedalUI::ptr piPedalUI_;
|
||||||
ModGui::ptr modGui_;
|
ModGui::ptr modGui_;
|
||||||
@@ -463,6 +470,7 @@ namespace pipedal
|
|||||||
LV2_PROPERTY_GETSET(minBlockLength)
|
LV2_PROPERTY_GETSET(minBlockLength)
|
||||||
LV2_PROPERTY_GETSET(maxBlockLength)
|
LV2_PROPERTY_GETSET(maxBlockLength)
|
||||||
LV2_PROPERTY_GETSET(powerOf2BlockLength)
|
LV2_PROPERTY_GETSET(powerOf2BlockLength)
|
||||||
|
LV2_PROPERTY_GETSET(audio_sidechain_title)
|
||||||
|
|
||||||
bool WantsWorkerThread() const;
|
bool WantsWorkerThread() const;
|
||||||
|
|
||||||
@@ -529,9 +537,11 @@ namespace pipedal
|
|||||||
class Lv2PluginUiPortGroup
|
class Lv2PluginUiPortGroup
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
std::vector<std::string> isA_;
|
||||||
std::string uri_;
|
std::string uri_;
|
||||||
std::string symbol_;
|
std::string symbol_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
std::string sideChainOf_;
|
||||||
|
|
||||||
std::string parent_group_;
|
std::string parent_group_;
|
||||||
int32_t program_list_id_ = -1; // used by VST3.
|
int32_t program_list_id_ = -1; // used by VST3.
|
||||||
@@ -546,9 +556,7 @@ namespace pipedal
|
|||||||
public:
|
public:
|
||||||
Lv2PluginUiPortGroup() {}
|
Lv2PluginUiPortGroup() {}
|
||||||
Lv2PluginUiPortGroup(Lv2PortGroup *pPortGroup)
|
Lv2PluginUiPortGroup(Lv2PortGroup *pPortGroup)
|
||||||
: symbol_(pPortGroup->symbol())
|
: isA_(pPortGroup->isA()), symbol_(pPortGroup->symbol()), name_(pPortGroup->name()), uri_(pPortGroup->uri()), sideChainOf_(pPortGroup->sideChainOf())
|
||||||
, name_(pPortGroup->name())
|
|
||||||
, uri_(pPortGroup->uri())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Lv2PluginUiPortGroup(
|
Lv2PluginUiPortGroup(
|
||||||
@@ -570,14 +578,18 @@ namespace pipedal
|
|||||||
}
|
}
|
||||||
Lv2PluginUiPort(const Lv2PluginInfo *pPlugin, const Lv2PortInfo *pPort)
|
Lv2PluginUiPort(const Lv2PluginInfo *pPlugin, const Lv2PortInfo *pPort)
|
||||||
: symbol_(pPort->symbol()), index_(pPort->index()),
|
: symbol_(pPort->symbol()), index_(pPort->index()),
|
||||||
is_input_(pPort->is_input()), name_(pPort->name()), min_value_(pPort->min_value()), max_value_(pPort->max_value()),
|
is_input_(pPort->is_input()),
|
||||||
|
is_sidechain_(pPort->is_sidechain()),
|
||||||
|
name_(pPort->name()),
|
||||||
|
min_value_(pPort->min_value()),
|
||||||
|
max_value_(pPort->max_value()),
|
||||||
default_value_(pPort->default_value()), range_steps_(pPort->range_steps()), display_priority_(pPort->display_priority()),
|
default_value_(pPort->default_value()), range_steps_(pPort->range_steps()), display_priority_(pPort->display_priority()),
|
||||||
is_logarithmic_(pPort->is_logarithmic()),
|
is_logarithmic_(pPort->is_logarithmic()),
|
||||||
integer_property_(pPort->integer_property()),
|
integer_property_(pPort->integer_property()),
|
||||||
mod_momentaryOffByDefault_(pPort->mod_momentaryOffByDefault()),
|
mod_momentaryOffByDefault_(pPort->mod_momentaryOffByDefault()),
|
||||||
mod_momentaryOnByDefault_(pPort->mod_momentaryOnByDefault()),
|
mod_momentaryOnByDefault_(pPort->mod_momentaryOnByDefault()),
|
||||||
pipedal_graphicEq_(pPort->pipedal_graphicEq()),
|
pipedal_graphicEq_(pPort->pipedal_graphicEq()),
|
||||||
|
|
||||||
enumeration_property_(pPort->enumeration_property()),
|
enumeration_property_(pPort->enumeration_property()),
|
||||||
toggled_property_(pPort->toggled_property()), not_on_gui_(pPort->not_on_gui()), scale_points_(pPort->scale_points()),
|
toggled_property_(pPort->toggled_property()), not_on_gui_(pPort->not_on_gui()), scale_points_(pPort->scale_points()),
|
||||||
trigger_property_(pPort->trigger_property()),
|
trigger_property_(pPort->trigger_property()),
|
||||||
@@ -606,7 +618,7 @@ namespace pipedal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is_bypass_ =
|
is_bypass_ =
|
||||||
pPort->is_bypass() ||
|
pPort->is_bypass() ||
|
||||||
name_ == "bypass" || name_ == "Bypass" || symbol_ == "bypass" || symbol_ == "Bypass";
|
name_ == "bypass" || name_ == "Bypass" || symbol_ == "bypass" || symbol_ == "Bypass";
|
||||||
}
|
}
|
||||||
@@ -616,6 +628,7 @@ namespace pipedal
|
|||||||
int index_;
|
int index_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
bool is_input_ = true;
|
bool is_input_ = true;
|
||||||
|
bool is_sidechain_ = false;
|
||||||
float min_value_ = 0, max_value_ = 1, default_value_ = 0;
|
float min_value_ = 0, max_value_ = 1, default_value_ = 0;
|
||||||
bool is_logarithmic_ = false;
|
bool is_logarithmic_ = false;
|
||||||
int display_priority_ = -1;
|
int display_priority_ = -1;
|
||||||
@@ -682,7 +695,8 @@ namespace pipedal
|
|||||||
std::string uri_;
|
std::string uri_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
uint32_t minorVersion_ = 0;
|
uint32_t minorVersion_ = 0;
|
||||||
uint32_t microVersion_ = 0;;
|
uint32_t microVersion_ = 0;
|
||||||
|
;
|
||||||
std::string brand_;
|
std::string brand_;
|
||||||
std::string label_;
|
std::string label_;
|
||||||
std::string author_name_;
|
std::string author_name_;
|
||||||
@@ -690,12 +704,17 @@ namespace pipedal
|
|||||||
PluginType plugin_type_;
|
PluginType plugin_type_;
|
||||||
std::string plugin_display_type_;
|
std::string plugin_display_type_;
|
||||||
int audio_inputs_ = 0;
|
int audio_inputs_ = 0;
|
||||||
|
int audio_side_chain_inputs_ = 0;
|
||||||
int audio_outputs_ = 0;
|
int audio_outputs_ = 0;
|
||||||
|
std::string audio_side_chain_title_;
|
||||||
int has_midi_input_ = false;
|
int has_midi_input_ = false;
|
||||||
int has_midi_output_ = false;
|
int has_midi_output_ = false;
|
||||||
std::string description_;
|
std::string description_;
|
||||||
bool is_vst3_ = false;
|
bool is_vst3_ = false;
|
||||||
|
|
||||||
|
int64_t side_chain_input_id = -1;
|
||||||
|
|
||||||
|
|
||||||
std::vector<Lv2PluginUiPort> controls_;
|
std::vector<Lv2PluginUiPort> controls_;
|
||||||
std::vector<Lv2PluginUiPortGroup> port_groups_;
|
std::vector<Lv2PluginUiPortGroup> port_groups_;
|
||||||
std::vector<UiFileProperty::ptr> fileProperties_;
|
std::vector<UiFileProperty::ptr> fileProperties_;
|
||||||
@@ -704,7 +723,6 @@ namespace pipedal
|
|||||||
ModGui::ptr modGui_;
|
ModGui::ptr modGui_;
|
||||||
std::vector<Lv2PatchPropertyInfo> patchProperties_;
|
std::vector<Lv2PatchPropertyInfo> patchProperties_;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LV2_PROPERTY_GETSET(uri)
|
LV2_PROPERTY_GETSET(uri)
|
||||||
LV2_PROPERTY_GETSET(name)
|
LV2_PROPERTY_GETSET(name)
|
||||||
@@ -718,6 +736,7 @@ namespace pipedal
|
|||||||
LV2_PROPERTY_GETSET(plugin_display_type)
|
LV2_PROPERTY_GETSET(plugin_display_type)
|
||||||
LV2_PROPERTY_GETSET_SCALAR(audio_inputs)
|
LV2_PROPERTY_GETSET_SCALAR(audio_inputs)
|
||||||
LV2_PROPERTY_GETSET_SCALAR(audio_outputs)
|
LV2_PROPERTY_GETSET_SCALAR(audio_outputs)
|
||||||
|
LV2_PROPERTY_GETSET(audio_side_chain_title)
|
||||||
LV2_PROPERTY_GETSET_SCALAR(has_midi_input)
|
LV2_PROPERTY_GETSET_SCALAR(has_midi_input)
|
||||||
LV2_PROPERTY_GETSET_SCALAR(has_midi_output)
|
LV2_PROPERTY_GETSET_SCALAR(has_midi_output)
|
||||||
LV2_PROPERTY_GETSET_SCALAR(description)
|
LV2_PROPERTY_GETSET_SCALAR(description)
|
||||||
@@ -729,6 +748,7 @@ namespace pipedal
|
|||||||
LV2_PROPERTY_GETSET(uiPortNotifications)
|
LV2_PROPERTY_GETSET(uiPortNotifications)
|
||||||
LV2_PROPERTY_GETSET(modGui)
|
LV2_PROPERTY_GETSET(modGui)
|
||||||
LV2_PROPERTY_GETSET(patchProperties)
|
LV2_PROPERTY_GETSET(patchProperties)
|
||||||
|
LV2_PROPERTY_GETSET_SCALAR(audio_side_chain_inputs)
|
||||||
|
|
||||||
static json_map::storage_type<Lv2PluginUiInfo> jmap;
|
static json_map::storage_type<Lv2PluginUiInfo> jmap;
|
||||||
};
|
};
|
||||||
@@ -772,6 +792,7 @@ namespace pipedal
|
|||||||
AutoLilvNode enumeration_property_uri;
|
AutoLilvNode enumeration_property_uri;
|
||||||
AutoLilvNode core__toggled;
|
AutoLilvNode core__toggled;
|
||||||
AutoLilvNode core__connectionOptional;
|
AutoLilvNode core__connectionOptional;
|
||||||
|
AutoLilvNode core__isSideChain;
|
||||||
AutoLilvNode portprops__not_on_gui_property_uri;
|
AutoLilvNode portprops__not_on_gui_property_uri;
|
||||||
AutoLilvNode portprops__trigger;
|
AutoLilvNode portprops__trigger;
|
||||||
AutoLilvNode midi__event;
|
AutoLilvNode midi__event;
|
||||||
@@ -782,9 +803,9 @@ namespace pipedal
|
|||||||
AutoLilvNode invada_units__unit; // typo in invada plugins.
|
AutoLilvNode invada_units__unit; // typo in invada plugins.
|
||||||
AutoLilvNode invada_portprops__logarithmic; // typo in invada plugins.
|
AutoLilvNode invada_portprops__logarithmic; // typo in invada plugins.
|
||||||
|
|
||||||
|
|
||||||
AutoLilvNode atom__bufferType;
|
AutoLilvNode atom__bufferType;
|
||||||
AutoLilvNode atom__Path;
|
AutoLilvNode atom__Path;
|
||||||
|
AutoLilvNode atom__String;
|
||||||
AutoLilvNode presets__preset;
|
AutoLilvNode presets__preset;
|
||||||
AutoLilvNode state__state;
|
AutoLilvNode state__state;
|
||||||
AutoLilvNode rdfs__label;
|
AutoLilvNode rdfs__label;
|
||||||
@@ -816,7 +837,6 @@ namespace pipedal
|
|||||||
AutoLilvNode pipedalUI__width;
|
AutoLilvNode pipedalUI__width;
|
||||||
AutoLilvNode pipedalUI__graphicEq;
|
AutoLilvNode pipedalUI__graphicEq;
|
||||||
|
|
||||||
|
|
||||||
AutoLilvNode pipedalUI__outputPorts;
|
AutoLilvNode pipedalUI__outputPorts;
|
||||||
AutoLilvNode pipedalUI__text;
|
AutoLilvNode pipedalUI__text;
|
||||||
|
|
||||||
@@ -846,7 +866,6 @@ namespace pipedal
|
|||||||
AutoLilvNode patch__readable;
|
AutoLilvNode patch__readable;
|
||||||
AutoLilvNode pipedal_patch__readable;
|
AutoLilvNode pipedal_patch__readable;
|
||||||
|
|
||||||
|
|
||||||
AutoLilvNode mod__brand;
|
AutoLilvNode mod__brand;
|
||||||
AutoLilvNode mod__label;
|
AutoLilvNode mod__label;
|
||||||
AutoLilvNode mod__preferMomentaryOffByDefault;
|
AutoLilvNode mod__preferMomentaryOffByDefault;
|
||||||
@@ -861,11 +880,9 @@ namespace pipedal
|
|||||||
AutoLilvNode buf_size__maxBlockLength;
|
AutoLilvNode buf_size__maxBlockLength;
|
||||||
AutoLilvNode buf_size__fixedBlockLength;
|
AutoLilvNode buf_size__fixedBlockLength;
|
||||||
AutoLilvNode buf_size__coarseBlockLength;
|
AutoLilvNode buf_size__coarseBlockLength;
|
||||||
|
AutoLilvNode port_groups__sideChainOf;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
LilvUris* lilvUris = nullptr;
|
LilvUris *lilvUris = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool vst3Enabled = true;
|
bool vst3Enabled = true;
|
||||||
@@ -896,7 +913,7 @@ namespace pipedal
|
|||||||
void free_world();
|
void free_world();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Lv2PluginInfo>> plugins_;
|
std::vector<std::shared_ptr<Lv2PluginInfo>> plugins_;
|
||||||
std::map<std::string,std::shared_ptr<Lv2PluginInfo>> pluginsByUri;
|
std::map<std::string, std::shared_ptr<Lv2PluginInfo>> pluginsByUri;
|
||||||
std::vector<Lv2PluginUiInfo> ui_plugins_;
|
std::vector<Lv2PluginUiInfo> ui_plugins_;
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<Lv2PluginClass>> classesMap;
|
std::map<std::string, std::shared_ptr<Lv2PluginClass>> classesMap;
|
||||||
@@ -947,22 +964,19 @@ namespace pipedal
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
virtual MapFeature &GetMapFeature() override { return this->mapFeature; }
|
virtual MapFeature &GetMapFeature() override { return this->mapFeature; }
|
||||||
void CheckForResourceInitialization(const std::string& pluginUri,const std::filesystem::path& pluginUploadDirectory);
|
void CheckForResourceInitialization(const std::string &pluginUri, const std::filesystem::path &pluginUploadDirectory);
|
||||||
|
|
||||||
|
std::string MapResourcePath(const std::string &uri, const std::string &relativePath);
|
||||||
|
|
||||||
std::string MapResourcePath(const std::string&uri, const std::string&relativePath);
|
|
||||||
|
|
||||||
void ReloadPlugins();
|
void ReloadPlugins();
|
||||||
|
|
||||||
// equivalent to LV2 MapPath AbstractPath features.
|
// equivalent to LV2 MapPath AbstractPath features.
|
||||||
std::string MapPath(const std::string &abstractPath);
|
std::string MapPath(const std::string &abstractPath);
|
||||||
std::string AbstractPath(const std::string&path);
|
std::string AbstractPath(const std::string &path);
|
||||||
json_variant MapPath(const json_variant&json);
|
json_variant MapPath(const json_variant &json);
|
||||||
json_variant AbstractPath(const json_variant&json);
|
json_variant AbstractPath(const json_variant &json);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::set<std::string> pluginsThatHaveBeenCheckedForResources;
|
std::set<std::string> pluginsThatHaveBeenCheckedForResources;
|
||||||
|
|
||||||
void CheckForResourceInitization(const std::string pluginUri);
|
void CheckForResourceInitization(const std::string pluginUri);
|
||||||
@@ -973,12 +987,11 @@ namespace pipedal
|
|||||||
}
|
}
|
||||||
static void PortValueCallback(const char *symbol, void *user_data, const void *value, uint32_t size, uint32_t type);
|
static void PortValueCallback(const char *symbol, void *user_data, const void *value, uint32_t size, uint32_t type);
|
||||||
static void StateRestoreCallback(
|
static void StateRestoreCallback(
|
||||||
const char* port_symbol,
|
const char *port_symbol,
|
||||||
void* user_data,
|
void *user_data,
|
||||||
const void* value,
|
const void *value,
|
||||||
uint32_t size,
|
uint32_t size,
|
||||||
uint32_t type);
|
uint32_t type);
|
||||||
|
|
||||||
|
|
||||||
virtual IEffect *CreateEffect(PedalboardItem &pedalboardItem);
|
virtual IEffect *CreateEffect(PedalboardItem &pedalboardItem);
|
||||||
void LoadPluginClassesFromLilv();
|
void LoadPluginClassesFromLilv();
|
||||||
@@ -995,9 +1008,9 @@ namespace pipedal
|
|||||||
|
|
||||||
IHost *asIHost() { return this; }
|
IHost *asIHost() { return this; }
|
||||||
|
|
||||||
virtual Lv2Pedalboard *CreateLv2Pedalboard(Pedalboard &pedalboard,Lv2PedalboardErrorList &errorList);
|
virtual Lv2Pedalboard *CreateLv2Pedalboard(Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList);
|
||||||
|
|
||||||
virtual Lv2Pedalboard *UpdateLv2PedalboardStructure(Pedalboard &pedalboard,Lv2Pedalboard *existingPedalboard,Lv2PedalboardErrorList &errorList);
|
virtual Lv2Pedalboard *UpdateLv2PedalboardStructure(Pedalboard &pedalboard, Lv2Pedalboard *existingPedalboard, Lv2PedalboardErrorList &errorList);
|
||||||
|
|
||||||
void setSampleRate(double sampleRate)
|
void setSampleRate(double sampleRate)
|
||||||
{
|
{
|
||||||
@@ -1010,9 +1023,8 @@ namespace pipedal
|
|||||||
|
|
||||||
class Urids;
|
class Urids;
|
||||||
|
|
||||||
Urids *urids = nullptr;
|
Urids *urids = nullptr;
|
||||||
ModGuiUris* mod_gui_uris = nullptr;
|
ModGuiUris *mod_gui_uris = nullptr;
|
||||||
|
|
||||||
|
|
||||||
void OnConfigurationChanged(const JackConfiguration &configuration, const JackChannelSelection &settings);
|
void OnConfigurationChanged(const JackConfiguration &configuration, const JackChannelSelection &settings);
|
||||||
|
|
||||||
@@ -1021,7 +1033,7 @@ namespace pipedal
|
|||||||
|
|
||||||
std::shared_ptr<Lv2PluginClass> GetLv2PluginClass() const;
|
std::shared_ptr<Lv2PluginClass> GetLv2PluginClass() const;
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<Lv2PluginInfo>>& GetPlugins() const { return plugins_; }
|
const std::vector<std::shared_ptr<Lv2PluginInfo>> &GetPlugins() const { return plugins_; }
|
||||||
const std::vector<Lv2PluginUiInfo> &GetUiPlugins() const { return ui_plugins_; }
|
const std::vector<Lv2PluginUiInfo> &GetUiPlugins() const { return ui_plugins_; }
|
||||||
|
|
||||||
virtual std::shared_ptr<Lv2PluginInfo> GetPluginInfo(const std::string &uri) const;
|
virtual std::shared_ptr<Lv2PluginInfo> GetPluginInfo(const std::string &uri) const;
|
||||||
|
|||||||
+14
-2
@@ -1717,7 +1717,7 @@ void Storage::ToAbstractPaths(PluginPreset &pluginPreset)
|
|||||||
std::map<std::string, std::string> newPathProperties;
|
std::map<std::string, std::string> newPathProperties;
|
||||||
for (const auto &pair : pluginPreset.pathProperties_)
|
for (const auto &pair : pluginPreset.pathProperties_)
|
||||||
{
|
{
|
||||||
newPathProperties[pair.first] = this->ToAbstractPathJson(pair.second);
|
newPathProperties[pair.first] = this->ToAbstractPathFromJson(pair.second);
|
||||||
}
|
}
|
||||||
pluginPreset.pathProperties_ = newPathProperties;
|
pluginPreset.pathProperties_ = newPathProperties;
|
||||||
}
|
}
|
||||||
@@ -2999,7 +2999,19 @@ std::string Storage::GetTone3000Auth() const
|
|||||||
return tone3000Auth;
|
return tone3000Auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Storage::ToAbstractPathJson(const std::string &pathJson)
|
std::filesystem::path Storage::FromAbstractPathString(const std::string &stringPath)
|
||||||
|
{
|
||||||
|
if (stringPath.empty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
fs::path path { stringPath};
|
||||||
|
if (path.is_absolute()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
return GetPluginUploadDirectory() / path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Storage::ToAbstractPathFromJson(const std::string &pathJson)
|
||||||
{
|
{
|
||||||
json_variant v = json_variant::parse(pathJson);
|
json_variant v = json_variant::parse(pathJson);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -129,8 +129,9 @@ public:
|
|||||||
|
|
||||||
const std::filesystem::path &GetPluginUploadDirectory() const;
|
const std::filesystem::path &GetPluginUploadDirectory() const;
|
||||||
|
|
||||||
std::string ToAbstractPathJson(const std::string &jsonAtomPath);
|
std::string ToAbstractPathFromJson(const std::string &jsonAtomPath);
|
||||||
std::string FromAbstractPathJson(const std::string &jsonAtomPath);
|
std::string FromAbstractPathJson(const std::string &jsonAtomPath);
|
||||||
|
std::filesystem::path FromAbstractPathString(const std::string &stringPath);
|
||||||
|
|
||||||
|
|
||||||
//std::vector<std::string> GetPedalboards();
|
//std::vector<std::string> GetPedalboards();
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ public:
|
|||||||
|
|
||||||
res.set(HttpField::content_type, "application/json");
|
res.set(HttpField::content_type, "application/json");
|
||||||
res.set(HttpField::cache_control, "no-cache");
|
res.set(HttpField::cache_control, "no-cache");
|
||||||
fs::path path = model->GetStorage().FromAbstractPathJson(request_uri.query("path"));
|
fs::path path = model->GetStorage().FromAbstractPathString(request_uri.query("path"));
|
||||||
|
|
||||||
if (!fs::exists(path) || !this->model->IsInUploadsDirectory(path) || HasDotDot(path))
|
if (!fs::exists(path) || !this->model->IsInUploadsDirectory(path) || HasDotDot(path))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export class Port implements Deserializable<Port> {
|
|||||||
this.scale_points = ScalePoint.deserialize_array(input.scale_points);
|
this.scale_points = ScalePoint.deserialize_array(input.scale_points);
|
||||||
this.is_input = input.is_input;
|
this.is_input = input.is_input;
|
||||||
this.is_output = input.is_output;
|
this.is_output = input.is_output;
|
||||||
|
this.is_sidechain = input.is_sidechain;
|
||||||
this.is_control_port = input.is_control_port;
|
this.is_control_port = input.is_control_port;
|
||||||
this.is_audio_port = input.is_audio_port;
|
this.is_audio_port = input.is_audio_port;
|
||||||
this.is_atom_port = input.is_atom_port;
|
this.is_atom_port = input.is_atom_port;
|
||||||
@@ -80,6 +81,7 @@ export class Port implements Deserializable<Port> {
|
|||||||
is_output: boolean = false
|
is_output: boolean = false
|
||||||
is_control_port: boolean = false;
|
is_control_port: boolean = false;
|
||||||
is_audio_port: boolean = false;
|
is_audio_port: boolean = false;
|
||||||
|
is_sidechain: boolean = false;
|
||||||
is_atom_port: boolean = false;
|
is_atom_port: boolean = false;
|
||||||
is_valid: boolean = false;
|
is_valid: boolean = false;
|
||||||
supports_midi: boolean = false;
|
supports_midi: boolean = false;
|
||||||
@@ -92,9 +94,11 @@ export class Port implements Deserializable<Port> {
|
|||||||
|
|
||||||
export class PortGroup {
|
export class PortGroup {
|
||||||
deserialize(input: any): PortGroup {
|
deserialize(input: any): PortGroup {
|
||||||
|
this.isA = input.isA;
|
||||||
this.uri = input.uri;
|
this.uri = input.uri;
|
||||||
this.symbol = input.symbol;
|
this.symbol = input.symbol;
|
||||||
this.name = input.name;
|
this.name = input.name;
|
||||||
|
this.sideChainof = input.sideChainOf;
|
||||||
this.parent_group = input.parent_group;
|
this.parent_group = input.parent_group;
|
||||||
this.program_list_id = input.program_list_id ?? -1;
|
this.program_list_id = input.program_list_id ?? -1;
|
||||||
|
|
||||||
@@ -108,9 +112,12 @@ export class PortGroup {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isA: string[] = [];
|
||||||
uri: string = "";
|
uri: string = "";
|
||||||
symbol: string = "";
|
symbol: string = "";
|
||||||
name: string = "";
|
name: string = "";
|
||||||
|
sideChainof: string = "";
|
||||||
|
|
||||||
parent_group: string = "";
|
parent_group: string = "";
|
||||||
program_list_id: number = -1;
|
program_list_id: number = -1;
|
||||||
};
|
};
|
||||||
@@ -967,6 +974,8 @@ export class UiPlugin implements Deserializable<UiPlugin> {
|
|||||||
this.author_name = input.author_name;
|
this.author_name = input.author_name;
|
||||||
this.author_homepage = input.author_homepage;
|
this.author_homepage = input.author_homepage;
|
||||||
this.audio_inputs = input.audio_inputs;
|
this.audio_inputs = input.audio_inputs;
|
||||||
|
this.audio_side_chain_inputs = input.audio_side_chain_inputs ?? 0;
|
||||||
|
this.audio_side_chain_title = input.audio_side_chain_title ?? "";
|
||||||
this.audio_outputs = input.audio_outputs;
|
this.audio_outputs = input.audio_outputs;
|
||||||
this.has_midi_input = input.has_midi_input;
|
this.has_midi_input = input.has_midi_input;
|
||||||
this.has_midi_output = input.has_midi_output;
|
this.has_midi_output = input.has_midi_output;
|
||||||
@@ -1057,7 +1066,9 @@ export class UiPlugin implements Deserializable<UiPlugin> {
|
|||||||
author_name: string = "";
|
author_name: string = "";
|
||||||
author_homepage: string = "";
|
author_homepage: string = "";
|
||||||
audio_inputs: number = 0;
|
audio_inputs: number = 0;
|
||||||
|
audio_side_chain_inputs: number = 0;
|
||||||
audio_outputs: number = 0;
|
audio_outputs: number = 0;
|
||||||
|
audio_side_chain_title: string = "";
|
||||||
has_midi_input: number = 0;
|
has_midi_input: number = 0;
|
||||||
has_midi_output: number = 0;
|
has_midi_output: number = 0;
|
||||||
description: string = "";
|
description: string = "";
|
||||||
@@ -1084,6 +1095,7 @@ export function makeSplitUiPlugin(): UiPlugin {
|
|||||||
author_name: "",
|
author_name: "",
|
||||||
author_homepage: "",
|
author_homepage: "",
|
||||||
audio_inputs: 1,
|
audio_inputs: 1,
|
||||||
|
audio_side_chain_inputs: 0,
|
||||||
audio_outputs: 1,
|
audio_outputs: 1,
|
||||||
has_midi_input: 0,
|
has_midi_input: 0,
|
||||||
has_midi_output: 0,
|
has_midi_output: 0,
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
|
|||||||
this.pathProperties = input.pathProperties;
|
this.pathProperties = input.pathProperties;
|
||||||
this.useModUi = input.useModUi ?? false;
|
this.useModUi = input.useModUi ?? false;
|
||||||
this.iconColor = input.iconColor??"";
|
this.iconColor = input.iconColor??"";
|
||||||
|
this.sideChainInputId = input.sideChainInputId ?? -1;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -217,6 +218,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
|
|||||||
pathProperties: {[Name: string]: string} = {};
|
pathProperties: {[Name: string]: string} = {};
|
||||||
useModUi: boolean = false; // true if this item should use the mod-ui.
|
useModUi: boolean = false; // true if this item should use the mod-ui.
|
||||||
iconColor: string = "";
|
iconColor: string = "";
|
||||||
|
sideChainInputId: number = -1; // -1 means no sidechain input.
|
||||||
};
|
};
|
||||||
|
|
||||||
export class SnapshotValue {
|
export class SnapshotValue {
|
||||||
|
|||||||
@@ -550,19 +550,16 @@ export class PiPedalModel //implements PiPedalModel
|
|||||||
);
|
);
|
||||||
zoomedUiControl: ObservableProperty<ZoomedControlInfo | undefined> = new ObservableProperty<ZoomedControlInfo | undefined>(undefined);
|
zoomedUiControl: ObservableProperty<ZoomedControlInfo | undefined> = new ObservableProperty<ZoomedControlInfo | undefined>(undefined);
|
||||||
|
|
||||||
|
uiPluginsByUri: Map<string, UiPlugin> = new Map<string, UiPlugin>();
|
||||||
|
|
||||||
svgImgUrl(svgImage: string): string {
|
svgImgUrl(svgImage: string): string {
|
||||||
//return this.varServerUrl + "img/" + svgImage;
|
// return this.varServerUrl + "img/" + svgImage;
|
||||||
return "img/" + svgImage;
|
return "img/" + svgImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getUiPlugin(uri: string): UiPlugin | null {
|
getUiPlugin(uri: string): UiPlugin | null {
|
||||||
let plugins: UiPlugin[] = this.ui_plugins.get();
|
return this.uiPluginsByUri.get(uri) ?? null;
|
||||||
|
|
||||||
for (let plugin of plugins) {
|
|
||||||
if (plugin.uri === uri) return plugin;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
androidHost?: AndroidHostInterface;
|
androidHost?: AndroidHostInterface;
|
||||||
@@ -1210,6 +1207,11 @@ export class PiPedalModel //implements PiPedalModel
|
|||||||
this.ui_plugins.set(
|
this.ui_plugins.set(
|
||||||
UiPlugin.deserialize_array(await this.getWebSocket().request<any>("plugins"))
|
UiPlugin.deserialize_array(await this.getWebSocket().request<any>("plugins"))
|
||||||
);
|
);
|
||||||
|
// index ui plugins.
|
||||||
|
this.uiPluginsByUri = new Map<string, UiPlugin>();
|
||||||
|
for (let i of this.ui_plugins.get()) {
|
||||||
|
this.uiPluginsByUri.set(i.uri, i);
|
||||||
|
}
|
||||||
this.setModelPedalboard(
|
this.setModelPedalboard(
|
||||||
new Pedalboard().deserialize(
|
new Pedalboard().deserialize(
|
||||||
await this.getWebSocket().request<Pedalboard>("currentPedalboard")
|
await this.getWebSocket().request<Pedalboard>("currentPedalboard")
|
||||||
@@ -3552,6 +3554,20 @@ export class PiPedalModel //implements PiPedalModel
|
|||||||
copyPresetsToBank(bankInstanceId: number, presets: number[]): Promise<number> {
|
copyPresetsToBank(bankInstanceId: number, presets: number[]): Promise<number> {
|
||||||
return nullCast(this.webSocket).request<number>("copyPresetsToBank", {bankInstanceId: bankInstanceId, presets: presets});
|
return nullCast(this.webSocket).request<number>("copyPresetsToBank", {bankInstanceId: bankInstanceId, presets: presets});
|
||||||
}
|
}
|
||||||
|
setPedalboardSideChainInput(instanceId: number, sideChainInputId: number): void {
|
||||||
|
let pedalboard = this.pedalboard.get().clone();
|
||||||
|
let pedalboardItem = pedalboard.getItem(instanceId);
|
||||||
|
if (!pedalboardItem)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pedalboardItem.sideChainInputId = sideChainInputId;
|
||||||
|
pedalboardItem.instanceId = ++pedalboard.nextInstanceId;
|
||||||
|
pedalboard.selectedPlugin = pedalboardItem.instanceId;
|
||||||
|
this.setModelPedalboard(pedalboard);
|
||||||
|
this.updateServerPedalboard();
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let instance: PiPedalModel | undefined = undefined;
|
let instance: PiPedalModel | undefined = undefined;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
} from './Pedalboard';
|
} from './Pedalboard';
|
||||||
import PluginControl from './PluginControl';
|
import PluginControl from './PluginControl';
|
||||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||||
|
import SideChainSelectControl from './SideChainSelectControl';
|
||||||
import VuMeter from './VuMeter';
|
import VuMeter from './VuMeter';
|
||||||
import { nullCast } from './Utility'
|
import { nullCast } from './Utility'
|
||||||
import { PiPedalStateError } from './PiPedalError';
|
import { PiPedalStateError } from './PiPedalError';
|
||||||
@@ -66,6 +67,11 @@ export interface ICustomizationHost {
|
|||||||
isLandscapeGrid(): boolean;
|
isLandscapeGrid(): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SideChainSelectItem {
|
||||||
|
instanceId: number;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
function makeIoPluginInfo(name: string, uri: string): UiPlugin {
|
function makeIoPluginInfo(name: string, uri: string): UiPlugin {
|
||||||
let result = new UiPlugin();
|
let result = new UiPlugin();
|
||||||
result.name = name;
|
result.name = name;
|
||||||
@@ -371,7 +377,7 @@ type PluginControlViewState = {
|
|||||||
|
|
||||||
const PluginControlView =
|
const PluginControlView =
|
||||||
withTheme(withStyles(
|
withTheme(withStyles(
|
||||||
class extends ResizeResponsiveComponent<PluginControlViewProps, PluginControlViewState> implements ICustomizationHost {
|
class extends ResizeResponsiveComponent<PluginControlViewProps, PluginControlViewState> {
|
||||||
model: PiPedalModel;
|
model: PiPedalModel;
|
||||||
|
|
||||||
constructor(props: PluginControlViewProps) {
|
constructor(props: PluginControlViewProps) {
|
||||||
@@ -553,6 +559,68 @@ const PluginControlView =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getSidechainSelectItems(): SideChainSelectItem[] {
|
||||||
|
let myInstanceId = this.props.item.instanceId;
|
||||||
|
|
||||||
|
let items: SideChainSelectItem[] = [];
|
||||||
|
items.push({ instanceId: -1, title: "None" });
|
||||||
|
items.push({ instanceId: -2, title: "Input" });
|
||||||
|
|
||||||
|
let pedalboard = this.model.pedalboard.get();
|
||||||
|
if (!pedalboard) return items;
|
||||||
|
|
||||||
|
let it = pedalboard.itemsGenerator();
|
||||||
|
|
||||||
|
let found = false;
|
||||||
|
while (true) {
|
||||||
|
let v = it.next();
|
||||||
|
if (v.done) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let pedalboardItem = v.value;
|
||||||
|
if (pedalboardItem.isSplit()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pedalboardItem.instanceId === myInstanceId) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pedalboardItem.uri.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let pluginInfo = this.model.getUiPlugin(pedalboardItem.uri);
|
||||||
|
if (!pluginInfo) continue;
|
||||||
|
let name = pluginInfo.name;
|
||||||
|
if (pedalboardItem.title.length !== 0) {
|
||||||
|
name = pedalboardItem.title;
|
||||||
|
}
|
||||||
|
items.push({ instanceId: pedalboardItem.instanceId, title: name });
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
return [{ instanceId: -1, title: "None" }];
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeSideChainSelect(uiPlugin: UiPlugin) {
|
||||||
|
let items = this.getSidechainSelectItems();
|
||||||
|
let selectedInstanceId = this.props.item.sideChainInputId;
|
||||||
|
let title = uiPlugin.audio_side_chain_title ? uiPlugin.audio_side_chain_title : "Side chain";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SideChainSelectControl
|
||||||
|
title={title}
|
||||||
|
selectItems={items}
|
||||||
|
selectedInstanceId={selectedInstanceId}
|
||||||
|
onChanged={(instanceId: number) => {
|
||||||
|
this.model.setPedalboardSideChainInput(this.props.item.instanceId, instanceId);
|
||||||
|
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
isLandscapeGrid(): boolean {
|
isLandscapeGrid(): boolean {
|
||||||
return this.state.landscapeGrid;
|
return this.state.landscapeGrid;
|
||||||
}
|
}
|
||||||
@@ -575,7 +643,7 @@ const PluginControlView =
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={key} className={!isLandscapeGrid ? classes.portGroup : classes.portGroupLandscape}
|
<div key={key} className={!isLandscapeGrid ? classes.portGroup : classes.portGroupLandscape}
|
||||||
style={{ borderWidth: (controlGroup.name === "" ? 0: undefined) }}
|
style={{ borderWidth: (controlGroup.name === "" ? 0 : undefined) }}
|
||||||
>
|
>
|
||||||
{controlGroup.name !== "" && (
|
{controlGroup.name !== "" && (
|
||||||
<div className={classes.portGroupTitle}>
|
<div className={classes.portGroupTitle}>
|
||||||
@@ -711,6 +779,11 @@ const PluginControlView =
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (plugin.audio_side_chain_inputs !== 0) {
|
||||||
|
|
||||||
|
result.push(this.makeSideChainSelect(plugin));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Theme } from '@mui/material/styles';
|
import { Theme } from '@mui/material/styles';
|
||||||
import WithStyles from './WithStyles';
|
import WithStyles from './WithStyles';
|
||||||
import {createStyles} from './WithStyles';
|
import { createStyles } from './WithStyles';
|
||||||
|
|
||||||
import { withStyles } from "tss-react/mui";
|
import { withStyles } from "tss-react/mui";
|
||||||
import { UiControl } from './Lv2Plugin';
|
import { UiControl } from './Lv2Plugin';
|
||||||
@@ -47,8 +47,7 @@ const defaultVuColors: VuColor[] = [
|
|||||||
|
|
||||||
function getVuColor(vuColors: VuColor[], levelDb: number): string {
|
function getVuColor(vuColors: VuColor[], levelDb: number): string {
|
||||||
let ix = 0;
|
let ix = 0;
|
||||||
for (let i = 0; i < vuColors.length; ++i)
|
for (let i = 0; i < vuColors.length; ++i) {
|
||||||
{
|
|
||||||
let c = vuColors[i];
|
let c = vuColors[i];
|
||||||
if (levelDb > c.minDb && levelDb <= c.maxDb) {
|
if (levelDb > c.minDb && levelDb <= c.maxDb) {
|
||||||
ix = i;
|
ix = i;
|
||||||
@@ -122,18 +121,18 @@ const styles = (theme: Theme) => createStyles({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
titleSection: css({
|
titleSection: css({
|
||||||
flex: "0 0 auto", alignSelf:"stretch", marginBottom: 8, marginLeft: 0, marginRight: 0
|
flex: "0 0 auto", alignSelf: "stretch", marginBottom: 8, marginLeft: 0, marginRight: 0
|
||||||
}),
|
}),
|
||||||
|
|
||||||
midSection: css({
|
midSection: css({
|
||||||
flex: "1 1 1", display: "flex",flexFlow: "column nowrap",alignContent: "center",justifyContent: "center"
|
flex: "1 1 1", display: "flex", flexFlow: "column nowrap", alignContent: "center", justifyContent: "center"
|
||||||
}),
|
}),
|
||||||
|
|
||||||
editSection: css({
|
editSection: css({
|
||||||
flex: "0 0 28", position: "relative", width: 60, height: 28, minHeight: 28
|
flex: "0 0 28", position: "relative", width: 60, height: 28, minHeight: 28
|
||||||
}),
|
}),
|
||||||
editSectionNoContent: css({
|
editSectionNoContent: css({
|
||||||
flex: "0 0 28", position: "relative", width: 1, height: 28, minHeight: 28
|
flex: "0 0 28", position: "relative", width: 1, height: 28, minHeight: 28
|
||||||
})
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -153,12 +152,12 @@ const PluginOutputControl =
|
|||||||
class extends Component<PluginOutputControlProps, PluginOutputControlState> {
|
class extends Component<PluginOutputControlProps, PluginOutputControlState> {
|
||||||
|
|
||||||
private model: PiPedalModel;
|
private model: PiPedalModel;
|
||||||
private vuRef: React.RefObject<HTMLDivElement|null>;
|
private vuRef: React.RefObject<HTMLDivElement | null>;
|
||||||
private progressRef: React.RefObject<HTMLDivElement|null>;
|
private progressRef: React.RefObject<HTMLDivElement | null>;
|
||||||
private dbVuRef: React.RefObject<HTMLDivElement|null>;
|
private dbVuRef: React.RefObject<HTMLDivElement | null>;
|
||||||
private dbVuTelltaleRef: React.RefObject<HTMLDivElement|null>;
|
private dbVuTelltaleRef: React.RefObject<HTMLDivElement | null>;
|
||||||
private dbVuTextRef: React.RefObject<HTMLDivElement|null>;
|
private dbVuTextRef: React.RefObject<HTMLDivElement | null>;
|
||||||
private lampRef: React.RefObject<HTMLDivElement|null>;
|
private lampRef: React.RefObject<HTMLDivElement | null>;
|
||||||
|
|
||||||
|
|
||||||
constructor(props: PluginOutputControlProps) {
|
constructor(props: PluginOutputControlProps) {
|
||||||
@@ -210,7 +209,7 @@ const PluginOutputControl =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PROGRESS_WIDTH = 40-4;
|
private PROGRESS_WIDTH = 40 - 4;
|
||||||
private VU_HEIGHT = 60 - 4;
|
private VU_HEIGHT = 60 - 4;
|
||||||
private DB_VU_HEIGHT = 60 - 4;
|
private DB_VU_HEIGHT = 60 - 4;
|
||||||
private animationHandle: number | undefined = undefined;
|
private animationHandle: number | undefined = undefined;
|
||||||
@@ -240,26 +239,23 @@ const PluginOutputControl =
|
|||||||
}
|
}
|
||||||
if (this.dbVuTextRef.current) {
|
if (this.dbVuTextRef.current) {
|
||||||
let text: string;
|
let text: string;
|
||||||
if (this.dbVuTelltale <= this.props.uiControl.min_value)
|
if (this.dbVuTelltale <= this.props.uiControl.min_value) {
|
||||||
{
|
|
||||||
text = "-";
|
text = "-";
|
||||||
} else {
|
} else {
|
||||||
if (Math.abs(this.dbVuTelltale) >= 99.5)
|
if (Math.abs(this.dbVuTelltale) >= 99.5) {
|
||||||
{
|
|
||||||
text = Math.round(this.dbVuTelltale).toString();
|
text = Math.round(this.dbVuTelltale).toString();
|
||||||
} else {
|
} else {
|
||||||
text = this.dbVuTelltale.toFixed(1);
|
text = this.dbVuTelltale.toFixed(1);
|
||||||
}
|
}
|
||||||
if (!text.startsWith("-")) {
|
if (!text.startsWith("-")) {
|
||||||
text = '+'+text;
|
text = '+' + text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.lastDbText !== text)
|
if (this.lastDbText !== text) {
|
||||||
{
|
|
||||||
this.lastDbText = text;
|
this.lastDbText = text;
|
||||||
this.dbVuTextRef.current.innerText = text;
|
this.dbVuTextRef.current.innerText = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.animationHandle = undefined;
|
this.animationHandle = undefined;
|
||||||
this.updateDbVuTelltale();
|
this.updateDbVuTelltale();
|
||||||
}
|
}
|
||||||
@@ -322,7 +318,7 @@ const PluginOutputControl =
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (this.vuRef.current) {
|
else if (this.vuRef.current) {
|
||||||
let control = this.props.uiControl;
|
let control = this.props.uiControl;
|
||||||
let range = (value - control.min_value) / (control.max_value - control.min_value);
|
let range = (value - control.min_value) / (control.max_value - control.min_value);
|
||||||
@@ -389,8 +385,7 @@ const PluginOutputControl =
|
|||||||
if (value > control.max_value) {
|
if (value > control.max_value) {
|
||||||
value = control.max_value;
|
value = control.max_value;
|
||||||
}
|
}
|
||||||
if (value < control.min_value)
|
if (value < control.min_value) {
|
||||||
{
|
|
||||||
value = control.min_value;
|
value = control.min_value;
|
||||||
}
|
}
|
||||||
let y = (control.max_value - value) * this.DB_VU_HEIGHT / (control.max_value - control.min_value);
|
let y = (control.max_value - value) * this.DB_VU_HEIGHT / (control.max_value - control.min_value);
|
||||||
@@ -439,13 +434,13 @@ const PluginOutputControl =
|
|||||||
} else if (control.isProgress()) {
|
} else if (control.isProgress()) {
|
||||||
item_width = undefined;
|
item_width = undefined;
|
||||||
return (
|
return (
|
||||||
<div className={classes.controlFrame}
|
<div className={classes.controlFrame}
|
||||||
style={{ width: item_width }}>
|
style={{ width: item_width }}>
|
||||||
{/* TITLE SECTION */}
|
{/* TITLE SECTION */}
|
||||||
<div className={classes.titleSection}
|
<div className={classes.titleSection}
|
||||||
style={{ width: "100%" }}>
|
style={{ width: "100%" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
<ControlTooltip uiControl={control}>
|
||||||
<Typography variant="caption" display="block" style={{
|
<Typography variant="caption" display="block" style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
textAlign: "center"
|
textAlign: "center"
|
||||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||||
@@ -453,15 +448,18 @@ const PluginOutputControl =
|
|||||||
</div>
|
</div>
|
||||||
{/* CONTROL SECTION */}
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
<div className={classes.midSection}
|
<div className={classes.midSection}
|
||||||
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||||
<div style={{ width: this.PROGRESS_WIDTH+2, height: 12, marginLeft: 8, marginRight: 8, background: "#181818", }}>
|
<div style={{ width: this.PROGRESS_WIDTH + 2, height: 12, marginLeft: 8, marginRight: 8, background: "#181818", }}>
|
||||||
<div style={{ height: 8, width: this.PROGRESS_WIDTH, overflow: "hidden", position: "absolute",
|
<div style={{
|
||||||
margin: "1px 1px 1px 1px", background: "#282828" }}>
|
height: 8, width: this.PROGRESS_WIDTH, overflow: "hidden", position: "absolute",
|
||||||
<div ref={this.progressRef} style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute", marginTop: 0, background: "#0C0" }} />
|
margin: "1px 1px 1px 1px", background: "#282828"
|
||||||
<div style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute",
|
}}>
|
||||||
|
<div ref={this.progressRef} style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute", marginTop: 0, background: "#0C0" }} />
|
||||||
|
<div style={{
|
||||||
|
height: 10, width: this.PROGRESS_WIDTH, position: "absolute",
|
||||||
boxShadow: "inset 0px 2px 4px #000D", background: "transparent"
|
boxShadow: "inset 0px 2px 4px #000D", background: "transparent"
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -478,45 +476,48 @@ const PluginOutputControl =
|
|||||||
let vuColors = defaultVuColors;
|
let vuColors = defaultVuColors;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.controlFrame}
|
<div className={classes.controlFrame}
|
||||||
style={{ width: item_width }}>
|
style={{ width: item_width }}>
|
||||||
{/* TITLE SECTION */}
|
{/* TITLE SECTION */}
|
||||||
<div className={classes.titleSection}
|
<div className={classes.titleSection}
|
||||||
style={{ width: "100%" }}>
|
style={{ width: "100%" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
<Typography variant="caption" display="block" style={{
|
||||||
<Typography variant="caption" display="block" style={{
|
width: "100%",
|
||||||
width: "100%",
|
textAlign: "center"
|
||||||
textAlign: "center"
|
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
|
||||||
</ControlTooltip>
|
|
||||||
</div>
|
</div>
|
||||||
{/* CONTROL SECTION */}
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
<div className={classes.midSection}
|
<div className={classes.midSection}
|
||||||
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||||
<div style={{ width: 8, height: this.DB_VU_HEIGHT + 4, background: "#000", }}>
|
<ControlTooltip uiControl={control}>
|
||||||
<div style={{ height: this.DB_VU_HEIGHT, width: 4, overflow: "hidden", position: "absolute", margin: 2 }}>
|
|
||||||
<div style={{ width: 4, height: this.DB_VU_HEIGHT, position: "absolute", left: 0, top: 0 }}>
|
|
||||||
{
|
|
||||||
vuColors.map((vuColor,ix)=>{
|
|
||||||
let top = Math.floor(this.dbVuMap(vuColor.maxDb));
|
|
||||||
let bottom = Math.ceil(this.dbVuMap(vuColor.minDb))+1;
|
|
||||||
|
|
||||||
return (
|
<div style={{ width: 8, height: this.DB_VU_HEIGHT + 4, background: "#000", }}>
|
||||||
<div key={ix}
|
<div style={{ height: this.DB_VU_HEIGHT, width: 4, overflow: "hidden", position: "absolute", margin: 2 }}>
|
||||||
style={{ position: "absolute", width: 4, height: (bottom-top),
|
<div style={{ width: 4, height: this.DB_VU_HEIGHT, position: "absolute", left: 0, top: 0 }}>
|
||||||
top: top, left:0, background: vuColor.color }} />
|
{
|
||||||
);
|
vuColors.map((vuColor, ix) => {
|
||||||
})
|
let top = Math.floor(this.dbVuMap(vuColor.maxDb));
|
||||||
}
|
let bottom = Math.ceil(this.dbVuMap(vuColor.minDb)) + 1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={ix}
|
||||||
|
style={{
|
||||||
|
position: "absolute", width: 4, height: (bottom - top),
|
||||||
|
top: top, left: 0, background: vuColor.color
|
||||||
|
}} />
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ref={this.dbVuRef} style={{
|
||||||
|
width: 4, position: "absolute", marginTop: 0, height: this.VU_HEIGHT, background: "#000"
|
||||||
|
}} />
|
||||||
|
<div ref={this.dbVuTelltaleRef} style={{ width: 4, position: "absolute", marginTop: 100, height: 3, background: "#C00" }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ref={this.dbVuRef} style={{
|
|
||||||
width: 4, position: "absolute", marginTop: 0, height: this.VU_HEIGHT, background: "#000"
|
|
||||||
}} />
|
|
||||||
<div ref={this.dbVuTelltaleRef} style={{ width: 4, position: "absolute", marginTop: 100, height: 3, background: "#C00" }} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ControlTooltip>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.editSection}>
|
<div className={classes.editSection}>
|
||||||
@@ -533,26 +534,28 @@ const PluginOutputControl =
|
|||||||
else if (control.isVu()) {
|
else if (control.isVu()) {
|
||||||
item_width = undefined;
|
item_width = undefined;
|
||||||
return (
|
return (
|
||||||
<div className={classes.controlFrame} style={{ width: item_width}}>
|
<div className={classes.controlFrame} style={{ width: item_width }}>
|
||||||
{/* TITLE SECTION */}
|
{/* TITLE SECTION */}
|
||||||
<div className={classes.titleSection}
|
<div className={classes.titleSection}
|
||||||
style={{ width: "100%" }}>
|
style={{ width: "100%" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
|
||||||
<Typography noWrap display="block" variant="caption" style={{
|
<Typography noWrap display="block" variant="caption" style={{
|
||||||
width: item_width,
|
width: item_width,
|
||||||
textAlign: "center"
|
textAlign: "center"
|
||||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||||
</ControlTooltip>
|
|
||||||
</div>
|
</div>
|
||||||
{/* CONTROL SECTION */}
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
<div className={classes.midSection}
|
<div className={classes.midSection}
|
||||||
style={{ display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
style={{ display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||||
<div style={{ width: 8, height: this.VU_HEIGHT + 4, background: "#000", }}>
|
<ControlTooltip uiControl={control}>
|
||||||
<div style={{ height: this.VU_HEIGHT, overflow: "hidden", position: "absolute", margin: 2 }}>
|
<div style={{ width: 8, height: this.VU_HEIGHT + 4, background: "#000", }}>
|
||||||
<div ref={this.vuRef} style={{ width: 4, height: this.VU_HEIGHT, background: "#0C0", }} />
|
<div style={{ height: this.VU_HEIGHT, overflow: "hidden", position: "absolute", margin: 2 }}>
|
||||||
|
<div ref={this.vuRef} style={{ width: 4, height: this.VU_HEIGHT, background: "#0C0", }} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ControlTooltip>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -575,11 +578,11 @@ const PluginOutputControl =
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={classes.controlFrame}
|
<div className={classes.controlFrame}
|
||||||
style={{width: attachedLamp? 15: item_width}}
|
style={{ width: attachedLamp ? 15 : item_width }}
|
||||||
>
|
>
|
||||||
{/* TITLE SECTION */}
|
{/* TITLE SECTION */}
|
||||||
<div className={classes.titleSection}
|
<div className={classes.titleSection}
|
||||||
style={{ flex: "0 0 auto", width: "100%"}}>
|
style={{ flex: "0 0 auto", width: "100%" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
<ControlTooltip uiControl={control}>
|
||||||
<Typography noWrap variant="caption" display="block" style={{
|
<Typography noWrap variant="caption" display="block" style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@@ -589,7 +592,7 @@ const PluginOutputControl =
|
|||||||
</div>
|
</div>
|
||||||
{/* CONTROL SECTION */}
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
<div className={classes.midSection}
|
<div className={classes.midSection}
|
||||||
style={{
|
style={{
|
||||||
display: "flex", justifyContent: "center", alignItems: "center", flexFlow: "row nowrap",
|
display: "flex", justifyContent: "center", alignItems: "center", flexFlow: "row nowrap",
|
||||||
}}>
|
}}>
|
||||||
@@ -613,23 +616,23 @@ const PluginOutputControl =
|
|||||||
);
|
);
|
||||||
} if (control.isOutputText()) {
|
} if (control.isOutputText()) {
|
||||||
return (
|
return (
|
||||||
<div className={classes.controlFrame}
|
<div className={classes.controlFrame}
|
||||||
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
||||||
{/* TITLE SECTION */}
|
{/* TITLE SECTION */}
|
||||||
<div className={classes.titleSection}
|
<div className={classes.titleSection}
|
||||||
style={{ flex: "0 0 auto", width: "100%" }}>
|
style={{ flex: "0 0 auto", width: "100%" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
<ControlTooltip uiControl={control}>
|
||||||
<Typography noWrap variant="caption" display="block" style={{
|
<Typography noWrap variant="caption" display="block" style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
textAlign: "left"
|
textAlign: "left"
|
||||||
}}> {control.name === "" ? "\u00A0": control.name}</Typography>
|
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||||
</ControlTooltip>
|
</ControlTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CONTROL SECTION */}
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
<div className={classes.midSection} style={{
|
<div className={classes.midSection} style={{
|
||||||
display: "flex", justifyContent: "center",
|
display: "flex", justifyContent: "center",
|
||||||
flexFlow: "row nowrap", paddingTop: 6
|
flexFlow: "row nowrap", paddingTop: 6
|
||||||
|
|
||||||
}}>
|
}}>
|
||||||
@@ -646,10 +649,10 @@ const PluginOutputControl =
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className={classes.controlFrame}
|
<div className={classes.controlFrame}
|
||||||
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
||||||
{/* TITLE SECTION */}
|
{/* TITLE SECTION */}
|
||||||
<div className={classes.titleSection}
|
<div className={classes.titleSection}
|
||||||
style={{ flex: "0 0 auto", width: "100%" }}>
|
style={{ flex: "0 0 auto", width: "100%" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
<ControlTooltip uiControl={control}>
|
||||||
<Typography noWrap variant="caption" display="block" style={{
|
<Typography noWrap variant="caption" display="block" style={{
|
||||||
@@ -660,7 +663,7 @@ const PluginOutputControl =
|
|||||||
</div>
|
</div>
|
||||||
{/* CONTROL SECTION */}
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
<div className={classes.midSection}
|
<div className={classes.midSection}
|
||||||
style={{ display: "flex", justifyContent: "start", alignItems: "center", flexFlow: "row nowrap" }}>
|
style={{ display: "flex", justifyContent: "start", alignItems: "center", flexFlow: "row nowrap" }}>
|
||||||
<Typography noWrap variant="caption" display="block" style={{ width: "100%" }}>
|
<Typography noWrap variant="caption" display="block" style={{ width: "100%" }}>
|
||||||
{text}
|
{text}
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) Robin E. R. Davies
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
* so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component } from 'react';
|
||||||
|
import { Theme } from '@mui/material/styles';
|
||||||
|
import { css } from '@emotion/react';
|
||||||
|
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel';
|
||||||
|
import Select from '@mui/material/Select';
|
||||||
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
|
||||||
|
|
||||||
|
export const StandardItemSize = { width: 80, height: 140 }
|
||||||
|
|
||||||
|
|
||||||
|
import { withStyles } from "tss-react/mui";
|
||||||
|
import WithStyles from './WithStyles';
|
||||||
|
import { withTheme } from './WithStyles';
|
||||||
|
|
||||||
|
const styles = (theme: Theme) => {
|
||||||
|
return {
|
||||||
|
frame: css({
|
||||||
|
position: "relative",
|
||||||
|
margin: "12px"
|
||||||
|
}),
|
||||||
|
controlFrame: css({
|
||||||
|
display: "flex", flexDirection: "column", alignItems: "start", justifyContent: "space-between", height: 116
|
||||||
|
}),
|
||||||
|
displayValue: css({
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 4,
|
||||||
|
textAlign: "center",
|
||||||
|
background: theme.mainBackground,
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
// zIndex: -1,
|
||||||
|
}),
|
||||||
|
titleSection: css({
|
||||||
|
flex: "0 0 auto", alignSelf: "stretch", marginBottom: 8, marginLeft: 8, marginRight: 0
|
||||||
|
}),
|
||||||
|
midSection: css({
|
||||||
|
flex: "1 1 1", display: "flex", flexFlow: "column nowrap", alignContent: "center", justifyContent: "center"
|
||||||
|
}),
|
||||||
|
editSection: css({
|
||||||
|
flex: "0 0 0", position: "relative", width: 60, height: 28, minHeight: 28
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
export interface SideChainSelectControlProps extends WithStyles<typeof styles> {
|
||||||
|
title: string;
|
||||||
|
selectItems: { instanceId: number, title: string }[];
|
||||||
|
selectedInstanceId: number;
|
||||||
|
onChanged(instanceId: number): void;
|
||||||
|
theme: Theme;
|
||||||
|
}
|
||||||
|
type SideChainSelectControlState = {
|
||||||
|
};
|
||||||
|
|
||||||
|
const SideChainSelectControl =
|
||||||
|
withTheme(withStyles(
|
||||||
|
class extends Component<SideChainSelectControlProps, SideChainSelectControlState> {
|
||||||
|
|
||||||
|
model: PiPedalModel;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(props: SideChainSelectControlProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
};
|
||||||
|
this.model = PiPedalModelFactory.getInstance();
|
||||||
|
this.onStateChanged = this.onStateChanged.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onStateChanged(state: State) {
|
||||||
|
}
|
||||||
|
mounted: boolean = false;
|
||||||
|
componentDidMount() {
|
||||||
|
this.model.state.addOnChangedHandler(this.onStateChanged);
|
||||||
|
this.mounted = true;
|
||||||
|
}
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.mounted = false;
|
||||||
|
this.model.state.removeOnChangedHandler(this.onStateChanged);
|
||||||
|
}
|
||||||
|
componentDidUpdate(prevProps: Readonly<SideChainSelectControlProps>, prevState: Readonly<SideChainSelectControlState>, snapshot?: any): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
//const classes = withStyles.getClasses(this.props);
|
||||||
|
|
||||||
|
const classes = withStyles.getClasses(this.props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.controlFrame}
|
||||||
|
style={{ width: 120 }}>
|
||||||
|
{/* TITLE SECTION */}
|
||||||
|
<div className={classes.titleSection}
|
||||||
|
>
|
||||||
|
<Typography variant="caption" display="block" noWrap style={{
|
||||||
|
width: "100%",
|
||||||
|
textAlign: "start"
|
||||||
|
}}> {this.props.title}</Typography>
|
||||||
|
</div>
|
||||||
|
{/* CONTROL SECTION */}
|
||||||
|
|
||||||
|
<div className={classes.midSection} style={{ width: "100%", paddingLeft: 8 }}>
|
||||||
|
<Select
|
||||||
|
variant="standard"
|
||||||
|
onChange={(event) => {
|
||||||
|
this.props.onChanged(event.target.value as number);
|
||||||
|
}}
|
||||||
|
value={this.props.selectedInstanceId}
|
||||||
|
style={{ width: "100%", fontSize: "0.8rem" }}
|
||||||
|
>
|
||||||
|
{this.props.selectItems.map((item) => {
|
||||||
|
return (
|
||||||
|
<MenuItem key={item.instanceId} value={item.instanceId}
|
||||||
|
selected={item.instanceId === this.props.selectedInstanceId}>
|
||||||
|
{item.title}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* LABEL/EDIT SECTION*/}
|
||||||
|
<div className={classes.editSection} >
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, styles)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
export default SideChainSelectControl;
|
||||||
Reference in New Issue
Block a user