diff options
author | falkTX <falktx@gmail.com> | 2018-08-04 11:40:17 +0200 |
---|---|---|
committer | falkTX <falktx@gmail.com> | 2018-08-04 11:40:17 +0200 |
commit | 421fdc2ccead216ac00a5810a568bd1ea03cbef1 (patch) | |
tree | b2fcabf0526ecf4b5ce2a31216749b52278888f4 | |
parent | b1facba4057de61d51868aea73f296c72da661fe (diff) |
Save & restore plugin parameters in VST chunks
Fixes #35
-rw-r--r-- | distrho/src/DistrhoPluginInternal.hpp | 12 | ||||
-rw-r--r-- | distrho/src/DistrhoPluginVST.cpp | 113 |
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; |