From 39b2e27561c5f0743f8d97211b4c260fa7977ba3 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 28 Jun 2015 01:48:25 +0200 Subject: [PATCH] Fix rename under jack multi-client mode --- source/backend/CarlaEngine.hpp | 2 + source/backend/engine/CarlaEngine.cpp | 49 +++++++----------- source/backend/engine/CarlaEngineClient.cpp | 10 ++++ source/backend/engine/CarlaEngineInternal.cpp | 16 ++++++ source/backend/engine/CarlaEngineInternal.hpp | 18 ++++++- source/backend/engine/CarlaEngineJack.cpp | 50 +++++++++++++------ source/backend/plugin/CarlaPlugin.cpp | 3 +- 7 files changed, 98 insertions(+), 50 deletions(-) diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index 2ec82bdb2..85e6983ea 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -645,6 +645,7 @@ protected: void _addCVPortName(const bool, const char* const); void _addEventPortName(const bool, const char* const); const char* _getUniquePortName(const char* const); + void _clearPorts(); CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineClient) #endif @@ -1074,6 +1075,7 @@ protected: friend class PendingRtEventsRunner; friend class ScopedActionLock; friend class ScopedEngineEnvironmentLocker; + friend class ScopedThreadStopper; friend struct PatchbayGraph; friend struct RackGraph; diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index bab724475..e6cf1d19e 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -576,9 +576,7 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, #ifndef BUILD_BRIDGE if (oldPlugin != nullptr) { - // the engine thread might be reading from the old plugin - pData->thread.stopThread(500); - pData->thread.startThread(); + const ScopedThreadStopper sts(this); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) pData->graph.replacePlugin(oldPlugin, plugin); @@ -635,7 +633,7 @@ bool CarlaEngine::removePlugin(const uint id) CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to remove"); CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); - pData->thread.stopThread(500); + const ScopedThreadStopper sts(this); #ifndef BUILD_BRIDGE if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) @@ -664,9 +662,6 @@ bool CarlaEngine::removePlugin(const uint id) delete plugin; - if (isRunning() && ! pData->aboutToClose) - pData->thread.startThread(); - callback(ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0.0f, nullptr); return true; } @@ -682,7 +677,7 @@ bool CarlaEngine::removeAllPlugins() if (pData->curPluginCount == 0) return true; - pData->thread.stopThread(500); + const ScopedThreadStopper sts(this); const uint curPluginCount(pData->curPluginCount); @@ -722,9 +717,6 @@ bool CarlaEngine::removeAllPlugins() callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr); } - if (isRunning() && ! pData->aboutToClose) - pData->thread.startThread(); - return true; } @@ -825,38 +817,31 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept CARLA_SAFE_ASSERT_RETURN_ERR(idB < pData->curPluginCount, "Invalid plugin Id"); carla_debug("CarlaEngine::switchPlugins(%i)", idA, idB); - { - CarlaPlugin* const pluginA(pData->plugins[idA].plugin); - CarlaPlugin* const pluginB(pData->plugins[idB].plugin); + CarlaPlugin* const pluginA(pData->plugins[idA].plugin); + CarlaPlugin* const pluginB(pData->plugins[idB].plugin); - CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch"); - CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch"); - CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data"); - CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data"); + CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch"); + CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch"); + CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data"); + CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data"); - pData->thread.stopThread(500); + const ScopedThreadStopper sts(this); - if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) - pData->graph.replacePlugin(pluginA, pluginB); - } + if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) + pData->graph.replacePlugin(pluginA, pluginB); const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/); const ScopedActionLock sal(this, kEnginePostActionSwitchPlugins, idA, idB, lockWait); + // TODO /* - CarlaPlugin* const pluginA(pData->plugins[idA].plugin); - CarlaPlugin* const pluginB(pData->plugins[idB].plugin); + pluginA->updateOscURL(); + pluginB->updateOscURL(); - if (pluginA != nullptr && pluginB != nullptr) - { - pluginA->updateOscURL(); - pluginB->updateOscURL(); - } + if (isOscControlRegistered()) + oscSend_control_switch_plugins(idA, idB); */ - // TODO - //if (isOscControlRegistered()) - // oscSend_control_switch_plugins(idA, idB); if (isRunning() && ! pData->aboutToClose) pData->thread.startThread(); diff --git a/source/backend/engine/CarlaEngineClient.cpp b/source/backend/engine/CarlaEngineClient.cpp index 57ccc9edd..6714560a7 100644 --- a/source/backend/engine/CarlaEngineClient.cpp +++ b/source/backend/engine/CarlaEngineClient.cpp @@ -263,6 +263,16 @@ const char* CarlaEngineClient::_getUniquePortName(const char* const name) return sname.dup(); } +void CarlaEngineClient::_clearPorts() +{ + pData->audioInList.clear(); + pData->audioOutList.clear(); + pData->cvInList.clear(); + pData->cvOutList.clear(); + pData->eventInList.clear(); + pData->eventOutList.clear(); +} + // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/engine/CarlaEngineInternal.cpp b/source/backend/engine/CarlaEngineInternal.cpp index a14a4cb82..7025a07c5 100644 --- a/source/backend/engine/CarlaEngineInternal.cpp +++ b/source/backend/engine/CarlaEngineInternal.cpp @@ -393,6 +393,22 @@ ScopedActionLock::~ScopedActionLock() noexcept pData->nextAction.mutex.unlock(); } +// ----------------------------------------------------------------------- +// ScopedThreadStopper + +ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept + : engine(e), + pData(e->pData) +{ + pData->thread.stopThread(500); +} + +ScopedThreadStopper::~ScopedThreadStopper() noexcept +{ + if (engine->isRunning() && ! pData->aboutToClose) + pData->thread.startThread(); +} + // ----------------------------------------------------------------------- // ScopedEngineEnvironmentLocker diff --git a/source/backend/engine/CarlaEngineInternal.hpp b/source/backend/engine/CarlaEngineInternal.hpp index 4f0c684cb..b71d7737d 100644 --- a/source/backend/engine/CarlaEngineInternal.hpp +++ b/source/backend/engine/CarlaEngineInternal.hpp @@ -220,8 +220,6 @@ struct CarlaEngine::ProtectedData { // ------------------------------------------------------------------- - //friend class ScopedActionLock; - #ifdef CARLA_PROPER_CPP11_SUPPORT ProtectedData() = delete; CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData) @@ -260,6 +258,22 @@ private: // ----------------------------------------------------------------------- +class ScopedThreadStopper +{ +public: + ScopedThreadStopper(CarlaEngine* const engine) noexcept; + ~ScopedThreadStopper() noexcept; + +private: + CarlaEngine* const engine; + CarlaEngine::ProtectedData* const pData; + + CARLA_PREVENT_HEAP_ALLOCATION + CARLA_DECLARE_NON_COPY_CLASS(ScopedThreadStopper) +}; + +// ----------------------------------------------------------------------- + CARLA_BACKEND_END_NAMESPACE #endif // CARLA_ENGINE_INTERNAL_HPP_INCLUDED diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 046693af3..c28717a86 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -530,8 +530,10 @@ public: const char* realName = name; // Create JACK port first, if needed - if (fUseClient && fJackClient != nullptr) + if (fUseClient) { + CARLA_SAFE_ASSERT_RETURN(fJackClient != nullptr, nullptr); + realName = _getUniquePortName(name); switch (portType) @@ -638,6 +640,32 @@ public: fEventPorts.removeAll(port); } + void closeForRename(jack_client_t* const client) noexcept + { + if (fJackClient != nullptr) + { + if (isActive()) + { + try { + jackbridge_activate(fJackClient); + } catch(...) {} + } + + try { + jackbridge_client_close(fJackClient); + } catch(...) {} + + invalidate(); + } + + fAudioPorts.clear(); + fCVPorts.clear(); + fEventPorts.clear(); + _clearPorts(); + + fJackClient = client; + } + private: jack_client_t* fJackClient; const bool fUseClient; @@ -646,8 +674,6 @@ private: LinkedList fCVPorts; LinkedList fEventPorts; - friend class CarlaEngineJack; - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) }; @@ -1017,6 +1043,8 @@ public: return nullptr; } + const ScopedThreadStopper sts(this); + CARLA_SAFE_ASSERT(plugin->getId() == id); CarlaString uniqueName; @@ -1025,7 +1053,7 @@ public: const char* const tmpName = getUniquePluginName(newName); uniqueName = tmpName; delete[] tmpName; - } CARLA_SAFE_EXCEPTION("JACK renamePlugin"); + } CARLA_SAFE_EXCEPTION("JACK renamePlugin getUniquePluginName"); if (uniqueName.isEmpty()) { @@ -1052,26 +1080,20 @@ public: // we should not be able to do this, jack really needs to allow client rename if (jack_client_t* const jackClient = jackbridge_client_open(uniqueName, JackNullOption, nullptr)) { - // close old client + // disable plugin plugin->setEnabled(false); - if (client->isActive()) - client->deactivate(); - - plugin->clearBuffers(); - - jackbridge_client_close(client->fJackClient); + // close client + client->closeForRename(jackClient); // set new client data uniqueName = jackbridge_get_client_name(jackClient); jackbridge_set_thread_init_callback(jackClient, carla_jack_thread_init_callback, nullptr); - jackbridge_set_process_callback(jackClient, carla_jack_process_callback_plugin, plugin); jackbridge_set_latency_callback(jackClient, carla_jack_latency_callback_plugin, plugin); + jackbridge_set_process_callback(jackClient, carla_jack_process_callback_plugin, plugin); jackbridge_on_shutdown(jackClient, carla_jack_shutdown_callback_plugin, plugin); - client->fJackClient = jackClient; - needsReinit = true; } else diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 20bd4646e..5ff13dd03 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -960,9 +960,8 @@ void CarlaPlugin::setEnabled(const bool yesNo) noexcept if (pData->enabled == yesNo) return; - pData->enabled = yesNo; - pData->masterMutex.lock(); + pData->enabled = yesNo; pData->masterMutex.unlock(); }