commit 53fd80aa9cefa527aaf32333a534114039b4c07f
parent fb947e978669c3f214c072db6fcba1b75ffa69f2
Author: falkTX <falktx@falktx.com>
Date: Thu, 10 Feb 2022 02:53:00 +0000
Start API for changing state from DSP
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
5 files changed, 80 insertions(+), 13 deletions(-)
diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp
@@ -926,6 +926,15 @@ public:
bool requestParameterValueChange(uint32_t index, float value) noexcept;
#endif
+#if DISTRHO_PLUGIN_WANT_STATE
+ /**
+ Notify the host about a state value change.
+ This function will automatically trigger a state update on the UI side.
+ It must not be called during run.
+ */
+ bool updateStateValue(const char* key, const char* value) noexcept;
+#endif
+
protected:
/* --------------------------------------------------------------------------------------------------------
* Information */
diff --git a/distrho/src/DistrhoPlugin.cpp b/distrho/src/DistrhoPlugin.cpp
@@ -145,6 +145,13 @@ bool Plugin::requestParameterValueChange(const uint32_t index, const float value
}
#endif
+#if DISTRHO_PLUGIN_WANT_STATE
+bool Plugin::updateStateValue(const char* const key, const char* const value) noexcept
+{
+ return pData->updateStateValueCallback(key, value);
+}
+#endif
+
/* ------------------------------------------------------------------------------------------------------------
* Init */
diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp
@@ -46,6 +46,7 @@ extern bool d_nextCanRequestParameterValueChanges;
typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent);
typedef bool (*requestParameterValueChangeFunc) (void* ptr, uint32_t index, float value);
+typedef bool (*updateStateValueFunc) (void* ptr, const char* key, const char* value);
// -----------------------------------------------------------------------
// Helpers
@@ -127,6 +128,7 @@ struct Plugin::PrivateData {
void* callbacksPtr;
writeMidiFunc writeMidiCallbackFunc;
requestParameterValueChangeFunc requestParameterValueChangeCallbackFunc;
+ updateStateValueFunc updateStateValueCallbackFunc;
uint32_t bufferSize;
double sampleRate;
@@ -159,6 +161,7 @@ struct Plugin::PrivateData {
callbacksPtr(nullptr),
writeMidiCallbackFunc(nullptr),
requestParameterValueChangeCallbackFunc(nullptr),
+ updateStateValueCallbackFunc(nullptr),
bufferSize(d_nextBufferSize),
sampleRate(d_nextSampleRate),
bundlePath(d_nextBundlePath != nullptr ? strdup(d_nextBundlePath) : nullptr)
@@ -257,6 +260,17 @@ struct Plugin::PrivateData {
return false;
}
#endif
+
+#if DISTRHO_PLUGIN_WANT_STATE
+ bool updateStateValueCallback(const char* const key, const char* const value)
+ {
+ d_stdout("updateStateValueCallback %p", updateStateValueCallbackFunc);
+ if (updateStateValueCallbackFunc != nullptr)
+ return updateStateValueCallbackFunc(callbacksPtr, key, value);
+
+ return false;
+ }
+#endif
};
// -----------------------------------------------------------------------
@@ -267,7 +281,8 @@ class PluginExporter
public:
PluginExporter(void* const callbacksPtr,
const writeMidiFunc writeMidiCall,
- const requestParameterValueChangeFunc requestParameterValueChangeCall)
+ const requestParameterValueChangeFunc requestParameterValueChangeCall,
+ const updateStateValueFunc updateStateValueCall)
: fPlugin(createPlugin()),
fData((fPlugin != nullptr) ? fPlugin->pData : nullptr),
fIsActive(false)
@@ -409,6 +424,7 @@ public:
fData->callbacksPtr = callbacksPtr;
fData->writeMidiCallbackFunc = writeMidiCall;
fData->requestParameterValueChangeCallbackFunc = requestParameterValueChangeCall;
+ fData->updateStateValueCallbackFunc = updateStateValueCall;
}
~PluginExporter()
diff --git a/distrho/src/DistrhoPluginLV2.cpp b/distrho/src/DistrhoPluginLV2.cpp
@@ -62,6 +62,9 @@ static const writeMidiFunc writeMidiCallback = nullptr;
#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
static const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr;
#endif
+#if ! DISTRHO_PLUGIN_WANT_STATE
+static const updateStateValueFunc updateStateValueCallback = nullptr;
+#endif
// -----------------------------------------------------------------------
@@ -73,7 +76,7 @@ public:
const LV2_Worker_Schedule* const worker,
const LV2_ControlInputPort_Change_Request* const ctrlInPortChangeReq,
const bool usingNominal)
- : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback),
+ : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback),
fUsingNominal(usingNominal),
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
fRunCount(0),
@@ -727,7 +730,11 @@ public:
if (hints & kStateIsHostVisible)
{
// object, prop key, prop urid, value key, value
- msgSize = sizeof(LV2_Atom_Object) + sizeof(LV2_URID) * 3 + value.length() + 1;
+ msgSize = sizeof(LV2_Atom_Object)
+ + sizeof(LV2_Atom_Property_Body) * 4
+ + sizeof(LV2_Atom_URID) * 3
+ + sizeof(LV2_Atom_String)
+ + value.length() + 1;
}
else
{
@@ -737,7 +744,8 @@ public:
if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset)
{
- d_stdout("Sending key '%s' to UI failed, out of space", key.buffer());
+ d_stdout("Sending key '%s' to UI failed, out of space (needs %u bytes)",
+ key.buffer(), msgSize);
break;
}
@@ -745,10 +753,9 @@ public:
aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset);
aev->time.frames = 0;
- uint8_t* const msgBuf = LV2_ATOM_BODY(&aev->body);
-
if (hints & kStateIsHostVisible)
{
+ uint8_t* const msgBuf = (uint8_t*)&aev->body;
LV2_Atom_Forge atomForge = fAtomForge;
lv2_atom_forge_set_buffer(&atomForge, msgBuf, msgSize);
@@ -759,7 +766,10 @@ public:
lv2_atom_forge_urid(&atomForge, fUrids[i]);
lv2_atom_forge_key(&atomForge, fURIDs.patchValue);
- lv2_atom_forge_path(&atomForge, value.buffer(), static_cast<uint32_t>(value.length()+1));
+ if ((hints & kStateIsFilenamePath) == kStateIsFilenamePath)
+ lv2_atom_forge_path(&atomForge, value.buffer(), static_cast<uint32_t>(value.length()+1));
+ else
+ lv2_atom_forge_string(&atomForge, value.buffer(), static_cast<uint32_t>(value.length()+1));
lv2_atom_forge_pop(&atomForge, &forgeFrame);
}
@@ -768,6 +778,7 @@ public:
aev->body.type = fURIDs.dpfKeyValue;
aev->body.size = msgSize;
+ uint8_t* const msgBuf = LV2_ATOM_BODY(&aev->body);
std::memset(msgBuf, 0, msgSize);
// write key and value in atom buffer
@@ -1248,11 +1259,14 @@ private:
{
fPlugin.setState(key, newValue);
- // check if we want to save this key
- if (! fPlugin.wantStateKey(key))
- return;
+ // save this key if necessary
+ if (fPlugin.wantStateKey(key))
+ updateState(key, newValue, false);
+ }
- // check if key already exists
+ bool updateState(const char* const key, const char* const newValue, const bool sendToUI)
+ {
+ // key must already exist
for (StringToStringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it)
{
const String& dkey(it->first);
@@ -1260,11 +1274,25 @@ private:
if (dkey == key)
{
it->second = newValue;
- return;
+
+ if (sendToUI)
+ {
+ for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
+ {
+ if (fPlugin.getStateKey(i) == key)
+ {
+ fNeededUiSends[i] = true;
+ break;
+ }
+ }
+ }
+
+ return true;
}
}
d_stderr("Failed to find plugin state with key \"%s\"", key);
+ return false;
}
#endif
@@ -1306,6 +1334,13 @@ private:
}
#endif
+#if DISTRHO_PLUGIN_WANT_STATE
+ static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value)
+ {
+ return ((PluginLv2*)ptr)->updateState(key, value, true);
+ }
+#endif
+
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool writeMidi(const MidiEvent& midiEvent)
{
diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp
@@ -244,7 +244,7 @@ void lv2_generate_ttl(const char* const basename)
d_nextBufferSize = 512;
d_nextSampleRate = 44100.0;
d_nextPluginIsDummy = true;
- PluginExporter plugin(nullptr, nullptr, nullptr);
+ PluginExporter plugin(nullptr, nullptr, nullptr, nullptr);
d_nextBufferSize = 0;
d_nextSampleRate = 0.0;
d_nextPluginIsDummy = false;