| @@ -96,6 +96,452 @@ void set_module_parameters(Fl_Widget* o) | |||||
| } | } | ||||
| #endif | #endif | ||||
| // ----------------------------------------------------------------------- | |||||
| class ZynAddSubFxPrograms | |||||
| { | |||||
| public: | |||||
| ZynAddSubFxPrograms() | |||||
| : fInitiated(false) | |||||
| { | |||||
| } | |||||
| ~ZynAddSubFxPrograms() | |||||
| { | |||||
| if (! fInitiated) | |||||
| return; | |||||
| for (auto it = fPrograms.begin(); it.valid(); it.next()) | |||||
| { | |||||
| const ProgramInfo*& pInfo(*it); | |||||
| delete pInfo; | |||||
| } | |||||
| fPrograms.clear(); | |||||
| } | |||||
| void init(Master& master) | |||||
| { | |||||
| if (fInitiated) | |||||
| return; | |||||
| fInitiated = true; | |||||
| fPrograms.append(new ProgramInfo(0, 0, "default")); | |||||
| pthread_mutex_lock(&master.mutex); | |||||
| // refresh banks | |||||
| master.bank.rescanforbanks(); | |||||
| for (uint32_t i=0, size = master.bank.banks.size(); i < size; ++i) | |||||
| { | |||||
| if (master.bank.banks[i].dir.empty()) | |||||
| continue; | |||||
| master.bank.loadbank(master.bank.banks[i].dir); | |||||
| for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument) | |||||
| { | |||||
| const std::string insName(master.bank.getname(instrument)); | |||||
| if (insName.empty() || insName[0] == '\0' || insName[0] == ' ') | |||||
| continue; | |||||
| fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str())); | |||||
| } | |||||
| } | |||||
| pthread_mutex_unlock(&master.mutex); | |||||
| } | |||||
| void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program) | |||||
| { | |||||
| if (bank == 0) | |||||
| { | |||||
| pthread_mutex_lock(&master->mutex); | |||||
| master->partonoff(channel, 1); | |||||
| master->part[channel]->defaults(); | |||||
| master->part[channel]->applyparameters(false); | |||||
| pthread_mutex_unlock(&master->mutex); | |||||
| return; | |||||
| } | |||||
| const std::string& bankdir(master->bank.banks[bank-1].dir); | |||||
| if (! bankdir.empty()) | |||||
| { | |||||
| pthread_mutex_lock(&master->mutex); | |||||
| master->partonoff(channel, 1); | |||||
| master->bank.loadbank(bankdir); | |||||
| master->bank.loadfromslot(program, master->part[channel]); | |||||
| master->part[channel]->applyparameters(false); | |||||
| pthread_mutex_unlock(&master->mutex); | |||||
| } | |||||
| } | |||||
| uint32_t count() | |||||
| { | |||||
| return fPrograms.count(); | |||||
| } | |||||
| const MidiProgram* getInfo(const uint32_t index) | |||||
| { | |||||
| if (index >= fPrograms.count()) | |||||
| return nullptr; | |||||
| const ProgramInfo*& pInfo(fPrograms.getAt(index)); | |||||
| fRetProgram.bank = pInfo->bank; | |||||
| fRetProgram.program = pInfo->prog; | |||||
| fRetProgram.name = pInfo->name; | |||||
| return &fRetProgram; | |||||
| } | |||||
| private: | |||||
| struct ProgramInfo { | |||||
| uint32_t bank; | |||||
| uint32_t prog; | |||||
| const char* name; | |||||
| ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_) | |||||
| : bank(bank_), | |||||
| prog(prog_), | |||||
| name(carla_strdup(name_)) {} | |||||
| ~ProgramInfo() | |||||
| { | |||||
| if (name != nullptr) | |||||
| { | |||||
| delete[] name; | |||||
| name = nullptr; | |||||
| } | |||||
| } | |||||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||||
| ProgramInfo() = delete; | |||||
| ProgramInfo(ProgramInfo&) = delete; | |||||
| ProgramInfo(const ProgramInfo&) = delete; | |||||
| #endif | |||||
| }; | |||||
| bool fInitiated; | |||||
| MidiProgram fRetProgram; | |||||
| NonRtList<const ProgramInfo*> fPrograms; | |||||
| CARLA_DECLARE_NON_COPYABLE(ZynAddSubFxPrograms) | |||||
| }; | |||||
| static ZynAddSubFxPrograms sPrograms; | |||||
| // ----------------------------------------------------------------------- | |||||
| class ZynAddSubFxInstanceCount | |||||
| { | |||||
| public: | |||||
| ZynAddSubFxInstanceCount() | |||||
| : fCount(0) | |||||
| { | |||||
| } | |||||
| ~ZynAddSubFxInstanceCount() | |||||
| { | |||||
| CARLA_ASSERT(fCount == 0); | |||||
| } | |||||
| void addOne(HostDescriptor* host) | |||||
| { | |||||
| if (fCount++ == 0) | |||||
| { | |||||
| CARLA_ASSERT(synth == nullptr); | |||||
| CARLA_ASSERT(denormalkillbuf == nullptr); | |||||
| reinit(host); | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| if (gPixmapPath.isEmpty()) | |||||
| { | |||||
| gPixmapPath = host->resource_dir; | |||||
| gPixmapPath += PIXMAP_PATH; | |||||
| gUiPixmapPath = gPixmapPath; | |||||
| } | |||||
| #endif | |||||
| } | |||||
| } | |||||
| void removeOne() | |||||
| { | |||||
| if (--fCount == 0) | |||||
| { | |||||
| CARLA_ASSERT(synth != nullptr); | |||||
| CARLA_ASSERT(denormalkillbuf != nullptr); | |||||
| Master::deleteInstance(); | |||||
| delete[] denormalkillbuf; | |||||
| denormalkillbuf = nullptr; | |||||
| delete synth; | |||||
| synth = nullptr; | |||||
| } | |||||
| } | |||||
| void reinit(HostDescriptor* host) | |||||
| { | |||||
| Master::deleteInstance(); | |||||
| if (denormalkillbuf != nullptr) | |||||
| { | |||||
| delete[] denormalkillbuf; | |||||
| denormalkillbuf = nullptr; | |||||
| } | |||||
| if (synth != nullptr) | |||||
| { | |||||
| delete synth; | |||||
| synth = nullptr; | |||||
| } | |||||
| synth = new SYNTH_T(); | |||||
| synth->buffersize = host->get_buffer_size(host->handle); | |||||
| synth->samplerate = host->get_sample_rate(host->handle); | |||||
| synth->alias(); | |||||
| config.init(); | |||||
| config.cfg.SoundBufferSize = synth->buffersize; | |||||
| config.cfg.SampleRate = synth->samplerate; | |||||
| config.cfg.GzipCompression = 0; | |||||
| sprng(std::time(nullptr)); | |||||
| denormalkillbuf = new float[synth->buffersize]; | |||||
| for (int i=0; i < synth->buffersize; ++i) | |||||
| denormalkillbuf[i] = (RND - 0.5f) * 1e-16; | |||||
| sPrograms.init(Master::getInstance()); | |||||
| } | |||||
| private: | |||||
| int fCount; | |||||
| CARLA_DECLARE_NON_COPYABLE(ZynAddSubFxInstanceCount) | |||||
| }; | |||||
| static ZynAddSubFxInstanceCount sInstanceCount; | |||||
| // ----------------------------------------------------------------------- | |||||
| class ZynAddSubFxThread : public QThread | |||||
| { | |||||
| public: | |||||
| ZynAddSubFxThread(Master* const master, const HostDescriptor* const host) | |||||
| : fMaster(master), | |||||
| kHost(host), | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| fUi(nullptr), | |||||
| fUiClosed(0), | |||||
| fNextUiAction(-1), | |||||
| #endif | |||||
| fQuit(false), | |||||
| fChangeProgram(false), | |||||
| fNextChannel(0), | |||||
| fNextBank(0), | |||||
| fNextProgram(0) | |||||
| { | |||||
| } | |||||
| ~ZynAddSubFxThread() | |||||
| { | |||||
| // must be closed by now | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| CARLA_ASSERT(fUi == nullptr); | |||||
| #endif | |||||
| CARLA_ASSERT(fQuit); | |||||
| } | |||||
| void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program) | |||||
| { | |||||
| fNextChannel = channel; | |||||
| fNextBank = bank; | |||||
| fNextProgram = program; | |||||
| fChangeProgram = true; | |||||
| } | |||||
| void stopLoadProgramLater() | |||||
| { | |||||
| fChangeProgram = false; | |||||
| fNextChannel = 0; | |||||
| fNextBank = 0; | |||||
| fNextProgram = 0; | |||||
| } | |||||
| void setMaster(Master* const master) | |||||
| { | |||||
| fMaster = master; | |||||
| } | |||||
| void stop() | |||||
| { | |||||
| fQuit = true; | |||||
| quit(); | |||||
| } | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| void uiHide() | |||||
| { | |||||
| fNextUiAction = 0; | |||||
| } | |||||
| void uiShow() | |||||
| { | |||||
| fNextUiAction = 1; | |||||
| } | |||||
| void uiRepaint() | |||||
| { | |||||
| if (fUi != nullptr) | |||||
| fNextUiAction = 2; | |||||
| } | |||||
| #endif | |||||
| protected: | |||||
| void run() override | |||||
| { | |||||
| while (! fQuit) | |||||
| { | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| Fl::lock(); | |||||
| if (fNextUiAction == 2) // repaint | |||||
| { | |||||
| CARLA_ASSERT(fUi != nullptr); | |||||
| if (fUi != nullptr) | |||||
| fUi->refresh_master_ui(); | |||||
| } | |||||
| else if (fNextUiAction == 1) // init/show | |||||
| { | |||||
| static bool initialized = false; | |||||
| if (! initialized) | |||||
| { | |||||
| initialized = true; | |||||
| fl_register_images(); | |||||
| Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL); | |||||
| if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png")) | |||||
| Fl_Dial::default_image(img); | |||||
| if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png")) | |||||
| Fl::scheme_bg(new Fl_Tiled_Image(img)); | |||||
| if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png")) | |||||
| gModuleBackdrop = new Fl_Tiled_Image(img); | |||||
| Fl::background(50, 50, 50); | |||||
| Fl::background2(70, 70, 70); | |||||
| Fl::foreground(255, 255, 255); | |||||
| Fl_Theme::set("Cairo"); | |||||
| } | |||||
| CARLA_ASSERT(fUi == nullptr); | |||||
| if (fUi == nullptr) | |||||
| { | |||||
| fUiClosed = 0; | |||||
| fUi = new MasterUI(fMaster, &fUiClosed); | |||||
| fUi->showUI(); | |||||
| } | |||||
| } | |||||
| else if (fNextUiAction == 0) // close | |||||
| { | |||||
| CARLA_ASSERT(fUi != nullptr); | |||||
| if (fUi != nullptr) | |||||
| { | |||||
| delete fUi; | |||||
| fUi = nullptr; | |||||
| } | |||||
| } | |||||
| fNextUiAction = -1; | |||||
| if (fUiClosed != 0) | |||||
| { | |||||
| fUiClosed = 0; | |||||
| fNextUiAction = 0; | |||||
| kHost->ui_closed(kHost->handle); | |||||
| } | |||||
| Fl::check(); | |||||
| Fl::unlock(); | |||||
| #endif | |||||
| if (fChangeProgram) | |||||
| { | |||||
| fChangeProgram = false; | |||||
| sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram); | |||||
| fNextChannel = 0; | |||||
| fNextBank = 0; | |||||
| fNextProgram = 0; | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| if (fUi != nullptr) | |||||
| { | |||||
| Fl::lock(); | |||||
| fUi->refresh_master_ui(); | |||||
| Fl::unlock(); | |||||
| } | |||||
| #endif | |||||
| carla_msleep(15); | |||||
| } | |||||
| else | |||||
| { | |||||
| carla_msleep(30); | |||||
| } | |||||
| } | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| if (fQuit && fUi != nullptr) | |||||
| { | |||||
| Fl::lock(); | |||||
| delete fUi; | |||||
| fUi = nullptr; | |||||
| Fl::check(); | |||||
| Fl::unlock(); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| private: | |||||
| Master* fMaster; | |||||
| const HostDescriptor* const kHost; | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| MasterUI* fUi; | |||||
| int fUiClosed; | |||||
| int fNextUiAction; | |||||
| #endif | |||||
| bool fQuit; | |||||
| bool fChangeProgram; | |||||
| uint8_t fNextChannel; | |||||
| uint32_t fNextBank; | |||||
| uint32_t fNextProgram; | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| class ZynAddSubFxPlugin : public PluginDescriptorClass | class ZynAddSubFxPlugin : public PluginDescriptorClass | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -111,7 +557,6 @@ public: | |||||
| fThread(fMaster, host) | fThread(fMaster, host) | ||||
| { | { | ||||
| fThread.start(); | fThread.start(); | ||||
| maybeInitPrograms(fMaster); | |||||
| for (int i = 0; i < NUM_MIDI_PARTS; ++i) | for (int i = 0; i < NUM_MIDI_PARTS; ++i) | ||||
| fMaster->partonoff(i, 1); | fMaster->partonoff(i, 1); | ||||
| @@ -195,19 +640,7 @@ protected: | |||||
| const MidiProgram* getMidiProgramInfo(const uint32_t index) override | const MidiProgram* getMidiProgramInfo(const uint32_t index) override | ||||
| { | { | ||||
| CARLA_ASSERT(index < getMidiProgramCount()); | |||||
| if (index >= sPrograms.count()) | |||||
| return nullptr; | |||||
| const ProgramInfo* const pInfo(sPrograms.getAt(index)); | |||||
| static MidiProgram midiProgram; | |||||
| midiProgram.bank = pInfo->bank; | |||||
| midiProgram.program = pInfo->prog; | |||||
| midiProgram.name = pInfo->name; | |||||
| return &midiProgram; | |||||
| return sPrograms.getInfo(index); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -236,13 +669,13 @@ protected: | |||||
| if (isOffline() || ! fIsActive) | if (isOffline() || ! fIsActive) | ||||
| { | { | ||||
| loadProgram(fMaster, channel, bank, program); | |||||
| sPrograms.load(fMaster, channel, bank, program); | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | #ifdef WANT_ZYNADDSUBFX_UI | ||||
| fThread.uiRepaint(); | fThread.uiRepaint(); | ||||
| #endif | #endif | ||||
| } | } | ||||
| else | else | ||||
| fThread.loadLater(channel, bank, program); | |||||
| fThread.loadProgramLater(channel, bank, program); | |||||
| } | } | ||||
| void setCustomData(const char* const key, const char* const value) override | void setCustomData(const char* const key, const char* const value) override | ||||
| @@ -354,7 +787,7 @@ protected: | |||||
| void setState(const char* const data) override | void setState(const char* const data) override | ||||
| { | { | ||||
| fThread.stopLoadLater(); | |||||
| fThread.stopLoadProgramLater(); | |||||
| fMaster->putalldata((char*)data, 0); | fMaster->putalldata((char*)data, 0); | ||||
| fMaster->applyparameters(true); | fMaster->applyparameters(true); | ||||
| } | } | ||||
| @@ -394,340 +827,16 @@ protected: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| private: | private: | ||||
| struct ProgramInfo { | |||||
| uint32_t bank; | |||||
| uint32_t prog; | |||||
| const char* name; | |||||
| ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_) | |||||
| : bank(bank_), | |||||
| prog(prog_), | |||||
| name(carla_strdup(name_)) {} | |||||
| ~ProgramInfo() | |||||
| { | |||||
| if (name != nullptr) | |||||
| { | |||||
| delete[] name; | |||||
| name = nullptr; | |||||
| } | |||||
| } | |||||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||||
| ProgramInfo() = delete; | |||||
| ProgramInfo(ProgramInfo&) = delete; | |||||
| ProgramInfo(const ProgramInfo&) = delete; | |||||
| #endif | |||||
| }; | |||||
| class ZynThread : public QThread | |||||
| { | |||||
| public: | |||||
| ZynThread(Master* const master, const HostDescriptor* const host) | |||||
| : fMaster(master), | |||||
| kHost(host), | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| fUi(nullptr), | |||||
| fUiClosed(0), | |||||
| fNextUiAction(-1), | |||||
| #endif | |||||
| fQuit(false), | |||||
| fChangeProgram(false), | |||||
| fNextChannel(0), | |||||
| fNextBank(0), | |||||
| fNextProgram(0) | |||||
| { | |||||
| } | |||||
| ~ZynThread() | |||||
| { | |||||
| // must be closed by now | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| CARLA_ASSERT(fUi == nullptr); | |||||
| #endif | |||||
| CARLA_ASSERT(fQuit); | |||||
| } | |||||
| void loadLater(const uint8_t channel, const uint32_t bank, const uint32_t program) | |||||
| { | |||||
| fNextChannel = channel; | |||||
| fNextBank = bank; | |||||
| fNextProgram = program; | |||||
| fChangeProgram = true; | |||||
| } | |||||
| void stopLoadLater() | |||||
| { | |||||
| fChangeProgram = false; | |||||
| fNextChannel = 0; | |||||
| fNextBank = 0; | |||||
| fNextProgram = 0; | |||||
| } | |||||
| void stop() | |||||
| { | |||||
| fQuit = true; | |||||
| quit(); | |||||
| } | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| void uiHide() | |||||
| { | |||||
| fNextUiAction = 0; | |||||
| } | |||||
| void uiShow() | |||||
| { | |||||
| fNextUiAction = 1; | |||||
| } | |||||
| void uiRepaint() | |||||
| { | |||||
| if (fUi != nullptr) | |||||
| fNextUiAction = 2; | |||||
| } | |||||
| #endif | |||||
| protected: | |||||
| void run() override | |||||
| { | |||||
| while (! fQuit) | |||||
| { | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| Fl::lock(); | |||||
| if (fNextUiAction == 2) // repaint | |||||
| { | |||||
| CARLA_ASSERT(fUi != nullptr); | |||||
| if (fUi != nullptr) | |||||
| fUi->refresh_master_ui(); | |||||
| } | |||||
| else if (fNextUiAction == 1) // init/show | |||||
| { | |||||
| static bool initialized = false; | |||||
| if (! initialized) | |||||
| { | |||||
| initialized = true; | |||||
| fl_register_images(); | |||||
| Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL); | |||||
| if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png")) | |||||
| Fl_Dial::default_image(img); | |||||
| if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png")) | |||||
| Fl::scheme_bg(new Fl_Tiled_Image(img)); | |||||
| if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png")) | |||||
| gModuleBackdrop = new Fl_Tiled_Image(img); | |||||
| Fl::background(50, 50, 50); | |||||
| Fl::background2(70, 70, 70); | |||||
| Fl::foreground(255, 255, 255); | |||||
| Fl_Theme::set("Cairo"); | |||||
| } | |||||
| CARLA_ASSERT(fUi == nullptr); | |||||
| if (fUi == nullptr) | |||||
| { | |||||
| fUiClosed = 0; | |||||
| fUi = new MasterUI(fMaster, &fUiClosed); | |||||
| fUi->showUI(); | |||||
| } | |||||
| } | |||||
| else if (fNextUiAction == 0) // close | |||||
| { | |||||
| CARLA_ASSERT(fUi != nullptr); | |||||
| if (fUi != nullptr) | |||||
| { | |||||
| delete fUi; | |||||
| fUi = nullptr; | |||||
| } | |||||
| } | |||||
| fNextUiAction = -1; | |||||
| if (fUiClosed != 0) | |||||
| { | |||||
| fUiClosed = 0; | |||||
| fNextUiAction = 0; | |||||
| kHost->ui_closed(kHost->handle); | |||||
| } | |||||
| Fl::check(); | |||||
| Fl::unlock(); | |||||
| #endif | |||||
| if (fChangeProgram) | |||||
| { | |||||
| fChangeProgram = false; | |||||
| loadProgram(fMaster, fNextChannel, fNextBank, fNextProgram); | |||||
| fNextChannel = 0; | |||||
| fNextBank = 0; | |||||
| fNextProgram = 0; | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| if (fUi != nullptr) | |||||
| { | |||||
| Fl::lock(); | |||||
| fUi->refresh_master_ui(); | |||||
| Fl::unlock(); | |||||
| } | |||||
| #endif | |||||
| carla_msleep(15); | |||||
| } | |||||
| else | |||||
| { | |||||
| carla_msleep(30); | |||||
| } | |||||
| } | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| if (fQuit && fUi != nullptr) | |||||
| { | |||||
| Fl::lock(); | |||||
| delete fUi; | |||||
| fUi = nullptr; | |||||
| Fl::check(); | |||||
| Fl::unlock(); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| private: | |||||
| Master* const fMaster; | |||||
| const HostDescriptor* const kHost; | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| MasterUI* fUi; | |||||
| int fUiClosed; | |||||
| int fNextUiAction; | |||||
| #endif | |||||
| bool fQuit; | |||||
| bool fChangeProgram; | |||||
| uint8_t fNextChannel; | |||||
| uint32_t fNextBank; | |||||
| uint32_t fNextProgram; | |||||
| }; | |||||
| Master* fMaster; | Master* fMaster; | ||||
| unsigned fSampleRate; | unsigned fSampleRate; | ||||
| bool fIsActive; | |||||
| ZynThread fThread; | |||||
| static int sInstanceCount; | |||||
| static NonRtList<ProgramInfo*> sPrograms; | |||||
| static void maybeInitPrograms(Master* const master) | |||||
| { | |||||
| static bool doSearch = true; | |||||
| if (! doSearch) | |||||
| return; | |||||
| doSearch = false; | |||||
| sPrograms.append(new ProgramInfo(0, 0, "default")); | |||||
| pthread_mutex_lock(&master->mutex); | |||||
| // refresh banks | |||||
| master->bank.rescanforbanks(); | |||||
| for (uint32_t i=0, size = master->bank.banks.size(); i < size; ++i) | |||||
| { | |||||
| if (master->bank.banks[i].dir.empty()) | |||||
| continue; | |||||
| master->bank.loadbank(master->bank.banks[i].dir); | |||||
| for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument) | |||||
| { | |||||
| const std::string insName(master->bank.getname(instrument)); | |||||
| if (insName.empty() || insName[0] == '\0' || insName[0] == ' ') | |||||
| continue; | |||||
| sPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str())); | |||||
| } | |||||
| } | |||||
| pthread_mutex_unlock(&master->mutex); | |||||
| } | |||||
| static void loadProgram(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program) | |||||
| { | |||||
| if (bank == 0) | |||||
| { | |||||
| pthread_mutex_lock(&master->mutex); | |||||
| master->part[channel]->defaults(); | |||||
| master->part[channel]->applyparameters(false); | |||||
| master->partonoff(channel, 1); | |||||
| pthread_mutex_unlock(&master->mutex); | |||||
| return; | |||||
| } | |||||
| const std::string& bankdir(master->bank.banks[bank-1].dir); | |||||
| if (! bankdir.empty()) | |||||
| { | |||||
| pthread_mutex_lock(&master->mutex); | |||||
| master->partonoff(channel, 1); | |||||
| master->bank.loadbank(bankdir); | |||||
| master->bank.loadfromslot(program, master->part[channel]); | |||||
| master->part[channel]->applyparameters(false); | |||||
| bool fIsActive; | |||||
| pthread_mutex_unlock(&master->mutex); | |||||
| } | |||||
| } | |||||
| ZynAddSubFxThread fThread; | |||||
| public: | public: | ||||
| static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host) | static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host) | ||||
| { | { | ||||
| if (sInstanceCount++ == 0) | |||||
| { | |||||
| CARLA_ASSERT(synth == nullptr); | |||||
| CARLA_ASSERT(denormalkillbuf == nullptr); | |||||
| synth = new SYNTH_T(); | |||||
| synth->buffersize = host->get_buffer_size(host->handle); | |||||
| synth->samplerate = host->get_sample_rate(host->handle); | |||||
| synth->alias(); | |||||
| config.init(); | |||||
| config.cfg.SoundBufferSize = synth->buffersize; | |||||
| config.cfg.SampleRate = synth->samplerate; | |||||
| config.cfg.GzipCompression = 0; | |||||
| sprng(std::time(nullptr)); | |||||
| denormalkillbuf = new float[synth->buffersize]; | |||||
| for (int i=0; i < synth->buffersize; ++i) | |||||
| denormalkillbuf[i] = (RND - 0.5f) * 1e-16; | |||||
| Master::getInstance(); | |||||
| #ifdef WANT_ZYNADDSUBFX_UI | |||||
| if (gPixmapPath.isEmpty()) | |||||
| { | |||||
| gPixmapPath = host->resource_dir; | |||||
| gPixmapPath += PIXMAP_PATH; | |||||
| gUiPixmapPath = gPixmapPath; | |||||
| } | |||||
| #endif | |||||
| } | |||||
| sInstanceCount.addOne(host); | |||||
| return new ZynAddSubFxPlugin(host); | return new ZynAddSubFxPlugin(host); | ||||
| } | } | ||||
| @@ -736,46 +845,13 @@ public: | |||||
| { | { | ||||
| delete (ZynAddSubFxPlugin*)handle; | delete (ZynAddSubFxPlugin*)handle; | ||||
| if (--sInstanceCount == 0) | |||||
| { | |||||
| CARLA_ASSERT(synth != nullptr); | |||||
| CARLA_ASSERT(denormalkillbuf != nullptr); | |||||
| Master::deleteInstance(); | |||||
| delete[] denormalkillbuf; | |||||
| denormalkillbuf = nullptr; | |||||
| delete synth; | |||||
| synth = nullptr; | |||||
| } | |||||
| } | |||||
| static void _clearPrograms() | |||||
| { | |||||
| for (auto it = sPrograms.begin(); it.valid(); it.next()) | |||||
| { | |||||
| ProgramInfo* const programInfo(*it); | |||||
| delete programInfo; | |||||
| } | |||||
| sPrograms.clear(); | |||||
| sInstanceCount.removeOne(); | |||||
| } | } | ||||
| private: | private: | ||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) | ||||
| }; | }; | ||||
| int ZynAddSubFxPlugin::sInstanceCount = 0; | |||||
| NonRtList<ZynAddSubFxPlugin::ProgramInfo*> ZynAddSubFxPlugin::sPrograms; | |||||
| static const struct ProgramsDestructor { | |||||
| ProgramsDestructor() {} | |||||
| ~ProgramsDestructor() { | |||||
| ZynAddSubFxPlugin::_clearPrograms(); | |||||
| } | |||||
| } _programsDestructor; | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| static const PluginDescriptor zynaddsubfxDesc = { | static const PluginDescriptor zynaddsubfxDesc = { | ||||