zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 1c08cf687573952da0b87ef72c9f94cbf9fe2cb3
parent 20ef9616811da98db7edd99d8b3dbd0df90f6e0b
Author: falkTX <falktx@gmail.com>
Date:   Fri,  8 Jan 2016 05:55:44 +0000

Plugin: Make get/setState more resilient

Diffstat:
Msrc/Plugin/ZynAddSubFX/ZynAddSubFX.cpp | 148++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 93 insertions(+), 55 deletions(-)

diff --git a/src/Plugin/ZynAddSubFX/ZynAddSubFX.cpp b/src/Plugin/ZynAddSubFX/ZynAddSubFX.cpp @@ -32,23 +32,96 @@ // Extra includes #include "extra/Mutex.hpp" #include "extra/Thread.hpp" +#include "extra/ScopedPointer.hpp" + #include <lo/lo.h> /* ------------------------------------------------------------------------------------------------------------ + * MiddleWare thread class */ + +class MiddleWareThread : public Thread +{ +public: + class ScopedStopper + { + public: + ScopedStopper(MiddleWareThread& mwt) noexcept + : wasRunning(mwt.isThreadRunning()), + thread(mwt), + middleware(mwt.middleware) + { + 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; + + DISTRHO_PREVENT_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPY_CLASS(ScopedStopper) + }; + + MiddleWareThread() + : Thread("ZynMiddleWare"), + middleware(nullptr) {} + + void start(MiddleWare* const mw) noexcept + { + middleware = mw; + startThread(); + } + + void stop() noexcept + { + stopThread(1000); + middleware = nullptr; + } + +protected: + void run() noexcept override + { + for (; ! shouldThreadExit();) + { + try { + middleware->tick(); + } catch(...) {} + + d_msleep(1); + } + } + +private: + MiddleWare* middleware; + + DISTRHO_DECLARE_NON_COPY_CLASS(MiddleWareThread) +}; + +/* ------------------------------------------------------------------------------------------------------------ * ZynAddSubFX plugin class */ -class ZynAddSubFX : public Plugin, - private Thread +class ZynAddSubFX : public Plugin { public: ZynAddSubFX() : Plugin(kParamCount, 1, 1), // 1 program, 1 state - Thread("ZynMwTick"), master(nullptr), middleware(nullptr), - active(false), defaultState(nullptr), - oscPort(0) + oscPort(0), + middlewareThread(new MiddleWareThread()) { config.init(); @@ -63,10 +136,13 @@ public: _initMaster(); defaultState = _getState(); + + middlewareThread->start(middleware); } ~ZynAddSubFX() override { + middlewareThread->stop(); _deleteMaster(); std::free(defaultState); } @@ -233,6 +309,7 @@ protected: */ void setState(const char* key, const char* value) override { + const MiddleWareThread::ScopedStopper mwss(*middlewareThread); const MutexLocker cml(mutex); master->putalldata(value); @@ -246,22 +323,6 @@ protected: * Audio/MIDI Processing */ /** - Activate this plugin. - */ - void activate() noexcept override - { - active = true; - } - - /** - Deactivate this plugin. - */ - void deactivate() noexcept override - { - active = false; - } - - /** Run/process function for plugins with MIDI input. @note Some parameters might be null if there are no audio inputs/outputs or MIDI events. */ @@ -363,6 +424,8 @@ protected: */ void bufferSizeChanged(uint32_t newBufferSize) override { + MiddleWareThread::ScopedStopper mwss(*middlewareThread); + char* const state(_getState()); _deleteMaster(); @@ -375,6 +438,7 @@ protected: synth.alias(); _initMaster(); + mwss.updateMiddleWare(middleware); setState(nullptr, state); std::free(state); @@ -386,6 +450,8 @@ protected: */ void sampleRateChanged(double newSampleRate) override { + MiddleWareThread::ScopedStopper mwss(*middlewareThread); + char* const state(_getState()); _deleteMaster(); @@ -394,6 +460,7 @@ protected: synth.alias(); _initMaster(); + mwss.updateMiddleWare(middleware); setState(nullptr, state); std::free(state); @@ -405,29 +472,18 @@ private: MiddleWare* middleware; SYNTH_T synth; - bool active; Mutex mutex; char* defaultState; int oscPort; + ScopedPointer<MiddleWareThread> middlewareThread; + char* _getState() const { - char* data = nullptr; - -#if 0 - // FIXME: this can lead to issues during startup - if (active) - { - middleware->doReadOnlyOp([this, &data]{ - master->getalldata(&data); - }); - } - else -#endif - { - master->getalldata(&data); - } + const MiddleWareThread::ScopedStopper mwss(*middlewareThread); + char* data = nullptr; + master->getalldata(&data); return data; } @@ -447,14 +503,10 @@ private: { oscPort = 0; } - - startThread(); } void _deleteMaster() { - stopThread(1000); - master = nullptr; delete middleware; middleware = nullptr; @@ -500,20 +552,6 @@ private: ((ZynAddSubFX*)ptr)->_idleCallback(); } - /* -------------------------------------------------------------------------------------------------------- */ - - void run() noexcept override - { - for (; ! shouldThreadExit();) - { - try { - middleware->tick(); - } catch(...) {} - - d_msleep(1); - } - } - DISTRHO_DECLARE_NON_COPY_CLASS(ZynAddSubFX) };