diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 9d7eb78c9..89147ec4b 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -24,6 +24,10 @@ #include #include +#ifdef WANT_LV2 +# include "lv2/atom.h" +#endif + CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- @@ -785,6 +789,7 @@ struct ParamSymbol { void CarlaPlugin::loadSaveState(const SaveState& saveState) { + bool hasChunk = (saveState.chunk != nullptr && (fOptions & PLUGIN_OPTION_USE_CHUNKS) != 0); char strBuf[STR_MAX+1]; // --------------------------------------------------------------------- @@ -794,8 +799,17 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) { const StateCustomData* const stateCustomData(*it); - if (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) != 0) + bool isChunk = (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) == 0); + +#ifdef WANT_LV2 + if (! isChunk) + isChunk = (std::strcmp(stateCustomData->type, LV2_ATOM__Chunk) == 0); +#endif + + if (! isChunk) setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true); + else + hasChunk = true; } // --------------------------------------------------------------------- @@ -846,122 +860,137 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) setMidiProgramById(saveState.currentMidiBank, saveState.currentMidiProgram, true, true, true); // --------------------------------------------------------------------- - // Part 4a - get plugin parameter symbols - - NonRtList paramSymbols; + // Part 4 - set parameter values (ONLY IF NO CHUNK) - if (type() == PLUGIN_LADSPA || type() == PLUGIN_LV2) + if (! hasChunk) { - for (uint32_t i=0; i < kData->param.count; ++i) - { - getParameterSymbol(i, strBuf); + // ----------------------------------------------------------------- + // Part 4a - get plugin parameter symbols - if (*strBuf != '\0') + NonRtList paramSymbols; + + if (type() == PLUGIN_LADSPA || type() == PLUGIN_LV2) + { + for (uint32_t i=0; i < kData->param.count; ++i) { - ParamSymbol* const paramSymbol(new ParamSymbol(i, strBuf)); - paramSymbols.append(paramSymbol); + getParameterSymbol(i, strBuf); + + if (*strBuf != '\0') + { + ParamSymbol* const paramSymbol(new ParamSymbol(i, strBuf)); + paramSymbols.append(paramSymbol); + } } } - } - // --------------------------------------------------------------------- - // Part 4b - set parameter values (carefully) + // ----------------------------------------------------------------- + // Part 4b - set parameter values (carefully) - const float sampleRate(kData->engine->getSampleRate()); + const float sampleRate(kData->engine->getSampleRate()); - for (NonRtList::Itenerator it = saveState.parameters.begin(); it.valid(); it.next()) - { - StateParameter* const stateParameter(*it); + for (NonRtList::Itenerator it = saveState.parameters.begin(); it.valid(); it.next()) + { + StateParameter* const stateParameter(*it); - int32_t index = -1; + int32_t index = -1; - if (type() == PLUGIN_LADSPA) - { - // Try to set by symbol, otherwise use index - if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) + if (type() == PLUGIN_LADSPA) { - for (NonRtList::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) + // Try to set by symbol, otherwise use index + if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) { - ParamSymbol* const paramSymbol(*it); - - if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) + for (NonRtList::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) { - index = paramSymbol->index; - break; + ParamSymbol* const paramSymbol(*it); + + if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) + { + index = paramSymbol->index; + break; + } } + if (index == -1) + index = stateParameter->index; } - if (index == -1) + else index = stateParameter->index; } - else - index = stateParameter->index; - } - else if (type() == PLUGIN_LV2) - { - // Symbol only - if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) + else if (type() == PLUGIN_LV2) { - for (NonRtList::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) + // Symbol only + if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0) { - ParamSymbol* const paramSymbol(*it); - - if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) + for (NonRtList::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) { - index = paramSymbol->index; - break; + ParamSymbol* const paramSymbol(*it); + + if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) + { + index = paramSymbol->index; + break; + } } + if (index == -1) + carla_stderr("Failed to find LV2 parameter symbol for '%s')", stateParameter->symbol); } - if (index == -1) - carla_stderr("Failed to find LV2 parameter symbol for '%s')", stateParameter->symbol); + else + carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name); } else - carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name); - } - else - { - // Index only - index = stateParameter->index; + { + // Index only + index = stateParameter->index; + } + + // Now set parameter + if (index >= 0 && index < static_cast(kData->param.count)) + { + if (kData->param.data[index].hints & PARAMETER_USES_SAMPLERATE) + stateParameter->value *= sampleRate; + + setParameterValue(index, stateParameter->value, true, true, true); + #ifndef BUILD_BRIDGE + setParameterMidiCC(index, stateParameter->midiCC, true, true); + setParameterMidiChannel(index, stateParameter->midiChannel, true, true); + #endif + } + else + carla_stderr("Could not set parameter data for '%s'", stateParameter->name); } - // Now set parameter - if (index >= 0 && index < static_cast(kData->param.count)) + // clear + for (NonRtList::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) { - if (kData->param.data[index].hints & PARAMETER_USES_SAMPLERATE) - stateParameter->value *= sampleRate; - - setParameterValue(index, stateParameter->value, true, true, true); -#ifndef BUILD_BRIDGE - setParameterMidiCC(index, stateParameter->midiCC, true, true); - setParameterMidiChannel(index, stateParameter->midiChannel, true, true); -#endif + ParamSymbol* const paramSymbol(*it); + paramSymbol->free(); + delete paramSymbol; } - else - carla_stderr("Could not set parameter data for '%s'", stateParameter->name); - } - // clear - for (NonRtList::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) - { - ParamSymbol* const paramSymbol(*it); - paramSymbol->free(); - delete paramSymbol; + paramSymbols.clear(); } + else + { + // --------------------------------------------------------------------- + // Part 4 - set chunk data - paramSymbols.clear(); + for (NonRtList::Itenerator it = saveState.customData.begin(); it.valid(); it.next()) + { + const StateCustomData* const stateCustomData(*it); - // --------------------------------------------------------------------- - // Part 5 - set chunk data + bool isChunk = (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) == 0); - for (NonRtList::Itenerator it = saveState.customData.begin(); it.valid(); it.next()) - { - const StateCustomData* const stateCustomData(*it); + #ifdef WANT_LV2 + if (! isChunk) + isChunk = (std::strcmp(stateCustomData->type, LV2_ATOM__Chunk) == 0); + #endif - if (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) == 0) - setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true); - } + if (isChunk) + setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true); + } - if (saveState.chunk != nullptr && (fOptions & PLUGIN_OPTION_USE_CHUNKS) != 0) - setChunkData(saveState.chunk); + if (saveState.chunk != nullptr && (fOptions & PLUGIN_OPTION_USE_CHUNKS) != 0) + setChunkData(saveState.chunk); + } // --------------------------------------------------------------------- // Part 6 - set internal stuff