| @@ -35,6 +35,7 @@ | |||
| using juce::roundToIntAccurate; | |||
| using juce::FloatVectorOperations; | |||
| using juce::ScopedPointer; | |||
| // #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: | |||
| enum Parameters { | |||
| @@ -210,12 +283,12 @@ public: | |||
| ZynAddSubFxPlugin(const NativeHostDescriptor* const host) | |||
| : NativePluginAndUiClass(host, "zynaddsubfx-ui"), | |||
| CarlaThread("ZynAddSubFxPlugin"), | |||
| fMiddleWare(nullptr), | |||
| fMaster(nullptr), | |||
| fSynth(), | |||
| fIsActive(false), | |||
| fMutex() | |||
| fMutex(), | |||
| fMiddleWareThread(new MiddleWareThread()) | |||
| { | |||
| sPrograms.initIfNeeded(); | |||
| fConfig.init(); | |||
| @@ -249,10 +322,13 @@ public: | |||
| _initMaster(); | |||
| _setMasterParameters(); | |||
| fMiddleWareThread->start(fMiddleWare); | |||
| } | |||
| ~ZynAddSubFxPlugin() override | |||
| { | |||
| fMiddleWareThread->stop(); | |||
| _deleteMaster(); | |||
| } | |||
| @@ -687,19 +763,10 @@ protected: | |||
| 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; | |||
| } | |||
| @@ -707,6 +774,7 @@ protected: | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||
| const MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||
| const CarlaMutexLocker cml(fMutex); | |||
| fMaster->putalldata(data); | |||
| @@ -723,6 +791,8 @@ protected: | |||
| void bufferSizeChanged(const uint32_t bufferSize) final | |||
| { | |||
| MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||
| char* const state(getState()); | |||
| _deleteMaster(); | |||
| @@ -735,6 +805,7 @@ protected: | |||
| fSynth.alias(); | |||
| _initMaster(); | |||
| mwss.updateMiddleWare(fMiddleWare); | |||
| setState(state); | |||
| std::free(state); | |||
| @@ -742,6 +813,8 @@ protected: | |||
| void sampleRateChanged(const double sampleRate) final | |||
| { | |||
| MiddleWareThread::ScopedStopper mwss(*fMiddleWareThread); | |||
| char* const state(getState()); | |||
| _deleteMaster(); | |||
| @@ -750,6 +823,7 @@ protected: | |||
| fSynth.alias(); | |||
| _initMaster(); | |||
| mwss.updateMiddleWare(fMiddleWare); | |||
| setState(state); | |||
| std::free(state); | |||
| @@ -767,6 +841,7 @@ private: | |||
| float fParameters[kParamCount]; | |||
| CarlaMutex fMutex; | |||
| ScopedPointer<MiddleWareThread> fMiddleWareThread; | |||
| 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() | |||
| @@ -830,7 +893,6 @@ private: | |||
| fMiddleWare->setUiCallback(__uiCallback, this); | |||
| fMiddleWare->setIdleCallback(_idleCallback, this); | |||
| _masterChangedCallback(fMiddleWare->spawnMaster()); | |||
| startThread(); | |||
| } | |||
| void _setMasterParameters() | |||
| @@ -887,8 +949,6 @@ private: | |||
| void _deleteMaster() | |||
| { | |||
| stopThread(1000); | |||
| fMaster = nullptr; | |||
| delete fMiddleWare; | |||
| fMiddleWare = nullptr; | |||