From 2bc0b3ddb793ea87462b1baf93e1aa0b97736a11 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 5 Feb 2015 09:31:19 +0000 Subject: [PATCH] Make NSM actions thread-safe --- source/backend/CarlaHost.h | 2 +- source/backend/CarlaStandalone.cpp | 113 +++++++++++++++++++++-------- source/carla_backend.py | 6 +- source/carla_host.py | 12 +-- 4 files changed, 95 insertions(+), 38 deletions(-) diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h index e6402cca7..2571f6751 100644 --- a/source/backend/CarlaHost.h +++ b/source/backend/CarlaHost.h @@ -907,7 +907,7 @@ CARLA_EXPORT bool carla_nsm_init(int pid, const char* executableName); /*! * Allow NSM callbacks. */ -CARLA_EXPORT void carla_nsm_ready(); +CARLA_EXPORT void carla_nsm_ready(int action); /** @} */ diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp index 43c93ca7b..d0e0b6cbf 100644 --- a/source/backend/CarlaStandalone.cpp +++ b/source/backend/CarlaStandalone.cpp @@ -104,10 +104,15 @@ public: fHasBroadcast(false), fHasOptionalGui(false), fHasServerControl(false), - fStarted() {} + fStarted(), + fReadyActionOpen(true), + fReadyActionSave(true) {} ~CarlaNSM() { + CARLA_SAFE_ASSERT(fReadyActionOpen); + CARLA_SAFE_ASSERT(fReadyActionSave); + if (fOscServerThread != nullptr) { lo_server_thread_stop(fOscServerThread); @@ -167,13 +172,47 @@ public: return true; } - void start() + void ready(const int action) { CARLA_SAFE_ASSERT_RETURN(fOscServerThread != nullptr,); - CARLA_SAFE_ASSERT_RETURN(! fStarted,); - fStarted = true; - lo_server_thread_start(fOscServerThread); + switch (action) + { + case -1: // init + CARLA_SAFE_ASSERT_BREAK(! fStarted); + fStarted = true; + lo_server_thread_start(fOscServerThread); + break; + + case 0: // error + break; + + case 1: // reply + break; + + case 2: // open + fReadyActionOpen = true; + break; + + case 3: // save + fReadyActionSave = true; + break; + + case 4: // session loaded + break; + + case 5: // show gui + CARLA_SAFE_ASSERT_BREAK(fOscAddress != nullptr); + CARLA_SAFE_ASSERT_BREAK(fOscServer != nullptr); + lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_shown", ""); + break; + + case 6: // hide gui + CARLA_SAFE_ASSERT_BREAK(fOscAddress != nullptr); + CARLA_SAFE_ASSERT_BREAK(fOscServer != nullptr); + lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_hidden", ""); + break; + } } static CarlaNSM& getInstance() @@ -251,28 +290,36 @@ protected: CARLA_SAFE_ASSERT_RETURN(fOscServer != nullptr, 1); carla_stdout("CarlaNSM::handleOpen(\"%s\", \"%s\", \"%s\")", projectPath, displayName, clientNameId); - if (carla_is_engine_running()) - carla_engine_close(); + if (gStandalone.engineCallback != nullptr) + { + fReadyActionOpen = false; + gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, 2, 0, 0.0f, projectPath); + + for (; ! fReadyActionOpen;) + carla_msleep(10); + } + else + { + using namespace juce; - carla_engine_init("JACK", clientNameId); + if (carla_is_engine_running()) + carla_engine_close(); - fProjectPath = projectPath; - fProjectPath += ".carxp"; + carla_engine_init("JACK", clientNameId); - fClientNameId = clientNameId; + fProjectPath = projectPath; + fProjectPath += ".carxp"; - using namespace juce; + const String jfilename = String(CharPointer_UTF8(fProjectPath)); - const String jfilename = String(CharPointer_UTF8(fProjectPath)); + if (File(jfilename).existsAsFile()) + carla_load_project(fProjectPath); + } - if (File(jfilename).existsAsFile()) - carla_load_project(fProjectPath); + fClientNameId = clientNameId; lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/open", "OK"); - if (gStandalone.engineCallback != nullptr) - gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, 2, 0, 0.0f, projectPath); - // Broadcast ourselves if (fHasBroadcast) { @@ -301,16 +348,25 @@ protected: { CARLA_SAFE_ASSERT_RETURN(fOscAddress != nullptr, 1); CARLA_SAFE_ASSERT_RETURN(fOscServer != nullptr, 1); - CARLA_SAFE_ASSERT_RETURN(fProjectPath.isNotEmpty(), 0); carla_stdout("CarlaNSM::handleSave()"); - carla_save_project(fProjectPath); - - lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/save", "OK"); - if (gStandalone.engineCallback != nullptr) + { + fReadyActionSave = false; gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, 3, 0, 0.0f, nullptr); + for (; ! fReadyActionSave;) + carla_msleep(10); + } + else + { + CARLA_SAFE_ASSERT_RETURN(fProjectPath.isNotEmpty(), 0); + + carla_save_project(fProjectPath); + } + + lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/save", "OK"); + return 0; } @@ -332,8 +388,6 @@ protected: CARLA_SAFE_ASSERT_RETURN(fOscServer != nullptr, 1); carla_stdout("CarlaNSM::handleShowOptionalGui()"); - lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_shown", ""); - if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, 5, 0, 0.0f, nullptr); @@ -346,8 +400,6 @@ protected: CARLA_SAFE_ASSERT_RETURN(fOscServer != nullptr, 1); carla_stdout("CarlaNSM::handleHideOptionalGui()"); - lo_send_from(fOscAddress, fOscServer, LO_TT_IMMEDIATE, "/nsm/client/gui_is_hidden", ""); - if (gStandalone.engineCallback != nullptr) gStandalone.engineCallback(gStandalone.engineCallbackPtr, CB::ENGINE_CALLBACK_NSM, 0, 6, 0, 0.0f, nullptr); @@ -591,6 +643,9 @@ private: bool fHasServerControl; bool fStarted; + volatile bool fReadyActionOpen; + volatile bool fReadyActionSave; + #define handlePtr ((CarlaNSM*)data) static void _osc_error_handler(int num, const char* msg, const char* path) @@ -2521,10 +2576,10 @@ bool carla_nsm_init(int pid, const char* executableName) #endif } -void carla_nsm_ready() +void carla_nsm_ready(int action) { #ifdef HAVE_LIBLO - CarlaNSM::getInstance().start(); + CarlaNSM::getInstance().ready(action); #endif } diff --git a/source/carla_backend.py b/source/carla_backend.py index 3d0b33ec0..24d9ea1ae 100644 --- a/source/carla_backend.py +++ b/source/carla_backend.py @@ -2348,7 +2348,7 @@ class CarlaHostDLL(CarlaHostMeta): self.lib.carla_nsm_init.argtypes = [c_int, c_char_p] self.lib.carla_nsm_init.restype = c_bool - self.lib.carla_nsm_ready.argtypes = None + self.lib.carla_nsm_ready.argtypes = [c_int] self.lib.carla_nsm_ready.restype = None # -------------------------------------------------------------------------------------------------------- @@ -2616,8 +2616,8 @@ class CarlaHostDLL(CarlaHostMeta): def nsm_init(self, pid, executableName): return bool(self.lib.carla_nsm_init(pid, executableName.encode("utf-8"))) - def nsm_ready(self): - self.lib.carla_nsm_ready() + def nsm_ready(self, action): + self.lib.carla_nsm_ready(action) # ------------------------------------------------------------------------------------------------------------ # Helper object for CarlaHostPlugin diff --git a/source/carla_host.py b/source/carla_host.py index 907f43015..0235662bb 100644 --- a/source/carla_host.py +++ b/source/carla_host.py @@ -411,9 +411,7 @@ class HostWindow(QMainWindow): # For NSM we wait for the open message if NSM_URL and host.nsmOK: - self.fFirstEngineInit = False - self.setEngineSettings() - host.nsm_ready() + host.nsm_ready(-1) return QTimer.singleShot(0, self.slot_engineStart) @@ -1594,11 +1592,13 @@ class HostWindow(QMainWindow): self.fClientName = os.path.basename(valueStr) self.fProjectFilename = QFileInfo(valueStr+".carxp").absoluteFilePath() self.setProperWindowTitle() - self.ui.act_file_save.setEnabled(True) + self.slot_engineStop(True) + self.slot_engineStart() + self.loadProjectNow() # Save elif value1 == 3: - pass + self.saveProjectNow() # Session is Loaded elif value1 == 4: @@ -1612,6 +1612,8 @@ class HostWindow(QMainWindow): elif value1 == 6: self.hide() + self.host.nsm_ready(value1) + # -------------------------------------------------------------------------------------------------------- @pyqtSlot(int, int, int, float, str)