DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 421fdc2ccead216ac00a5810a568bd1ea03cbef1
parent b1facba4057de61d51868aea73f296c72da661fe
Author: falkTX <falktx@gmail.com>
Date:   Sat,  4 Aug 2018 11:39:50 +0200

Save & restore plugin parameters in VST chunks
Fixes #35

Diffstat:
Mdistrho/src/DistrhoPluginInternal.hpp | 12++++++++++++
Mdistrho/src/DistrhoPluginVST.cpp | 113++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 121 insertions(+), 4 deletions(-)

diff --git 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 @@ -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;