groups in MIDI bindings and info dialog. Momentary swtiches, Progress ctl,, TooB Looper and Record plugins.
This commit is contained in:
+1
-1
@@ -867,6 +867,7 @@ private:
|
||||
pEffect->RequestAllPathPatchProperties();
|
||||
}
|
||||
}
|
||||
realtimeActivePedalboard->UpdateAudioPorts();
|
||||
}
|
||||
reEntered = false;
|
||||
|
||||
@@ -1696,7 +1697,6 @@ public:
|
||||
{
|
||||
if (pPedalboard)
|
||||
{
|
||||
pPedalboard->Deactivate();
|
||||
std::lock_guard guard(mutex);
|
||||
|
||||
for (auto it = activePedalboards.begin(); it != activePedalboards.end(); ++it)
|
||||
|
||||
+4
-2
@@ -724,7 +724,8 @@ void SetVarPermissions(
|
||||
|
||||
if (chown(entry.path().c_str(), uid, gid) != 0)
|
||||
{
|
||||
std::cout << "Error: failed to set ownership of file " << entry.path() << std::endl;
|
||||
// Expect spurious pulse config files to be un-chown-able.
|
||||
// std::cout << "Error: failed to set ownership of file " << entry.path() << std::endl;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -740,7 +741,8 @@ void SetVarPermissions(
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cout << "Error: failed to set permissions on file " << entry.path() << std::endl;
|
||||
// spurious errors on pulse config files.
|
||||
// std::cout << "Error: failed to set permissions on file " << entry.path() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-11
@@ -353,7 +353,6 @@ void Lv2Effect::PreparePortIndices()
|
||||
{
|
||||
this->isInputTriggerControlPort[portIndex] = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -402,6 +401,13 @@ void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
|
||||
{
|
||||
this->inputAudioBuffers[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 (inputAudioPortIndices.size() == inputAudioBuffers.size())
|
||||
{
|
||||
int pluginIndex = this->inputAudioPortIndices[index];
|
||||
@@ -409,12 +415,13 @@ void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
|
||||
}
|
||||
else
|
||||
{
|
||||
// cases: 1->0, 1->1, 2->0, 2->1
|
||||
if (index < inputAudioPortIndices.size())
|
||||
{
|
||||
int pluginIndex = this->inputAudioPortIndices[index];
|
||||
lilv_instance_connect_port(this->pInstance, pluginIndex, buffer);
|
||||
}
|
||||
throw std::runtime_error("Invalid input buffer index.");
|
||||
// // cases: 1->0, 1->1, 2->0, 2->1
|
||||
// if (index < inputAudioPortIndices.size())
|
||||
// {
|
||||
// int pluginIndex = this->inputAudioPortIndices[index];
|
||||
// lilv_instance_connect_port(this->pInstance, pluginIndex, buffer);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +432,7 @@ void Lv2Effect::SetAudioInputBuffer(float *left)
|
||||
SetAudioInputBuffer(0, left);
|
||||
SetAudioInputBuffer(1, left);
|
||||
}
|
||||
else if (GetNumberOfInputAudioBuffers() != 0)
|
||||
else if (GetNumberOfInputAudioBuffers() != 0)
|
||||
{
|
||||
SetAudioInputBuffer(0, left);
|
||||
}
|
||||
@@ -448,6 +455,13 @@ void Lv2Effect::SetAudioOutputBuffer(int index, float *buffer)
|
||||
{
|
||||
this->outputAudioBuffers[index] = buffer;
|
||||
|
||||
if (borrowedEffect)
|
||||
{
|
||||
// Effect is already running on the realtime thread,
|
||||
// so don't update the audio ports until the updated pedalboard gets placed on the realtime thread.
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->inputAudioPortIndices.size() != 0) // i.e. we're not mixing a zero-input control
|
||||
{
|
||||
if ((size_t)index < this->inputAudioPortIndices.size())
|
||||
@@ -470,6 +484,10 @@ int Lv2Effect::GetControlIndex(const std::string &key) const
|
||||
|
||||
Lv2Effect::~Lv2Effect()
|
||||
{
|
||||
if (activated)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
if (worker)
|
||||
{
|
||||
worker->Close();
|
||||
@@ -489,11 +507,40 @@ Lv2Effect::~Lv2Effect()
|
||||
|
||||
void Lv2Effect::Activate()
|
||||
{
|
||||
if (this->activated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->activated = true;
|
||||
this->AssignUnconnectedPorts();
|
||||
lilv_instance_activate(pInstance);
|
||||
this->BypassTo(this->bypass ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
void Lv2Effect::UpdateAudioPorts()
|
||||
{
|
||||
// called on realtime thread to switch borrowed effects to the new buffer pointers.
|
||||
if (borrowedEffect)
|
||||
{
|
||||
for (size_t i = 0; i < this->inputAudioPortIndices.size(); ++i)
|
||||
{
|
||||
int portIndex = this->inputAudioPortIndices[i];
|
||||
if (GetAudioInputBuffer(i) != nullptr)
|
||||
{
|
||||
lilv_instance_connect_port(pInstance, portIndex, GetAudioInputBuffer(i));
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < this->outputAudioPortIndices.size(); ++i)
|
||||
{
|
||||
int portIndex = this->outputAudioPortIndices[i];
|
||||
if (GetAudioOutputBuffer(i) != nullptr)
|
||||
{
|
||||
lilv_instance_connect_port(pInstance, portIndex, GetAudioOutputBuffer(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lv2Effect::AssignUnconnectedPorts()
|
||||
{
|
||||
for (size_t i = 0; i < this->inputAudioPortIndices.size(); ++i)
|
||||
@@ -545,6 +592,11 @@ void Lv2Effect::AssignUnconnectedPorts()
|
||||
}
|
||||
void Lv2Effect::Deactivate()
|
||||
{
|
||||
if (!activated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
activated = false;
|
||||
if (worker)
|
||||
{
|
||||
worker->Close();
|
||||
@@ -591,15 +643,18 @@ void Lv2Effect::Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBuff
|
||||
for (size_t i = 0; i < this->outputMixBuffers.size(); ++i)
|
||||
{
|
||||
float *__restrict input;
|
||||
if (i >= this->inputAudioBuffers.size()) {
|
||||
if (i >= this->inputAudioBuffers.size())
|
||||
{
|
||||
if (this->inputAudioBuffers.size() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
input = this->inputAudioBuffers[0];
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
input = this->inputAudioBuffers[i];
|
||||
}
|
||||
}
|
||||
float *__restrict pluginOutput = this->outputMixBuffers[i].data();
|
||||
float *__restrict finalOutput = this->outputAudioBuffers[i];
|
||||
|
||||
|
||||
+6
-1
@@ -199,9 +199,14 @@ namespace pipedal
|
||||
int actualAudioOutputs = 0;
|
||||
std::vector<std::vector<float>> outputMixBuffers;
|
||||
void BypassTo(float value);
|
||||
bool borrowedEffect = false;
|
||||
bool activated = false;
|
||||
|
||||
public:
|
||||
|
||||
bool IsBorrowedEffect() const { return borrowedEffect; }
|
||||
void SetBorrowedEffect(bool value) { borrowedEffect = value; }
|
||||
void UpdateAudioPorts();
|
||||
|
||||
// non RT-thread use only.
|
||||
std::string GetPathPatchProperty(const std::string&propertyUri);
|
||||
// non RT-thread use only.
|
||||
|
||||
+102
-62
@@ -60,18 +60,20 @@ int Lv2Pedalboard::GetControlIndex(uint64_t instanceId, const std::string &symbo
|
||||
std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
std::vector<PedalboardItem> &items,
|
||||
std::vector<float *> inputBuffers,
|
||||
Lv2PedalboardErrorList &errorList)
|
||||
Lv2PedalboardErrorList &errorList,
|
||||
ExistingEffectMap *existingEffects)
|
||||
{
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
{
|
||||
auto &item = items[i];
|
||||
if (!item.isEmpty())
|
||||
{
|
||||
IEffect *pEffect = nullptr;
|
||||
std::shared_ptr<IEffect> pEffect = nullptr;
|
||||
|
||||
if (item.isSplit())
|
||||
{
|
||||
auto pSplit = new SplitEffect(item.instanceId(), pHost->GetSampleRate(), inputBuffers);
|
||||
pEffect = pSplit;
|
||||
pEffect = std::shared_ptr<IEffect>(pSplit);
|
||||
|
||||
int topInputChannels = inputBuffers.size();
|
||||
int bottomInputChannels = inputBuffers.size();
|
||||
@@ -84,8 +86,8 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
|
||||
this->processActions.push_back(preMixAction);
|
||||
|
||||
std::vector<float *> topResult = PrepareItems(item.topChain(), topInputs, errorList);
|
||||
std::vector<float *> bottomResult = PrepareItems(item.bottomChain(), bottomInputs, errorList);
|
||||
std::vector<float *> topResult = PrepareItems(item.topChain(), topInputs, errorList,existingEffects);
|
||||
std::vector<float *> bottomResult = PrepareItems(item.bottomChain(), bottomInputs, errorList,existingEffects);
|
||||
|
||||
this->processActions.push_back(
|
||||
[pSplit](uint32_t frames)
|
||||
@@ -94,7 +96,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
// if split is L/R, always output stereo.
|
||||
|
||||
bool forceStereo = (controlValue != nullptr && controlValue->value() == 2);
|
||||
pSplit->SetChainBuffers(topInputs, bottomInputs, topResult, bottomResult,forceStereo);
|
||||
pSplit->SetChainBuffers(topInputs, bottomInputs, topResult, bottomResult, forceStereo);
|
||||
|
||||
for (int i = 0; i < item.controlValues().size(); ++i)
|
||||
{
|
||||
@@ -108,31 +110,39 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<IEffect> pLv2Effect;
|
||||
|
||||
IEffect *pLv2Effect = nullptr;
|
||||
try
|
||||
if (existingEffects && existingEffects->contains(item.instanceId()))
|
||||
{
|
||||
pLv2Effect = this->pHost->CreateEffect(item);
|
||||
pLv2Effect = existingEffects->at(item.instanceId());
|
||||
((Lv2Effect*)pLv2Effect.get())->SetBorrowedEffect(true);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
else
|
||||
{
|
||||
Lv2Log::warning(SS(e.what()));
|
||||
}
|
||||
try
|
||||
{
|
||||
pLv2Effect = std::shared_ptr<IEffect>(this->pHost->CreateEffect(item));
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
Lv2Log::warning(SS(e.what()));
|
||||
}
|
||||
|
||||
if (pLv2Effect)
|
||||
{
|
||||
|
||||
if (pLv2Effect->HasErrorMessage())
|
||||
if (pLv2Effect && pLv2Effect->HasErrorMessage())
|
||||
{
|
||||
std::string error = pLv2Effect->TakeErrorMessage();
|
||||
Lv2Log::error(error);
|
||||
errorList.push_back({item.instanceId(), error});
|
||||
}
|
||||
}
|
||||
|
||||
if (pLv2Effect)
|
||||
{
|
||||
|
||||
pEffect = pLv2Effect;
|
||||
|
||||
uint64_t instanceId = pEffect->GetInstanceId();
|
||||
pLv2Effect->PrepareNoInputEffect(inputBuffers.size(),pHost->GetMaxAudioBufferSize());
|
||||
pLv2Effect->PrepareNoInputEffect(inputBuffers.size(), pHost->GetMaxAudioBufferSize());
|
||||
|
||||
if (inputBuffers.size() == 1)
|
||||
{
|
||||
@@ -173,35 +183,34 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
// Reset any trigger controls to default state after processing
|
||||
if (pLv2Effect->IsLv2Effect())
|
||||
{
|
||||
Lv2Effect*lv2Effect = (Lv2Effect*)pLv2Effect;
|
||||
Lv2Effect *lv2Effect = (Lv2Effect *)pLv2Effect.get();
|
||||
auto pluginInfo = pHost->GetPluginInfo(item.uri());
|
||||
if (pluginInfo) {
|
||||
for (auto control: pluginInfo->ports())
|
||||
if (pluginInfo)
|
||||
{
|
||||
for (auto control : pluginInfo->ports())
|
||||
{
|
||||
if (control->trigger_property() && control->is_input() && control->is_control_port())
|
||||
{
|
||||
int controlIndex = lv2Effect->GetControlIndex(control->symbol());
|
||||
if (controlIndex >= 0)
|
||||
if (controlIndex >= 0)
|
||||
{
|
||||
float defaultValue = control->default_value();
|
||||
this->processActions.push_back(
|
||||
[pLv2Effect,controlIndex,defaultValue](int32_t frames) {
|
||||
pLv2Effect->SetControl(controlIndex,defaultValue);
|
||||
}
|
||||
);
|
||||
[pLv2Effect, controlIndex, defaultValue](int32_t frames)
|
||||
{
|
||||
pLv2Effect->SetControl(controlIndex, defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pEffect)
|
||||
{
|
||||
this->effects.push_back(std::shared_ptr<IEffect>(pEffect)); // for ownership.
|
||||
this->realtimeEffects.push_back(pEffect); // because std::shared_ptr is not threadsafe.
|
||||
this->effects.push_back(pEffect); // for ownership.
|
||||
this->realtimeEffects.push_back(pEffect.get()); // because std::shared_ptr is not threadsafe.
|
||||
|
||||
std::vector<float *> effectOutput;
|
||||
|
||||
@@ -214,7 +223,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
effectOutput.push_back(CreateNewAudioBuffer());
|
||||
effectOutput.push_back(CreateNewAudioBuffer());
|
||||
}
|
||||
for (size_t i = 0; i < effectOutput.size(); ++i)
|
||||
for (size_t i = 0; i < effectOutput.size(); ++i)
|
||||
{
|
||||
pEffect->SetAudioOutputBuffer(i, effectOutput[i]);
|
||||
}
|
||||
@@ -225,7 +234,7 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
return inputBuffers;
|
||||
}
|
||||
|
||||
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList)
|
||||
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList, ExistingEffectMap *existingEffects)
|
||||
{
|
||||
this->pHost = pHost;
|
||||
|
||||
@@ -242,7 +251,7 @@ void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardE
|
||||
this->pedalboardInputBuffers.push_back(bufferPool.AllocateBuffer<float>(pHost->GetMaxAudioBufferSize()));
|
||||
}
|
||||
|
||||
auto outputs = PrepareItems(pedalboard.items(), this->pedalboardInputBuffers, errorList);
|
||||
auto outputs = PrepareItems(pedalboard.items(), this->pedalboardInputBuffers, errorList, existingEffects);
|
||||
int nOutputs = pHost->GetNumberOfOutputAudioChannels();
|
||||
if (nOutputs == 1)
|
||||
{
|
||||
@@ -276,7 +285,6 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
|
||||
else
|
||||
{
|
||||
pluginInfo = pHost->GetPluginInfo(pedalboardItem.uri());
|
||||
|
||||
}
|
||||
|
||||
int effectIndex = this->GetIndexOfInstanceId(pedalboardItem.instanceId());
|
||||
@@ -315,10 +323,15 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
|
||||
mapping.midiBinding = binding;
|
||||
mapping.instanceId = pedalboardItem.instanceId();
|
||||
|
||||
if (pPortInfo->trigger_property())
|
||||
if (pPortInfo->mod_momentaryOffByDefault() || pPortInfo->mod_momentaryOnByDefault())
|
||||
{
|
||||
mapping.mappingType = MidiControlType::MomentarySwitch;
|
||||
}
|
||||
else if (pPortInfo->trigger_property())
|
||||
{
|
||||
mapping.mappingType = MidiControlType::Trigger;
|
||||
} else if (pPortInfo->IsSwitch())
|
||||
}
|
||||
else if (pPortInfo->IsSwitch())
|
||||
{
|
||||
mapping.mappingType = MidiControlType::Toggle;
|
||||
}
|
||||
@@ -326,7 +339,7 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
|
||||
{
|
||||
mapping.mappingType = MidiControlType::Select;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
mapping.mappingType = MidiControlType::Dial;
|
||||
}
|
||||
@@ -365,12 +378,25 @@ void Lv2Pedalboard::PrepareMidiMap(const Pedalboard &pedalboard)
|
||||
{
|
||||
auto &item = pedalboard.items()[i];
|
||||
PrepareMidiMap(item);
|
||||
|
||||
}
|
||||
std::sort(this->midiMappings.begin(), this->midiMappings.end(),
|
||||
[](const MidiMapping &left, const MidiMapping &right)
|
||||
{ return left.key < right.key; });
|
||||
[](const MidiMapping &left, const MidiMapping &right)
|
||||
{ return left.key < right.key; });
|
||||
}
|
||||
|
||||
void Lv2Pedalboard::UpdateAudioPorts()
|
||||
{
|
||||
for (int i = 0; i < this->effects.size(); ++i)
|
||||
{
|
||||
IEffect *effect = this->realtimeEffects[i];
|
||||
if (effect->IsLv2Effect())
|
||||
{
|
||||
Lv2Effect *lv2Effect = (Lv2Effect *)effect;
|
||||
lv2Effect->UpdateAudioPorts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lv2Pedalboard::Activate()
|
||||
{
|
||||
for (int i = 0; i < this->effects.size(); ++i)
|
||||
@@ -522,19 +548,18 @@ void Lv2Pedalboard::ResetAtomBuffers()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Lv2Pedalboard::GatherPathPatchProperties(IPatchWriterCallback*cbPatchWriter)
|
||||
void Lv2Pedalboard::GatherPathPatchProperties(IPatchWriterCallback *cbPatchWriter)
|
||||
{
|
||||
for (auto& pEffect : this->effects) {
|
||||
for (auto &pEffect : this->effects)
|
||||
{
|
||||
if (pEffect->IsLv2Effect())
|
||||
{
|
||||
Lv2Effect *pLv2Effect = (Lv2Effect*)pEffect.get();
|
||||
Lv2Effect *pLv2Effect = (Lv2Effect *)pEffect.get();
|
||||
pLv2Effect->GatherPathPatchProperties(cbPatchWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Lv2Pedalboard::ProcessParameterRequests(RealtimePatchPropertyRequest *pParameterRequests)
|
||||
{
|
||||
while (pParameterRequests != nullptr)
|
||||
@@ -572,7 +597,6 @@ void Lv2Pedalboard::ProcessParameterRequests(RealtimePatchPropertyRequest *pPara
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Lv2Pedalboard::GatherPatchProperties(RealtimePatchPropertyRequest *pParameterRequests)
|
||||
{
|
||||
while (pParameterRequests != nullptr)
|
||||
@@ -630,7 +654,7 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
|
||||
if (size < 3)
|
||||
return;
|
||||
index = message[1];
|
||||
value = message[2] == 0? 0: 127; // zero velocity = note off.
|
||||
value = message[2] == 0 ? 0 : 127; // zero velocity = note off.
|
||||
}
|
||||
else if (cmd == 0xB0) // midi control.
|
||||
{
|
||||
@@ -689,22 +713,25 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
|
||||
case MidiControlType::Trigger:
|
||||
{
|
||||
bool triggered = false;
|
||||
if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TRIGGER_ON_RISING_EDGE
|
||||
|| mapping.midiBinding.bindingType() == BINDING_TYPE_NOTE
|
||||
)
|
||||
if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TRIGGER_ON_RISING_EDGE || mapping.midiBinding.bindingType() == BINDING_TYPE_NOTE)
|
||||
{
|
||||
if (mapping.lastValue < range)
|
||||
{
|
||||
if (!mapping.lastValueIncreasing) {
|
||||
if (!mapping.lastValueIncreasing)
|
||||
{
|
||||
triggered = true;
|
||||
}
|
||||
mapping.lastValueIncreasing = true;
|
||||
mapping.lastValue = range;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping.lastValueIncreasing = false;
|
||||
mapping.lastValue = range;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
triggered = true;
|
||||
}
|
||||
if (triggered)
|
||||
@@ -730,12 +757,15 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
|
||||
{
|
||||
if (range > mapping.lastValue)
|
||||
{
|
||||
if (!mapping.lastValueIncreasing) {
|
||||
if (!mapping.lastValueIncreasing)
|
||||
{
|
||||
triggered = true;
|
||||
}
|
||||
mapping.lastValueIncreasing = true;
|
||||
mapping.lastValue = range;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping.lastValueIncreasing = false;
|
||||
mapping.lastValue = range;
|
||||
}
|
||||
@@ -748,30 +778,40 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
|
||||
pEffect->SetControl(mapping.controlIndex, currentValue);
|
||||
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), currentValue);
|
||||
}
|
||||
} else if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TOGGLE_ON_VALUE)
|
||||
}
|
||||
else if (mapping.midiBinding.switchControlType() == SwitchControlTypeT::TOGGLE_ON_VALUE)
|
||||
{
|
||||
triggered = true;
|
||||
mapping.lastValue = range;
|
||||
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
|
||||
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
|
||||
float currentValue = pEffect->GetControlValue(mapping.controlIndex);
|
||||
if (currentValue != range)
|
||||
{
|
||||
pEffect->SetControl(mapping.controlIndex, range);
|
||||
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), range);
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// any control value toggles.
|
||||
triggered = true;
|
||||
mapping.lastValue = range;
|
||||
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
|
||||
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
|
||||
float currentValue = pEffect->GetControlValue(mapping.controlIndex);
|
||||
currentValue = currentValue == 0 ? 1: 0;
|
||||
currentValue = currentValue == 0 ? 1 : 0;
|
||||
pEffect->SetControl(mapping.controlIndex, currentValue);
|
||||
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), currentValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MidiControlType::MomentarySwitch:
|
||||
{
|
||||
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
|
||||
pEffect->SetControl(mapping.controlIndex, range != 0 ? mapping.pPortInfo->max_value() : mapping.pPortInfo->min_value());
|
||||
// do NOT notify anyone!
|
||||
}
|
||||
break;
|
||||
|
||||
case MidiControlType::Select:
|
||||
case MidiControlType::Dial:
|
||||
{
|
||||
@@ -780,12 +820,12 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
|
||||
float currentValue = mapping.pPortInfo->rangeToValue(range);
|
||||
if (pEffect->GetControlValue(mapping.controlIndex) != currentValue)
|
||||
{
|
||||
this->SetControlValue(mapping.effectIndex, mapping.controlIndex,currentValue);
|
||||
this->SetControlValue(mapping.effectIndex, mapping.controlIndex, currentValue);
|
||||
pfnCallback(callbackHandle, mapping.instanceId, mapping.pPortInfo->index(), currentValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MidiControlType::None:
|
||||
case MidiControlType::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+12
-3
@@ -35,6 +35,8 @@ namespace pipedal
|
||||
class RealtimePatchPropertyRequest;
|
||||
class RealtimeRingBufferWriter;
|
||||
|
||||
using ExistingEffectMap = std::map<uint64_t, std::shared_ptr<IEffect>>;
|
||||
|
||||
struct Lv2PedalboardError
|
||||
{
|
||||
int64_t intanceId;
|
||||
@@ -78,7 +80,8 @@ namespace pipedal
|
||||
Select,
|
||||
Dial,
|
||||
Toggle,
|
||||
Trigger
|
||||
Trigger,
|
||||
MomentarySwitch
|
||||
};
|
||||
class MidiMapping
|
||||
{
|
||||
@@ -101,7 +104,8 @@ namespace pipedal
|
||||
std::vector<float *> PrepareItems(
|
||||
std::vector<PedalboardItem> &items,
|
||||
std::vector<float *> inputBuffers,
|
||||
Lv2PedalboardErrorList &errorList);
|
||||
Lv2PedalboardErrorList &errorList,
|
||||
ExistingEffectMap *existingEffects);
|
||||
|
||||
void PrepareMidiMap(const Pedalboard &pedalboard);
|
||||
void PrepareMidiMap(const PedalboardItem &pedalboardItem);
|
||||
@@ -114,9 +118,12 @@ namespace pipedal
|
||||
Lv2Pedalboard() {}
|
||||
~Lv2Pedalboard() {}
|
||||
|
||||
void Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList);
|
||||
|
||||
void Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList, ExistingEffectMap *existingEffects = nullptr);
|
||||
|
||||
std::vector<IEffect *> &GetEffects() { return realtimeEffects; }
|
||||
std::vector<std::shared_ptr<IEffect>> &GetSharedEffectList() { return effects; }
|
||||
|
||||
|
||||
int GetIndexOfInstanceId(uint64_t instanceId)
|
||||
{
|
||||
@@ -140,6 +147,8 @@ namespace pipedal
|
||||
}
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
void UpdateAudioPorts();
|
||||
|
||||
bool Run(float **inputBuffers, float **outputBuffers, uint32_t samples, RealtimeRingBufferWriter *realtimeWriter);
|
||||
|
||||
void ResetAtomBuffers();
|
||||
|
||||
+26
-7
@@ -508,6 +508,7 @@ void PiPedalModel::FireBanksChanged(int64_t clientId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PiPedalModel::FirePedalboardChanged(int64_t clientId, bool loadAudioThread)
|
||||
{
|
||||
if (loadAudioThread)
|
||||
@@ -593,10 +594,28 @@ void PiPedalModel::UpdateCurrentPedalboard(int64_t clientId, Pedalboard &pedalbo
|
||||
|
||||
UpdateVst3Settings(pedalboard);
|
||||
|
||||
this->pedalboard = pedalboard;
|
||||
UpdateDefaults(&this->pedalboard);
|
||||
|
||||
this->FirePedalboardChanged(clientId);
|
||||
|
||||
Lv2PedalboardErrorList errorMessages;
|
||||
std::shared_ptr<Lv2Pedalboard> lv2Pedalboard{
|
||||
this->pluginHost.UpdateLv2PedalboardStructure(pedalboard, this->lv2Pedalboard.get(), errorMessages)
|
||||
};
|
||||
this->lv2Pedalboard = lv2Pedalboard;
|
||||
|
||||
// apply the error messages to the lv2Pedalboard.
|
||||
// return true if the error messages have changed
|
||||
audioHost->SetPedalboard(lv2Pedalboard);
|
||||
this->pedalboard = pedalboard;
|
||||
previousPedalboard = this->pedalboard;
|
||||
previousPedalboardLoaded = true;
|
||||
this->pedalboard = pedalboard;
|
||||
|
||||
UpdateRealtimeVuSubscriptions();
|
||||
UpdateRealtimeMonitorPortSubscriptions();
|
||||
|
||||
|
||||
|
||||
this->FirePedalboardChanged(clientId,false);
|
||||
this->SetPresetChanged(clientId, true);
|
||||
}
|
||||
}
|
||||
@@ -2159,10 +2178,10 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
|
||||
for (int i = 0; i < midiEventListeners.size(); ++i)
|
||||
for (int i = 0; i < midiEventListeners.size(); ++i)
|
||||
{
|
||||
auto &listener = midiEventListeners[i];
|
||||
if ((!isNote) || (!listener.listenForControlsOnly))
|
||||
if ((!isNote) == (listener.listenForControls))
|
||||
{
|
||||
auto subscriber = this->GetNotificationSubscriber(listener.clientId);
|
||||
if (subscriber)
|
||||
@@ -2179,10 +2198,10 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
|
||||
audioHost->SetListenForMidiEvent(midiEventListeners.size() != 0);
|
||||
}
|
||||
|
||||
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly)
|
||||
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControls)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
MidiListener listener{clientId, clientHandle, listenForControlsOnly};
|
||||
MidiListener listener{clientId, clientHandle, listenForControls};
|
||||
midiEventListeners.push_back(listener);
|
||||
audioHost->SetListenForMidiEvent(true);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace pipedal
|
||||
public:
|
||||
int64_t clientId;
|
||||
int64_t clientHandle;
|
||||
bool listenForControlsOnly;
|
||||
bool listenForControls;
|
||||
};
|
||||
class AtomOutputListener
|
||||
{
|
||||
@@ -436,7 +436,7 @@ namespace pipedal
|
||||
JackServerSettings GetJackServerSettings();
|
||||
void SetJackServerSettings(const JackServerSettings &jackServerSettings);
|
||||
|
||||
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly);
|
||||
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControls);
|
||||
void CancelListenForMidiEvent(int64_t clientId, int64_t clientHandle);
|
||||
|
||||
void MonitorPatchProperty(int64_t clientId, int64_t clientHandle, uint64_t instanceId, const std::string &propertyUri);
|
||||
|
||||
@@ -181,13 +181,13 @@ JSON_MAP_END()
|
||||
class ListenForMidiEventBody
|
||||
{
|
||||
public:
|
||||
bool listenForControlsOnly_;
|
||||
bool listenForControls_;
|
||||
int64_t handle_;
|
||||
DECLARE_JSON_MAP(ListenForMidiEventBody);
|
||||
};
|
||||
|
||||
JSON_MAP_BEGIN(ListenForMidiEventBody)
|
||||
JSON_MAP_REFERENCE(ListenForMidiEventBody, listenForControlsOnly)
|
||||
JSON_MAP_REFERENCE(ListenForMidiEventBody, listenForControls)
|
||||
JSON_MAP_REFERENCE(ListenForMidiEventBody, handle)
|
||||
JSON_MAP_END()
|
||||
|
||||
@@ -1072,7 +1072,7 @@ public:
|
||||
{
|
||||
ListenForMidiEventBody body;
|
||||
pReader->read(&body);
|
||||
this->model.ListenForMidiEvent(this->clientId, body.handle_, body.listenForControlsOnly_);
|
||||
this->model.ListenForMidiEvent(this->clientId, body.handle_, body.listenForControls_);
|
||||
}
|
||||
else if (message == "cancelListenForMidiEvent")
|
||||
{
|
||||
|
||||
+35
-1
@@ -172,6 +172,8 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
|
||||
#define MOD_PREFIX "http://moddevices.com/ns/mod#"
|
||||
mod__label = lilv_new_uri(pWorld, MOD_PREFIX "label");
|
||||
mod__brand = lilv_new_uri(pWorld, MOD_PREFIX "brand");
|
||||
mod__preferMomentaryOffByDefault = lilv_new_uri(pWorld, MOD_PREFIX "preferMomentaryOffByDefault");
|
||||
mod__preferMomentaryOnByDefault = lilv_new_uri(pWorld, MOD_PREFIX "preferMomentaryOnByDefault");
|
||||
// ui:portNotification
|
||||
// [
|
||||
// ui:portIndex 3;
|
||||
@@ -1000,7 +1002,8 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
|
||||
}
|
||||
}
|
||||
this->integer_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->integer_property_uri);
|
||||
|
||||
this->mod_momentaryOffByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOffByDefault);
|
||||
this->mod_momentaryOnByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOnByDefault);
|
||||
this->enumeration_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->enumeration_property_uri);
|
||||
|
||||
this->toggled_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__toggled);
|
||||
@@ -1238,6 +1241,32 @@ std::shared_ptr<Lv2PluginInfo> PluginHost::GetPluginInfo(const std::string &uri)
|
||||
return ff->second;
|
||||
}
|
||||
|
||||
Lv2Pedalboard *PluginHost::UpdateLv2PedalboardStructure(Pedalboard &pedalboard,Lv2Pedalboard *existingPedalboard,Lv2PedalboardErrorList &errorList)
|
||||
{
|
||||
ExistingEffectMap existingEffects;
|
||||
|
||||
if (existingPedalboard)
|
||||
{
|
||||
for (auto &effect : existingPedalboard->GetSharedEffectList())
|
||||
{
|
||||
if (effect->IsLv2Effect()) {
|
||||
existingEffects[effect->GetInstanceId()] = effect;
|
||||
}
|
||||
}
|
||||
}
|
||||
Lv2Pedalboard *pPedalboard = new Lv2Pedalboard();
|
||||
try
|
||||
{
|
||||
pPedalboard->Prepare(this, pedalboard, errorList,&existingEffects);
|
||||
return pPedalboard;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
delete pPedalboard;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Lv2Pedalboard *PluginHost::CreateLv2Pedalboard(Pedalboard &pedalboard, Lv2PedalboardErrorList &errorMessages)
|
||||
{
|
||||
Lv2Pedalboard *pPedalboard = new Lv2Pedalboard();
|
||||
@@ -1697,6 +1726,8 @@ json_map::storage_type<Lv2PortInfo> Lv2PortInfo::jmap{
|
||||
MAP_REF(Lv2PortInfo, integer_property),
|
||||
MAP_REF(Lv2PortInfo, enumeration_property),
|
||||
MAP_REF(Lv2PortInfo, toggled_property),
|
||||
MAP_REF(Lv2PortInfo, mod_momentaryOffByDefault),
|
||||
MAP_REF(Lv2PortInfo, mod_momentaryOnByDefault),
|
||||
MAP_REF(Lv2PortInfo, not_on_gui),
|
||||
MAP_REF(Lv2PortInfo, buffer_type),
|
||||
MAP_REF(Lv2PortInfo, port_group),
|
||||
@@ -1761,6 +1792,9 @@ json_map::storage_type<Lv2PluginUiPort> Lv2PluginUiPort::jmap{{
|
||||
|
||||
MAP_REF(Lv2PluginUiPort, range_steps),
|
||||
MAP_REF(Lv2PluginUiPort, integer_property),
|
||||
|
||||
MAP_REF(Lv2PluginUiPort, mod_momentaryOffByDefault),
|
||||
MAP_REF(Lv2PluginUiPort, mod_momentaryOnByDefault),
|
||||
MAP_REF(Lv2PluginUiPort, enumeration_property),
|
||||
MAP_REF(Lv2PluginUiPort, not_on_gui),
|
||||
MAP_REF(Lv2PluginUiPort, toggled_property),
|
||||
|
||||
+19
-2
@@ -218,6 +218,10 @@ namespace pipedal
|
||||
bool integer_property_ = false;
|
||||
bool enumeration_property_ = false;
|
||||
bool toggled_property_ = false;
|
||||
|
||||
bool mod_momentaryOffByDefault_ = false;
|
||||
bool mod_momentaryOnByDefault_ = false;
|
||||
|
||||
bool not_on_gui_ = false;
|
||||
std::string buffer_type_;
|
||||
std::string port_group_;
|
||||
@@ -288,6 +292,8 @@ namespace pipedal
|
||||
LV2_PROPERTY_GETSET_SCALAR(range_steps);
|
||||
LV2_PROPERTY_GETSET_SCALAR(trigger_property);
|
||||
LV2_PROPERTY_GETSET_SCALAR(integer_property);
|
||||
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOffByDefault);
|
||||
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOnByDefault);
|
||||
LV2_PROPERTY_GETSET_SCALAR(enumeration_property);
|
||||
LV2_PROPERTY_GETSET_SCALAR(toggled_property);
|
||||
LV2_PROPERTY_GETSET_SCALAR(not_on_gui);
|
||||
@@ -503,7 +509,12 @@ namespace pipedal
|
||||
: symbol_(pPort->symbol()), index_(pPort->index()),
|
||||
is_input_(pPort->is_input()), 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()),
|
||||
is_logarithmic_(pPort->is_logarithmic()), integer_property_(pPort->integer_property()), enumeration_property_(pPort->enumeration_property()),
|
||||
is_logarithmic_(pPort->is_logarithmic()),
|
||||
integer_property_(pPort->integer_property()),
|
||||
mod_momentaryOffByDefault_(pPort->mod_momentaryOffByDefault()),
|
||||
mod_momentaryOnByDefault_(pPort->mod_momentaryOnByDefault()),
|
||||
|
||||
enumeration_property_(pPort->enumeration_property()),
|
||||
toggled_property_(pPort->toggled_property()), not_on_gui_(pPort->not_on_gui()), scale_points_(pPort->scale_points()),
|
||||
trigger_property_(pPort->trigger_property()),
|
||||
pipedal_ledColor_(pPort->pipedal_ledColor()),
|
||||
@@ -544,6 +555,9 @@ namespace pipedal
|
||||
|
||||
int range_steps_ = 0;
|
||||
bool integer_property_ = false;
|
||||
|
||||
bool mod_momentaryOffByDefault_ = false;
|
||||
bool mod_momentaryOnByDefault_ = false;
|
||||
bool enumeration_property_ = false;
|
||||
bool not_on_gui_ = false;
|
||||
bool toggled_property_ = false;
|
||||
@@ -746,7 +760,8 @@ namespace pipedal
|
||||
|
||||
AutoLilvNode mod__brand;
|
||||
AutoLilvNode mod__label;
|
||||
|
||||
AutoLilvNode mod__preferMomentaryOffByDefault;
|
||||
AutoLilvNode mod__preferMomentaryOnByDefault;
|
||||
AutoLilvNode dc__format;
|
||||
|
||||
AutoLilvNode mod__fileTypes;
|
||||
@@ -885,6 +900,8 @@ namespace pipedal
|
||||
|
||||
virtual Lv2Pedalboard *CreateLv2Pedalboard(Pedalboard &pedalboard,Lv2PedalboardErrorList &errorList);
|
||||
|
||||
virtual Lv2Pedalboard *UpdateLv2PedalboardStructure(Pedalboard &pedalboard,Lv2Pedalboard *existingPedalboard,Lv2PedalboardErrorList &errorList);
|
||||
|
||||
void setSampleRate(double sampleRate)
|
||||
{
|
||||
this->sampleRate = sampleRate;
|
||||
|
||||
Reference in New Issue
Block a user