@@ -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) | |||
{ | |||