Browse Source

Initial work for LV2 internal display

tags/1.9.8
falkTX 7 years ago
parent
commit
856bbf6015
4 changed files with 170 additions and 40 deletions
  1. +17
    -0
      source/backend/CarlaHost.h
  2. +23
    -0
      source/backend/CarlaStandalone.cpp
  3. +102
    -40
      source/backend/plugin/CarlaPluginLV2.cpp
  4. +28
    -0
      source/carla_backend.py

+ 17
- 0
source/backend/CarlaHost.h View File

@@ -268,6 +268,17 @@ typedef struct _CarlaTransportInfo {

} CarlaTransportInfo;

/*!
* Image data for LV2 inline display API.
* raw image pixmap format is ARGB32,
*/
typedef struct {
unsigned char* data;
int width;
int height;
int stride;
} CarlaInlineDisplayImageSurface;

/* ------------------------------------------------------------------------------------------------------------
* Carla Host API (C functions) */

@@ -709,6 +720,12 @@ CARLA_EXPORT float carla_get_input_peak_value(uint pluginId, bool isLeft);
*/
CARLA_EXPORT float carla_get_output_peak_value(uint pluginId, bool isLeft);

/*!
* Render a plugin's inline display.
* @param pluginId Plugin
*/
CARLA_EXPORT CarlaInlineDisplayImageSurface* carla_render_inline_display(uint pluginId, int width, int height);

/*!
* Enable or disable a plugin.
* @param pluginId Plugin


+ 23
- 0
source/backend/CarlaStandalone.cpp View File

@@ -1578,6 +1578,29 @@ float carla_get_output_peak_value(uint pluginId, bool isLeft)

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

CARLA_BACKEND_START_NAMESPACE

// defined in CarlaPluginLV2.cpp
void* carla_render_inline_display_lv2(CarlaPlugin* plugin, int width, int height);

CARLA_BACKEND_END_NAMESPACE

CarlaInlineDisplayImageSurface* carla_render_inline_display(uint pluginId, int width, int height)
{
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, nullptr);

if (CarlaPlugin* const plugin = gStandalone.engine->getPlugin(pluginId))
{
CARLA_SAFE_ASSERT_RETURN(plugin->getType() == CB::PLUGIN_LV2, nullptr);
return (CarlaInlineDisplayImageSurface*)CB::carla_render_inline_display_lv2(plugin, width, height);
}

carla_stderr2("carla_render_inline_display(%i, %i, %i) - could not find plugin", pluginId, width, height);
return nullptr;
}

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

void carla_set_active(uint pluginId, bool onOff)
{
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,);


+ 102
- 40
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -61,10 +61,11 @@ static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
const uint MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000

// Extra Plugin Hints
const uint PLUGIN_HAS_EXTENSION_OPTIONS = 0x1000;
const uint PLUGIN_HAS_EXTENSION_PROGRAMS = 0x2000;
const uint PLUGIN_HAS_EXTENSION_STATE = 0x4000;
const uint PLUGIN_HAS_EXTENSION_WORKER = 0x8000;
const uint PLUGIN_HAS_EXTENSION_OPTIONS = 0x01000;
const uint PLUGIN_HAS_EXTENSION_PROGRAMS = 0x02000;
const uint PLUGIN_HAS_EXTENSION_STATE = 0x04000;
const uint PLUGIN_HAS_EXTENSION_WORKER = 0x08000;
const uint PLUGIN_HAS_EXTENSION_INLINE_DISPLAY = 0x10000;

// Extra Parameter Hints
const uint PARAMETER_IS_STRICT_BOUNDS = 0x1000;
@@ -130,42 +131,45 @@ const uint32_t CARLA_URI_MAP_ID_CARLA_TRANSIENT_WIN_ID = 47;
const uint32_t CARLA_URI_MAP_ID_COUNT = 48;

// LV2 Feature Ids
const uint32_t kFeatureIdBufSizeBounded = 0;
const uint32_t kFeatureIdBufSizeFixed = 1;
const uint32_t kFeatureIdBufSizePowerOf2 = 2;
const uint32_t kFeatureIdEvent = 3;
const uint32_t kFeatureIdHardRtCapable = 4;
const uint32_t kFeatureIdInPlaceBroken = 5;
const uint32_t kFeatureIdIsLive = 6;
const uint32_t kFeatureIdLogs = 7;
const uint32_t kFeatureIdOptions = 8;
const uint32_t kFeatureIdPrograms = 9;
const uint32_t kFeatureIdResizePort = 10;
const uint32_t kFeatureIdRtMemPool = 11;
const uint32_t kFeatureIdRtMemPoolOld = 12;
const uint32_t kFeatureIdStateMakePath = 13;
const uint32_t kFeatureIdStateMapPath = 14;
const uint32_t kFeatureIdStrictBounds = 15;
const uint32_t kFeatureIdUriMap = 16;
const uint32_t kFeatureIdUridMap = 17;
const uint32_t kFeatureIdUridUnmap = 18;
const uint32_t kFeatureIdWorker = 19;
const uint32_t kFeatureCountPlugin = 20;
const uint32_t kFeatureIdUiDataAccess = 20;
const uint32_t kFeatureIdUiInstanceAccess = 21;
const uint32_t kFeatureIdUiIdleInterface = 22;
const uint32_t kFeatureIdUiFixedSize = 23;
const uint32_t kFeatureIdUiMakeResident = 24;
const uint32_t kFeatureIdUiMakeResident2 = 25;
const uint32_t kFeatureIdUiNoUserResize = 26;
const uint32_t kFeatureIdUiParent = 27;
const uint32_t kFeatureIdUiPortMap = 28;
const uint32_t kFeatureIdUiPortSubscribe = 29;
const uint32_t kFeatureIdUiResize = 30;
const uint32_t kFeatureIdUiTouch = 31;
const uint32_t kFeatureIdExternalUi = 32;
const uint32_t kFeatureIdExternalUiOld = 33;
const uint32_t kFeatureCountAll = 34;
enum CarlaLv2Features {
kFeatureIdBufSizeBounded = 0,
kFeatureIdBufSizeFixed,
kFeatureIdBufSizePowerOf2,
kFeatureIdEvent,
kFeatureIdHardRtCapable,
kFeatureIdInPlaceBroken,
kFeatureIdIsLive,
kFeatureIdLogs,
kFeatureIdOptions,
kFeatureIdPrograms,
kFeatureIdResizePort,
kFeatureIdRtMemPool,
kFeatureIdRtMemPoolOld,
kFeatureIdStateMakePath,
kFeatureIdStateMapPath,
kFeatureIdStrictBounds,
kFeatureIdUriMap,
kFeatureIdUridMap,
kFeatureIdUridUnmap,
kFeatureIdWorker,
kFeatureIdInlineDisplay,
kFeatureCountPlugin,
kFeatureIdUiDataAccess,
kFeatureIdUiInstanceAccess,
kFeatureIdUiIdleInterface,
kFeatureIdUiFixedSize,
kFeatureIdUiMakeResident,
kFeatureIdUiMakeResident2,
kFeatureIdUiNoUserResize,
kFeatureIdUiParent,
kFeatureIdUiPortMap,
kFeatureIdUiPortSubscribe,
kFeatureIdUiResize,
kFeatureIdUiTouch,
kFeatureIdExternalUi,
kFeatureIdExternalUiOld,
kFeatureCountAll
};

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

@@ -668,6 +672,9 @@ public:
if (fFeatures[kFeatureIdWorker] != nullptr && fFeatures[kFeatureIdWorker]->data != nullptr)
delete (LV2_Worker_Schedule*)fFeatures[kFeatureIdWorker]->data;

if (fFeatures[kFeatureIdInlineDisplay] != nullptr && fFeatures[kFeatureIdInlineDisplay]->data != nullptr)
delete (LV2_Inline_Display*)fFeatures[kFeatureIdInlineDisplay]->data;

for (uint32_t i=0; i < kFeatureCountAll; ++i)
{
if (fFeatures[i] != nullptr)
@@ -4172,6 +4179,7 @@ public:
fExt.programs = nullptr;
fExt.state = nullptr;
fExt.worker = nullptr;
fExt.inlineDisplay = nullptr;

for (uint32_t i=0; i < fRdfDescriptor->ExtensionCount; ++i)
{
@@ -4185,6 +4193,8 @@ public:
pData->hints |= PLUGIN_HAS_EXTENSION_STATE;
else if (std::strcmp(fRdfDescriptor->Extensions[i], LV2_WORKER__interface) == 0)
pData->hints |= PLUGIN_HAS_EXTENSION_WORKER;
else if (std::strcmp(fRdfDescriptor->Extensions[i], LV2_INLINEDISPLAY__interface) == 0)
pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY;
else
carla_stdout("Plugin has non-supported extension: '%s'", fRdfDescriptor->Extensions[i]);
}
@@ -4203,6 +4213,9 @@ public:
if (pData->hints & PLUGIN_HAS_EXTENSION_WORKER)
fExt.worker = (const LV2_Worker_Interface*)fDescriptor->extension_data(LV2_WORKER__interface);

if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY)
fExt.inlineDisplay = (const LV2_Inline_Display_Interface*)fDescriptor->extension_data(LV2_INLINEDISPLAY__interface);

// check if invalid
if (fExt.options != nullptr && fExt.options->get == nullptr && fExt.options->set == nullptr)
fExt.options = nullptr;
@@ -4215,6 +4228,14 @@ public:

if (fExt.worker != nullptr && fExt.worker->work == nullptr)
fExt.worker = nullptr;

if (fExt.inlineDisplay != nullptr)
{
if (fExt.inlineDisplay->render != nullptr)
pData->hints |= PLUGIN_HAS_INLINE_DISPLAY;
else
fExt.inlineDisplay = nullptr;
}
}

CARLA_SAFE_ASSERT_RETURN(fLatencyIndex == -1,);
@@ -4498,6 +4519,20 @@ public:

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

void handleInlineDisplayQueueRedraw()
{
// TODO
}

LV2_Inline_Display_Image_Surface* renderInlineDisplay(int width, int height)
{
CARLA_SAFE_ASSERT_RETURN(fExt.inlineDisplay != nullptr && fExt.inlineDisplay->render != nullptr, nullptr);

return fExt.inlineDisplay->render(fHandle, width, height);
}

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

void handleExternalUIClosed()
{
CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EXTERNAL,);
@@ -4964,6 +4999,10 @@ public:
workerFt->handle = this;
workerFt->schedule_work = carla_lv2_worker_schedule;

LV2_Inline_Display* const inlineDisplay = new LV2_Inline_Display;
inlineDisplay->handle = this;
inlineDisplay->queue_draw = carla_lv2_inline_display_queue_draw;

// ---------------------------------------------------------------
// initialize features (part 2)

@@ -5032,6 +5071,9 @@ public:
fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule;
fFeatures[kFeatureIdWorker]->data = workerFt;

fFeatures[kFeatureIdInlineDisplay]->URI = LV2_INLINEDISPLAY__queue_draw;
fFeatures[kFeatureIdInlineDisplay]->data = inlineDisplay;

// ---------------------------------------------------------------
// initialize plugin

@@ -5593,6 +5635,7 @@ private:
const LV2_Options_Interface* options;
const LV2_State_Interface* state;
const LV2_Worker_Interface* worker;
const LV2_Inline_Display_Interface* inlineDisplay;
const LV2_Programs_Interface* programs;
const LV2UI_Idle_Interface* uiidle;
const LV2UI_Show_Interface* uishow;
@@ -5603,6 +5646,7 @@ private:
: options(nullptr),
state(nullptr),
worker(nullptr),
inlineDisplay(nullptr),
programs(nullptr),
uiidle(nullptr),
uishow(nullptr),
@@ -6087,6 +6131,17 @@ private:
return ((CarlaPluginLV2*)handle)->handleWorkerRespond(size, data);
}

// -------------------------------------------------------------------
// Inline Display Feature

static void carla_lv2_inline_display_queue_draw(LV2_Inline_Display_Handle handle)
{
CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
carla_debug("carla_lv2_inline_display_queue_draw(%p)", handle);

((CarlaPluginLV2*)handle)->handleInlineDisplayQueueRedraw();
}

// -------------------------------------------------------------------
// External UI Feature

@@ -6248,6 +6303,13 @@ CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init)
return plugin;
}

void* carla_render_inline_display_lv2(CarlaPlugin* plugin, int width, int height)
{
CarlaPluginLV2* const lv2Plugin = (CarlaPluginLV2*)plugin;

return lv2Plugin->renderInlineDisplay(width, height);
}

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

CARLA_BACKEND_END_NAMESPACE

+ 28
- 0
source/carla_backend.py View File

@@ -1141,6 +1141,16 @@ class CarlaTransportInfo(Structure):
("bpm", c_double)
]

# Image data for LV2 inline display API.
# raw image pixmap format is ARGB32,
class CarlaInlineDisplayImageSurface(Structure):
_fields_ = [
("data", POINTER(c_ubyte)),
("width", c_int),
("height", c_int),
("stride", c_int)
]

# ------------------------------------------------------------------------------------------------------------
# Carla Host API (Python compatible stuff)

@@ -1647,6 +1657,12 @@ class CarlaHostMeta(object):
def get_output_peak_value(self, pluginId, isLeft):
raise NotImplementedError

# Render a plugin's inline display.
# @param pluginId Plugin
@abstractmethod
def render_inline_display(self, pluginId, width, height):
raise NotImplementedError

# Enable a plugin's option.
# @param pluginId Plugin
# @param option An option from PluginOptions
@@ -2018,6 +2034,9 @@ class CarlaHostNull(CarlaHostMeta):
def get_output_peak_value(self, pluginId, isLeft):
return 0.0

def render_inline_display(self, pluginId, width, height):
return None

def set_option(self, pluginId, option, yesNo):
return

@@ -2291,6 +2310,9 @@ class CarlaHostDLL(CarlaHostMeta):
self.lib.carla_get_output_peak_value.argtypes = [c_uint, c_bool]
self.lib.carla_get_output_peak_value.restype = c_float

self.lib.carla_render_inline_display.argtypes = [c_uint, c_uint, c_uint]
self.lib.carla_render_inline_display.restype = POINTER(CarlaInlineDisplayImageSurface)

self.lib.carla_set_option.argtypes = [c_uint, c_uint, c_bool]
self.lib.carla_set_option.restype = None

@@ -2559,6 +2581,9 @@ class CarlaHostDLL(CarlaHostMeta):
def get_output_peak_value(self, pluginId, isLeft):
return float(self.lib.carla_get_output_peak_value(pluginId, isLeft))

def render_inline_display(self, pluginId, width, height):
return structToDict(self.lib.carla_render_inline_display(pluginId, width, height))

def set_option(self, pluginId, option, yesNo):
self.lib.carla_set_option(pluginId, option, yesNo)

@@ -2894,6 +2919,9 @@ class CarlaHostPlugin(CarlaHostMeta):
def get_output_peak_value(self, pluginId, isLeft):
return self.fPluginsInfo[pluginId].peaks[2 if isLeft else 3]

def render_inline_display(self, pluginId, width, height):
return None

def set_option(self, pluginId, option, yesNo):
self.sendMsg(["set_option", pluginId, option, yesNo])



Loading…
Cancel
Save