Browse Source

Implement CLAP state

Signed-off-by: falkTX <falktx@falktx.com>
pull/1689/head
falkTX 2 years ago
parent
commit
9abb529dec
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
4 changed files with 170 additions and 46 deletions
  1. +21
    -12
      source/backend/plugin/CarlaPlugin.cpp
  2. +73
    -30
      source/backend/plugin/CarlaPluginCLAP.cpp
  3. +66
    -1
      source/utils/CarlaClapUtils.hpp
  4. +10
    -3
      source/utils/CarlaStateUtils.cpp

+ 21
- 12
source/backend/plugin/CarlaPlugin.cpp View File

@@ -521,7 +521,7 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)
prepareForSave(true);
}

const PluginType pluginType(getType());
const PluginType pluginType = getType();

char strBuf[STR_MAX+1];
carla_zeroChars(strBuf, STR_MAX+1);
@@ -567,7 +567,7 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)
if (pData->options & PLUGIN_OPTION_USE_CHUNKS)
{
void* data = nullptr;
const std::size_t dataSize(getChunkData(&data));
const std::size_t dataSize = getChunkData(&data);

if (data != nullptr && dataSize > 0)
{
@@ -601,7 +601,7 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)
// ---------------------------------------------------------------
// Parameters

const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
const float sampleRate = static_cast<float>(pData->engine->getSampleRate());

for (uint32_t i=0; i < pData->param.count; ++i)
{
@@ -683,8 +683,8 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)

void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
{
const bool usesMultiProgs(pData->hints & PLUGIN_USES_MULTI_PROGS);
const PluginType pluginType(getType());
const bool usesMultiProgs = pData->hints & PLUGIN_USES_MULTI_PROGS;
const PluginType pluginType = getType();

char strBuf[STR_MAX+1];
carla_zeroChars(strBuf, STR_MAX+1);
@@ -753,7 +753,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)

LinkedList<ParamSymbol*> paramSymbols;

if (pluginType == PLUGIN_LADSPA || pluginType == PLUGIN_LV2)
if (pluginType == PLUGIN_LADSPA || pluginType == PLUGIN_LV2 || pluginType == PLUGIN_CLAP)
{
for (uint32_t i=0; i < pData->param.count; ++i)
{
@@ -771,7 +771,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
// ---------------------------------------------------------------
// Part 4b - set parameter values (carefully)

const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
const float sampleRate = static_cast<float>(pData->engine->getSampleRate());

for (CarlaStateSave::ParameterItenerator it = stateSave.parameters.begin2(); it.valid(); it.next())
{
@@ -805,7 +805,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
index = stateParameter->index;
}
}
else if (pluginType == PLUGIN_LV2)
else if (pluginType == PLUGIN_LV2 || pluginType == PLUGIN_CLAP)
{
// Symbol only
if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
@@ -823,12 +823,21 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
}
}
if (index == -1)
carla_stderr("Failed to find LV2 parameter symbol '%s' for '%s'",
stateParameter->symbol, pData->name);
{
if (pluginType == PLUGIN_LV2)
carla_stderr("Failed to find LV2 parameter symbol '%s' for '%s'",
stateParameter->symbol, pData->name);
else
carla_stderr("Failed to find CLAP parameter id '%s' for '%s'",
stateParameter->symbol, pData->name);
}
}
else
{
carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name);
if (pluginType == PLUGIN_LV2)
carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name);
else
carla_stderr("CLAP Plugin parameter '%s' has no id", stateParameter->name);
}
}
else
@@ -941,7 +950,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
// ---------------------------------------------------------------
// Part 6 - set internal stuff

const uint availOptions(getOptionsAvailable());
const uint availOptions = getOptionsAvailable();

for (uint i=0; i<10; ++i) // FIXME - get this value somehow...
{


+ 73
- 30
source/backend/plugin/CarlaPluginCLAP.cpp View File

@@ -132,6 +132,7 @@ struct carla_clap_host : clap_host_t {
virtual void clapRequestRestart() = 0;
virtual void clapRequestProcess() = 0;
virtual void clapRequestCallback() = 0;
virtual void clapMarkDirty() = 0;
#ifdef CLAP_WINDOW_API_NATIVE
// gui
virtual void clapGuiResizeHintsChanged() = 0;
@@ -147,6 +148,7 @@ struct carla_clap_host : clap_host_t {

Callbacks* const hostCallbacks;

clap_host_state_t state;
#ifdef CLAP_WINDOW_API_NATIVE
clap_host_gui_t gui;
clap_host_timer_support_t timer;
@@ -167,12 +169,15 @@ struct carla_clap_host : clap_host_t {
request_process = carla_request_process;
request_callback = carla_request_callback;

state.mark_dirty = carla_mark_dirty;

#ifdef CLAP_WINDOW_API_NATIVE
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;
#endif
@@ -213,6 +218,11 @@ struct carla_clap_host : clap_host_t {
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapRequestCallback();
}

static void carla_mark_dirty(const clap_host_t* const host)
{
static_cast<const carla_clap_host*>(host->host_data)->hostCallbacks->clapMarkDirty();
}

#ifdef CLAP_WINDOW_API_NATIVE
static void carla_resize_hints_changed(const clap_host_t* const host)
{
@@ -571,10 +581,11 @@ public:
fInputAudioBuffers(),
fOutputAudioBuffers(),
fInputEvents(),
fOutputEvents()
fOutputEvents(),
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
, fAudioOutBuffers(nullptr)
fAudioOutBuffers(nullptr),
#endif
fLastChunk(nullptr)
{
carla_debug("CarlaPluginCLAP::CarlaPluginCLAP(%p, %i)", engine, id);
}
@@ -607,6 +618,12 @@ public:
fPlugin = nullptr;
}

if (fLastChunk != nullptr)
{
std::free(fLastChunk);
fLastChunk = nullptr;
}

clearBuffers();

if (fPluginEntry != nullptr)
@@ -692,11 +709,19 @@ public:
CARLA_SAFE_ASSERT_RETURN(fExtensions.state != nullptr, 0);
CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);

*dataPtr = nullptr;

// TODO
std::free(fLastChunk);

return 0;
clap_ostream_impl stream;
if (fExtensions.state->save(fPlugin, &stream))
{
*dataPtr = fLastChunk = stream.buffer;
return stream.size;
}
else
{
*dataPtr = fLastChunk = nullptr;
return 0;
}
}

// -------------------------------------------------------------------
@@ -877,9 +902,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);

// TODO
pData->updateParameterValues(this, true, true, false);
const clap_istream_impl stream(data, dataSize);
if (fExtensions.state->load(fPlugin, &stream))
pData->updateParameterValues(this, true, true, false);
}

// -------------------------------------------------------------------
@@ -1048,7 +1073,10 @@ public:
HostTimerDetails& timer(it.getValue(kTimerFallbackNC));

if (currentTimeInMs > timer.lastCallTimeInMs + timer.periodInMs)
{
timer.lastCallTimeInMs = currentTimeInMs;
fExtensions.timer->on_timer(fPlugin, timer.clapId);
}
}

CarlaPlugin::uiIdle();
@@ -1363,7 +1391,7 @@ public:
continue;

pData->param.data[j].index = j;
pData->param.data[j].rindex = paramInfo.id;
pData->param.data[j].rindex = static_cast<int32_t>(paramInfo.id);

double min, max, def, step, stepSmall, stepLarge;

@@ -2189,7 +2217,7 @@ public:
case CLAP_EVENT_PARAM_VALUE:
for (uint32_t j=0; j<pData->param.count; ++j)
{
if (pData->param.data[j].rindex != ev.param.param_id)
if (pData->param.data[j].rindex != static_cast<int32_t>(ev.param.param_id))
continue;
pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(j), ev.param.value);
break;
@@ -2328,6 +2356,12 @@ protected:

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

void clapMarkDirty() override
{
}

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

#ifdef CLAP_WINDOW_API_NATIVE
void clapGuiResizeHintsChanged() override
{
@@ -2431,12 +2465,6 @@ public:
return false;
}

if (id == nullptr || id[0] == '\0')
{
pData->engine->setLastError("null label/id");
return false;
}

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

const clap_plugin_entry_t* entry;
@@ -2512,16 +2540,36 @@ public:

if (const uint32_t count = factory->get_plugin_count(factory))
{
for (uint32_t i=0; i<count; ++i)
// null id requested, use first available plugin
if (id == nullptr || id[0] == '\0')
{
const clap_plugin_descriptor_t* const desc = factory->get_plugin_descriptor(factory, i);
CARLA_SAFE_ASSERT_CONTINUE(desc != nullptr);
CARLA_SAFE_ASSERT_CONTINUE(desc->id != nullptr);
fPluginDescriptor = factory->get_plugin_descriptor(factory, 0);

if (std::strcmp(desc->id, id) == 0)
if (fPluginDescriptor == nullptr)
{
fPluginDescriptor = desc;
break;
pData->engine->setLastError("Plugin library does not contain a valid first plugin");
return false;
}
}
else
{
for (uint32_t i=0; i<count; ++i)
{
const clap_plugin_descriptor_t* const desc = factory->get_plugin_descriptor(factory, i);
CARLA_SAFE_ASSERT_CONTINUE(desc != nullptr);
CARLA_SAFE_ASSERT_CONTINUE(desc->id != nullptr);

if (std::strcmp(desc->id, id) == 0)
{
fPluginDescriptor = desc;
break;
}
}

if (fPluginDescriptor == nullptr)
{
pData->engine->setLastError("Plugin library does not contain the requested plugin");
return false;
}
}
}
@@ -2531,12 +2579,6 @@ public:
return false;
}

if (fPluginDescriptor == nullptr)
{
pData->engine->setLastError("Plugin library does not contain the requested plugin");
return false;
}

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

fPlugin = factory->create_plugin(factory, &fHost, fPluginDescriptor->id);
@@ -2679,6 +2721,7 @@ private:
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
float** fAudioOutBuffers;
#endif
void* fLastChunk;

#ifdef CARLA_OS_MAC
BundleLoader fBundleLoader;


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

@@ -148,7 +148,6 @@ 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)
@@ -160,6 +159,72 @@ bool clapFeaturesContainInstrument(const char* const* const features) noexcept

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

struct clap_istream_impl : clap_istream_t {
const void* buffer;
const uint64_t size;
uint64_t readPos;

clap_istream_impl(const void* const buf, const uint64_t bufsize) noexcept
: buffer(buf),
size(bufsize),
readPos(0)
{
ctx = this;
read = read_impl;
}

static int64_t read_impl(const clap_istream_t* const stream, void* const buffer, const uint64_t size) noexcept
{
clap_istream_impl* const self = static_cast<clap_istream_impl*>(stream->ctx);

if (const uint64_t bytesRead = std::min(self->size - self->readPos, size))
{
std::memcpy(buffer, static_cast<const uint8_t*>(self->buffer) + self->readPos, bytesRead);
self->readPos += bytesRead;
return bytesRead;
}

return 0;
}
};

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

struct clap_ostream_impl : clap_ostream_t {
void* buffer;
uint64_t size;

clap_ostream_impl() noexcept
: buffer(nullptr),
size(0)
{
ctx = this;
write = write_impl;
}

static int64_t write_impl(const clap_ostream* const stream, const void* const buffer, const uint64_t size) noexcept
{
CARLA_SAFE_ASSERT_RETURN(size != 0, 0);

clap_ostream_impl* const self = static_cast<clap_ostream_impl*>(stream->ctx);

void* const oldBuffer = self->buffer;
self->buffer = std::realloc(self->buffer, self->size + size);

if (self->buffer == nullptr)
{
std::free(oldBuffer);
return -1;
}

std::memcpy(static_cast<uint8_t*>(self->buffer) + self->size, buffer, size);
self->size += size;
return size;
}
};

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

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_CLAP_UTILS_HPP_INCLUDED

+ 10
- 3
source/utils/CarlaStateUtils.cpp View File

@@ -429,7 +429,7 @@ bool CarlaStateSave::fillFromXmlElement(const XmlElement* const xmlElement)
{
stateParameter->name = xmlSafeStringCharDup(pText, false);
}
else if (pTag == "Symbol")
else if (pTag == "Symbol" || pTag == "Identifier")
{
stateParameter->symbol = xmlSafeStringCharDup(pText, false);
}
@@ -559,6 +559,8 @@ bool CarlaStateSave::fillFromXmlElement(const XmlElement* const xmlElement)

void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const
{
const PluginType pluginType = getPluginTypeFromString(type);

{
MemoryOutputStream infoXml;

@@ -566,7 +568,7 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const
infoXml << " <Type>" << String(type != nullptr ? type : "") << "</Type>\n";
infoXml << " <Name>" << xmlSafeString(name, true) << "</Name>\n";

switch (getPluginTypeFromString(type))
switch (pluginType)
{
case PLUGIN_NONE:
break;
@@ -666,7 +668,12 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const
parameterXml << " <Name>" << xmlSafeString(stateParameter->name, true) << "</Name>\n";

if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
parameterXml << " <Symbol>" << xmlSafeString(stateParameter->symbol, true) << "</Symbol>\n";
{
if (pluginType == PLUGIN_CLAP)
parameterXml << " <Identifier>" << xmlSafeString(stateParameter->symbol, true) << "</Identifier>\n";
else
parameterXml << " <Symbol>" << xmlSafeString(stateParameter->symbol, true) << "</Symbol>\n";
}

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
if (stateParameter->mappedControlIndex > CONTROL_INDEX_NONE && stateParameter->mappedControlIndex <= CONTROL_INDEX_MAX_ALLOWED)


Loading…
Cancel
Save