| @@ -35,6 +35,7 @@ | |||||
| using juce::roundToIntAccurate; | using juce::roundToIntAccurate; | ||||
| using juce::FloatVectorOperations; | using juce::FloatVectorOperations; | ||||
| using juce::ScopedPointer; | |||||
| // #define ZYN_MSG_ANYWHERE | // #define ZYN_MSG_ANYWHERE | ||||
| @@ -188,8 +189,80 @@ static ZynAddSubFxPrograms sPrograms; | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| class ZynAddSubFxPlugin : public NativePluginAndUiClass, | |||||
| private CarlaThread | |||||
| class MiddleWareThread : public CarlaThread | |||||
| { | |||||
| public: | |||||
| class ScopedStopper | |||||
| { | |||||
| public: | |||||
| ScopedStopper(MiddleWareThread& mwt) noexcept | |||||
| : wasRunning(mwt.isThreadRunning()), | |||||
| thread(mwt), | |||||
| middleWare(mwt.fMiddleWare) | |||||
| { | |||||
| if (wasRunning) | |||||
| thread.stop(); | |||||
| } | |||||
| ~ScopedStopper() noexcept | |||||
| { | |||||
| if (wasRunning) | |||||
| thread.start(middleWare); | |||||
| } | |||||
| void updateMiddleWare(MiddleWare* const mw) noexcept | |||||
| { | |||||
| middleWare = mw; | |||||
| } | |||||
| private: | |||||
| const bool wasRunning; | |||||
| MiddleWareThread& thread; | |||||
| MiddleWare* middleWare; | |||||
| CARLA_PREVENT_HEAP_ALLOCATION | |||||
| CARLA_DECLARE_NON_COPY_CLASS(ScopedStopper) | |||||
| }; | |||||
| MiddleWareThread() | |||||
| : CarlaThread("ZynMiddleWare"), | |||||
| fMiddleWare(nullptr) {} | |||||
| void start(MiddleWare* const mw) noexcept | |||||
| { | |||||
| fMiddleWare = mw; | |||||
| startThread(); | |||||
| } | |||||
| void stop() noexcept | |||||
| { | |||||
| stopThread(1000); | |||||
| fMiddleWare = nullptr; | |||||
| } | |||||
| private: | |||||
| MiddleWare* fMiddleWare; | |||||
| void run() noexcept override | |||||
| { | |||||
| for (; ! shouldThreadExit();) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fMiddleWare != nullptr,); | |||||
| try { | |||||
| fMiddleWare->tick(); | |||||
| } CARLA_SAFE_EXCEPTION("ZynAddSubFX MiddleWare tick"); | |||||
| carla_msleep(1); | |||||
| } | |||||
| } | |||||
| CARLA_DECLARE_NON_COPY_CLASS(MiddleWareThread) | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| class ZynAddSubFxPlugin : public NativePluginAndUiClass | |||||
| { | { | ||||
| public: | public: | ||||
| enum Parameters { | enum Parameters { | ||||
| @@ -210,12 +283,12 @@ public: | |||||
| ZynAddSubFxPlugin(const NativeHostDescriptor* const host) | ZynAddSubFxPlugin(const NativeHostDescriptor* const host) | ||||
| : NativePluginAndUiClass(host, "zynaddsubfx-ui"), | : NativePluginAndUiClass(host, "zynaddsubfx-ui"), | ||||
| CarlaThread("ZynAddSubFxPlugin"), | |||||
| fMiddleWare(nullptr), | fMiddleWare(nullptr), | ||||
| fMaster(nullptr), | fMaster(nullptr), | ||||
| fSynth(), | fSynth(), | ||||
| fIsActive(false), | fIsActive(false), | ||||
| fMutex() | |||||
| fMutex(), | |||||
| fMiddleWareThread(new MiddleWareThread()) | |||||
| { | { | ||||
| sPrograms.initIfNeeded(); | sPrograms.initIfNeeded(); | ||||
| fConfig.init(); | fConfig.init(); | ||||
| @@ -249,10 +322,13 @@ public: | |||||
| _initMaster(); | _initMaster(); | ||||
| _setMasterParameters(); | _setMasterParameters(); | ||||
| fMiddleWareThread->start(fMiddleWare); | |||||
| } | } | ||||
| ~ZynAddSubFxPlugin() override | ~ZynAddSubFxPlugin() override | ||||
| { | { | ||||
| fMiddleWareThread->stop(); | |||||
| _deleteMaster(); | _deleteMaster(); | ||||
| } | } | ||||
| @@ -687,19 +763,10 @@ protected: | |||||
| char* getState() const override | char* getState() const override | ||||
| { | { | ||||
| char* data = nullptr; | |||||
| if (fIsActive) | |||||
| { | |||||
| fMiddleWare->doReadOnlyOp([this, &data]{ | |||||
| fMaster->getalldata(&data); | |||||
| }); | |||||
| } | |||||
| else | |||||
| { | |||||
| fMaster->getalldata(&data); | |||||
| } | |||||
| const MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||||
| char* data = nullptr; | |||||
| fMaster->getalldata(&data); | |||||
| return data; | return data; | ||||
| } | } | ||||
| @@ -707,6 +774,7 @@ protected: | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | ||||
| const MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||||
| const CarlaMutexLocker cml(fMutex); | const CarlaMutexLocker cml(fMutex); | ||||
| fMaster->putalldata(data); | fMaster->putalldata(data); | ||||
| @@ -723,6 +791,8 @@ protected: | |||||
| void bufferSizeChanged(const uint32_t bufferSize) final | void bufferSizeChanged(const uint32_t bufferSize) final | ||||
| { | { | ||||
| MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||||
| char* const state(getState()); | char* const state(getState()); | ||||
| _deleteMaster(); | _deleteMaster(); | ||||
| @@ -735,6 +805,7 @@ protected: | |||||
| fSynth.alias(); | fSynth.alias(); | ||||
| _initMaster(); | _initMaster(); | ||||
| mwss.updateMiddleWare(fMiddleWare); | |||||
| setState(state); | setState(state); | ||||
| std::free(state); | std::free(state); | ||||
| @@ -742,6 +813,8 @@ protected: | |||||
| void sampleRateChanged(const double sampleRate) final | void sampleRateChanged(const double sampleRate) final | ||||
| { | { | ||||
| MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||||
| char* const state(getState()); | char* const state(getState()); | ||||
| _deleteMaster(); | _deleteMaster(); | ||||
| @@ -750,6 +823,7 @@ protected: | |||||
| fSynth.alias(); | fSynth.alias(); | ||||
| _initMaster(); | _initMaster(); | ||||
| mwss.updateMiddleWare(fMiddleWare); | |||||
| setState(state); | setState(state); | ||||
| std::free(state); | std::free(state); | ||||
| @@ -767,6 +841,7 @@ private: | |||||
| float fParameters[kParamCount]; | float fParameters[kParamCount]; | ||||
| CarlaMutex fMutex; | CarlaMutex fMutex; | ||||
| ScopedPointer<MiddleWareThread> fMiddleWareThread; | |||||
| static MidiControllers getZynControlFromIndex(const uint index) | static MidiControllers getZynControlFromIndex(const uint index) | ||||
| { | { | ||||
| @@ -810,18 +885,6 @@ private: | |||||
| } | } | ||||
| } | } | ||||
| void run() noexcept override | |||||
| { | |||||
| for (; ! shouldThreadExit();) | |||||
| { | |||||
| try { | |||||
| fMiddleWare->tick(); | |||||
| } CARLA_SAFE_EXCEPTION("ZynAddSubFX MiddleWare tick"); | |||||
| carla_msleep(1); | |||||
| } | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| void _initMaster() | void _initMaster() | ||||
| @@ -830,7 +893,6 @@ private: | |||||
| fMiddleWare->setUiCallback(__uiCallback, this); | fMiddleWare->setUiCallback(__uiCallback, this); | ||||
| fMiddleWare->setIdleCallback(_idleCallback, this); | fMiddleWare->setIdleCallback(_idleCallback, this); | ||||
| _masterChangedCallback(fMiddleWare->spawnMaster()); | _masterChangedCallback(fMiddleWare->spawnMaster()); | ||||
| startThread(); | |||||
| } | } | ||||
| void _setMasterParameters() | void _setMasterParameters() | ||||
| @@ -887,8 +949,6 @@ private: | |||||
| void _deleteMaster() | void _deleteMaster() | ||||
| { | { | ||||
| stopThread(1000); | |||||
| fMaster = nullptr; | fMaster = nullptr; | ||||
| delete fMiddleWare; | delete fMiddleWare; | ||||
| fMiddleWare = nullptr; | fMiddleWare = nullptr; | ||||