Browse Source

Implement CLAP host gui and a few more details

Signed-off-by: falkTX <falktx@falktx.com>
pull/1689/head
falkTX 2 years ago
parent
commit
044428594e
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
3 changed files with 448 additions and 98 deletions
  1. +426
    -95
      source/backend/plugin/CarlaPluginCLAP.cpp
  2. +2
    -1
      source/frontend/Makefile
  3. +20
    -2
      source/utils/CarlaClapUtils.hpp

+ 426
- 95
source/backend/plugin/CarlaPluginCLAP.cpp View File

@@ -31,11 +31,13 @@

#include "water/files/File.h"

CARLA_BACKEND_START_NAMESPACE

// --------------------------------------------------------------------------------------------------------------------
// FIXME
// #ifndef CLAP_WINDOW_API_NATIVE
// #define CLAP_WINDOW_API_NATIVE ""
// #define HAVE_X11 1
// #endif

static_assert(kPluginMaxMidiEvents > MAX_MIDI_NOTE, "Enough space for input events");
CARLA_BACKEND_START_NAMESPACE

// --------------------------------------------------------------------------------------------------------------------

@@ -112,6 +114,12 @@ struct CarlaPluginClapEventData {
// --------------------------------------------------------------------------------------------------------------------

struct carla_clap_host : clap_host_t {
clap_host_gui_t gui;
clap_host_timer_support_t timer;

// TESTING
clap_id inUseTimerId;

carla_clap_host()
{
clap_version = CLAP_VERSION;
@@ -120,16 +128,70 @@ struct carla_clap_host : clap_host_t {
vendor = "falkTX";
url = "https://kx.studio/carla";
version = CARLA_VERSION_STRING;

get_extension = carla_get_extension;
request_restart = carla_request_restart;
request_process = carla_request_process;
request_callback = carla_request_callback;

gui.resize_hints_changed = carla_resize_hints_changed;
gui.request_resize = carla_request_resize;
gui.request_show = carla_request_show;
gui.request_hide = carla_request_hide;
gui.closed = carla_closed;

timer.register_timer = carla_register_timer;
timer.unregister_timer = carla_unregister_timer;

// TESTING
inUseTimerId = CLAP_INVALID_ID;
}

static const void* carla_get_extension(const clap_host_t* const host, const char* const extension_id)
{
const carla_clap_host* const self = static_cast<const carla_clap_host*>(host->host_data);

if (std::strcmp(extension_id, CLAP_EXT_GUI) == 0)
return &self->gui;
if (std::strcmp(extension_id, CLAP_EXT_TIMER_SUPPORT) == 0)
return &self->timer;

return nullptr;
}

static const void* carla_get_extension(const clap_host_t*, const char*) { return nullptr; }
static void carla_request_restart(const clap_host_t*) {}
static void carla_request_process(const clap_host_t*) {}
static void carla_request_callback(const clap_host_t*) {}

static void carla_resize_hints_changed(const clap_host_t *host) {}
static bool carla_request_resize(const clap_host_t *host, uint32_t width, uint32_t height) { return false; }
static bool carla_request_show(const clap_host_t *host) { return false; }
static bool carla_request_hide(const clap_host_t *host) { return false; }
static void carla_closed(const clap_host_t *host, bool was_destroyed) {}

static bool carla_register_timer(const clap_host_t* const host, uint32_t /*period_ms*/, clap_id* const timer_id)
{
carla_clap_host* const self = static_cast<carla_clap_host*>(host->host_data);

if (self->inUseTimerId != CLAP_INVALID_ID)
return false;

self->inUseTimerId = *timer_id = 1;
return true;
}

static bool carla_unregister_timer(const clap_host_t* const host, const clap_id timer_id)
{
carla_clap_host* const self = static_cast<carla_clap_host*>(host->host_data);

if (self->inUseTimerId == CLAP_INVALID_ID)
return false;
if (self->inUseTimerId != timer_id)
return false;

self->inUseTimerId = CLAP_INVALID_ID;
return true;
}
};

// --------------------------------------------------------------------------------------------------------------------
@@ -147,7 +209,7 @@ struct carla_clap_input_audio_buffers {
delete[] buffers;
}

void init(const uint32_t portCount)
void realloc(const uint32_t portCount)
{
delete[] buffers;
count = portCount;
@@ -182,7 +244,7 @@ struct carla_clap_output_audio_buffers {
delete[] buffers;
}

void init(const uint32_t portCount)
void realloc(const uint32_t portCount)
{
delete[] buffers;
count = portCount;
@@ -215,13 +277,13 @@ struct carla_clap_input_events : clap_input_events_t, CarlaPluginClapEventData {
clap_event_midi_sysex_t sysex;
};

struct UpdatedParam {
struct ScheduledParameterUpdate {
bool updated;
double value;
clap_id clapId;
void* cookie;

UpdatedParam()
ScheduledParameterUpdate()
: updated(false),
value(0.f),
clapId(0),
@@ -229,7 +291,7 @@ struct carla_clap_input_events : clap_input_events_t, CarlaPluginClapEventData {
};

Event* events;
UpdatedParam* updatedParams;
ScheduledParameterUpdate* updatedParams;

uint32_t numEventsAllocated;
uint32_t numEventsUsed;
@@ -256,7 +318,7 @@ struct carla_clap_input_events : clap_input_events_t, CarlaPluginClapEventData {

// called on plugin reload
// NOTE: clapId and cookie must be separately set outside this function
void init(CarlaEngineEventPort* const defPortIn, const uint32_t portCount, const uint32_t paramCount)
void realloc(CarlaEngineEventPort* const defPortIn, const uint32_t portCount, const uint32_t paramCount)
{
numEventsUsed = 0;
numParams = paramCount;
@@ -265,9 +327,11 @@ struct carla_clap_input_events : clap_input_events_t, CarlaPluginClapEventData {

if (paramCount != 0)
{
static_assert(kPluginMaxMidiEvents > MAX_MIDI_NOTE, "Enough space for input events");

numEventsAllocated = paramCount * 2 + kPluginMaxMidiEvents * std::max(1u, portCount);
events = new Event[numEventsAllocated];
updatedParams = new UpdatedParam[paramCount];
updatedParams = new ScheduledParameterUpdate[paramCount];
}
else
{
@@ -283,7 +347,7 @@ struct carla_clap_input_events : clap_input_events_t, CarlaPluginClapEventData {
}

// called just before plugin processing
void prepareScheduledParameterUpdates()
void handleScheduledParameterUpdates()
{
uint32_t count = 0;

@@ -383,7 +447,7 @@ struct carla_clap_output_events : clap_output_events_t, CarlaPluginClapEventData
}

// called on plugin reload
void init(CarlaEngineEventPort* const defPortOut, const uint32_t portCount, const uint32_t paramCount)
void realloc(CarlaEngineEventPort* const defPortOut, const uint32_t portCount, const uint32_t paramCount)
{
numEventsUsed = 0;
delete[] events;
@@ -449,30 +513,23 @@ public:
fInputAudioBuffers(),
fOutputAudioBuffers(),
fInputEvents(),
fOutputEvents(),
fSteadyTime(0),
fAudioOutBuffers(nullptr)
fOutputEvents()
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
, fAudioOutBuffers(nullptr)
#endif
{
carla_debug("CarlaPluginCLAP::CarlaPluginCLAP(%p, %i)", engine, id);

}

~CarlaPluginCLAP() override
{
carla_debug("CarlaPluginCLAP::~CarlaPluginCLAP()");

#ifdef CLAP_WINDOW_API_NATIVE
// close UI
// if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
// {
// if (! fUI.isEmbed)
// showCustomUI(false);
//
// if (fUI.isOpen)
// {
// fUI.isOpen = false;
// dispatcher(effEditClose);
// }
// }
if (fUI.isCreated)
showCustomUI(false);
#endif

pData->singleMutex.lock();
pData->masterMutex.lock();
@@ -480,8 +537,6 @@ public:
if (pData->client != nullptr && pData->client->isActive())
pData->client->deactivate(true);

// CARLA_ASSERT(! fIsProcessing);

if (pData->active)
{
deactivate();
@@ -530,11 +585,49 @@ public:
// -------------------------------------------------------------------
// Information (count)

// nothing
uint32_t getMidiInCount() const noexcept override
{
return fInputEvents.portCount;
}

uint32_t getMidiOutCount() const noexcept override
{
return fOutputEvents.portCount;
}

// -------------------------------------------------------------------
// Information (current data)

uint getAudioPortHints(const bool isOutput, const uint32_t portIndex) const noexcept override
{
uint hints = 0x0;

if (isOutput)
{
for (uint32_t i=0, j=0; i<fOutputAudioBuffers.count; ++i, j+=fOutputAudioBuffers.buffers[i].channel_count)
{
if (j != portIndex)
continue;

if (!fOutputAudioBuffers.buffers[i].isMain)
hints |= AUDIO_PORT_IS_SIDECHAIN;
}
}
else
{
for (uint32_t i=0, j=0; i<fInputAudioBuffers.count; ++i, j+=fInputAudioBuffers.buffers[i].channel_count)
{
if (j != portIndex)
continue;

if (!fInputAudioBuffers.buffers[i].isMain)
hints |= AUDIO_PORT_IS_SIDECHAIN;
}
}

return hints;
}

/*
std::size_t getChunkData(void** const dataPtr) noexcept override
{
@@ -619,6 +712,15 @@ public:
return true;
}

bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
{
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);

const clap_id clapId = pData->param.data[parameterId].rindex;
std::snprintf(strBuf, STR_MAX, "%u", clapId);
return true;
}

bool getParameterText(const uint32_t parameterId, char* const strBuf) noexcept override
{
CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr, false);
@@ -633,15 +735,29 @@ public:
return fExtensions.params->value_to_text(fPlugin, clapId, value, strBuf, STR_MAX);
}

/*
bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
{
}

bool getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept override
{
CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(fExtensions.params != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);

const clap_id clapId = pData->param.data[parameterId].rindex;

clap_param_info_t paramInfo = {};
CARLA_SAFE_ASSERT_RETURN(fExtensions.params->get_info(fPlugin, clapId, &paramInfo), false);

if (paramInfo.module[0] == '\0')
return false;

if (char* const sep = std::strrchr(paramInfo.module, '/'))
{
paramInfo.module[STR_MAX/2-2] = sep[0] = '\0';
std::snprintf(strBuf, STR_MAX, "%s:%s", paramInfo.module, paramInfo.module);
return true;
}

return false;
}
*/

// -------------------------------------------------------------------
// Set data (state)
@@ -651,11 +767,15 @@ public:
// -------------------------------------------------------------------
// Set data (internal stuff)

/*
#ifdef CLAP_WINDOW_API_NATIVE
void setName(const char* const newName) override
{
CarlaPlugin::setName(newName);

if (fUI.isCreated && pData->uiTitle.isEmpty())
setWindowTitle(nullptr);
}
*/
#endif

// -------------------------------------------------------------------
// Set data (plugin-specific stuff)
@@ -699,15 +819,157 @@ public:
// -------------------------------------------------------------------
// Set ui stuff

/*
#ifdef CLAP_WINDOW_API_NATIVE
void setWindowTitle(const char* const title) noexcept
{
if (!fUI.isCreated)
return;

CarlaString uiTitle;

if (title != nullptr)
{
uiTitle = title;
}
else
{
uiTitle = pData->name;
uiTitle += " (GUI)";
}

if (fUI.isEmbed)
{
if (fUI.window != nullptr)
fUI.window->setTitle(pData->uiTitle.buffer());
}
else
{
fExtensions.gui->suggest_title(fPlugin, pData->uiTitle.buffer());
}
}

void setCustomUITitle(const char* const title) noexcept override
{
setWindowTitle(title);
CarlaPlugin::setCustomUITitle(title);
}

void showCustomUI(const bool yesNo) override
{
CARLA_SAFE_ASSERT_RETURN(fExtensions.gui != nullptr,);

if (yesNo)
{
if (fUI.isVisible)
{
fExtensions.gui->show(fPlugin);

if (fUI.isEmbed)
{
CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
fUI.window->show();
fUI.window->focus();
}
return;
}

const EngineOptions& opts(pData->engine->getOptions());

if (!fUI.initalized)
{
fUI.isEmbed = fExtensions.gui->is_api_supported(fPlugin, CLAP_WINDOW_API_NATIVE, false);
fUI.initalized = true;
}

if (!fUI.isCreated)
{
if (!fExtensions.gui->create(fPlugin, CLAP_WINDOW_API_NATIVE, !fUI.isEmbed))
{
pData->engine->callback(true, true,
ENGINE_CALLBACK_UI_STATE_CHANGED,
pData->id,
-1,
0, 0, 0.0f,
"Plugin refused to open its own UI");
return;
}
fUI.isCreated = true;
}

const bool resizable = fExtensions.gui->can_resize(fPlugin);

#if defined(CARLA_OS_WIN)
fUI.window = CarlaPluginUI::newWindows(this, opts.frontendWinId, opts.pluginsAreStandalone, resizable);
#elif defined(CARLA_OS_MAC)
fUI.window = CarlaPluginUI::newCocoa(this, opts.frontendWinId, opts.pluginsAreStandalone, resizable);
#elif defined(HAVE_X11)
fUI.window = CarlaPluginUI::newX11(this, opts.frontendWinId, opts.pluginsAreStandalone, resizable, false);
#else
#error why is CLAP_WINDOW_API_NATIVE defined??
#endif

if (carla_isNotZero(opts.uiScale))
fExtensions.gui->set_scale(fPlugin, opts.uiScale);

if (fUI.isEmbed)
{
clap_window_t win = { CLAP_WINDOW_API_NATIVE, {} };
win.ptr = fUI.window->getPtr();
fExtensions.gui->set_parent(fPlugin, &win);

if (pData->uiTitle.isNotEmpty())
fUI.window->setTitle(pData->uiTitle.buffer());

fExtensions.gui->show(fPlugin);
fUI.window->show();
}
else
{
clap_window_t win = { CLAP_WINDOW_API_NATIVE, {} };
win.uptr = opts.frontendWinId;
fExtensions.gui->set_transient(fPlugin, &win);

if (pData->uiTitle.isNotEmpty())
fExtensions.gui->suggest_title(fPlugin, pData->uiTitle.buffer());

fExtensions.gui->show(fPlugin);

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
pData->tryTransient();
#endif
}

fUI.isVisible = true;
}
else
{
fUI.isVisible = false;

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
pData->transientTryCounter = 0;
#endif

if (fUI.window != nullptr)
fUI.window->hide();

fExtensions.gui->hide(fPlugin);

if (fUI.isCreated)
{
fExtensions.gui->destroy(fPlugin);
fUI.isCreated = false;
}

if (fUI.window != nullptr)
{
delete fUI.window;
fUI.window = nullptr;
}
}
}
#endif

/*
void* embedCustomUI(void* const ptr) override
{
}
@@ -720,6 +982,9 @@ public:

void uiIdle() override
{
if (fHost.inUseTimerId != CLAP_INVALID_ID && fExtensions.timer != nullptr)
fExtensions.timer->on_timer(fPlugin, fHost.inUseTimerId);

CarlaPlugin::uiIdle();
}

@@ -749,6 +1014,9 @@ public:
const clap_plugin_params_t* paramsExt = static_cast<const clap_plugin_params_t*>(
fPlugin->get_extension(fPlugin, CLAP_EXT_PARAMS));

const clap_plugin_timer_support_t* timerExt = static_cast<const clap_plugin_timer_support_t*>(
fPlugin->get_extension(fPlugin, CLAP_EXT_TIMER_SUPPORT));

if (audioPortsExt != nullptr && (audioPortsExt->count == nullptr || audioPortsExt->get == nullptr))
audioPortsExt = nullptr;

@@ -758,7 +1026,34 @@ public:
if (paramsExt != nullptr && (paramsExt->count == nullptr || paramsExt->get_info == nullptr))
paramsExt = nullptr;

if (timerExt != nullptr && (timerExt->on_timer == nullptr))
timerExt = nullptr;

fExtensions.params = paramsExt;
fExtensions.timer = timerExt;

#ifdef CLAP_WINDOW_API_NATIVE
const clap_plugin_gui_t* guiExt = static_cast<const clap_plugin_gui_t*>(
fPlugin->get_extension(fPlugin, CLAP_EXT_GUI));

if (guiExt != nullptr && (guiExt->is_api_supported == nullptr
|| guiExt->create == nullptr
|| guiExt->destroy == nullptr
|| guiExt->set_scale == nullptr
|| guiExt->get_size == nullptr
|| guiExt->can_resize == nullptr
|| guiExt->get_resize_hints == nullptr
|| guiExt->adjust_size == nullptr
|| guiExt->set_size == nullptr
|| guiExt->set_parent == nullptr
|| guiExt->set_transient == nullptr
|| guiExt->suggest_title == nullptr
|| guiExt->show == nullptr
|| guiExt->hide == nullptr))
guiExt = nullptr;

fExtensions.gui = guiExt;
#endif

const uint32_t numAudioInputPorts = audioPortsExt != nullptr ? audioPortsExt->count(fPlugin, true) : 0;
const uint32_t numAudioOutputPorts = audioPortsExt != nullptr ? audioPortsExt->count(fPlugin, false) : 0;
@@ -772,8 +1067,8 @@ public:
bool needsCtrlIn, needsCtrlOut;
needsCtrlIn = needsCtrlOut = false;

fInputAudioBuffers.init(numAudioInputPorts);
fOutputAudioBuffers.init(numAudioOutputPorts);
fInputAudioBuffers.realloc(numAudioInputPorts);
fOutputAudioBuffers.realloc(numAudioOutputPorts);

for (uint32_t i=0; i<numAudioInputPorts; ++i)
{
@@ -782,6 +1077,8 @@ public:

fInputAudioBuffers.buffers[i].channel_count = portInfo.channel_count;
fInputAudioBuffers.buffers[i].offset = aIns;
fInputAudioBuffers.buffers[i].isMain = portInfo.flags & CLAP_AUDIO_PORT_IS_MAIN;

aIns += portInfo.channel_count;
}

@@ -792,6 +1089,7 @@ public:

fOutputAudioBuffers.buffers[i].channel_count = portInfo.channel_count;
fOutputAudioBuffers.buffers[i].offset = aOuts;
fOutputAudioBuffers.buffers[i].isMain = portInfo.flags & CLAP_AUDIO_PORT_IS_MAIN;
for (uint32_t j=0; j<portInfo.channel_count; ++j)
fOutputAudioBuffers.buffers[i].constant_mask |= (1 << j);

@@ -833,11 +1131,13 @@ public:
if (aOuts > 0)
{
pData->audioOut.createNew(aOuts);
fAudioOutBuffers = new float*[aOuts];
needsCtrlIn = true;

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
fAudioOutBuffers = new float*[aOuts];
for (uint32_t i=0; i < aOuts; ++i)
fAudioOutBuffers[i] = nullptr;
#endif
}

if (mIns == 1)
@@ -852,8 +1152,8 @@ public:
needsCtrlIn = true;
}

fInputEvents.init(pData->event.portIn, mIns, params);
fOutputEvents.init(pData->event.portOut, mOuts, params);
fInputEvents.realloc(pData->event.portIn, mIns, params);
fOutputEvents.realloc(pData->event.portOut, mOuts, params);

const EngineProcessMode processMode = pData->engine->getProccessMode();
const uint portNameSize = pData->engine->getMaxPortNameSize();
@@ -980,10 +1280,11 @@ public:
}

// Parameters
for (uint32_t j=0; j < params; ++j)
for (uint32_t i=0, j=0; i<numParameters; ++i)
{
clap_param_info_t paramInfo = {};
CARLA_SAFE_ASSERT_BREAK(paramsExt->get_info(fPlugin, j, &paramInfo));
CARLA_SAFE_ASSERT_BREAK(paramsExt->get_info(fPlugin, i, &paramInfo));
CARLA_SAFE_ASSERT_BREAK(j < params);

if (paramInfo.flags & (CLAP_PARAM_IS_HIDDEN|CLAP_PARAM_IS_BYPASS))
continue;
@@ -1058,6 +1359,8 @@ public:

fInputEvents.updatedParams[j].clapId = paramInfo.id;
fInputEvents.updatedParams[j].cookie = paramInfo.cookie;

++j;
}

if (needsCtrlIn)
@@ -1098,32 +1401,28 @@ public:
pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);

if (mOuts == 1)
fOutputEvents.portData[0].port = pData->event.portIn;
fOutputEvents.portData[0].port = pData->event.portOut;
}

// plugin hints
const PluginCategory category = fPluginDescriptor->features != nullptr ? getPluginCategoryFromClapFeatures(fPluginDescriptor->features)
: PLUGIN_CATEGORY_NONE;

pData->hints = 0x0;

if (category == PLUGIN_CATEGORY_SYNTH)
if (clapFeaturesContainInstrument(fPluginDescriptor->features))
pData->hints |= PLUGIN_IS_SYNTH;

#ifdef CLAP_WINDOW_API_NATIVE
if (const clap_plugin_gui_t* const guiExt = static_cast<const clap_plugin_gui_t*>(fPlugin->get_extension(fPlugin, CLAP_EXT_GUI)))
if (guiExt != nullptr)
{
if (guiExt->is_api_supported != nullptr)
if (guiExt->is_api_supported(fPlugin, CLAP_WINDOW_API_NATIVE, false))
{
if (guiExt->is_api_supported(fPlugin, CLAP_WINDOW_API_NATIVE, false))
{
pData->hints |= PLUGIN_HAS_CUSTOM_UI;
pData->hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
}
else if (guiExt->is_api_supported(fPlugin, CLAP_WINDOW_API_NATIVE, false))
{
pData->hints |= PLUGIN_HAS_CUSTOM_UI;
}
pData->hints |= PLUGIN_HAS_CUSTOM_UI;
pData->hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
}
else if (guiExt->is_api_supported(fPlugin, CLAP_WINDOW_API_NATIVE, true))
{
pData->hints |= PLUGIN_HAS_CUSTOM_UI;
pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
}
}
#endif
@@ -1210,14 +1509,18 @@ public:
if (pData->audioOut.count > 0)
{
CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr,);
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
CARLA_SAFE_ASSERT_RETURN(fAudioOutBuffers != nullptr,);
#endif
}

// --------------------------------------------------------------------------------------------------------
// Set audio buffers

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
for (uint32_t i=0; i < pData->audioOut.count; ++i)
carla_zeroFloats(fAudioOutBuffers[i], frames);
#endif

// --------------------------------------------------------------------------------------------------------
// Try lock, silence otherwise
@@ -1235,7 +1538,7 @@ public:

// --------------------------------------------------------------------------------------------------------

fInputEvents.prepareScheduledParameterUpdates();
fInputEvents.handleScheduledParameterUpdates();

// --------------------------------------------------------------------------------------------------------
// Check if needs reset
@@ -1353,16 +1656,16 @@ public:
}

// --------------------------------------------------------------------------------------------------------
// Event Input
// Event Input (main port)

if (fInputEvents.portCount != 0)
if (pData->event.portIn != nullptr)
{
// ----------------------------------------------------------------------------------------------------
// MIDI Input (External)

if (pData->extNotes.mutex.tryLock())
{
if (fInputEvents.portCount != 0)
if (fInputEvents.portCount == 0)
{
// does not handle MIDI
pData->extNotes.data.clear();
@@ -1410,11 +1713,9 @@ public:
pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, true, pData->event.portIn);
#endif

const uint32_t numEvents = fInputEvents.defaultPort != nullptr && fInputEvents.defaultPort->port != nullptr
? fInputEvents.defaultPort->port->getEventCount()
: 0;
const uint32_t numSysEvents = pData->event.portIn->getEventCount();

for (uint32_t i=0; i < numEvents; ++i)
for (uint32_t i=0; i < numSysEvents; ++i)
{
EngineEvent& event(fInputEvents.defaultPort->port->getEvent(i));

@@ -1669,7 +1970,15 @@ public:

pData->postRtEvents.trySplice();

} // End of Event Input and Processing
} // End of Event Input (main port)

// --------------------------------------------------------------------------------------------------------
// Event input (multi MIDI port)

if (fInputEvents.portCount > 1)
{
// TODO
}

// --------------------------------------------------------------------------------------------------------
// Plugin processing
@@ -1678,10 +1987,16 @@ public:
fInputAudioBuffers.buffers[i].data32 = audioIn + fInputAudioBuffers.buffers[i].offset;

for (uint32_t i=0; i<fOutputAudioBuffers.count; ++i)
{
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
fOutputAudioBuffers.buffers[i].data32 = fAudioOutBuffers + fOutputAudioBuffers.buffers[i].offset;
#else
fOutputAudioBuffers.buffers[i].data32 = audioOut + fOutputAudioBuffers.buffers[i].offset;
#endif
}

const clap_process_t process = {
fSteadyTime,
static_cast<int64_t>(timeInfo.frame),
frames,
&clapTransport,
fInputAudioBuffers.cast(),
@@ -1697,7 +2012,6 @@ public:
fPlugin->process(fPlugin, &process);

fInputEvents.numEventsUsed = 0;
fSteadyTime += frames;

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
// --------------------------------------------------------------------------------------------------------
@@ -1764,12 +2078,6 @@ public:
}

} // End of Post-processing
#else // BUILD_BRIDGE_ALTERNATIVE_ARCH
for (uint32_t i=0; i < pData->audioOut.count; ++i)
{
for (uint32_t k=0; k < frames; ++k)
audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
}
#endif // BUILD_BRIDGE_ALTERNATIVE_ARCH

// --------------------------------------------------------------------------------------------------------
@@ -1794,6 +2102,7 @@ public:
#endif
}

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
void bufferSizeChanged(const uint32_t newBufferSize) override
{
CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
@@ -1812,18 +2121,7 @@ public:
if (pData->active)
activate();
}

void sampleRateChanged(const double newSampleRate) override
{
CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
carla_debug("CarlaPluginCLAP::sampleRateChanged(%g)", newSampleRate);

if (pData->active)
deactivate();

if (pData->active)
activate();
}
#endif

// -------------------------------------------------------------------
// Plugin buffers
@@ -1840,6 +2138,7 @@ public:
{
carla_debug("CarlaPluginCLAP::clearBuffers() - start");

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
if (fAudioOutBuffers != nullptr)
{
for (uint32_t i=0; i < pData->audioOut.count; ++i)
@@ -1854,6 +2153,7 @@ public:
delete[] fAudioOutBuffers;
fAudioOutBuffers = nullptr;
}
#endif

fInputEvents.clear(pData->event.portIn);
fOutputEvents.clear(pData->event.portOut);
@@ -2094,19 +2394,50 @@ private:

struct Extensions {
const clap_plugin_params_t* params;
#ifdef CLAP_WINDOW_API_NATIVE
const clap_plugin_gui_t* gui;
#endif
const clap_plugin_timer_support_t* timer;

Extensions()
: params(nullptr) {}
: params(nullptr),
#ifdef CLAP_WINDOW_API_NATIVE
gui(nullptr),
#endif
timer(nullptr) {}

CARLA_DECLARE_NON_COPYABLE(Extensions)
} fExtensions;

#ifdef CLAP_WINDOW_API_NATIVE
struct UI {
bool initalized;
bool isCreated;
bool isEmbed;
bool isVisible;
CarlaPluginUI* window;

UI()
: initalized(false),
isCreated(false),
isEmbed(false),
isVisible(false),
window(nullptr) {}

~UI()
{
CARLA_SAFE_ASSERT(window == nullptr);
}
} fUI;
#endif

carla_clap_input_audio_buffers fInputAudioBuffers;
carla_clap_output_audio_buffers fOutputAudioBuffers;
carla_clap_input_events fInputEvents;
carla_clap_output_events fOutputEvents;
int64_t fSteadyTime;
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
float** fAudioOutBuffers;
#endif

#ifdef CARLA_OS_MAC
BundleLoader fBundleLoader;


+ 2
- 1
source/frontend/Makefile View File

@@ -159,7 +159,8 @@ debug:

# ---------------------------------------------------------------------------------------------------------------------

tests: $(UI_FILES:%.ui=%$(APP_EXT))
tests:
# $(UI_FILES:%.ui=%$(APP_EXT))

pluginlist/jackappdialog$(APP_EXT): pluginlist/jackappdialog.cpp pluginlist/jackappdialog.ui pluginlist/jackappdialog_ui.hpp
$(CXX) $< $(BUILD_CXX_FLAGS) $(QT5_LINK_FLAGS) -o $@


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

@@ -49,7 +49,8 @@ typedef struct clap_audio_buffer_with_offset {
uint32_t channel_count;
uint32_t latency;
uint64_t constant_mask;
uint32_t offset;
uint16_t offset;
bool isMain;
} clap_audio_buffer_with_offset_t;

typedef struct clap_audio_buffer_const_with_offset {
@@ -59,7 +60,8 @@ typedef struct clap_audio_buffer_const_with_offset {
uint32_t channel_count;
uint32_t latency;
uint64_t constant_mask;
uint32_t offset;
uint16_t offset;
bool isMain;
} clap_audio_buffer_const_with_offset_t;

}
@@ -140,6 +142,22 @@ PluginCategory getPluginCategoryFromClapFeatures(const char* const* const featur
return PLUGIN_CATEGORY_OTHER;
}

static inline
bool clapFeaturesContainInstrument(const char* const* const features) noexcept
{
if (features == nullptr)
return false;

// 1st pass for main categories
for (uint32_t i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i], CLAP_PLUGIN_FEATURE_INSTRUMENT) == 0)
return true;
}

return false;
}

// --------------------------------------------------------------------------------------------------------------------

CARLA_BACKEND_END_NAMESPACE


Loading…
Cancel
Save