|
@@ -157,6 +157,7 @@ struct carla_clap_host : clap_host_t { |
|
|
virtual void clapRequestProcess() = 0; |
|
|
virtual void clapRequestProcess() = 0; |
|
|
virtual void clapRequestCallback() = 0; |
|
|
virtual void clapRequestCallback() = 0; |
|
|
virtual void clapMarkDirty() = 0; |
|
|
virtual void clapMarkDirty() = 0; |
|
|
|
|
|
virtual void clapLatencyChanged() = 0; |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
// gui |
|
|
// gui |
|
|
virtual void clapGuiResizeHintsChanged() = 0; |
|
|
virtual void clapGuiResizeHintsChanged() = 0; |
|
@@ -178,6 +179,7 @@ struct carla_clap_host : clap_host_t { |
|
|
|
|
|
|
|
|
Callbacks* const hostCallbacks; |
|
|
Callbacks* const hostCallbacks; |
|
|
|
|
|
|
|
|
|
|
|
clap_host_latency_t latency; |
|
|
clap_host_state_t state; |
|
|
clap_host_state_t state; |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
clap_host_gui_t gui; |
|
|
clap_host_gui_t gui; |
|
@@ -202,6 +204,8 @@ struct carla_clap_host : clap_host_t { |
|
|
request_process = carla_request_process; |
|
|
request_process = carla_request_process; |
|
|
request_callback = carla_request_callback; |
|
|
request_callback = carla_request_callback; |
|
|
|
|
|
|
|
|
|
|
|
latency.changed = carla_latency_changed; |
|
|
|
|
|
|
|
|
state.mark_dirty = carla_mark_dirty; |
|
|
state.mark_dirty = carla_mark_dirty; |
|
|
|
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
@@ -226,6 +230,8 @@ struct carla_clap_host : clap_host_t { |
|
|
{ |
|
|
{ |
|
|
carla_clap_host* const self = static_cast<carla_clap_host*>(host->host_data); |
|
|
carla_clap_host* const self = static_cast<carla_clap_host*>(host->host_data); |
|
|
|
|
|
|
|
|
|
|
|
if (std::strcmp(extension_id, CLAP_EXT_LATENCY) == 0) |
|
|
|
|
|
return &self->latency; |
|
|
if (std::strcmp(extension_id, CLAP_EXT_STATE) == 0) |
|
|
if (std::strcmp(extension_id, CLAP_EXT_STATE) == 0) |
|
|
return &self->state; |
|
|
return &self->state; |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
@@ -258,12 +264,17 @@ struct carla_clap_host : clap_host_t { |
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapRequestCallback(); |
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapRequestCallback(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static CLAP_ABI void carla_latency_changed(const clap_host_t* const host) |
|
|
|
|
|
{ |
|
|
|
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapLatencyChanged(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static CLAP_ABI void carla_mark_dirty(const clap_host_t* const host) |
|
|
static CLAP_ABI void carla_mark_dirty(const clap_host_t* const host) |
|
|
{ |
|
|
{ |
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapMarkDirty(); |
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapMarkDirty(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
|
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
static CLAP_ABI void carla_resize_hints_changed(const clap_host_t* const host) |
|
|
static CLAP_ABI void carla_resize_hints_changed(const clap_host_t* const host) |
|
|
{ |
|
|
{ |
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapGuiResizeHintsChanged(); |
|
|
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapGuiResizeHintsChanged(); |
|
@@ -315,7 +326,7 @@ struct carla_clap_host : clap_host_t { |
|
|
{ |
|
|
{ |
|
|
return static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapUnregisterTimer(timer_id); |
|
|
return static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapUnregisterTimer(timer_id); |
|
|
} |
|
|
} |
|
|
#endif |
|
|
|
|
|
|
|
|
#endif |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
@@ -471,6 +482,35 @@ struct carla_clap_input_events : clap_input_events_t, CarlaPluginClapEventData { |
|
|
CarlaPluginClapEventData::createNew(portCount); |
|
|
CarlaPluginClapEventData::createNew(portCount); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// used for temporary copies (this instance must be empty) |
|
|
|
|
|
void reallocEqualTo(const carla_clap_input_events& other) |
|
|
|
|
|
{ |
|
|
|
|
|
numParams = other.numParams; |
|
|
|
|
|
numEventsAllocated = other.numEventsAllocated; |
|
|
|
|
|
|
|
|
|
|
|
if (numEventsAllocated != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
events = new Event[numEventsAllocated]; |
|
|
|
|
|
updatedParams = new ScheduledParameterUpdate[numParams]; |
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t i=0; i<numParams; ++i) |
|
|
|
|
|
{ |
|
|
|
|
|
updatedParams[i].clapId = other.updatedParams[i].clapId; |
|
|
|
|
|
updatedParams[i].cookie = other.updatedParams[i].cookie; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void swap(carla_clap_input_events& other) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(numParams == other.numParams,); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(numEventsAllocated == other.numEventsAllocated,); |
|
|
|
|
|
|
|
|
|
|
|
std::swap(numEventsUsed, other.numEventsUsed); |
|
|
|
|
|
std::swap(updatedParams, other.updatedParams); |
|
|
|
|
|
std::swap(events, other.events); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const clap_input_events_t* cast() const noexcept |
|
|
const clap_input_events_t* cast() const noexcept |
|
|
{ |
|
|
{ |
|
|
return static_cast<const clap_input_events_t*>(this); |
|
|
return static_cast<const clap_input_events_t*>(this); |
|
@@ -670,10 +710,16 @@ public: |
|
|
fOutputAudioBuffers(), |
|
|
fOutputAudioBuffers(), |
|
|
fInputEvents(), |
|
|
fInputEvents(), |
|
|
fOutputEvents(), |
|
|
fOutputEvents(), |
|
|
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH |
|
|
|
|
|
|
|
|
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH |
|
|
fAudioOutBuffers(nullptr), |
|
|
fAudioOutBuffers(nullptr), |
|
|
#endif |
|
|
|
|
|
|
|
|
#endif |
|
|
fLastChunk(nullptr), |
|
|
fLastChunk(nullptr), |
|
|
|
|
|
fLastKnownLatency(0), |
|
|
|
|
|
kEngineHasIdleOnMainThread(engine->hasIdleOnMainThread()), |
|
|
|
|
|
fLatencyChanged(false), |
|
|
|
|
|
fNeedsParamFlush(false), |
|
|
|
|
|
fNeedsRestart(false), |
|
|
|
|
|
fNeedsProcess(false), |
|
|
fNeedsIdleCallback(false) |
|
|
fNeedsIdleCallback(false) |
|
|
{ |
|
|
{ |
|
|
carla_debug("CarlaPluginCLAP::CarlaPluginCLAP(%p, %i)", engine, id); |
|
|
carla_debug("CarlaPluginCLAP::CarlaPluginCLAP(%p, %i)", engine, id); |
|
@@ -683,7 +729,7 @@ public: |
|
|
{ |
|
|
{ |
|
|
carla_debug("CarlaPluginCLAP::~CarlaPluginCLAP()"); |
|
|
carla_debug("CarlaPluginCLAP::~CarlaPluginCLAP()"); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
|
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
// close UI |
|
|
// close UI |
|
@@ -742,11 +788,12 @@ public: |
|
|
return getPluginCategoryFromClapFeatures(fPluginDescriptor->features); |
|
|
return getPluginCategoryFromClapFeatures(fPluginDescriptor->features); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
uint32_t getLatencyInFrames() const noexcept override |
|
|
uint32_t getLatencyInFrames() const noexcept override |
|
|
{ |
|
|
{ |
|
|
|
|
|
// under clap we can only request plugin latency in main thread, |
|
|
|
|
|
// which is unsuitable for this call |
|
|
|
|
|
return fLastKnownLatency; |
|
|
} |
|
|
} |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
// ------------------------------------------------------------------- |
|
|
// Information (count) |
|
|
// Information (count) |
|
@@ -806,13 +853,13 @@ public: |
|
|
if (fExtensions.state->save(fPlugin, &stream)) |
|
|
if (fExtensions.state->save(fPlugin, &stream)) |
|
|
{ |
|
|
{ |
|
|
*dataPtr = fLastChunk = stream.buffer; |
|
|
*dataPtr = fLastChunk = stream.buffer; |
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
return stream.size; |
|
|
return stream.size; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
*dataPtr = fLastChunk = nullptr; |
|
|
*dataPtr = fLastChunk = nullptr; |
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@@ -827,35 +874,48 @@ public: |
|
|
if (fExtensions.state != nullptr) |
|
|
if (fExtensions.state != nullptr) |
|
|
options |= PLUGIN_OPTION_USE_CHUNKS; |
|
|
options |= PLUGIN_OPTION_USE_CHUNKS; |
|
|
|
|
|
|
|
|
// TODO alternative if plugin does not support CLAP_NOTE_DIALECT_MIDI |
|
|
|
|
|
|
|
|
|
|
|
if (fInputEvents.portCount != 0) |
|
|
|
|
|
|
|
|
for (uint32_t i=0; i<fInputEvents.portCount; ++i) |
|
|
{ |
|
|
{ |
|
|
options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_PITCHBEND; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; |
|
|
|
|
|
options |= PLUGIN_OPTION_SKIP_SENDING_NOTES; |
|
|
|
|
|
|
|
|
if (fInputEvents.portData[i].supportedDialects & CLAP_NOTE_DIALECT_MIDI) |
|
|
|
|
|
{ |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_PITCHBEND; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; |
|
|
|
|
|
options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES; |
|
|
|
|
|
options |= PLUGIN_OPTION_SKIP_SENDING_NOTES; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
if (fInputEvents.portData[i].supportedDialects & CLAP_NOTE_DIALECT_CLAP) |
|
|
|
|
|
{ |
|
|
|
|
|
options |= PLUGIN_OPTION_SKIP_SENDING_NOTES; |
|
|
|
|
|
// nobreak, in case another port supports MIDI |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return options; |
|
|
return options; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
float getParameterValue(const uint32_t parameterId) const noexcept override |
|
|
|
|
|
|
|
|
double getBestParameterValue(const uint32_t parameterId, const clap_id clapId) const noexcept |
|
|
{ |
|
|
{ |
|
|
CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.f); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(fExtensions.params != nullptr, 0.f); |
|
|
|
|
|
|
|
|
|
|
|
const clap_id clapId = pData->param.data[parameterId].rindex; |
|
|
|
|
|
|
|
|
if (fInputEvents.updatedParams[parameterId].updated) |
|
|
|
|
|
return fInputEvents.updatedParams[parameterId].value; |
|
|
|
|
|
|
|
|
double value; |
|
|
double value; |
|
|
CARLA_SAFE_ASSERT_RETURN(fExtensions.params->get_value(fPlugin, clapId, &value), 0.f); |
|
|
|
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(fExtensions.params->get_value(fPlugin, clapId, &value), 0.0); |
|
|
|
|
|
|
|
|
return value; |
|
|
return value; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float getParameterValue(const uint32_t parameterId) const noexcept override |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.f); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(fExtensions.params != nullptr, 0.f); |
|
|
|
|
|
|
|
|
|
|
|
return getBestParameterValue(parameterId, pData->param.data[parameterId].rindex); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
bool getLabel(char* const strBuf) const noexcept override |
|
|
bool getLabel(char* const strBuf) const noexcept override |
|
|
{ |
|
|
{ |
|
|
CARLA_SAFE_ASSERT_RETURN(fPluginDescriptor != nullptr, false); |
|
|
CARLA_SAFE_ASSERT_RETURN(fPluginDescriptor != nullptr, false); |
|
@@ -914,9 +974,7 @@ public: |
|
|
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); |
|
|
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false); |
|
|
|
|
|
|
|
|
const clap_id clapId = pData->param.data[parameterId].rindex; |
|
|
const clap_id clapId = pData->param.data[parameterId].rindex; |
|
|
|
|
|
|
|
|
double value; |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(fExtensions.params->get_value(fPlugin, clapId, &value), false); |
|
|
|
|
|
|
|
|
const double value = getBestParameterValue(parameterId, clapId); |
|
|
|
|
|
|
|
|
return fExtensions.params->value_to_text(fPlugin, clapId, value, strBuf, STR_MAX); |
|
|
return fExtensions.params->value_to_text(fPlugin, clapId, value, strBuf, STR_MAX); |
|
|
} |
|
|
} |
|
@@ -972,6 +1030,9 @@ public: |
|
|
const float fixedValue = pData->param.getFixedValue(parameterId, value); |
|
|
const float fixedValue = pData->param.getFixedValue(parameterId, value); |
|
|
fInputEvents.setParamValue(parameterId, fixedValue); |
|
|
fInputEvents.setParamValue(parameterId, fixedValue); |
|
|
|
|
|
|
|
|
|
|
|
if (!pData->active && fExtensions.params->flush != nullptr) |
|
|
|
|
|
fNeedsParamFlush = true; |
|
|
|
|
|
|
|
|
CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); |
|
|
CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -997,7 +1058,7 @@ public: |
|
|
if (fExtensions.state->load(fPlugin, &stream)) |
|
|
if (fExtensions.state->load(fPlugin, &stream)) |
|
|
pData->updateParameterValues(this, true, true, false); |
|
|
pData->updateParameterValues(this, true, true, false); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
// ------------------------------------------------------------------- |
|
@@ -1055,7 +1116,7 @@ public: |
|
|
fUI.window->focus(); |
|
|
fUI.window->focus(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -1157,7 +1218,7 @@ public: |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
@@ -1169,6 +1230,9 @@ public: |
|
|
|
|
|
|
|
|
void idle() override |
|
|
void idle() override |
|
|
{ |
|
|
{ |
|
|
|
|
|
if (kEngineHasIdleOnMainThread) |
|
|
|
|
|
runIdleCallbacksAsNeeded(true); |
|
|
|
|
|
|
|
|
CarlaPlugin::idle(); |
|
|
CarlaPlugin::idle(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -1214,7 +1278,8 @@ public: |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
if (!kEngineHasIdleOnMainThread) |
|
|
|
|
|
runIdleCallbacksAsNeeded(true); |
|
|
|
|
|
|
|
|
CarlaPlugin::uiIdle(); |
|
|
CarlaPlugin::uiIdle(); |
|
|
} |
|
|
} |
|
@@ -1239,17 +1304,15 @@ public: |
|
|
const clap_plugin_audio_ports_t* audioPortsExt = static_cast<const clap_plugin_audio_ports_t*>( |
|
|
const clap_plugin_audio_ports_t* audioPortsExt = static_cast<const clap_plugin_audio_ports_t*>( |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_AUDIO_PORTS)); |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_AUDIO_PORTS)); |
|
|
|
|
|
|
|
|
|
|
|
const clap_plugin_latency_t* latencyExt = static_cast<const clap_plugin_latency_t*>( |
|
|
|
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_LATENCY)); |
|
|
|
|
|
|
|
|
const clap_plugin_note_ports_t* notePortsExt = static_cast<const clap_plugin_note_ports_t*>( |
|
|
const clap_plugin_note_ports_t* notePortsExt = static_cast<const clap_plugin_note_ports_t*>( |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_NOTE_PORTS)); |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_NOTE_PORTS)); |
|
|
|
|
|
|
|
|
const clap_plugin_params_t* paramsExt = static_cast<const clap_plugin_params_t*>( |
|
|
const clap_plugin_params_t* paramsExt = static_cast<const clap_plugin_params_t*>( |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_PARAMS)); |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_PARAMS)); |
|
|
|
|
|
|
|
|
#ifdef _POSIX_VERSION |
|
|
|
|
|
const clap_plugin_posix_fd_support_t* posixFdExt = static_cast<const clap_plugin_posix_fd_support_t*>( |
|
|
|
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_POSIX_FD_SUPPORT)); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
const clap_plugin_state_t* stateExt = static_cast<const clap_plugin_state_t*>( |
|
|
const clap_plugin_state_t* stateExt = static_cast<const clap_plugin_state_t*>( |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_STATE)); |
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_STATE)); |
|
|
|
|
|
|
|
@@ -1259,27 +1322,23 @@ public: |
|
|
if (audioPortsExt != nullptr && (audioPortsExt->count == nullptr || audioPortsExt->get == nullptr)) |
|
|
if (audioPortsExt != nullptr && (audioPortsExt->count == nullptr || audioPortsExt->get == nullptr)) |
|
|
audioPortsExt = nullptr; |
|
|
audioPortsExt = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
if (latencyExt != nullptr && latencyExt->get == nullptr) |
|
|
|
|
|
latencyExt = nullptr; |
|
|
|
|
|
|
|
|
if (notePortsExt != nullptr && (notePortsExt->count == nullptr || notePortsExt->get == nullptr)) |
|
|
if (notePortsExt != nullptr && (notePortsExt->count == nullptr || notePortsExt->get == nullptr)) |
|
|
notePortsExt = nullptr; |
|
|
notePortsExt = nullptr; |
|
|
|
|
|
|
|
|
if (paramsExt != nullptr && (paramsExt->count == nullptr || paramsExt->get_info == nullptr)) |
|
|
if (paramsExt != nullptr && (paramsExt->count == nullptr || paramsExt->get_info == nullptr)) |
|
|
paramsExt = nullptr; |
|
|
paramsExt = nullptr; |
|
|
|
|
|
|
|
|
#ifdef _POSIX_VERSION |
|
|
|
|
|
if (posixFdExt != nullptr && (posixFdExt->on_fd == nullptr)) |
|
|
|
|
|
posixFdExt = nullptr; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if (stateExt != nullptr && (stateExt->save == nullptr || stateExt->load == nullptr)) |
|
|
if (stateExt != nullptr && (stateExt->save == nullptr || stateExt->load == nullptr)) |
|
|
stateExt = nullptr; |
|
|
stateExt = nullptr; |
|
|
|
|
|
|
|
|
if (timerExt != nullptr && (timerExt->on_timer == nullptr)) |
|
|
|
|
|
|
|
|
if (timerExt != nullptr && timerExt->on_timer == nullptr) |
|
|
timerExt = nullptr; |
|
|
timerExt = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
fExtensions.latency = latencyExt; |
|
|
fExtensions.params = paramsExt; |
|
|
fExtensions.params = paramsExt; |
|
|
#ifdef _POSIX_VERSION |
|
|
|
|
|
fExtensions.posixFD = posixFdExt; |
|
|
|
|
|
#endif |
|
|
|
|
|
fExtensions.state = stateExt; |
|
|
fExtensions.state = stateExt; |
|
|
fExtensions.timer = timerExt; |
|
|
fExtensions.timer = timerExt; |
|
|
|
|
|
|
|
@@ -1306,6 +1365,16 @@ public: |
|
|
fExtensions.gui = guiExt; |
|
|
fExtensions.gui = guiExt; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if defined(CLAP_WINDOW_API_NATIVE) && defined(_POSIX_VERSION) |
|
|
|
|
|
const clap_plugin_posix_fd_support_t* posixFdExt = static_cast<const clap_plugin_posix_fd_support_t*>( |
|
|
|
|
|
fPlugin->get_extension(fPlugin, CLAP_EXT_POSIX_FD_SUPPORT)); |
|
|
|
|
|
|
|
|
|
|
|
if (posixFdExt != nullptr && posixFdExt->on_fd == nullptr) |
|
|
|
|
|
posixFdExt = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
fExtensions.posixFD = posixFdExt; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
const uint32_t numAudioInputPorts = audioPortsExt != nullptr ? audioPortsExt->count(fPlugin, true) : 0; |
|
|
const uint32_t numAudioInputPorts = audioPortsExt != nullptr ? audioPortsExt->count(fPlugin, true) : 0; |
|
|
const uint32_t numAudioOutputPorts = audioPortsExt != nullptr ? audioPortsExt->count(fPlugin, false) : 0; |
|
|
const uint32_t numAudioOutputPorts = audioPortsExt != nullptr ? audioPortsExt->count(fPlugin, false) : 0; |
|
|
const uint32_t numNoteInputPorts = notePortsExt != nullptr ? notePortsExt->count(fPlugin, true) : 0; |
|
|
const uint32_t numNoteInputPorts = notePortsExt != nullptr ? notePortsExt->count(fPlugin, true) : 0; |
|
@@ -1659,7 +1728,7 @@ public: |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// plugin hints |
|
|
// plugin hints |
|
|
pData->hints = 0x0; |
|
|
|
|
|
|
|
|
pData->hints = PLUGIN_NEEDS_MAIN_THREAD_IDLE; |
|
|
|
|
|
|
|
|
if (clapFeaturesContainInstrument(fPluginDescriptor->features)) |
|
|
if (clapFeaturesContainInstrument(fPluginDescriptor->features)) |
|
|
pData->hints |= PLUGIN_IS_SYNTH; |
|
|
pData->hints |= PLUGIN_IS_SYNTH; |
|
@@ -1693,13 +1762,21 @@ public: |
|
|
// extra plugin hints |
|
|
// extra plugin hints |
|
|
pData->extraHints = 0x0; |
|
|
pData->extraHints = 0x0; |
|
|
|
|
|
|
|
|
|
|
|
if (const uint32_t latency = fExtensions.latency != nullptr ? fExtensions.latency->get(fPlugin) : 0) |
|
|
|
|
|
{ |
|
|
|
|
|
pData->client->setLatency(latency); |
|
|
|
|
|
#ifndef BUILD_BRIDGE |
|
|
|
|
|
pData->latency.recreateBuffers(std::max(aIns, aOuts), latency); |
|
|
|
|
|
#endif |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
bufferSizeChanged(pData->engine->getBufferSize()); |
|
|
bufferSizeChanged(pData->engine->getBufferSize()); |
|
|
reloadPrograms(true); |
|
|
reloadPrograms(true); |
|
|
|
|
|
|
|
|
if (pData->active) |
|
|
if (pData->active) |
|
|
activate(); |
|
|
activate(); |
|
|
else |
|
|
else |
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
|
|
|
|
|
|
carla_debug("CarlaPluginCLAP::reload() - end"); |
|
|
carla_debug("CarlaPluginCLAP::reload() - end"); |
|
|
} |
|
|
} |
|
@@ -1720,7 +1797,8 @@ public: |
|
|
fPlugin->activate(fPlugin, pData->engine->getSampleRate(), 1, pData->engine->getBufferSize()); |
|
|
fPlugin->activate(fPlugin, pData->engine->getSampleRate(), 1, pData->engine->getBufferSize()); |
|
|
fPlugin->start_processing(fPlugin); |
|
|
fPlugin->start_processing(fPlugin); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
fNeedsParamFlush = false; |
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void deactivate() noexcept override |
|
|
void deactivate() noexcept override |
|
@@ -1731,7 +1809,7 @@ public: |
|
|
fPlugin->stop_processing(fPlugin); |
|
|
fPlugin->stop_processing(fPlugin); |
|
|
fPlugin->deactivate(fPlugin); |
|
|
fPlugin->deactivate(fPlugin); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(); |
|
|
|
|
|
|
|
|
runIdleCallbacksAsNeeded(false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void process(const float* const* const audioIn, |
|
|
void process(const float* const* const audioIn, |
|
@@ -2183,7 +2261,7 @@ public: |
|
|
case kEngineEventTypeMidi: { |
|
|
case kEngineEventTypeMidi: { |
|
|
const EngineMidiEvent& midiEvent(event.midi); |
|
|
const EngineMidiEvent& midiEvent(event.midi); |
|
|
|
|
|
|
|
|
if (midiEvent.size > sizeof(clap_event_midi::data)/sizeof(clap_event_midi::data[0])) |
|
|
|
|
|
|
|
|
if (midiEvent.size > 3) |
|
|
continue; |
|
|
continue; |
|
|
|
|
|
|
|
|
CARLA_SAFE_ASSERT_BREAK(midiEvent.port < fInputEvents.portCount); |
|
|
CARLA_SAFE_ASSERT_BREAK(midiEvent.port < fInputEvents.portCount); |
|
@@ -2572,11 +2650,15 @@ protected: |
|
|
void clapRequestRestart() override |
|
|
void clapRequestRestart() override |
|
|
{ |
|
|
{ |
|
|
carla_stdout("CarlaPluginCLAP::clapRequestRestart()"); |
|
|
carla_stdout("CarlaPluginCLAP::clapRequestRestart()"); |
|
|
|
|
|
|
|
|
|
|
|
fNeedsRestart = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void clapRequestProcess() override |
|
|
void clapRequestProcess() override |
|
|
{ |
|
|
{ |
|
|
carla_stdout("CarlaPluginCLAP::clapRequestProcess()"); |
|
|
carla_stdout("CarlaPluginCLAP::clapRequestProcess()"); |
|
|
|
|
|
|
|
|
|
|
|
fNeedsProcess = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void clapRequestCallback() override |
|
|
void clapRequestCallback() override |
|
@@ -2589,6 +2671,16 @@ protected: |
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
// ------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
void clapLatencyChanged() override |
|
|
|
|
|
{ |
|
|
|
|
|
carla_stdout("CarlaPluginCLAP::clapLatencyChanged()"); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(fExtensions.latency != nullptr,); |
|
|
|
|
|
|
|
|
|
|
|
fLatencyChanged = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
void clapMarkDirty() override |
|
|
void clapMarkDirty() override |
|
|
{ |
|
|
{ |
|
|
carla_stdout("CarlaPluginCLAP::clapMarkDirty()"); |
|
|
carla_stdout("CarlaPluginCLAP::clapMarkDirty()"); |
|
@@ -2680,7 +2772,7 @@ protected: |
|
|
CARLA_SAFE_ASSERT_RETURN(hostFd >= 0, false); |
|
|
CARLA_SAFE_ASSERT_RETURN(hostFd >= 0, false); |
|
|
|
|
|
|
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
struct epoll_event ev = {}; |
|
|
|
|
|
|
|
|
struct ::epoll_event ev = {}; |
|
|
if (flags & CLAP_POSIX_FD_READ) |
|
|
if (flags & CLAP_POSIX_FD_READ) |
|
|
ev.events |= EPOLLIN; |
|
|
ev.events |= EPOLLIN; |
|
|
if (flags & CLAP_POSIX_FD_WRITE) |
|
|
if (flags & CLAP_POSIX_FD_WRITE) |
|
@@ -2720,7 +2812,7 @@ protected: |
|
|
return true; |
|
|
return true; |
|
|
|
|
|
|
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
struct epoll_event ev = {}; |
|
|
|
|
|
|
|
|
struct ::epoll_event ev = {}; |
|
|
if (flags & CLAP_POSIX_FD_READ) |
|
|
if (flags & CLAP_POSIX_FD_READ) |
|
|
ev.events |= EPOLLIN; |
|
|
ev.events |= EPOLLIN; |
|
|
if (flags & CLAP_POSIX_FD_WRITE) |
|
|
if (flags & CLAP_POSIX_FD_WRITE) |
|
@@ -3006,8 +3098,6 @@ public: |
|
|
clap_note_port_info_t portInfo = {}; |
|
|
clap_note_port_info_t portInfo = {}; |
|
|
CARLA_SAFE_ASSERT_BREAK(notePortsExt->get(fPlugin, i, true, &portInfo)); |
|
|
CARLA_SAFE_ASSERT_BREAK(notePortsExt->get(fPlugin, i, true, &portInfo)); |
|
|
|
|
|
|
|
|
// TODO alternative if plugin does not support CLAP_NOTE_DIALECT_MIDI |
|
|
|
|
|
|
|
|
|
|
|
if (portInfo.supported_dialects & CLAP_NOTE_DIALECT_MIDI) |
|
|
if (portInfo.supported_dialects & CLAP_NOTE_DIALECT_MIDI) |
|
|
{ |
|
|
{ |
|
|
if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) |
|
|
if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES)) |
|
@@ -3026,6 +3116,12 @@ public: |
|
|
pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES; |
|
|
pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
if (portInfo.supported_dialects & CLAP_NOTE_DIALECT_CLAP) |
|
|
|
|
|
{ |
|
|
|
|
|
if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES)) |
|
|
|
|
|
pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES; |
|
|
|
|
|
// nobreak, in case another port supports MIDI |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -3043,26 +3139,30 @@ private: |
|
|
const carla_clap_host fHost; |
|
|
const carla_clap_host fHost; |
|
|
|
|
|
|
|
|
struct Extensions { |
|
|
struct Extensions { |
|
|
|
|
|
const clap_plugin_latency_t* latency; |
|
|
const clap_plugin_params_t* params; |
|
|
const clap_plugin_params_t* params; |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
|
|
|
|
|
|
const clap_plugin_state_t* state; |
|
|
|
|
|
const clap_plugin_timer_support_t* timer; |
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
const clap_plugin_gui_t* gui; |
|
|
const clap_plugin_gui_t* gui; |
|
|
#endif |
|
|
|
|
|
#ifdef _POSIX_VERSION |
|
|
#ifdef _POSIX_VERSION |
|
|
const clap_plugin_posix_fd_support_t* posixFD; |
|
|
const clap_plugin_posix_fd_support_t* posixFD; |
|
|
#endif |
|
|
#endif |
|
|
const clap_plugin_state_t* state; |
|
|
|
|
|
const clap_plugin_timer_support_t* timer; |
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
Extensions() |
|
|
Extensions() |
|
|
: params(nullptr), |
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
|
|
|
gui(nullptr), |
|
|
|
|
|
#endif |
|
|
|
|
|
#ifdef _POSIX_VERSION |
|
|
|
|
|
posixFD(nullptr), |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
: latency(nullptr), |
|
|
|
|
|
params(nullptr), |
|
|
state(nullptr), |
|
|
state(nullptr), |
|
|
timer(nullptr) {} |
|
|
|
|
|
|
|
|
timer(nullptr) |
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
|
|
|
, gui(nullptr) |
|
|
|
|
|
#ifdef _POSIX_VERSION |
|
|
|
|
|
, posixFD(nullptr) |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
CARLA_DECLARE_NON_COPYABLE(Extensions) |
|
|
CARLA_DECLARE_NON_COPYABLE(Extensions) |
|
|
} fExtensions; |
|
|
} fExtensions; |
|
@@ -3097,6 +3197,8 @@ private: |
|
|
{ |
|
|
{ |
|
|
CARLA_SAFE_ASSERT(window == nullptr); |
|
|
CARLA_SAFE_ASSERT(window == nullptr); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CARLA_DECLARE_NON_COPYABLE(UI) |
|
|
} fUI; |
|
|
} fUI; |
|
|
|
|
|
|
|
|
#ifdef _POSIX_VERSION |
|
|
#ifdef _POSIX_VERSION |
|
@@ -3113,20 +3215,73 @@ private: |
|
|
float** fAudioOutBuffers; |
|
|
float** fAudioOutBuffers; |
|
|
#endif |
|
|
#endif |
|
|
void* fLastChunk; |
|
|
void* fLastChunk; |
|
|
|
|
|
uint32_t fLastKnownLatency; |
|
|
|
|
|
const bool kEngineHasIdleOnMainThread; |
|
|
|
|
|
bool fLatencyChanged; |
|
|
|
|
|
bool fNeedsParamFlush; |
|
|
|
|
|
bool fNeedsRestart; |
|
|
|
|
|
bool fNeedsProcess; |
|
|
bool fNeedsIdleCallback; |
|
|
bool fNeedsIdleCallback; |
|
|
|
|
|
|
|
|
#ifdef CARLA_OS_MAC |
|
|
#ifdef CARLA_OS_MAC |
|
|
BundleLoader fBundleLoader; |
|
|
BundleLoader fBundleLoader; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
void runIdleCallbacksAsNeeded() |
|
|
|
|
|
|
|
|
void runIdleCallbacksAsNeeded(const bool isIdleCallback) |
|
|
{ |
|
|
{ |
|
|
|
|
|
if (isIdleCallback && (fNeedsRestart || fNeedsProcess)) |
|
|
|
|
|
{ |
|
|
|
|
|
carla_stdout("runIdleCallbacksAsNeeded %d %d", fNeedsRestart, fNeedsProcess); |
|
|
|
|
|
const bool needsRestart = fNeedsRestart; |
|
|
|
|
|
|
|
|
|
|
|
if (needsRestart) |
|
|
|
|
|
{ |
|
|
|
|
|
fNeedsRestart = false; |
|
|
|
|
|
setActive(false, true, true); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fNeedsProcess) |
|
|
|
|
|
{ |
|
|
|
|
|
fNeedsProcess = false; |
|
|
|
|
|
setEnabled(true); |
|
|
|
|
|
setActive(true, true, true); |
|
|
|
|
|
} |
|
|
|
|
|
else if (needsRestart) |
|
|
|
|
|
{ |
|
|
|
|
|
setActive(true, true, true); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fNeedsParamFlush) |
|
|
|
|
|
{ |
|
|
|
|
|
fNeedsParamFlush = false; |
|
|
|
|
|
|
|
|
|
|
|
carla_clap_input_events copy; |
|
|
|
|
|
copy.reallocEqualTo(fInputEvents); |
|
|
|
|
|
|
|
|
|
|
|
carla_stdout("lock flush start"); |
|
|
|
|
|
{ |
|
|
|
|
|
const ScopedSingleProcessLocker sspl(this, true); |
|
|
|
|
|
fInputEvents.handleScheduledParameterUpdates(); |
|
|
|
|
|
fInputEvents.swap(copy); |
|
|
|
|
|
} |
|
|
|
|
|
carla_stdout("lock flush end"); |
|
|
|
|
|
|
|
|
|
|
|
fExtensions.params->flush(fPlugin, copy.cast(), nullptr); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (fNeedsIdleCallback) |
|
|
if (fNeedsIdleCallback) |
|
|
{ |
|
|
{ |
|
|
fNeedsIdleCallback = false; |
|
|
fNeedsIdleCallback = false; |
|
|
fPlugin->on_main_thread(fPlugin); |
|
|
fPlugin->on_main_thread(fPlugin); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fLatencyChanged) |
|
|
|
|
|
{ |
|
|
|
|
|
fLatencyChanged = false; |
|
|
|
|
|
fLastKnownLatency = fExtensions.latency->get(fPlugin); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef CLAP_WINDOW_API_NATIVE |
|
|
#ifdef _POSIX_VERSION |
|
|
#ifdef _POSIX_VERSION |
|
|
for (LinkedList<HostPosixFileDescriptorDetails>::Itenerator it = fPosixFileDescriptors.begin2(); it.valid(); it.next()) |
|
|
for (LinkedList<HostPosixFileDescriptorDetails>::Itenerator it = fPosixFileDescriptors.begin2(); it.valid(); it.next()) |
|
@@ -3134,11 +3289,11 @@ private: |
|
|
const HostPosixFileDescriptorDetails& posixFD(it.getValue(kPosixFileDescriptorFallback)); |
|
|
const HostPosixFileDescriptorDetails& posixFD(it.getValue(kPosixFileDescriptorFallback)); |
|
|
|
|
|
|
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
epoll_event event; |
|
|
|
|
|
|
|
|
struct ::epoll_event event; |
|
|
#else |
|
|
#else |
|
|
const int16_t filter = posixFD.flags & CLAP_POSIX_FD_WRITE ? EVFILT_WRITE : EVFILT_READ; |
|
|
const int16_t filter = posixFD.flags & CLAP_POSIX_FD_WRITE ? EVFILT_WRITE : EVFILT_READ; |
|
|
struct kevent kev = {}, event; |
|
|
|
|
|
struct timespec timeout = {}; |
|
|
|
|
|
|
|
|
struct ::kevent kev = {}, event; |
|
|
|
|
|
struct ::timespec timeout = {}; |
|
|
EV_SET(&kev, posixFD.pluginFd, filter, EV_ADD|EV_ENABLE, 0, 0, nullptr); |
|
|
EV_SET(&kev, posixFD.pluginFd, filter, EV_ADD|EV_ENABLE, 0, 0, nullptr); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
@@ -3147,7 +3302,7 @@ private: |
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
#ifdef CARLA_CLAP_POSIX_EPOLL |
|
|
switch (::epoll_wait(posixFD.hostFd, &event, 1, 0)) |
|
|
switch (::epoll_wait(posixFD.hostFd, &event, 1, 0)) |
|
|
#else |
|
|
#else |
|
|
switch (kevent(posixFD.hostFd, &kev, 1, &event, 1, &timeout)) |
|
|
|
|
|
|
|
|
switch (::kevent(posixFD.hostFd, &kev, 1, &event, 1, &timeout)) |
|
|
#endif |
|
|
#endif |
|
|
{ |
|
|
{ |
|
|
case 1: |
|
|
case 1: |
|
|