| @@ -41,6 +41,7 @@ using namespace AT1; | |||||
| // AT1 Plugin | // AT1 Plugin | ||||
| class AT1Plugin : public NativePluginClass, | class AT1Plugin : public NativePluginClass, | ||||
| public X_handler_thread<Mainwin>::SetValueCallback, | |||||
| private Mainwin::ValueChangedCallback | private Mainwin::ValueChangedCallback | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -68,7 +69,7 @@ public: | |||||
| rootwin(nullptr), | rootwin(nullptr), | ||||
| mainwin(nullptr), | mainwin(nullptr), | ||||
| handler(nullptr), | handler(nullptr), | ||||
| handlerThread(), | |||||
| handlerThread(this), | |||||
| leakDetector_AT1Plugin() | leakDetector_AT1Plugin() | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT(host != nullptr); | CARLA_SAFE_ASSERT(host != nullptr); | ||||
| @@ -347,18 +348,7 @@ public: | |||||
| if (mainwin == nullptr) | if (mainwin == nullptr) | ||||
| return; | return; | ||||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||||
| if (index < kParameterNROTARY) | |||||
| { | |||||
| mainwin->_rotary[index]->set_value(value); | |||||
| return; | |||||
| } | |||||
| if (index == kParameterM_CHANNEL) | |||||
| { | |||||
| mainwin->setchan_ui(value); | |||||
| return; | |||||
| } | |||||
| handlerThread.setParameterValueLater(index, value); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -396,6 +386,25 @@ public: | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // X_handler_thread callbacks | |||||
| void setParameterValueFromHandlerThread(uint32_t index, float value) override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(mainwin != nullptr,); | |||||
| if (index < kParameterNROTARY) | |||||
| { | |||||
| mainwin->_rotary[index]->set_value(value); | |||||
| return; | |||||
| } | |||||
| if (index == kParameterM_CHANNEL) | |||||
| { | |||||
| mainwin->setchan_ui(value); | |||||
| return; | |||||
| } | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| private: | private: | ||||
| // Fake jack client | // Fake jack client | ||||
| @@ -41,6 +41,7 @@ using namespace BLS1; | |||||
| // BLS1 Plugin | // BLS1 Plugin | ||||
| class BLS1Plugin : public NativePluginClass, | class BLS1Plugin : public NativePluginClass, | ||||
| public X_handler_thread<Mainwin>::SetValueCallback, | |||||
| private Mainwin::ValueChangedCallback | private Mainwin::ValueChangedCallback | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -66,7 +67,7 @@ public: | |||||
| rootwin(nullptr), | rootwin(nullptr), | ||||
| mainwin(nullptr), | mainwin(nullptr), | ||||
| handler(nullptr), | handler(nullptr), | ||||
| handlerThread(), | |||||
| handlerThread(this), | |||||
| leakDetector_BLS1Plugin() | leakDetector_BLS1Plugin() | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT(host != nullptr); | CARLA_SAFE_ASSERT(host != nullptr); | ||||
| @@ -306,9 +307,7 @@ public: | |||||
| if (mainwin == nullptr) | if (mainwin == nullptr) | ||||
| return; | return; | ||||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||||
| mainwin->_rotary[index]->set_value(value); | |||||
| handlerThread.setParameterValueLater(index, value); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -346,6 +345,16 @@ public: | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // X_handler_thread callbacks | |||||
| void setParameterValueFromHandlerThread(uint32_t index, float value) override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(mainwin != nullptr,); | |||||
| mainwin->_rotary[index]->set_value(value); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| private: | private: | ||||
| // Fake jack client | // Fake jack client | ||||
| @@ -20,6 +20,7 @@ | |||||
| #include "CarlaMutex.hpp" | #include "CarlaMutex.hpp" | ||||
| #include "CarlaThread.hpp" | #include "CarlaThread.hpp" | ||||
| #include "LinkedList.hpp" | |||||
| #include <png.h> | #include <png.h> | ||||
| #include <clxclient.h> | #include <clxclient.h> | ||||
| @@ -29,17 +30,32 @@ | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| struct X_handler_Param { | |||||
| uint32_t index; | |||||
| float value; | |||||
| }; | |||||
| typedef LinkedList<X_handler_Param> ParamList; | |||||
| template<class MainwinType> | template<class MainwinType> | ||||
| class X_handler_thread : public CarlaThread | class X_handler_thread : public CarlaThread | ||||
| { | { | ||||
| public: | public: | ||||
| X_handler_thread() | |||||
| struct SetValueCallback { | |||||
| virtual ~SetValueCallback() {} | |||||
| virtual void setParameterValueFromHandlerThread(const uint32_t index, const float value) = 0; | |||||
| }; | |||||
| X_handler_thread(SetValueCallback* const cb) | |||||
| : CarlaThread("X_handler"), | : CarlaThread("X_handler"), | ||||
| fCallback(cb), | |||||
| fMutex(), | fMutex(), | ||||
| fHandler(nullptr), | fHandler(nullptr), | ||||
| fRootwin(nullptr), | fRootwin(nullptr), | ||||
| fMainwin(nullptr), | fMainwin(nullptr), | ||||
| fClosed(false) {} | |||||
| fClosed(false), | |||||
| fParamMutex(), | |||||
| fParamChanges() {} | |||||
| void setupAndRun(X_handler* const h, X_rootwin* const r, MainwinType* const m) noexcept | void setupAndRun(X_handler* const h, X_rootwin* const r, MainwinType* const m) noexcept | ||||
| { | { | ||||
| @@ -71,6 +87,14 @@ public: | |||||
| return fMutex; | return fMutex; | ||||
| } | } | ||||
| void setParameterValueLater(const uint32_t index, const float value) noexcept | |||||
| { | |||||
| const CarlaMutexLocker cml(fParamMutex); | |||||
| const X_handler_Param param = { index, value }; | |||||
| fParamChanges.append(param); | |||||
| } | |||||
| bool wasClosed() noexcept | bool wasClosed() noexcept | ||||
| { | { | ||||
| if (fClosed) | if (fClosed) | ||||
| @@ -82,12 +106,17 @@ public: | |||||
| } | } | ||||
| private: | private: | ||||
| SetValueCallback* const fCallback; | |||||
| CarlaMutex fMutex; | CarlaMutex fMutex; | ||||
| X_handler* fHandler; | X_handler* fHandler; | ||||
| X_rootwin* fRootwin; | X_rootwin* fRootwin; | ||||
| MainwinType* fMainwin; | MainwinType* fMainwin; | ||||
| volatile bool fClosed; | volatile bool fClosed; | ||||
| CarlaMutex fParamMutex; | |||||
| ParamList fParamChanges; | |||||
| void run() override | void run() override | ||||
| { | { | ||||
| for (; ! shouldThreadExit();) | for (; ! shouldThreadExit();) | ||||
| @@ -99,6 +128,18 @@ private: | |||||
| CARLA_SAFE_ASSERT_RETURN(fMainwin != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fMainwin != nullptr,); | ||||
| { | |||||
| const CarlaMutexLocker cml(fParamMutex); | |||||
| for (ParamList::Itenerator it = fParamChanges.begin(); it.valid(); it.next()) | |||||
| { | |||||
| const X_handler_Param& param(it.getValue()); | |||||
| fCallback->setParameterValueFromHandlerThread(param.index, param.value); | |||||
| } | |||||
| fParamChanges.clear(); | |||||
| } | |||||
| for (; (ev = fMainwin->process()) == EV_X11;) | for (; (ev = fMainwin->process()) == EV_X11;) | ||||
| { | { | ||||
| fRootwin->handle_event(); | fRootwin->handle_event(); | ||||
| @@ -40,6 +40,7 @@ using namespace REV1; | |||||
| // REV1 Plugin | // REV1 Plugin | ||||
| class REV1Plugin : public NativePluginClass, | class REV1Plugin : public NativePluginClass, | ||||
| public X_handler_thread<Mainwin>::SetValueCallback, | |||||
| private Mainwin::ValueChangedCallback | private Mainwin::ValueChangedCallback | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -69,7 +70,7 @@ public: | |||||
| rootwin(nullptr), | rootwin(nullptr), | ||||
| mainwin(nullptr), | mainwin(nullptr), | ||||
| handler(nullptr), | handler(nullptr), | ||||
| handlerThread(), | |||||
| handlerThread(this), | |||||
| leakDetector_REV1Plugin() | leakDetector_REV1Plugin() | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT(host != nullptr); | CARLA_SAFE_ASSERT(host != nullptr); | ||||
| @@ -387,14 +388,7 @@ public: | |||||
| if (mainwin == nullptr) | if (mainwin == nullptr) | ||||
| return; | return; | ||||
| uint32_t rindex = index; | |||||
| if (kIsAmbisonic && index == kParameterOPMIXorRGXYZ) | |||||
| rindex += 1; | |||||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||||
| mainwin->_rotary[rindex]->set_value(value); | |||||
| handlerThread.setParameterValueLater(index, value); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -437,6 +431,21 @@ public: | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // X_handler_thread callbacks | |||||
| void setParameterValueFromHandlerThread(uint32_t index, float value) override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(mainwin != nullptr,); | |||||
| uint32_t rindex = index; | |||||
| if (kIsAmbisonic && index == kParameterOPMIXorRGXYZ) | |||||
| rindex += 1; | |||||
| mainwin->_rotary[rindex]->set_value(value); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| private: | private: | ||||
| const bool kIsAmbisonic; | const bool kIsAmbisonic; | ||||