Browse Source

Implement CLAP latency, handle special host callbacks when possible

Signed-off-by: falkTX <falktx@falktx.com>
pull/1723/head
falkTX 2 years ago
parent
commit
6c27da80ec
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
3 changed files with 232 additions and 76 deletions
  1. +3
    -3
      source/backend/plugin/CarlaPlugin.cpp
  2. +227
    -72
      source/backend/plugin/CarlaPluginCLAP.cpp
  3. +2
    -1
      source/utils/CarlaClapUtils.hpp

+ 3
- 3
source/backend/plugin/CarlaPlugin.cpp View File

@@ -2099,9 +2099,9 @@ void CarlaPlugin::idle()
if (! pData->enabled) if (! pData->enabled)
return; return;


const bool hasUI(pData->hints & PLUGIN_HAS_CUSTOM_UI);
const bool needsUiMainThread(pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD);
const uint32_t latency(getLatencyInFrames());
const bool hasUI = pData->hints & PLUGIN_HAS_CUSTOM_UI;
const bool needsUiMainThread = pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD;
const uint32_t latency = getLatencyInFrames();


if (pData->latency.frames != latency) if (pData->latency.frames != latency)
{ {


+ 227
- 72
source/backend/plugin/CarlaPluginCLAP.cpp View File

@@ -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:


+ 2
- 1
source/utils/CarlaClapUtils.hpp View File

@@ -25,8 +25,9 @@
#include "clap/plugin-factory.h" #include "clap/plugin-factory.h"
#include "clap/plugin-features.h" #include "clap/plugin-features.h"
#include "clap/ext/audio-ports.h" #include "clap/ext/audio-ports.h"
#include "clap/ext/note-ports.h"
#include "clap/ext/latency.h"
#include "clap/ext/gui.h" #include "clap/ext/gui.h"
#include "clap/ext/note-ports.h"
#include "clap/ext/params.h" #include "clap/ext/params.h"
#include "clap/ext/posix-fd-support.h" #include "clap/ext/posix-fd-support.h"
#include "clap/ext/state.h" #include "clap/ext/state.h"


Loading…
Cancel
Save