summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfalkTX <falktx@gmail.com>2018-08-04 11:40:17 +0200
committerfalkTX <falktx@gmail.com>2018-08-04 11:40:17 +0200
commit421fdc2ccead216ac00a5810a568bd1ea03cbef1 (patch)
treeb2fcabf0526ecf4b5ce2a31216749b52278888f4
parentb1facba4057de61d51868aea73f296c72da661fe (diff)
Save & restore plugin parameters in VST chunks
Fixes #35
-rw-r--r--distrho/src/DistrhoPluginInternal.hpp12
-rw-r--r--distrho/src/DistrhoPluginVST.cpp113
2 files changed, 121 insertions, 4 deletions
diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp
index 785bfbd6..604f4d98 100644
--- a/distrho/src/DistrhoPluginInternal.hpp
+++ b/distrho/src/DistrhoPluginInternal.hpp
@@ -356,6 +356,18 @@ public:
return (getParameterHints(index) & kParameterIsOutput) != 0x0;
}
+ bool isParameterOutputOrTrigger(const uint32_t index) const noexcept
+ {
+ const uint32_t hints = getParameterHints(index);
+
+ if (hints & kParameterIsOutput)
+ return true;
+ if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
+ return true;
+
+ return false;
+ }
+
const String& getParameterName(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
diff --git a/distrho/src/DistrhoPluginVST.cpp b/distrho/src/DistrhoPluginVST.cpp
index 671e089b..2f389ed5 100644
--- a/distrho/src/DistrhoPluginVST.cpp
+++ b/distrho/src/DistrhoPluginVST.cpp
@@ -37,6 +37,7 @@
#define VESTIGE_HEADER
#define VST_FORCE_DEPRECATED 0
+#include <clocale>
#include <map>
#include <string>
@@ -93,6 +94,32 @@ void snprintf_iparam(char* const dst, const int32_t value, const size_t size)
// -----------------------------------------------------------------------
+class ScopedSafeLocale {
+public:
+ ScopedSafeLocale() noexcept
+ : locale(::strdup(::setlocale(LC_NUMERIC, nullptr)))
+ {
+ ::setlocale(LC_NUMERIC, "C");
+ }
+
+ ~ScopedSafeLocale() noexcept
+ {
+ if (locale != nullptr)
+ {
+ ::setlocale(LC_NUMERIC, locale);
+ std::free(locale);
+ }
+ }
+
+private:
+ char* const locale;
+
+ DISTRHO_DECLARE_NON_COPY_CLASS(ScopedSafeLocale)
+ DISTRHO_PREVENT_HEAP_ALLOCATION
+};
+
+// -----------------------------------------------------------------------
+
class ParameterCheckHelper
{
public:
@@ -618,6 +645,7 @@ public:
#if DISTRHO_PLUGIN_WANT_STATE
case effGetChunk:
+ {
if (ptr == nullptr)
return 0;
@@ -627,7 +655,9 @@ public:
fStateChunk = nullptr;
}
- if (fPlugin.getStateCount() == 0)
+ const uint32_t paramCount = fPlugin.getParameterCount();
+
+ if (fPlugin.getStateCount() == 0 && paramCount == 0)
{
fStateChunk = new char[1];
fStateChunk[0] = '\0';
@@ -661,6 +691,30 @@ public:
chunkStr += tmpStr;
}
+ if (paramCount != 0)
+ {
+ // add another separator
+ chunkStr += "\xff";
+
+ // temporarily set locale to "C" while converting floats
+ const ScopedSafeLocale ssl;
+
+ for (uint32_t i=0; i<paramCount; ++i)
+ {
+ if (fPlugin.isParameterOutputOrTrigger(i))
+ continue;
+
+ // join key and value
+ String tmpStr;
+ tmpStr = fPlugin.getParameterSymbol(i);
+ tmpStr += "\xff";
+ tmpStr += String(fPlugin.getParameterValue(i));
+ tmpStr += "\xff";
+
+ chunkStr += tmpStr;
+ }
+ }
+
const std::size_t chunkSize(chunkStr.length()+1);
fStateChunk = new char[chunkSize];
@@ -678,21 +732,27 @@ public:
*(void**)ptr = fStateChunk;
return ret;
+ }
case effSetChunk:
{
if (value <= 1 || ptr == nullptr)
return 0;
+ const size_t chunkSize = static_cast<size_t>(value);
+
const char* key = (const char*)ptr;
const char* value = nullptr;
+ size_t size, bytesRead = 0;
- for (;;)
+ while (bytesRead < chunkSize)
{
if (key[0] == '\0')
break;
- value = key+(std::strlen(key)+1);
+ size = std::strlen(key)+1;
+ value = key + size;
+ bytesRead += size;
setStateFromUI(key, value);
@@ -702,7 +762,52 @@ public:
# endif
// get next key
- key = value+(std::strlen(value)+1);
+ size = std::strlen(value)+1;
+ key = value + size;
+ bytesRead += size;
+ }
+
+ const uint32_t paramCount = fPlugin.getParameterCount();
+
+ if (bytesRead+4 < chunkSize && paramCount != 0)
+ {
+ ++key;
+ float fvalue;
+
+ // temporarily set locale to "C" while converting floats
+ const ScopedSafeLocale ssl;
+
+ while (bytesRead < chunkSize)
+ {
+ if (key[0] == '\0')
+ break;
+
+ size = std::strlen(key)+1;
+ value = key + size;
+ bytesRead += size;
+
+ // find parameter with this symbol, and set its value
+ for (uint32_t i=0; i<paramCount; ++i)
+ {
+ if (fPlugin.isParameterOutputOrTrigger(i))
+ continue;
+ if (fPlugin.getParameterSymbol(i) != key)
+ continue;
+
+ fvalue = std::atof(value);
+ fPlugin.setParameterValue(i, fvalue);
+# if DISTRHO_PLUGIN_HAS_UI
+ if (fVstUI != nullptr)
+ setParameterValueFromPlugin(i, fvalue);
+# endif
+ break;
+ }
+
+ // get next key
+ size = std::strlen(value)+1;
+ key = value + size;
+ bytesRead += size;
+ }
}
return 1;