From 8d553a81aca0a5c652ab67c28348d91ec4fcaa25 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 15 Mar 2013 03:30:14 +0000 Subject: [PATCH] Load zyn programs in a separate thread, so we don't block audio --- source/backend/native/zynaddsubfx.cpp | 109 ++++++++++++++++++++------ 1 file changed, 87 insertions(+), 22 deletions(-) diff --git a/source/backend/native/zynaddsubfx.cpp b/source/backend/native/zynaddsubfx.cpp index 79d685291..e1bdb15d5 100644 --- a/source/backend/native/zynaddsubfx.cpp +++ b/source/backend/native/zynaddsubfx.cpp @@ -22,6 +22,7 @@ #include "CarlaNative.hpp" #include "CarlaMIDI.h" #include "CarlaString.hpp" +#include "CarlaThread.hpp" #include "RtList.hpp" #include "zynaddsubfx/Misc/Master.h" @@ -29,8 +30,6 @@ #include -// TODO - free sPrograms - // Dummy variables and functions for linking purposes const char* instance_name = nullptr; class WavFile; @@ -55,9 +54,12 @@ public: ZynAddSubFxPlugin(const HostDescriptor* const host) : PluginDescriptorClass(host), kMaster(new Master()), - kSampleRate(getSampleRate()) + kSampleRate(getSampleRate()), + fThread(kMaster) { - _maybeInitPrograms(kMaster); + fThread.start(); + maybeInitPrograms(kMaster); + fThread.waitForStarted(); } ~ZynAddSubFxPlugin() @@ -65,6 +67,7 @@ public: //ensure that everything has stopped pthread_mutex_lock(&kMaster->mutex); pthread_mutex_unlock(&kMaster->mutex); + fThread.stop(); delete kMaster; } @@ -174,21 +177,12 @@ protected: if (program >= BANK_SIZE) return; - const std::string& bankdir(kMaster->bank.banks[bank].dir); - - if (! bankdir.empty()) - { - pthread_mutex_lock(&kMaster->mutex); - - kMaster->bank.loadbank(bankdir); + bool isOffline = false; - for (int i=0; i < NUM_MIDI_PARTS; i++) - kMaster->bank.loadfromslot(program, kMaster->part[i]); - - pthread_mutex_unlock(&kMaster->mutex); - - kMaster->applyparameters(); - } + if (isOffline) + loadProgram(kMaster, bank, program); + else + fThread.loadLater(bank, program); } // ------------------------------------------------------------------- @@ -284,13 +278,65 @@ private: ProgramInfo(const ProgramInfo&) = delete; }; + class ZynThread : public CarlaThread + { + public: + ZynThread(Master* const master) + : kMaster(master), + fQuit(false), + fChangeNow(false), + fNextBank(0), + fNextProgram(0) + { + } + + void loadLater(const uint32_t bank, const uint32_t program) + { + fNextBank = bank; + fNextProgram = program; + fChangeNow = true; + } + + void stop() + { + fQuit = true; + CarlaThread::stop(); + } + + protected: + void run() + { + while (! fQuit) + { + if (fChangeNow) + { + loadProgram(kMaster, fNextBank, fNextProgram); + fNextBank = 0; + fNextProgram = 0; + fChangeNow = false; + } + carla_msleep(10); + } + } + + private: + Master* const kMaster; + + bool fQuit; + bool fChangeNow; + uint32_t fNextBank; + uint32_t fNextProgram; + }; + Master* const kMaster; const unsigned kSampleRate; -public: + ZynThread fThread; + static int sInstanceCount; static NonRtList sPrograms; +public: static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host) { if (sInstanceCount++ == 0) @@ -338,7 +384,7 @@ public: } } - static void _maybeInitPrograms(Master* const master) + static void maybeInitPrograms(Master* const master) { static bool doSearch = true; @@ -372,7 +418,26 @@ public: pthread_mutex_unlock(&master->mutex); } - static void _clearPrograms() + static void loadProgram(Master* const master, const uint32_t bank, const uint32_t program) + { + const std::string& bankdir(master->bank.banks[bank].dir); + + if (! bankdir.empty()) + { + pthread_mutex_lock(&master->mutex); + + master->bank.loadbank(bankdir); + + for (int i=0; i < NUM_MIDI_PARTS; i++) + master->bank.loadfromslot(program, master->part[i]); + + master->applyparameters(false); + + pthread_mutex_unlock(&master->mutex); + } + } + + static void clearPrograms() { for (auto it = sPrograms.begin(); it.valid(); it.next()) { @@ -394,7 +459,7 @@ struct ProgramsDestructor { ProgramsDestructor() {} ~ProgramsDestructor() { - ZynAddSubFxPlugin::_clearPrograms(); + ZynAddSubFxPlugin::clearPrograms(); } } programsDestructor;