| @@ -10,6 +10,6 @@ export CFLAGS="-DJACKBRIDGE_DIRECT=1 -DSTOAT_TEST_BUILD=1" | |||
| export CXXFLAGS=${CFLAGS} | |||
| export LDFLAGS="-ljack" | |||
| make -j 8 EXTERNAL_PLUGINS=false backend | |||
| make -j 8 EXTERNAL_PLUGINS=false backend && \ | |||
| stoat --recursive build/ -b data/stoat/blacklist.txt -w data/stoat/whitelist.txt | |||
| # -G stoat-output.png | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -632,6 +632,12 @@ public: | |||
| */ | |||
| void setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept; | |||
| /*! | |||
| * Overloaded functions, to be called from within RT context only. | |||
| */ | |||
| virtual void setProgramRT(const uint32_t index) noexcept; | |||
| virtual void setMidiProgramRT(const uint32_t index) noexcept; | |||
| // ------------------------------------------------------------------- | |||
| // Plugin state | |||
| @@ -1690,10 +1690,17 @@ void CarlaPlugin::setProgram(const int32_t index, const bool sendGui, const bool | |||
| if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0) | |||
| uiProgramChange(static_cast<uint32_t>(index)); | |||
| if (getType() == PLUGIN_GIG || getType() == PLUGIN_SF2 || getType() == PLUGIN_SFZ) | |||
| return; | |||
| switch (getType()) | |||
| { | |||
| case PLUGIN_GIG: | |||
| case PLUGIN_SF2: | |||
| case PLUGIN_SFZ: | |||
| break; | |||
| pData->updateParameterValues(this, reallySendOsc, sendCallback, true); | |||
| default: | |||
| pData->updateParameterValues(this, reallySendOsc, sendCallback, true); | |||
| break; | |||
| } | |||
| } | |||
| // may be unused | |||
| @@ -1718,15 +1725,23 @@ void CarlaPlugin::setMidiProgram(const int32_t index, const bool sendGui, const | |||
| if (sendCallback) | |||
| pData->engine->callback(ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr); | |||
| // Change default parameter values | |||
| if (index >= 0) | |||
| { | |||
| if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0) | |||
| uiMidiProgramChange(static_cast<uint32_t>(index)); | |||
| if (getType() == PLUGIN_GIG || getType() == PLUGIN_SF2 || getType() == PLUGIN_SFZ) | |||
| return; | |||
| switch (getType()) | |||
| { | |||
| case PLUGIN_GIG: | |||
| case PLUGIN_SF2: | |||
| case PLUGIN_SFZ: | |||
| break; | |||
| pData->updateParameterValues(this, reallySendOsc, sendCallback, true); | |||
| default: | |||
| pData->updateParameterValues(this, reallySendOsc, sendCallback, true); | |||
| break; | |||
| } | |||
| } | |||
| // may be unused | |||
| @@ -1742,6 +1757,52 @@ void CarlaPlugin::setMidiProgramById(const uint32_t bank, const uint32_t program | |||
| } | |||
| } | |||
| void CarlaPlugin::setProgramRT(const uint32_t uindex) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,); | |||
| const int32_t index = static_cast<int32_t>(uindex); | |||
| pData->prog.current = index; | |||
| // Change default parameter values | |||
| switch (getType()) | |||
| { | |||
| case PLUGIN_GIG: | |||
| case PLUGIN_SF2: | |||
| case PLUGIN_SFZ: | |||
| break; | |||
| default: | |||
| pData->updateDefaultParameterValues(this); | |||
| break; | |||
| } | |||
| pData->postponeRtEvent(kPluginPostRtEventProgramChange, index, 0, 0.0f); | |||
| } | |||
| void CarlaPlugin::setMidiProgramRT(const uint32_t uindex) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); | |||
| const int32_t index = static_cast<int32_t>(uindex); | |||
| pData->midiprog.current = index; | |||
| // Change default parameter values | |||
| switch (getType()) | |||
| { | |||
| case PLUGIN_GIG: | |||
| case PLUGIN_SF2: | |||
| case PLUGIN_SFZ: | |||
| break; | |||
| default: | |||
| pData->updateDefaultParameterValues(this); | |||
| break; | |||
| } | |||
| pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, index, 0, 0.0f); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin state | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Bridge | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -659,7 +659,7 @@ public: | |||
| void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); | |||
| { | |||
| const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | |||
| @@ -677,8 +677,8 @@ public: | |||
| void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| const float fixedValue(pData->param.getFixedValue(parameterId, value)); | |||
| fParams[parameterId].value = fixedValue; | |||
| @@ -698,9 +698,9 @@ public: | |||
| void setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); | |||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||
| CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); | |||
| { | |||
| const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | |||
| @@ -716,9 +716,9 @@ public: | |||
| void setParameterMidiCC(const uint32_t parameterId, const int16_t cc, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); | |||
| CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL,); | |||
| CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); | |||
| { | |||
| const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | |||
| @@ -734,8 +734,8 @@ public: | |||
| void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| { | |||
| const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | |||
| @@ -750,8 +750,8 @@ public: | |||
| void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| { | |||
| const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | |||
| @@ -764,6 +764,21 @@ public: | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setMidiProgramRT(const uint32_t uindex) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); | |||
| { | |||
| const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | |||
| fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram); | |||
| fShmNonRtClientControl.writeInt(static_cast<int32_t>(uindex)); | |||
| fShmNonRtClientControl.commitWrite(); | |||
| } | |||
| CarlaPlugin::setMidiProgramRT(uindex); | |||
| } | |||
| void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); | |||
| @@ -1420,11 +1435,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| carla_zeroFloats(audioOut[i], frames); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin, DSSI implementation | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -645,28 +645,45 @@ public: | |||
| CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| if (index >= 0 && fHandles.count() > 0) | |||
| { | |||
| const uint32_t bank(pData->midiprog.data[index].bank); | |||
| const uint32_t program(pData->midiprog.data[index].program); | |||
| const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next()) | |||
| { | |||
| LADSPA_Handle const handle(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); | |||
| try { | |||
| fDssiDescriptor->select_program(handle, bank, program); | |||
| } CARLA_SAFE_EXCEPTION("DSSI setMidiProgram") | |||
| } | |||
| setMidiProgramInDSSI(static_cast<uint32_t>(index)); | |||
| } | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setMidiProgramRT(const uint32_t uindex) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); | |||
| setMidiProgramInDSSI(uindex); | |||
| CarlaPlugin::setMidiProgramRT(uindex); | |||
| } | |||
| void setMidiProgramInDSSI(const uint32_t uindex) noexcept | |||
| { | |||
| const uint32_t bank(pData->midiprog.data[uindex].bank); | |||
| const uint32_t program(pData->midiprog.data[uindex].program); | |||
| for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next()) | |||
| { | |||
| LADSPA_Handle const handle(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr); | |||
| try { | |||
| fDssiDescriptor->select_program(handle, bank, program); | |||
| } CARLA_SAFE_EXCEPTION("DSSI setMidiProgram") | |||
| } | |||
| } | |||
| #ifdef HAVE_LIBLO | |||
| // ------------------------------------------------------------------- | |||
| // Set ui stuff | |||
| @@ -1542,9 +1559,7 @@ public: | |||
| { | |||
| if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId) | |||
| { | |||
| const int32_t index(static_cast<int32_t>(k)); | |||
| setMidiProgram(index, false, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, index, 0, 0.0f); | |||
| setMidiProgramRT(k); | |||
| break; | |||
| } | |||
| } | |||
| @@ -1756,11 +1771,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla FluidSynth Plugin | |||
| * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -387,6 +387,7 @@ public: | |||
| void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| float fixedValue; | |||
| @@ -530,17 +531,18 @@ public: | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| if (index >= 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | |||
| { | |||
| const uint32_t bank = pData->midiprog.data[index].bank; | |||
| const uint32_t program = pData->midiprog.data[index].program; | |||
| //const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| try { | |||
| fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program); | |||
| } catch(...) {} | |||
| } CARLA_SAFE_EXCEPTION("fluid_synth_program_select") | |||
| fCurMidiProgs[pData->ctrlChannel] = index; | |||
| } | |||
| @@ -548,6 +550,26 @@ public: | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setMidiProgramRT(const uint32_t uindex) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); | |||
| if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | |||
| { | |||
| const uint32_t bank = pData->midiprog.data[uindex].bank; | |||
| const uint32_t program = pData->midiprog.data[uindex].program; | |||
| try { | |||
| fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program); | |||
| } CARLA_SAFE_EXCEPTION("fluid_synth_program_select") | |||
| fCurMidiProgs[pData->ctrlChannel] = static_cast<int32_t>(uindex); | |||
| } | |||
| CarlaPlugin::setMidiProgramRT(uindex); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Set ui stuff | |||
| @@ -1403,11 +1425,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||
| @@ -819,6 +819,12 @@ void CarlaPlugin::ProtectedData::updateParameterValues(CarlaPlugin* const plugin | |||
| return; (void)sendOsc; | |||
| } | |||
| void CarlaPlugin::ProtectedData::updateDefaultParameterValues(CarlaPlugin* const plugin) noexcept | |||
| { | |||
| for (uint32_t i=0; i < param.count; ++i) | |||
| param.ranges[i].def = param.ranges[i].getFixedValue(plugin->getParameterValue(i)); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| @@ -370,6 +370,7 @@ struct CarlaPlugin::ProtectedData { | |||
| void tryTransient() noexcept; | |||
| #endif | |||
| void updateParameterValues(CarlaPlugin* const plugin, const bool sendOsc, const bool sendCallback, const bool useDefault) noexcept; | |||
| void updateDefaultParameterValues(CarlaPlugin* const plugin) noexcept; | |||
| // ------------------------------------------------------------------- | |||
| @@ -918,11 +918,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| carla_zeroFloats(audioOut[i], frames); | |||
| @@ -1120,11 +1120,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla LV2 Plugin | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -1227,6 +1227,7 @@ public: | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| if (index >= 0 && index < static_cast<int32_t>(fRdfDescriptor->PresetCount)) | |||
| { | |||
| @@ -1263,6 +1264,7 @@ public: | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| if (index >= 0 && fExt.programs != nullptr && fExt.programs->select_program != nullptr) | |||
| { | |||
| @@ -1286,6 +1288,31 @@ public: | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setMidiProgramRT(const uint32_t uindex) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,); | |||
| if (fExt.programs != nullptr && fExt.programs->select_program != nullptr) | |||
| { | |||
| const uint32_t bank(pData->midiprog.data[uindex].bank); | |||
| const uint32_t program(pData->midiprog.data[uindex].program); | |||
| try { | |||
| fExt.programs->select_program(fHandle, bank, program); | |||
| } catch(...) {} | |||
| if (fHandle2 != nullptr) | |||
| { | |||
| try { | |||
| fExt.programs->select_program(fHandle2, bank, program); | |||
| } catch(...) {} | |||
| } | |||
| } | |||
| CarlaPlugin::setMidiProgramRT(uindex); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Set ui stuff | |||
| @@ -2997,7 +3024,7 @@ public: | |||
| } | |||
| else if (! lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom))) | |||
| { | |||
| carla_stdout("Event input buffer full, at least 1 message lost"); | |||
| carla_stderr2("Event input buffer full, at least 1 message lost"); | |||
| continue; | |||
| } | |||
| } | |||
| @@ -3279,9 +3306,7 @@ public: | |||
| { | |||
| if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId) | |||
| { | |||
| const int32_t index(static_cast<int32_t>(k)); | |||
| setMidiProgram(index, false, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, index, 0, 0.0f); | |||
| setMidiProgramRT(k); | |||
| break; | |||
| } | |||
| } | |||
| @@ -3597,11 +3622,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla LinuxSampler Plugin | |||
| * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -488,7 +488,10 @@ public: | |||
| const int index(it->getIntValue()); | |||
| if (index >= 0) | |||
| setProgramInternal(static_cast<uint>(index), channel, true, false); | |||
| { | |||
| const ScopedSingleProcessLocker spl(this, true); | |||
| setProgramInternal(static_cast<uint>(index), channel); | |||
| } | |||
| if (++channel >= MAX_MIDI_CHANNELS) | |||
| break; | |||
| @@ -502,57 +505,72 @@ public: | |||
| void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| const int8_t channel(kIsGIG ? pData->ctrlChannel : int8_t(0)); | |||
| if (index >= 0 && channel >= 0) | |||
| setProgramInternal(static_cast<uint>(index), static_cast<uint8_t>(channel), sendCallback, false); | |||
| { | |||
| const uint32_t uindex = static_cast<uint32_t>(index); | |||
| bool internalSetOk; | |||
| { | |||
| const ScopedSingleProcessLocker spl(this, sendGui || sendOsc || sendCallback); | |||
| internalSetOk = setProgramInternal(uindex, static_cast<uint8_t>(channel)); | |||
| } | |||
| if (internalSetOk && sendCallback) | |||
| pData->engine->callback(ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr); | |||
| } | |||
| CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setProgramInternal(const uint32_t index, const uint8_t channel, const bool sendCallback, const bool inRtContent) noexcept | |||
| void setProgramRT(const uint32_t uindex) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,); | |||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,); | |||
| const int8_t channel(kIsGIG ? pData->ctrlChannel : int8_t(0)); | |||
| if (fCurProgs[channel] == index) | |||
| if (channel < 0) | |||
| return; | |||
| if (! setProgramInternal(uindex, static_cast<uint8_t>(channel))) | |||
| return; | |||
| LinuxSampler::EngineChannel* const engineChannel(fEngineChannels[kIsGIG ? channel : 0]); | |||
| CARLA_SAFE_ASSERT_RETURN(engineChannel != nullptr,); | |||
| CarlaPlugin::setProgramRT(uindex); | |||
| } | |||
| const ScopedSingleProcessLocker spl(this, !inRtContent); | |||
| bool setProgramInternal(const uint32_t uindex, const uint8_t channel) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); | |||
| if (fCurProgs[channel] == uindex) | |||
| return false; | |||
| LinuxSampler::EngineChannel* const engineChannel(fEngineChannels[kIsGIG ? channel : 0]); | |||
| CARLA_SAFE_ASSERT_RETURN(engineChannel != nullptr, false); | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| try { | |||
| engineChannel->PrepareLoadInstrument(pData->filename, index); | |||
| engineChannel->PrepareLoadInstrument(pData->filename, uindex); | |||
| engineChannel->LoadInstrument(); | |||
| } CARLA_SAFE_EXCEPTION("LoadInstrument"); | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| try { | |||
| LinuxSampler::InstrumentManager::LoadInstrumentInBackground(fInstrumentIds[index], engineChannel); | |||
| LinuxSampler::InstrumentManager::LoadInstrumentInBackground(fInstrumentIds[uindex], engineChannel); | |||
| } CARLA_SAFE_EXCEPTION("LoadInstrumentInBackground"); | |||
| } | |||
| fCurProgs[channel] = index; | |||
| if (pData->ctrlChannel == channel) | |||
| { | |||
| const int32_t iindex(static_cast<int32_t>(index)); | |||
| pData->prog.current = iindex; | |||
| fCurProgs[channel] = uindex; | |||
| if (inRtContent) | |||
| pData->postponeRtEvent(kPluginPostRtEventProgramChange, iindex, 0, 0.0f); | |||
| else if (sendCallback) | |||
| pData->engine->callback(ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, iindex, 0, 0.0f, nullptr); | |||
| } | |||
| return (pData->ctrlChannel == channel); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -1005,9 +1023,7 @@ public: | |||
| case kEngineControlEventTypeMidiProgram: | |||
| if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) | |||
| { | |||
| setProgramInternal(ctrlEvent.param, event.channel, false, true); | |||
| } | |||
| setProgramInternal(ctrlEvent.param, event.channel); | |||
| break; | |||
| case kEngineControlEventTypeAllSoundOff: | |||
| @@ -1103,11 +1119,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugin | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -716,6 +716,7 @@ public: | |||
| CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| // TODO, put into check below | |||
| if ((pData->hints & PLUGIN_IS_SYNTH) != 0 && (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)) | |||
| @@ -746,6 +747,36 @@ public: | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setMidiProgramRT(const uint32_t index) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); | |||
| // TODO, put into check below | |||
| if ((pData->hints & PLUGIN_IS_SYNTH) != 0 && (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)) | |||
| return CarlaPlugin::setMidiProgramRT(index); | |||
| const uint8_t channel = uint8_t((pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0); | |||
| const uint32_t bank = pData->midiprog.data[index].bank; | |||
| const uint32_t program = pData->midiprog.data[index].program; | |||
| try { | |||
| fDescriptor->set_midi_program(fHandle, channel, bank, program); | |||
| } catch(...) {} | |||
| if (fHandle2 != nullptr) | |||
| { | |||
| try { | |||
| fDescriptor->set_midi_program(fHandle2, channel, bank, program); | |||
| } catch(...) {} | |||
| } | |||
| fCurMidiProgs[channel] = index; | |||
| CarlaPlugin::setMidiProgramRT(index); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Set ui stuff | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla VST Plugin | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -409,6 +409,7 @@ public: | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),); | |||
| CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); | |||
| if (index >= 0) | |||
| { | |||
| @@ -432,6 +433,26 @@ public: | |||
| CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setProgramRT(const uint32_t uindex) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,); | |||
| try { | |||
| dispatcher(effBeginSetProgram, 0, 0, nullptr, 0.0f); | |||
| } CARLA_SAFE_EXCEPTION_RETURN("effBeginSetProgram",); | |||
| try { | |||
| dispatcher(effSetProgram, 0, static_cast<intptr_t>(uindex), nullptr, 0.0f); | |||
| } CARLA_SAFE_EXCEPTION("effSetProgram"); | |||
| try { | |||
| dispatcher(effEndSetProgram, 0, 0, nullptr, 0.0f); | |||
| } CARLA_SAFE_EXCEPTION("effEndSetProgram"); | |||
| CarlaPlugin::setProgramRT(uindex); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Set ui stuff | |||
| @@ -1352,8 +1373,7 @@ public: | |||
| { | |||
| if (ctrlEvent.param < pData->prog.count) | |||
| { | |||
| setProgram(ctrlEvent.param, false, false, false); | |||
| pData->postponeRtEvent(kPluginPostRtEventProgramChange, ctrlEvent.param, 0, 0.0f); | |||
| setProgramRT(ctrlEvent.param); | |||
| break; | |||
| } | |||
| } | |||
| @@ -1523,11 +1543,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| #ifndef STOAT_TEST_BUILD | |||
| if (pData->engine->isOffline()) | |||
| { | |||
| pData->singleMutex.lock(); | |||
| } | |||
| else if (! pData->singleMutex.tryLock()) | |||
| else | |||
| #endif | |||
| if (! pData->singleMutex.tryLock()) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||