Browse Source

Start placing common lv2 carla-plugin into common class

tags/1.9.8
falkTX 7 years ago
parent
commit
65029231d2
4 changed files with 304 additions and 366 deletions
  1. +14
    -121
      source/bridges-plugin/CarlaBridgeLV2.cpp
  2. +19
    -211
      source/plugin/carla-lv2.cpp
  3. +268
    -31
      source/utils/CarlaLv2Utils.hpp
  4. +3
    -3
      source/utils/CarlaUtils.hpp

+ 14
- 121
source/bridges-plugin/CarlaBridgeLV2.cpp View File

@@ -29,57 +29,30 @@


#include "water/files/File.h" #include "water/files/File.h"


// ---------------------------------------------------------------------------------------------------------------------
// -Weffc++ compat ext widget

extern "C" {

typedef struct _LV2_External_UI_Widget_Compat {
void (*run )(struct _LV2_External_UI_Widget_Compat*);
void (*show)(struct _LV2_External_UI_Widget_Compat*);
void (*hide)(struct _LV2_External_UI_Widget_Compat*);

_LV2_External_UI_Widget_Compat() noexcept
: run(nullptr), show(nullptr), hide(nullptr) {}

} LV2_External_UI_Widget_Compat;

}

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


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Weffc++"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Weffc++"
#endif
class CarlaEngineLV2Single : public CarlaEngine, class CarlaEngineLV2Single : public CarlaEngine,
public LV2_External_UI_Widget_Compat
public Lv2PluginBaseClass
{ {
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
public: public:
CarlaEngineLV2Single(const uint32_t bufferSize, const double sampleRate, const char* const bundlePath, const LV2_URID_Map* uridMap)
: fPlugin(nullptr),
CarlaEngineLV2Single(const double sampleRate,
const char* const bundlePath,
const LV2_Feature* const* const features)
: Lv2PluginBaseClass(sampleRate, features),
fPlugin(nullptr),
fIsActive(false), fIsActive(false),
fIsOffline(false), fIsOffline(false),
fPorts(), fPorts(),
fUI() fUI()
{ {
run = extui_run;
show = extui_show;
hide = extui_hide;

CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount == 0,) CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount == 0,)
CARLA_SAFE_ASSERT_RETURN(pData->plugins[0].plugin == nullptr,); CARLA_SAFE_ASSERT_RETURN(pData->plugins[0].plugin == nullptr,);


if (! loadedInProperHost())
return;

// xxxxx // xxxxx
CarlaString binaryDir(bundlePath); CarlaString binaryDir(bundlePath);
binaryDir += CARLA_OS_SEP_STR "bin" CARLA_OS_SEP_STR; binaryDir += CARLA_OS_SEP_STR "bin" CARLA_OS_SEP_STR;
@@ -87,7 +60,7 @@ public:
CarlaString resourceDir(bundlePath); CarlaString resourceDir(bundlePath);
resourceDir += CARLA_OS_SEP_STR "res" CARLA_OS_SEP_STR; resourceDir += CARLA_OS_SEP_STR "res" CARLA_OS_SEP_STR;


pData->bufferSize = bufferSize;
pData->bufferSize = fBufferSize;
pData->sampleRate = sampleRate; pData->sampleRate = sampleRate;
pData->initTime(nullptr); pData->initTime(nullptr);


@@ -383,20 +356,20 @@ protected:


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


void handleUiRun() const
void handleUiRun() const override
{ {
try { try {
fPlugin->uiIdle(); fPlugin->uiIdle();
} CARLA_SAFE_EXCEPTION("fPlugin->uiIdle()") } CARLA_SAFE_EXCEPTION("fPlugin->uiIdle()")
} }


void handleUiShow()
void handleUiShow() override
{ {
fPlugin->showCustomUI(true); fPlugin->showCustomUI(true);
fUI.visible = true; fUI.visible = true;
} }


void handleUiHide()
void handleUiHide() override
{ {
fUI.visible = false; fUI.visible = false;
fPlugin->showCustomUI(false); fPlugin->showCustomUI(false);
@@ -582,21 +555,6 @@ private:


#define handlePtr ((CarlaEngineLV2Single*)handle) #define handlePtr ((CarlaEngineLV2Single*)handle)


static void extui_run(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiRun();
}

static void extui_show(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiShow();
}

static void extui_hide(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiHide();
}

static void _engine_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr) static void _engine_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr)
{ {
handlePtr->engineCallback(action, pluginId, value1, value2, value3, valueStr); handlePtr->engineCallback(action, pluginId, value1, value2, value3, valueStr);
@@ -618,72 +576,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor* lv2Descriptor, double sa
{ {
carla_stdout("lv2_instantiate(%p, %g, %s, %p)", lv2Descriptor, sampleRate, bundlePath, features); carla_stdout("lv2_instantiate(%p, %g, %s, %p)", lv2Descriptor, sampleRate, bundlePath, features);


const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2_URID_Unmap* uridUnmap = nullptr;

for (int i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
options = (const LV2_Options_Option*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
uridMap = (const LV2_URID_Map*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__unmap) == 0)
uridUnmap = (const LV2_URID_Unmap*)features[i]->data;
}

if (options == nullptr || uridMap == nullptr)
{
carla_stderr("Host doesn't provide option or urid-map features");
return nullptr;
}

uint32_t bufferSize = 0;

for (int i=0; options[i].key != 0; ++i)
{
if (uridUnmap != nullptr) {
carla_stdout("Host option %i:\"%s\"", i, uridUnmap->unmap(uridUnmap->handle, options[i].key));
}

if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

bufferSize = static_cast<uint32_t>(value);
break;
}

carla_stderr("Host provides nominalBlockLength but has wrong value type");
}

if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

bufferSize = static_cast<uint32_t>(value);
// no break, continue in case host supports nominalBlockLength
}
else
{
carla_stderr("Host provides maxBlockLength but has wrong value type");
}
}
}

if (bufferSize == 0)
{
carla_stderr("Host doesn't provide bufferSize feature");
return nullptr;
}

CarlaEngineLV2Single* const instance(new CarlaEngineLV2Single(bufferSize, sampleRate, bundlePath, uridMap));
CarlaEngineLV2Single* const instance(new CarlaEngineLV2Single(sampleRate, bundlePath, features));


if (instance->hasPlugin()) if (instance->hasPlugin())
return (LV2_Handle)instance; return (LV2_Handle)instance;


+ 19
- 211
source/plugin/carla-lv2.cpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Native Plugins * Carla Native Plugins
* Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -22,45 +22,20 @@
#include "CarlaMathUtils.hpp" #include "CarlaMathUtils.hpp"
#include "CarlaString.hpp" #include "CarlaString.hpp"


// -----------------------------------------------------------------------
// -Weffc++ compat ext widget

extern "C" {

typedef struct _LV2_External_UI_Widget_Compat {
void (*run )(struct _LV2_External_UI_Widget_Compat*);
void (*show)(struct _LV2_External_UI_Widget_Compat*);
void (*hide)(struct _LV2_External_UI_Widget_Compat*);

_LV2_External_UI_Widget_Compat() noexcept
: run(nullptr), show(nullptr), hide(nullptr) {}

} LV2_External_UI_Widget_Compat;

}

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// LV2 descriptor functions // LV2 descriptor functions


#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Weffc++"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Weffc++"
#endif
class NativePlugin : public LV2_External_UI_Widget_Compat
class NativePlugin : public Lv2PluginBaseClass
{ {
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
public: public:
static const uint32_t kMaxMidiEvents = 512; static const uint32_t kMaxMidiEvents = 512;


NativePlugin(const NativePluginDescriptor* const desc, const double sampleRate, const char* const bundlePath, const LV2_Feature* const* features)
: fHandle(nullptr),
NativePlugin(const NativePluginDescriptor* const desc,
const double sampleRate,
const char* const bundlePath,
const LV2_Feature* const* const features)
: Lv2PluginBaseClass(sampleRate, features),
fHandle(nullptr),
fHost(), fHost(),
fDescriptor(desc), fDescriptor(desc),
#ifdef CARLA_PROPER_CPP11_SUPPORT #ifdef CARLA_PROPER_CPP11_SUPPORT
@@ -68,25 +43,20 @@ public:
#endif #endif
fMidiEventCount(0), fMidiEventCount(0),
fTimeInfo(), fTimeInfo(),
fIsOffline(false),
fBufferSize(0),
fSampleRate(sampleRate),
fUsingNominal(false),
fUridMap(nullptr),
fLastPositionData(), fLastPositionData(),
fURIs(),
fUI(), fUI(),
fPorts() fPorts()
{ {
run = extui_run;
show = extui_show;
hide = extui_hide;
carla_zeroStruct(fHost);

if (! loadedInProperHost())
return;


CarlaString resourceDir(bundlePath); CarlaString resourceDir(bundlePath);
resourceDir += CARLA_OS_SEP_STR "resources" CARLA_OS_SEP_STR; resourceDir += CARLA_OS_SEP_STR "resources" CARLA_OS_SEP_STR;


fHost.handle = this; fHost.handle = this;
fHost.resourceDir = resourceDir.dup();
fHost.resourceDir = resourceDir.dupSafe();
fHost.uiName = nullptr; fHost.uiName = nullptr;
fHost.uiParentId = 0; fHost.uiParentId = 0;


@@ -101,74 +71,11 @@ public:
fHost.ui_open_file = host_ui_open_file; fHost.ui_open_file = host_ui_open_file;
fHost.ui_save_file = host_ui_save_file; fHost.ui_save_file = host_ui_save_file;
fHost.dispatcher = host_dispatcher; fHost.dispatcher = host_dispatcher;

const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2_URID_Unmap* uridUnmap = nullptr;

for (int i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
options = (const LV2_Options_Option*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
uridMap = (const LV2_URID_Map*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__unmap) == 0)
uridUnmap = (const LV2_URID_Unmap*)features[i]->data;
}

if (options == nullptr || uridMap == nullptr)
{
carla_stderr("Host doesn't provide option or urid-map features");
return;
}

for (int i=0; options[i].key != 0; ++i)
{
if (uridUnmap != nullptr)
{
carla_debug("Host option %i:\"%s\"", i, uridUnmap->unmap(uridUnmap->handle, options[i].key));
}

if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

fBufferSize = static_cast<uint32_t>(value);
fUsingNominal = true;
}
else
{
carla_stderr("Host provides nominalBlockLength but has wrong value type");
}
break;
}

if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

fBufferSize = static_cast<uint32_t>(value);
}
else
{
carla_stderr("Host provides maxBlockLength but has wrong value type");
}
// no break, continue in case host supports nominalBlockLength
}
}

fUridMap = uridMap;
} }


~NativePlugin() ~NativePlugin()
{ {
CARLA_ASSERT(fHandle == nullptr);
CARLA_SAFE_ASSERT(fHandle == nullptr);


if (fHost.resourceDir != nullptr) if (fHost.resourceDir != nullptr)
{ {
@@ -179,23 +86,14 @@ public:


bool init() bool init()
{ {
if (fUridMap == nullptr)
{
// host is missing features
if (fHost.resourceDir == nullptr)
return false; return false;
}

if (fDescriptor->instantiate == nullptr || fDescriptor->process == nullptr) if (fDescriptor->instantiate == nullptr || fDescriptor->process == nullptr)
{ {
carla_stderr("Plugin is missing something..."); carla_stderr("Plugin is missing something...");
return false; return false;
} }
if (fBufferSize == 0)
{
carla_stderr("Host is missing bufferSize feature");
//return false;
// as testing, continue for now
fBufferSize = 1024;
}


carla_zeroStructs(fMidiEvents, kMaxMidiEvents); carla_zeroStructs(fMidiEvents, kMaxMidiEvents);
carla_zeroStruct(fTimeInfo); carla_zeroStruct(fTimeInfo);
@@ -214,8 +112,6 @@ public:
fUI.portOffset += fDescriptor->audioOuts; fUI.portOffset += fDescriptor->audioOuts;


fPorts.init(fDescriptor, fHandle); fPorts.init(fDescriptor, fHandle);
fURIs.map(fUridMap);

return true; return true;
} }


@@ -968,13 +864,13 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------


protected: protected:
void handleUiRun() const
void handleUiRun() const override
{ {
if (fDescriptor->ui_idle != nullptr) if (fDescriptor->ui_idle != nullptr)
fDescriptor->ui_idle(fHandle); fDescriptor->ui_idle(fHandle);
} }


void handleUiShow()
void handleUiShow() override
{ {
if (fDescriptor->ui_show != nullptr) if (fDescriptor->ui_show != nullptr)
fDescriptor->ui_show(fHandle, true); fDescriptor->ui_show(fHandle, true);
@@ -982,7 +878,7 @@ protected:
fUI.isVisible = true; fUI.isVisible = true;
} }


void handleUiHide()
void handleUiHide() override
{ {
if (fDescriptor->ui_show != nullptr) if (fDescriptor->ui_show != nullptr)
fDescriptor->ui_show(fHandle, false); fDescriptor->ui_show(fHandle, false);
@@ -1116,14 +1012,6 @@ private:
NativeMidiEvent fMidiEvents[kMaxMidiEvents]; NativeMidiEvent fMidiEvents[kMaxMidiEvents];
NativeTimeInfo fTimeInfo; NativeTimeInfo fTimeInfo;


// Lv2 host data
bool fIsOffline;
uint32_t fBufferSize;
double fSampleRate;
bool fUsingNominal;

const LV2_URID_Map* fUridMap;

struct Lv2PositionData { struct Lv2PositionData {
int32_t bar; int32_t bar;
float bar_f; float bar_f;
@@ -1148,69 +1036,6 @@ private:


} fLastPositionData; } fLastPositionData;


struct URIDs {
LV2_URID atomBlank;
LV2_URID atomObject;
LV2_URID atomDouble;
LV2_URID atomFloat;
LV2_URID atomInt;
LV2_URID atomLong;
LV2_URID atomSequence;
LV2_URID atomString;
LV2_URID midiEvent;
LV2_URID timePos;
LV2_URID timeBar;
LV2_URID timeBarBeat;
LV2_URID timeBeatsPerBar;
LV2_URID timeBeatsPerMinute;
LV2_URID timeBeatUnit;
LV2_URID timeFrame;
LV2_URID timeSpeed;
LV2_URID timeTicksPerBeat;

URIDs()
: atomBlank(0),
atomObject(0),
atomDouble(0),
atomFloat(0),
atomInt(0),
atomLong(0),
atomSequence(0),
atomString(0),
midiEvent(0),
timePos(0),
timeBar(0),
timeBarBeat(0),
timeBeatsPerBar(0),
timeBeatsPerMinute(0),
timeBeatUnit(0),
timeFrame(0),
timeSpeed(0),
timeTicksPerBeat(0) {}

void map(const LV2_URID_Map* const uridMap)
{
atomBlank = uridMap->map(uridMap->handle, LV2_ATOM__Blank);
atomObject = uridMap->map(uridMap->handle, LV2_ATOM__Object);
atomDouble = uridMap->map(uridMap->handle, LV2_ATOM__Double);
atomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float);
atomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int);
atomLong = uridMap->map(uridMap->handle, LV2_ATOM__Long);
atomSequence = uridMap->map(uridMap->handle, LV2_ATOM__Sequence);
atomString = uridMap->map(uridMap->handle, LV2_ATOM__String);
midiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
timePos = uridMap->map(uridMap->handle, LV2_TIME__Position);
timeBar = uridMap->map(uridMap->handle, LV2_TIME__bar);
timeBarBeat = uridMap->map(uridMap->handle, LV2_TIME__barBeat);
timeBeatUnit = uridMap->map(uridMap->handle, LV2_TIME__beatUnit);
timeFrame = uridMap->map(uridMap->handle, LV2_TIME__frame);
timeSpeed = uridMap->map(uridMap->handle, LV2_TIME__speed);
timeBeatsPerBar = uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar);
timeBeatsPerMinute = uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute);
timeTicksPerBeat = uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat);
}
} fURIs;

struct UI { struct UI {
const LV2_External_UI_Host* host; const LV2_External_UI_Host* host;
LV2UI_Write_Function writeFunction; LV2UI_Write_Function writeFunction;
@@ -1447,23 +1272,6 @@ private:


#define handlePtr ((NativePlugin*)handle) #define handlePtr ((NativePlugin*)handle)


static void extui_run(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiRun();
}

static void extui_show(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiShow();
}

static void extui_hide(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiHide();
}

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

static uint32_t host_get_buffer_size(NativeHostHandle handle) static uint32_t host_get_buffer_size(NativeHostHandle handle)
{ {
return handlePtr->fBufferSize; return handlePtr->fBufferSize;


+ 268
- 31
source/utils/CarlaLv2Utils.hpp View File

@@ -18,7 +18,7 @@
#ifndef CARLA_LV2_UTILS_HPP_INCLUDED #ifndef CARLA_LV2_UTILS_HPP_INCLUDED
#define CARLA_LV2_UTILS_HPP_INCLUDED #define CARLA_LV2_UTILS_HPP_INCLUDED


#include "CarlaUtils.hpp"
#include "CarlaMathUtils.hpp"


#ifndef nullptr #ifndef nullptr
# undef NULL # undef NULL
@@ -89,7 +89,7 @@
#include <map> #include <map>
typedef std::map<double,const LilvScalePoint*> LilvScalePointMap; typedef std::map<double,const LilvScalePoint*> LilvScalePointMap;


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Define namespaces and missing prefixes // Define namespaces and missing prefixes


#define NS_dct "http://purl.org/dc/terms/" #define NS_dct "http://purl.org/dc/terms/"
@@ -109,7 +109,7 @@ typedef std::map<double,const LilvScalePoint*> LilvScalePointMap;
// TODO: update LV2 headers once again // TODO: update LV2 headers once again
#define LV2_CORE__enabled LV2_CORE_PREFIX "enabled" ///< http://lv2plug.in/ns/lv2core#enabled #define LV2_CORE__enabled LV2_CORE_PREFIX "enabled" ///< http://lv2plug.in/ns/lv2core#enabled


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Custom Atom types // Custom Atom types


struct LV2_Atom_MidiEvent { struct LV2_Atom_MidiEvent {
@@ -123,7 +123,24 @@ uint32_t lv2_atom_total_size(const LV2_Atom_MidiEvent& midiEv)
return static_cast<uint32_t>(sizeof(LV2_Atom)) + midiEv.atom.size; return static_cast<uint32_t>(sizeof(LV2_Atom)) + midiEv.atom.size;
} }


// -----------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// -Weffc++ compat ext widget

extern "C" {

typedef struct _LV2_External_UI_Widget_Compat {
void (*run )(struct _LV2_External_UI_Widget_Compat*);
void (*show)(struct _LV2_External_UI_Widget_Compat*);
void (*hide)(struct _LV2_External_UI_Widget_Compat*);

_LV2_External_UI_Widget_Compat() noexcept
: run(nullptr), show(nullptr), hide(nullptr) {}

} LV2_External_UI_Widget_Compat;

}

// --------------------------------------------------------------------------------------------------------------------
// Our LV2 World class // Our LV2 World class


class Lv2WorldClass : public Lilv::World class Lv2WorldClass : public Lilv::World
@@ -258,7 +275,7 @@ public:
const LilvPlugin** cachedPlugins; const LilvPlugin** cachedPlugins;
uint pluginCount; uint pluginCount;


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


Lv2WorldClass() Lv2WorldClass()
: Lilv::World(), : Lilv::World(),
@@ -498,7 +515,227 @@ public:
CARLA_DECLARE_NON_COPY_STRUCT(Lv2WorldClass) CARLA_DECLARE_NON_COPY_STRUCT(Lv2WorldClass)
}; };


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Our LV2 Plugin base class

#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Weffc++"
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Weffc++"
#endif
class Lv2PluginBaseClass : public LV2_External_UI_Widget_Compat
{
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop
#endif
public:
Lv2PluginBaseClass(const double sampleRate, const LV2_Feature* const* const features)
: fIsOffline(false),
fBufferSize(0),
fSampleRate(sampleRate),
fUsingNominal(false),
fUridMap(nullptr)
{
run = extui_run;
show = extui_show;
hide = extui_hide;

if (fSampleRate < 1.0)
{
carla_stderr("Host doesn't provide a valid sample rate");
return;
}

const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2_URID_Unmap* uridUnmap = nullptr;

for (int i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
options = (const LV2_Options_Option*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
uridMap = (const LV2_URID_Map*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__unmap) == 0)
uridUnmap = (const LV2_URID_Unmap*)features[i]->data;
}

if (options == nullptr || uridMap == nullptr)
{
carla_stderr("Host doesn't provide option or urid-map features");
return;
}

for (int i=0; options[i].key != 0; ++i)
{
if (uridUnmap != nullptr) {
carla_debug("Host option %i:\"%s\"", i, uridUnmap->unmap(uridUnmap->handle, options[i].key));
}

if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

fBufferSize = static_cast<uint32_t>(value);
fUsingNominal = true;
}
else
{
carla_stderr("Host provides nominalBlockLength but has wrong value type");
}
break;
}

if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

fBufferSize = static_cast<uint32_t>(value);
}
else
{
carla_stderr("Host provides maxBlockLength but has wrong value type");
}
// no break, continue in case host supports nominalBlockLength
}
}

if (fBufferSize == 0)
{
carla_stderr("Host doesn't provide buffer-size feature");
//return;
// as testing, continue for now
fBufferSize = 1024;
}

fUridMap = uridMap;
fURIs.map(uridMap);
}

virtual ~Lv2PluginBaseClass()
{
}

bool loadedInProperHost() const noexcept
{
return fUridMap != nullptr && fBufferSize != 0;
}

protected:
virtual void handleUiRun() const = 0;
virtual void handleUiShow() = 0;
virtual void handleUiHide() = 0;

// LV2 host data
bool fIsOffline;
uint32_t fBufferSize;
double fSampleRate;
bool fUsingNominal;

// LV2 host features
const LV2_URID_Map* fUridMap;

struct URIDs {
LV2_URID atomBlank;
LV2_URID atomObject;
LV2_URID atomDouble;
LV2_URID atomFloat;
LV2_URID atomInt;
LV2_URID atomLong;
LV2_URID atomSequence;
LV2_URID atomString;
LV2_URID midiEvent;
LV2_URID timePos;
LV2_URID timeBar;
LV2_URID timeBarBeat;
LV2_URID timeBeatsPerBar;
LV2_URID timeBeatsPerMinute;
LV2_URID timeBeatUnit;
LV2_URID timeFrame;
LV2_URID timeSpeed;
LV2_URID timeTicksPerBeat;

URIDs()
: atomBlank(0),
atomObject(0),
atomDouble(0),
atomFloat(0),
atomInt(0),
atomLong(0),
atomSequence(0),
atomString(0),
midiEvent(0),
timePos(0),
timeBar(0),
timeBarBeat(0),
timeBeatsPerBar(0),
timeBeatsPerMinute(0),
timeBeatUnit(0),
timeFrame(0),
timeSpeed(0),
timeTicksPerBeat(0) {}

void map(const LV2_URID_Map* const uridMap)
{
atomBlank = uridMap->map(uridMap->handle, LV2_ATOM__Blank);
atomObject = uridMap->map(uridMap->handle, LV2_ATOM__Object);
atomDouble = uridMap->map(uridMap->handle, LV2_ATOM__Double);
atomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float);
atomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int);
atomLong = uridMap->map(uridMap->handle, LV2_ATOM__Long);
atomSequence = uridMap->map(uridMap->handle, LV2_ATOM__Sequence);
atomString = uridMap->map(uridMap->handle, LV2_ATOM__String);
midiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
timePos = uridMap->map(uridMap->handle, LV2_TIME__Position);
timeBar = uridMap->map(uridMap->handle, LV2_TIME__bar);
timeBarBeat = uridMap->map(uridMap->handle, LV2_TIME__barBeat);
timeBeatUnit = uridMap->map(uridMap->handle, LV2_TIME__beatUnit);
timeFrame = uridMap->map(uridMap->handle, LV2_TIME__frame);
timeSpeed = uridMap->map(uridMap->handle, LV2_TIME__speed);
timeBeatsPerBar = uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar);
timeBeatsPerMinute = uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute);
timeTicksPerBeat = uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat);
}
} fURIs;

private:
// ----------------------------------------------------------------------------------------------------------------

#define handlePtr ((Lv2PluginBaseClass*)handle)

static void extui_run(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiRun();
}

static void extui_show(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiShow();
}

static void extui_hide(LV2_External_UI_Widget_Compat* handle)
{
handlePtr->handleUiHide();
}

#undef handlePtr

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

CARLA_DECLARE_NON_COPY_STRUCT(Lv2PluginBaseClass)
};

// --------------------------------------------------------------------------------------------------------------------
// Create new RDF object (using lilv) // Create new RDF object (using lilv)


static inline static inline
@@ -514,7 +751,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
Lilv::Plugin lilvPlugin(cPlugin); Lilv::Plugin lilvPlugin(cPlugin);
LV2_RDF_Descriptor* const rdfDescriptor(new LV2_RDF_Descriptor()); LV2_RDF_Descriptor* const rdfDescriptor(new LV2_RDF_Descriptor());


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin Type // Set Plugin Type
{ {
Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type)); Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
@@ -600,7 +837,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin Information // Set Plugin Information
{ {
rdfDescriptor->URI = carla_strdup(uri); rdfDescriptor->URI = carla_strdup(uri);
@@ -632,7 +869,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin UniqueID // Set Plugin UniqueID
{ {
Lilv::Nodes replaceNodes(lilvPlugin.get_value(lv2World.dct_replaces)); Lilv::Nodes replaceNodes(lilvPlugin.get_value(lv2World.dct_replaces));
@@ -673,7 +910,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(replaceNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(replaceNodes.me));
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin Ports // Set Plugin Ports


if (lilvPlugin.get_num_ports() > 0) if (lilvPlugin.get_num_ports() > 0)
@@ -686,7 +923,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i)); Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[i]); LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[i]);


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Information // Set Port Information
{ {
if (LilvNode* const nameNode = lilv_port_get_name(lilvPlugin.me, lilvPort.me)) if (LilvNode* const nameNode = lilv_port_get_name(lilvPlugin.me, lilvPort.me))
@@ -700,7 +937,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
rdfPort->Symbol = carla_strdup(symbol); rdfPort->Symbol = carla_strdup(symbol);
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Mode and Type // Set Port Mode and Type
{ {
// Input or Output // Input or Output
@@ -800,7 +1037,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of unkown data type", uri, rdfPort->Name); carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of unkown data type", uri, rdfPort->Name);
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Properties // Set Port Properties
{ {
if (lilvPort.has_property(lv2World.pprop_optional)) if (lilvPort.has_property(lv2World.pprop_optional))
@@ -899,7 +1136,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
} }
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Designation // Set Port Designation
{ {
if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me)) if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
@@ -947,7 +1184,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
} }
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port MIDI Map // Set Port MIDI Map
{ {
if (LilvNode* const midiMapNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.mm_defaultControl.me)) if (LilvNode* const midiMapNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.mm_defaultControl.me))
@@ -982,7 +1219,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
// TODO - also check using new official MIDI API too // TODO - also check using new official MIDI API too
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Points // Set Port Points
{ {
if (LilvNode* const defNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_default.me)) if (LilvNode* const defNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_default.me))
@@ -1007,7 +1244,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
} }
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Unit // Set Port Unit
{ {
if (LilvNode* const unitUnitNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.unit_unit.me)) if (LilvNode* const unitUnitNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.unit_unit.me))
@@ -1105,7 +1342,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
} }
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Minimum Size // Set Port Minimum Size
{ {
if (LilvNode* const minimumSizeNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.rz_minSize.me)) if (LilvNode* const minimumSizeNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.rz_minSize.me))
@@ -1121,7 +1358,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
} }
} }


// -----------------------------------------------------------
// --------------------------------------------------------------------------------------------------------
// Set Port Scale Points // Set Port Scale Points


{ {
@@ -1170,7 +1407,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
} }
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin Presets // Set Plugin Presets


if (loadPresets) if (loadPresets)
@@ -1266,7 +1503,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(presetNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(presetNodes.me));
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin Features // Set Plugin Features
{ {
Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features()); Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
@@ -1300,7 +1537,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin Extensions // Set Plugin Extensions
{ {
Lilv::Nodes lilvExtensionDataNodes(lilvPlugin.get_extension_data()); Lilv::Nodes lilvExtensionDataNodes(lilvPlugin.get_extension_data());
@@ -1336,7 +1573,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me));
} }


// -------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin UIs // Set Plugin UIs
{ {
Lilv::UIs lilvUIs(lilvPlugin.get_uis()); Lilv::UIs lilvUIs(lilvPlugin.get_uis());
@@ -1354,7 +1591,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
Lilv::UI lilvUI(lilvUIs.get(it)); Lilv::UI lilvUI(lilvUIs.get(it));
LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[h++]); LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[h++]);


// -------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
// Set UI Type // Set UI Type


/**/ if (lilvUI.is_a(lv2World.ui_gtk2)) /**/ if (lilvUI.is_a(lv2World.ui_gtk2))
@@ -1380,7 +1617,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
else else
carla_stderr("lv2_rdf_new(\"%s\") - UI '%s' is of unknown type", uri, lilvUI.get_uri().as_uri()); carla_stderr("lv2_rdf_new(\"%s\") - UI '%s' is of unknown type", uri, lilvUI.get_uri().as_uri());


// -------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
// Set UI Information // Set UI Information
{ {
if (const char* const uiURI = lilvUI.get_uri().as_uri()) if (const char* const uiURI = lilvUI.get_uri().as_uri())
@@ -1393,7 +1630,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
rdfUI->Bundle = carla_strdup_free(lilv_file_uri_parse(uiBundle, nullptr)); rdfUI->Bundle = carla_strdup_free(lilv_file_uri_parse(uiBundle, nullptr));
} }


// -------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
// Set UI Features // Set UI Features
{ {
Lilv::Nodes lilvFeatureNodes(lilvUI.get_supported_features()); Lilv::Nodes lilvFeatureNodes(lilvUI.get_supported_features());
@@ -1427,7 +1664,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me)); lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
} }


// -------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
// Set UI Extensions // Set UI Extensions
{ {
Lilv::Nodes lilvExtensionDataNodes(lilvUI.get_extension_data()); Lilv::Nodes lilvExtensionDataNodes(lilvUI.get_extension_data());
@@ -1471,7 +1708,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
return rdfDescriptor; return rdfDescriptor;
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Check if we support a plugin port // Check if we support a plugin port


static inline static inline
@@ -1492,7 +1729,7 @@ bool is_lv2_port_supported(const LV2_Property types) noexcept
return false; return false;
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Check if we support a plugin feature // Check if we support a plugin feature


static inline static inline
@@ -1545,7 +1782,7 @@ bool is_lv2_feature_supported(const LV2_URI uri) noexcept
return false; return false;
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Check if we support a plugin or UI feature // Check if we support a plugin or UI feature


static inline static inline
@@ -1588,6 +1825,6 @@ bool is_lv2_ui_feature_supported(const LV2_URI uri) noexcept
return false; return false;
} }


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


#endif // CARLA_LV2_UTILS_HPP_INCLUDED #endif // CARLA_LV2_UTILS_HPP_INCLUDED

+ 3
- 3
source/utils/CarlaUtils.hpp View File

@@ -369,14 +369,14 @@ const char* carla_strdup_free(char* const strBuf)


/* /*
* Custom 'strdup' function, safe version. * Custom 'strdup' function, safe version.
* Returned value may be null.
* Returned value may be null. It must be freed with "delete[] var".
*/ */
static inline static inline
const char* carla_strdup_safe(const char* const strBuf) noexcept const char* carla_strdup_safe(const char* const strBuf) noexcept
{ {
CARLA_SAFE_ASSERT(strBuf != nullptr);
CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, nullptr);


const std::size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0;
const std::size_t bufferLen = std::strlen(strBuf);
char* buffer; char* buffer;


try { try {


Loading…
Cancel
Save