diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 888e9e59a..7a63b9a32 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -406,13 +406,6 @@ public: */ virtual void prepareForSave(bool temporary); - /*! - * Call LV2 restore. - * @param temporary Wherever we are saving into a temporary location - * (for duplication, renaming or similar) - */ - virtual void restoreLV2State(bool temporary) noexcept; - /*! * Reset all possible parameters. */ @@ -991,6 +984,18 @@ protected: // Internal helper functions protected: + /*! + * Clone/copy files from another LV2 plugin into this one.. + */ + virtual void cloneLV2Files(const CarlaPlugin& other); + + /*! + * Call LV2 restore. + * @param temporary Wherever we are saving into a temporary location + * (for duplication, renaming or similar) + */ + virtual void restoreLV2State(bool temporary) noexcept; + /*! * Allow engine to signal that plugin will be deleted soon. */ diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index befb5ea1c..8573b366e 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -935,7 +935,10 @@ bool CarlaEngine::clonePlugin(const uint id) CARLA_SAFE_ASSERT_RETURN_ERR(pluginCountBefore+1 == pData->curPluginCount, "No new plugin found"); if (const CarlaPluginPtr newPlugin = pData->plugins[pluginCountBefore].plugin) - newPlugin->loadStateSave(plugin->getStateSave()); + { + newPlugin->cloneLV2Files(*plugin); + newPlugin->loadStateSave(plugin->getStateSave(true)); + } return true; } diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 0168e9b0a..da9ef05c1 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -507,14 +507,14 @@ void CarlaPlugin::randomizeParameters() noexcept const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave) { + pData->stateSave.clear(); + if (callPrepareForSave) { pData->stateSave.temporary = true; prepareForSave(true); } - pData->stateSave.clear(); - const PluginType pluginType(getType()); char strBuf[STR_MAX+1]; @@ -550,11 +550,14 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave) pData->stateSave.ctrlChannel = pData->ctrlChannel; #endif - bool usingChunk = false; + if (pData->hints & PLUGIN_IS_BRIDGE) + waitForBridgeSaveSignal(); // --------------------------------------------------------------- // Chunk + bool usingChunk = false; + if (pData->options & PLUGIN_OPTION_USE_CHUNKS) { void* data = nullptr; @@ -650,9 +653,6 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave) // --------------------------------------------------------------- // Custom Data - if (pData->hints & PLUGIN_IS_BRIDGE) - waitForBridgeSaveSignal(); - for (LinkedList::Itenerator it = pData->custom.begin2(); it.valid(); it.next()) { const CustomData& cData(it.getValue(kCustomDataFallback)); @@ -2567,6 +2567,11 @@ void CarlaPlugin::setPatchbayNodeId(const uint32_t nodeId) noexcept // ------------------------------------------------------------------- +void CarlaPlugin::cloneLV2Files(const CarlaPlugin&) +{ + carla_stderr2("Warning: cloneLV2Files() called for non-implemented type"); +} + void CarlaPlugin::restoreLV2State(const bool temporary) noexcept { carla_stderr2("Warning: restoreLV2State(%s) called for non-implemented type", bool2str(temporary)); diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index dbe91554e..5a4abe46f 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -4863,6 +4863,28 @@ public: // ------------------------------------------------------------------- // Internal helper functions + void cloneLV2Files(const CarlaPlugin& other) override + { + CARLA_SAFE_ASSERT_RETURN(other.getType() == PLUGIN_LV2,); + + const CarlaPluginLV2& otherLV2((const CarlaPluginLV2&)other); + + const File tmpDir(handleStateMapToAbsolutePath(false, false, true, ".")); + + if (tmpDir.exists()) + tmpDir.deleteRecursively(); + + const File otherStateDir(otherLV2.handleStateMapToAbsolutePath(false, false, false, ".")); + + if (otherStateDir.exists()) + otherStateDir.copyDirectoryTo(tmpDir); + + const File otherTmpDir(otherLV2.handleStateMapToAbsolutePath(false, false, true, ".")); + + if (otherTmpDir.exists()) + otherTmpDir.copyDirectoryTo(tmpDir); + } + void restoreLV2State(const bool temporary) noexcept override { if (fExt.state == nullptr || fExt.state->restore == nullptr) @@ -5290,7 +5312,7 @@ public: // ------------------------------------------------------------------- - char* handleStateMapToAbstractPath(const bool temporary, const char* const absolutePath) + char* handleStateMapToAbstractPath(const bool temporary, const char* const absolutePath) const { // may already be an abstract path if (! File::isAbsolutePath(absolutePath)) @@ -5357,7 +5379,7 @@ public: File handleStateMapToAbsolutePath(const bool createDirIfNeeded, const bool symlinkIfNeeded, const bool temporary, - const char* const abstractPath) + const char* const abstractPath) const { File targetDir, targetPath;