@@ -523,11 +523,11 @@ protected: | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
/** | /** | ||||
Set the key name of the state @a index. | |||||
Set the state key and default value of @a index. | |||||
This function will be called once, shortly after the plugin is created. | This function will be called once, shortly after the plugin is created. | ||||
Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. | Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. | ||||
*/ | */ | ||||
virtual void d_initStateKey(uint32_t index, d_string& stateKey) = 0; | |||||
virtual void d_initState(uint32_t index, d_string& stateKey, d_string& defaultStateValue) = 0; | |||||
#endif | #endif | ||||
/* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
@@ -55,8 +55,9 @@ Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
if (stateCount > 0) | if (stateCount > 0) | ||||
{ | { | ||||
pData->stateCount = stateCount; | |||||
pData->stateKeys = new d_string[stateCount]; | |||||
pData->stateCount = stateCount; | |||||
pData->stateKeys = new d_string[stateCount]; | |||||
pData->stateDefValues = new d_string[stateCount]; | |||||
} | } | ||||
#else | #else | ||||
DISTRHO_SAFE_ASSERT(stateCount == 0); | DISTRHO_SAFE_ASSERT(stateCount == 0); | ||||
@@ -49,6 +49,7 @@ struct Plugin::PrivateData { | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
uint32_t stateCount; | uint32_t stateCount; | ||||
d_string* stateKeys; | d_string* stateKeys; | ||||
d_string* stateDefValues; | |||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
@@ -73,6 +74,7 @@ struct Plugin::PrivateData { | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
stateCount(0), | stateCount(0), | ||||
stateKeys(nullptr), | stateKeys(nullptr), | ||||
stateDefValues(nullptr), | |||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
latency(0), | latency(0), | ||||
@@ -106,6 +108,12 @@ struct Plugin::PrivateData { | |||||
delete[] stateKeys; | delete[] stateKeys; | ||||
stateKeys = nullptr; | stateKeys = nullptr; | ||||
} | } | ||||
if (stateDefValues != nullptr) | |||||
{ | |||||
delete[] stateDefValues; | |||||
stateDefValues = nullptr; | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
}; | }; | ||||
@@ -134,7 +142,7 @@ public: | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
for (uint32_t i=0, count=fData->stateCount; i < count; ++i) | for (uint32_t i=0, count=fData->stateCount; i < count; ++i) | ||||
fPlugin->d_initStateKey(i, fData->stateKeys[i]); | |||||
fPlugin->d_initState(i, fData->stateKeys[i], fData->stateDefValues[i]); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -305,6 +313,13 @@ public: | |||||
return fData->stateKeys[index]; | return fData->stateKeys[index]; | ||||
} | } | ||||
const d_string& getStateDefaultValue(const uint32_t index) const noexcept | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); | |||||
return fData->stateDefValues[index]; | |||||
} | |||||
void setState(const char* const key, const char* const value) | void setState(const char* const key, const char* const value) | ||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | ||||
@@ -48,7 +48,7 @@ | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
typedef std::map<d_string,d_string> StringMap; | |||||
typedef std::map<const d_string,d_string> StringMap; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -114,7 +114,12 @@ public: | |||||
fNeededUiSends = new bool[count]; | fNeededUiSends = new bool[count]; | ||||
for (uint32_t i=0; i < count; ++i) | for (uint32_t i=0; i < count; ++i) | ||||
{ | |||||
fNeededUiSends[i] = false; | fNeededUiSends[i] = false; | ||||
const d_string& d_key(fPlugin.getStateKey(i)); | |||||
fStateMap[d_key] = fPlugin.getStateDefaultValue(i); | |||||
} | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -592,7 +597,10 @@ public: | |||||
const d_string& key = cit->first; | const d_string& key = cit->first; | ||||
const d_string& value = cit->second; | const d_string& value = cit->second; | ||||
store(handle, fUridMap->map(fUridMap->handle, key.buffer()), value.buffer(), value.length(), fURIDs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); | |||||
const d_string urnKey("urn:distrho:" + key); | |||||
// some hosts need +1 for the null terminator, even though the type is string | |||||
store(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), value.buffer(), value.length()+1, fURIDs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); | |||||
} | } | ||||
return LV2_STATE_SUCCESS; | return LV2_STATE_SUCCESS; | ||||
@@ -606,11 +614,12 @@ public: | |||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | ||||
{ | { | ||||
const d_string& key(fPlugin.getStateKey(i)); | const d_string& key(fPlugin.getStateKey(i)); | ||||
const d_string urnKey("urn:distrho:" + key); | |||||
size = 0; | size = 0; | ||||
type = 0; | type = 0; | ||||
flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; | flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; | ||||
const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, key.buffer()), &size, &type, &flags); | |||||
const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), &size, &type, &flags); | |||||
if (data == nullptr || size == 0) | if (data == nullptr || size == 0) | ||||
continue; | continue; | ||||
@@ -618,7 +627,8 @@ public: | |||||
DISTRHO_SAFE_ASSERT_CONTINUE(type == fURIDs.atomString); | DISTRHO_SAFE_ASSERT_CONTINUE(type == fURIDs.atomString); | ||||
const char* const value((const char*)data); | const char* const value((const char*)data); | ||||
DISTRHO_SAFE_ASSERT_CONTINUE(std::strlen(value) == size); | |||||
const std::size_t length(std::strlen(value)); | |||||
DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size); | |||||
setState(key, value); | setState(key, value); | ||||
@@ -762,9 +772,7 @@ private: | |||||
} | } | ||||
} | } | ||||
// nope, add a new one then | |||||
d_string d_key(key); | |||||
fStateMap[d_key] = newValue; | |||||
d_stderr("Failed to find plugin state with key \"%s\"", key); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -65,7 +65,7 @@ struct ERect { | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
typedef std::map<d_string,d_string> StringMap; | |||||
typedef std::map<const d_string,d_string> StringMap; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -311,6 +311,12 @@ public: | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
fStateChunk = nullptr; | fStateChunk = nullptr; | ||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i<count; ++i) | |||||
{ | |||||
const d_string& d_key(fPlugin.getStateKey(i)); | |||||
fStateMap[d_key] = fPlugin.getStateDefaultValue(i); | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
@@ -745,12 +751,12 @@ private: | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// functions called from the UI side, may block | // functions called from the UI side, may block | ||||
void setStateFromUi(const char* const newKey, const char* const newValue) override | |||||
void setStateFromUi(const char* const key, const char* const newValue) override | |||||
{ | { | ||||
fPlugin.setState(newKey, newValue); | |||||
fPlugin.setState(key, newValue); | |||||
// check if we want to save this key | // check if we want to save this key | ||||
if (! fPlugin.wantStateKey(newKey)) | |||||
if (! fPlugin.wantStateKey(key)) | |||||
return; | return; | ||||
// check if key already exists | // check if key already exists | ||||
@@ -758,16 +764,14 @@ private: | |||||
{ | { | ||||
const d_string& d_key(it->first); | const d_string& d_key(it->first); | ||||
if (d_key == newKey) | |||||
if (d_key == key) | |||||
{ | { | ||||
it->second = newValue; | it->second = newValue; | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
// nope, add a new one then | |||||
d_string d_key(newKey); | |||||
fStateMap[d_key] = newValue; | |||||
d_stderr("Failed to find plugin state with key \"%s\"", key); | |||||
} | } | ||||
#endif | #endif | ||||
}; | }; | ||||