Browse Source

Some Carla rework related to ui-bridges/osc (Gtk2 ready)

tags/v0.9.0
falkTX 13 years ago
parent
commit
ae792557ff
12 changed files with 969 additions and 505 deletions
  1. +52
    -21
      src/carla-bridge-ui/carla_bridge_gtk2.cpp
  2. +470
    -193
      src/carla-bridge-ui/carla_bridge_lv2.cpp
  3. +50
    -35
      src/carla-bridge-ui/carla_bridge_ui.h
  4. +14
    -9
      src/carla-bridge-ui/qtcreator/carla-bridge-lv2-gtk2.pro
  5. +184
    -71
      src/carla-bridge/carla_bridge_osc.cpp
  6. +14
    -33
      src/carla-bridge/carla_bridge_osc.h
  7. +52
    -0
      src/carla-includes/carla_osc_includes.h
  8. +3
    -3
      src/carla-includes/lv2/lv2-midifunctions.h
  9. +1
    -1
      src/carla.py
  10. +2
    -25
      src/carla/carla_osc.h
  11. +69
    -110
      src/carla/lv2.cpp
  12. +58
    -4
      src/carla/lv2_rdf.h

+ 52
- 21
src/carla-bridge-ui/carla_bridge_gtk2.cpp View File

@@ -15,55 +15,80 @@
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "carla_bridge_osc.h"
#include "carla_bridge_ui.h"
#include "../carla-bridge/carla_osc.h"

#ifdef BRIDGE_LV2_X11
#error X11 UI uses Qt4
#endif

#include <gtk/gtk.h>
#include <QtCore/QSettings>

static GtkWidget* window;
static GtkWidget* window = nullptr;
static QSettings settings("Cadence", "Carla-UIs");

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

gint last_x, last_y, last_width, last_height;

void save_window_settings()
{
settings.setValue(QString("%1/pos_x").arg(ui->get_title()), last_x);
settings.setValue(QString("%1/pos_y").arg(ui->get_title()), last_y);
settings.setValue(QString("%1/width").arg(ui->get_title()), last_width);
settings.setValue(QString("%1/height").arg(ui->get_title()), last_height);
}

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

gboolean gtk_ui_recheck(void*)
{
gtk_window_get_position(GTK_WINDOW(window), &last_x, &last_y);
gtk_window_get_size(GTK_WINDOW(window), &last_width, &last_height);
return ui->run_messages();
}

void gtk_ui_destroy(GtkWidget*, void*)
{
window = nullptr;
gtk_main_quit();
toolkit_quit();
}

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

void toolkit_init()
{
int argc = 0;
char** argv = nullptr;
static int argc = 0;
static char** argv = { nullptr };
gtk_init(&argc, &argv);
}

void toolkit_loop(const char* ui_title, bool reparent)
void toolkit_loop()
{
if (reparent)
{
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)ui->get_widget());
}
else
{
window = (GtkWidget*)ui->get_widget();
}
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)ui->get_widget());

g_timeout_add(50, gtk_ui_recheck, nullptr);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_ui_destroy), nullptr);

gtk_window_get_position(GTK_WINDOW(window), &last_x, &last_y);
gtk_window_get_size(GTK_WINDOW(window), &last_width, &last_height);

gtk_window_set_resizable(GTK_WINDOW(window), ui->is_resizable());
gtk_window_set_title(GTK_WINDOW(window), ui_title);
gtk_window_set_title(GTK_WINDOW(window), ui->get_title());

if (settings.contains(QString("%1/pos_x").arg(ui->get_title())))
{
last_x = settings.value(QString("%1/pos_x").arg(ui->get_title()), last_x).toInt();
last_y = settings.value(QString("%1/pos_y").arg(ui->get_title()), last_y).toInt();
last_width = settings.value(QString("%1/width").arg(ui->get_title()), last_width).toInt();
last_height = settings.value(QString("%1/height").arg(ui->get_title()), last_height).toInt();

gtk_window_move(GTK_WINDOW(window), last_x, last_y);
gtk_window_resize(GTK_WINDOW(window), last_width, last_height);
}

osc_send_update();
osc_send_update(nullptr);

// Main loop
gtk_main();
@@ -73,22 +98,28 @@ void toolkit_quit()
{
if (window)
{
save_window_settings();
gtk_widget_destroy(window);
gtk_main_quit();
}

window = nullptr;
}

void toolkit_window_show()
{
gtk_widget_show_all(window);
if (window)
gtk_widget_show_all(window);
}

void toolkit_window_hide()
{
gtk_widget_hide_all(window);
if (window)
gtk_widget_hide_all(window);
}

void toolkit_window_resize(int width, int height)
{
gtk_window_resize(GTK_WINDOW(window), width, height);
if (window)
gtk_window_resize(GTK_WINDOW(window), width, height);
}

+ 470
- 193
src/carla-bridge-ui/carla_bridge_lv2.cpp View File

@@ -15,19 +15,14 @@
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "carla_bridge_osc.h"
#include "carla_bridge_ui.h"
#include "carla_osc.h"
#include "carla_midi.h"

#include "lv2/lv2.h"
#include "lv2/atom.h"
#include "lv2/event.h"
#include "lv2/uri-map.h"
#include "lv2/urid.h"
#include "lv2/ui.h"

#include <cstring>
#include "lv2_rdf.h"

#ifdef BRIDGE_LV2_X11
// FIXME, use x11 something
#include <QtGui/QDialog>
#endif

@@ -36,119 +31,76 @@ UiData* ui = nullptr;
// -------------------------------------------------------------------------

// feature ids
const uint32_t lv2_feature_id_uri_map = 0;
const uint32_t lv2_feature_id_urid_map = 1;
const uint32_t lv2_feature_id_urid_unmap = 2;
const uint32_t lv2_feature_id_event = 3;
const uint32_t lv2_feature_id_ui_resize = 4;
const uint32_t lv2_feature_id_ui_parent = 5;
const uint32_t lv2_feature_count = 6;
const uint32_t lv2_feature_id_event = 0;
const uint32_t lv2_feature_id_logs = 1;
const uint32_t lv2_feature_id_programs = 2;
const uint32_t lv2_feature_id_state_make_path = 3;
const uint32_t lv2_feature_id_state_map_path = 4;
const uint32_t lv2_feature_id_uri_map = 5;
const uint32_t lv2_feature_id_urid_map = 6;
const uint32_t lv2_feature_id_urid_unmap = 7;
const uint32_t lv2_feature_id_ui_parent = 8;
const uint32_t lv2_feature_id_ui_port_map = 9;
const uint32_t lv2_feature_id_ui_resize = 10;
const uint32_t lv2_feature_count = 11;

// pre-set uri[d] map ids
const uint32_t CARLA_URI_MAP_ID_NULL = 0;
const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 1;
const uint32_t CARLA_URI_MAP_ID_EVENT_MIDI = 2;
const uint32_t CARLA_URI_MAP_ID_EVENT_TIME = 3;
const uint32_t CARLA_URI_MAP_ID_COUNT = 4;

// ----------------- URI-Map Feature ---------------------------------------
static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
{
qDebug("carla_lv2_uri_to_id(%p, %s, %s)", data, map, uri);

if (map && strcmp(map, LV2_EVENT_URI) == 0)
{
// Event types
if (strcmp(uri, "http://lv2plug.in/ns/ext/midi#MidiEvent") == 0)
return CARLA_URI_MAP_ID_EVENT_MIDI;
else if (strcmp(uri, "http://lv2plug.in/ns/ext/time#Position") == 0)
return CARLA_URI_MAP_ID_EVENT_TIME;
}
else if (strcmp(uri, LV2_ATOM__String) == 0)
{
return CARLA_URI_MAP_ID_ATOM_STRING;
}

return CARLA_URI_MAP_ID_NULL;
}

// ----------------- URID Feature ------------------------------------------
static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
{
qDebug("carla_lv2_urid_map(%p, %s)", handle, uri);

if (strcmp(uri, "http://lv2plug.in/ns/ext/midi#MidiEvent") == 0)
return CARLA_URI_MAP_ID_EVENT_MIDI;
else if (strcmp(uri, "http://lv2plug.in/ns/ext/time#Position") == 0)
return CARLA_URI_MAP_ID_EVENT_TIME;
else if (strcmp(uri, LV2_ATOM__String) == 0)
return CARLA_URI_MAP_ID_ATOM_STRING;

return CARLA_URI_MAP_ID_NULL;
}

static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
{
qDebug("carla_lv2_urid_unmap(%p, %i)", handle, urid);

if (urid == CARLA_URI_MAP_ID_EVENT_MIDI)
return "http://lv2plug.in/ns/ext/midi#MidiEvent";
else if (urid == CARLA_URI_MAP_ID_EVENT_TIME)
return "http://lv2plug.in/ns/ext/time#Position";
else if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
return LV2_ATOM__String;

return nullptr;
}

// ----------------- UI Resize Feature -------------------------------------
static int carla_lv2_ui_resize(LV2UI_Feature_Handle data, int width, int height)
{
qDebug("carla_lv2_ui_resized(%p, %i, %i)", data, width, height);

if (data)
{
UiData* ui = (UiData*)data;
ui->queque_message(BRIDGE_MESSAGE_RESIZE_GUI, width, height, 0.0);
return 0;
}

return 1;
}

// ----------------- UI Extension ------------------------------------------
static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
{
qDebug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);

if (controller)
{
//UiData* ui = (UiData*)controller;

if (format == 0 && buffer_size == sizeof(float))
{
float value = *(float*)buffer;
osc_send_control(nullptr, port_index, value);
}
}
}
const uint32_t CARLA_URI_MAP_ID_NULL = 0;
const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1;
const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 2;
const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 3;
const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 4;
const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 5;
const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 6;
const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 7;
const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 8;
const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 9;
const uint32_t CARLA_URI_MAP_ID_COUNT = 10;

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

class Lv2UiData : public UiData
{
public:
Lv2UiData() : UiData()
Lv2UiData(const char* ui_title) : UiData(ui_title)
{
handle = nullptr;
widget = nullptr;
descriptor = nullptr;

rdf_descriptor = nullptr;
rdf_ui_descriptor = nullptr;

programs = nullptr;

#ifdef BRIDGE_LV2_X11
x11_widget = new QDialog(nullptr);
x11_widget = new QDialog;
#endif

// Initialize features
LV2_Event_Feature* Event_Feature = new LV2_Event_Feature;
Event_Feature->callback_data = this;
Event_Feature->lv2_event_ref = carla_lv2_event_ref;
Event_Feature->lv2_event_unref = carla_lv2_event_unref;

LV2_Log_Log* Log_Feature = new LV2_Log_Log;
Log_Feature->handle = this;
Log_Feature->printf = carla_lv2_log_printf;
Log_Feature->vprintf = carla_lv2_log_vprintf;

LV2_Programs_Host* Programs_Feature = new LV2_Programs_Host;
Programs_Feature->handle = this;
Programs_Feature->program_changed = carla_lv2_program_changed;

LV2_State_Make_Path* State_MakePath_Feature = new LV2_State_Make_Path;
State_MakePath_Feature->handle = this;
State_MakePath_Feature->path = carla_lv2_state_make_path;

LV2_State_Map_Path* State_MapPath_Feature = new LV2_State_Map_Path;
State_MapPath_Feature->handle = this;
State_MapPath_Feature->abstract_path = carla_lv2_state_map_abstract_path;
State_MapPath_Feature->absolute_path = carla_lv2_state_map_absolute_path;

LV2_URI_Map_Feature* URI_Map_Feature = new LV2_URI_Map_Feature;
URI_Map_Feature->callback_data = this;
URI_Map_Feature->uri_to_id = carla_lv2_uri_to_id;
@@ -161,54 +113,74 @@ public:
URID_Unmap_Feature->handle = this;
URID_Unmap_Feature->unmap = carla_lv2_urid_unmap;

LV2_Event_Feature* Event_Feature = new LV2_Event_Feature;
Event_Feature->callback_data = this;
Event_Feature->lv2_event_ref = nullptr;
Event_Feature->lv2_event_unref = nullptr;
LV2UI_Port_Map* UI_PortMap_Feature = new LV2UI_Port_Map;
UI_PortMap_Feature->handle = this;
UI_PortMap_Feature->port_index = carla_lv2_ui_port_map;

LV2UI_Resize* UI_Resize_Feature = new LV2UI_Resize;
UI_Resize_Feature->handle = this;
UI_Resize_Feature->ui_resize = carla_lv2_ui_resize;

features[lv2_feature_id_uri_map] = new LV2_Feature;
features[lv2_feature_id_uri_map]->URI = LV2_URI_MAP_URI;
features[lv2_feature_id_uri_map]->data = URI_Map_Feature;
features[lv2_feature_id_event] = new LV2_Feature;
features[lv2_feature_id_event]->URI = LV2_EVENT_URI;
features[lv2_feature_id_event]->data = Event_Feature;

features[lv2_feature_id_urid_map] = new LV2_Feature;
features[lv2_feature_id_urid_map]->URI = LV2_URID_MAP_URI;
features[lv2_feature_id_urid_map]->data = URID_Map_Feature;
features[lv2_feature_id_logs] = new LV2_Feature;
features[lv2_feature_id_logs]->URI = LV2_LOG__log;
features[lv2_feature_id_logs]->data = Log_Feature;

features[lv2_feature_id_urid_unmap] = new LV2_Feature;
features[lv2_feature_id_urid_unmap]->URI = LV2_URID_UNMAP_URI;
features[lv2_feature_id_urid_unmap]->data = URID_Unmap_Feature;
features[lv2_feature_id_programs] = new LV2_Feature;
features[lv2_feature_id_programs]->URI = LV2_PROGRAMS__Host;
features[lv2_feature_id_programs]->data = Programs_Feature;

features[lv2_feature_id_event] = new LV2_Feature;
features[lv2_feature_id_event]->URI = LV2_EVENT_URI;
features[lv2_feature_id_event]->data = Event_Feature;
features[lv2_feature_id_state_make_path] = new LV2_Feature;
features[lv2_feature_id_state_make_path]->URI = LV2_STATE__makePath;
features[lv2_feature_id_state_make_path]->data = State_MakePath_Feature;

features[lv2_feature_id_ui_resize] = new LV2_Feature;
features[lv2_feature_id_ui_resize]->URI = LV2_UI__resize;
features[lv2_feature_id_ui_resize]->data = UI_Resize_Feature;
features[lv2_feature_id_state_map_path] = new LV2_Feature;
features[lv2_feature_id_state_map_path]->URI = LV2_STATE__mapPath;
features[lv2_feature_id_state_map_path]->data = State_MapPath_Feature;

features[lv2_feature_id_uri_map] = new LV2_Feature;
features[lv2_feature_id_uri_map]->URI = LV2_URI_MAP_URI;
features[lv2_feature_id_uri_map]->data = URI_Map_Feature;

features[lv2_feature_id_urid_map] = new LV2_Feature;
features[lv2_feature_id_urid_map]->URI = LV2_URID__map;
features[lv2_feature_id_urid_map]->data = URID_Map_Feature;

features[lv2_feature_id_urid_unmap] = new LV2_Feature;
features[lv2_feature_id_urid_unmap]->URI = LV2_URID__unmap;
features[lv2_feature_id_urid_unmap]->data = URID_Unmap_Feature;

features[lv2_feature_id_ui_parent] = new LV2_Feature;
features[lv2_feature_id_ui_parent]->URI = LV2_UI__parent;
#ifdef BRIDGE_LV2_X11
features[lv2_feature_id_ui_parent] = new LV2_Feature;
features[lv2_feature_id_ui_parent]->URI = LV2_UI__parent;
features[lv2_feature_id_ui_parent]->data = (void*)x11_widget->winId();
features[lv2_feature_id_ui_parent]->data = (void*)x11_widget->winId();
#else
features[lv2_feature_id_ui_parent] = nullptr;
features[lv2_feature_id_ui_parent]->data = nullptr;
#endif

features[lv2_feature_count] = nullptr;
features[lv2_feature_id_ui_port_map] = new LV2_Feature;
features[lv2_feature_id_ui_port_map]->URI = LV2_UI__portMap;
features[lv2_feature_id_ui_port_map]->data = UI_PortMap_Feature;

resizable = true;
features[lv2_feature_id_ui_resize] = new LV2_Feature;
features[lv2_feature_id_ui_resize]->URI = LV2_UI__resize;
features[lv2_feature_id_ui_resize]->data = UI_Resize_Feature;
}

~Lv2UiData()
{
delete (LV2_Event_Feature*)features[lv2_feature_id_event]->data;
delete (LV2_Log_Log*)features[lv2_feature_id_logs]->data;
delete (LV2_Programs_Host*)features[lv2_feature_id_programs]->data;
delete (LV2_State_Make_Path*)features[lv2_feature_id_state_make_path]->data;
delete (LV2_State_Map_Path*)features[lv2_feature_id_state_map_path]->data;
delete (LV2_URI_Map_Feature*)features[lv2_feature_id_uri_map]->data;
delete (LV2_URID_Map*)features[lv2_feature_id_urid_map]->data;
delete (LV2_URID_Unmap*)features[lv2_feature_id_urid_unmap]->data;
delete (LV2_Event_Feature*)features[lv2_feature_id_event]->data;
delete (LV2UI_Port_Map*)features[lv2_feature_id_ui_port_map]->data;
delete (LV2UI_Resize*)features[lv2_feature_id_ui_resize]->data;

for (uint32_t i=0; i < lv2_feature_count; i++)
@@ -216,50 +188,90 @@ public:
if (features[i])
delete features[i];
}

if (rdf_descriptor)
lv2_rdf_free(rdf_descriptor);

#ifdef WANT_X11
//delete x11_widget;
#endif
}

virtual bool init(const char* plugin_uri, const char* ui_uri, const char* ui_bundle, bool resizable_)
// ---------------------------------------------------------------------
// initialization

bool init(const char* plugin_uri, const char* ui_uri)
{
LV2UI_DescriptorFunction ui_descfn = (LV2UI_DescriptorFunction)lib_symbol("lv2ui_descriptor");
Lv2World.init();
rdf_descriptor = lv2_rdf_new(plugin_uri);

if (ui_descfn)
if (rdf_descriptor)
{
uint32_t i = 0;
while ((descriptor = ui_descfn(i++)))
for (uint32_t i=0; i < rdf_descriptor->UICount; i++)
{
if (strcmp(descriptor->URI, ui_uri) == 0)
if (strcmp(rdf_descriptor->UIs[i].URI, ui_uri) == 0)
{
rdf_ui_descriptor = &rdf_descriptor->UIs[i];
break;
}
}

if (descriptor)
if (rdf_ui_descriptor && lib_open(rdf_ui_descriptor->Binary))
{
handle = descriptor->instantiate(descriptor,
plugin_uri,
ui_bundle,
carla_lv2_ui_write_function,
this,
&widget,
features);

resizable = resizable_;

return bool(handle);
LV2UI_DescriptorFunction ui_descfn = (LV2UI_DescriptorFunction)lib_symbol("lv2ui_descriptor");

if (ui_descfn)
{
uint32_t i = 0;
while ((descriptor = ui_descfn(i++)))
{
if (strcmp(descriptor->URI, ui_uri) == 0)
break;
}

if (descriptor)
{
handle = descriptor->instantiate(descriptor,
plugin_uri,
rdf_ui_descriptor->Bundle,
carla_lv2_ui_write_function,
this,
&widget,
features);

if (handle && descriptor->extension_data)
{
for (uint32_t j=0; j < rdf_ui_descriptor->ExtensionCount; j++)
{
if (strcmp(rdf_ui_descriptor->Extensions[j], LV2_PROGRAMS__UIInterface) == 0)
{
programs = (LV2_Programs_UI_Interface*)descriptor->extension_data(LV2_PROGRAMS__UIInterface);
break;
}
}
}

return bool(handle);
}
}
}
}

return false;
}

virtual void close()
void close()
{
if (handle && descriptor && descriptor->cleanup)
descriptor->cleanup(handle);

lib_close();
}

virtual void update_parameter(int index, double value)
// ---------------------------------------------------------------------
// processing

void set_parameter(int index, double value)
{
if (descriptor && descriptor->port_event)
{
@@ -268,12 +280,44 @@ public:
}
}

virtual void update_program(int) {}
virtual void update_midi_program(int, int) {}
virtual void send_note_on(int, int) {}
virtual void send_note_off(int) {}
void set_program(int) {}

virtual void* get_widget()
void set_midi_program(int bank, int program)
{
if (programs)
programs->select_program(handle, bank, program);
}

void send_note_on(int, int) {}
void send_note_off(int) {}

// ---------------------------------------------------------------------
// gui

bool has_parent() const
{
#ifdef BRIDGE_LV2_X11
return false;
#else
return true;
#endif
}

bool is_resizable() const
{
if (rdf_ui_descriptor)
{
for (uint32_t i=0; i < rdf_ui_descriptor->FeatureCount; i++)
{
if (strcmp(rdf_ui_descriptor->Features[i].URI, LV2_UI__fixedSize) == 0 || strcmp(rdf_ui_descriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
return false;
}
return true;
}
return false;
}

void* get_widget() const
{
#ifdef BRIDGE_LV2_X11
return x11_widget;
@@ -282,9 +326,248 @@ public:
#endif
}

virtual bool is_resizable()
// ----------------- Event Feature ---------------------------------------------------
static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
{
qDebug("carla_lv2_event_ref(%p, %p)", callback_data, event);
return 0;
}

static uint32_t carla_lv2_event_unref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
{
qDebug("carla_lv2_event_unref(%p, %p)", callback_data, event);
return 0;
}

// ----------------- Logs Feature ----------------------------------------------------
static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
{
qDebug("carla_lv2_log_vprintf(%p, %i, %s, ...)", handle, type, fmt);

char buf[8196];
vsprintf(buf, fmt, ap);

if (buf[0] == 0)
return 0;

switch (type)
{
case CARLA_URI_MAP_ID_LOG_ERROR:
qCritical("%s", buf);
break;
case CARLA_URI_MAP_ID_LOG_NOTE:
printf("%s\n", buf);
break;
case CARLA_URI_MAP_ID_LOG_TRACE:
qDebug("%s", buf);
break;
case CARLA_URI_MAP_ID_LOG_WARNING:
qWarning("%s", buf);
break;
default:
break;
}

return strlen(buf);
}

static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
{
qDebug("carla_lv2_log_printf(%p, %i, %s, ...)", handle, type, fmt);

va_list args;
va_start(args, fmt);
const int ret = carla_lv2_log_vprintf(handle, type, fmt, args);
va_end(args);

return ret;
}

// ----------------- Programs Feature ------------------------------------------------
static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
{
qDebug("Lv2Plugin::carla_lv2_program_changed(%p, %i)", handle, index);

osc_send_configure(nullptr, "reloadprograms", "");
// QString::number(index).toUtf8().constData()
}

// ----------------- State Feature ---------------------------------------------------
static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
{
qDebug("carla_lv2_state_make_path(%p, %p)", handle, path);
return strdup(path);
}

static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path)
{
qDebug("carla_lv2_state_map_abstract_path(%p, %p)", handle, absolute_path);
return strdup(absolute_path);
}

static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path)
{
qDebug("carla_lv2_state_map_absolute_path(%p, %p)", handle, abstract_path);
return strdup(abstract_path);
}

// ----------------- URI-Map Feature ---------------------------------------
static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
{
qDebug("carla_lv2_uri_to_id(%p, %s, %s)", data, map, uri);

// Atom types
if (strcmp(uri, LV2_ATOM__Chunk) == 0)
return CARLA_URI_MAP_ID_ATOM_CHUNK;
else if (strcmp(uri, LV2_ATOM__Path) == 0)
return CARLA_URI_MAP_ID_ATOM_PATH;
else if (strcmp(uri, LV2_ATOM__Sequence) == 0)
return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
else if (strcmp(uri, LV2_ATOM__String) == 0)
return CARLA_URI_MAP_ID_ATOM_STRING;

// Log types
else if (strcmp(uri, LV2_LOG__Error) == 0)
return CARLA_URI_MAP_ID_LOG_ERROR;
else if (strcmp(uri, LV2_LOG__Note) == 0)
return CARLA_URI_MAP_ID_LOG_NOTE;
else if (strcmp(uri, LV2_LOG__Trace) == 0)
return CARLA_URI_MAP_ID_LOG_TRACE;
else if (strcmp(uri, LV2_LOG__Warning) == 0)
return CARLA_URI_MAP_ID_LOG_WARNING;

// Others
else if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
return CARLA_URI_MAP_ID_MIDI_EVENT;

return CARLA_URI_MAP_ID_NULL;
}

// ----------------- URID Feature ------------------------------------------
static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
{
qDebug("carla_lv2_urid_map(%p, %s)", handle, uri);

// Atom types
if (strcmp(uri, LV2_ATOM__Chunk) == 0)
return CARLA_URI_MAP_ID_ATOM_CHUNK;
else if (strcmp(uri, LV2_ATOM__Path) == 0)
return CARLA_URI_MAP_ID_ATOM_PATH;
else if (strcmp(uri, LV2_ATOM__Sequence) == 0)
return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
else if (strcmp(uri, LV2_ATOM__String) == 0)
return CARLA_URI_MAP_ID_ATOM_STRING;

// Log types
else if (strcmp(uri, LV2_LOG__Error) == 0)
return CARLA_URI_MAP_ID_LOG_ERROR;
else if (strcmp(uri, LV2_LOG__Note) == 0)
return CARLA_URI_MAP_ID_LOG_NOTE;
else if (strcmp(uri, LV2_LOG__Trace) == 0)
return CARLA_URI_MAP_ID_LOG_TRACE;
else if (strcmp(uri, LV2_LOG__Warning) == 0)
return CARLA_URI_MAP_ID_LOG_WARNING;

// Others
else if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
return CARLA_URI_MAP_ID_MIDI_EVENT;

return CARLA_URI_MAP_ID_NULL;
}

static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
{
qDebug("carla_lv2_urid_unmap(%p, %i)", handle, urid);

// Atom types
if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
return LV2_ATOM__Chunk;
else if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
return LV2_ATOM__Path;
else if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
return LV2_ATOM__Sequence;
else if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
return LV2_ATOM__String;

// Log types
else if (urid == CARLA_URI_MAP_ID_LOG_ERROR)
return LV2_LOG__Error;
else if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
return LV2_LOG__Note;
else if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
return LV2_LOG__Trace;
else if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
return LV2_LOG__Warning;

// Others
else if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
return LV2_MIDI__MidiEvent;

return nullptr;
}

// ----------------- UI Port-Map Feature ---------------------------------------------
static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
{
return resizable;
qDebug("Lv2Plugin::carla_lv2_ui_port_map(%p, %s)", handle, symbol);

if (handle)
{
Lv2UiData* lv2ui = (Lv2UiData*)handle;

for (uint32_t i=0; i < lv2ui->rdf_descriptor->PortCount; i++)
{
if (strcmp(lv2ui->rdf_descriptor->Ports[i].Symbol, symbol) == 0)
return i;
}
}

return 0;
}

// ----------------- UI Resize Feature -------------------------------------
static int carla_lv2_ui_resize(LV2UI_Feature_Handle data, int width, int height)
{
qDebug("carla_lv2_ui_resized(%p, %i, %i)", data, width, height);

if (data)
{
Lv2UiData* lv2ui = (Lv2UiData*)data;
lv2ui->queque_message(BRIDGE_MESSAGE_RESIZE_GUI, width, height, 0.0);
return 0;
}

return 1;
}

// ----------------- UI Extension ------------------------------------------
static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
{
qDebug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);

if (controller)
{
if (format == 0)
{
if (buffer_size == sizeof(float))
{
float value = *(float*)buffer;
osc_send_control(nullptr, port_index, value);
}
}
else if (format == CARLA_URI_MAP_ID_MIDI_EVENT)
{
const uint8_t* data = (const uint8_t*)buffer;
uint8_t status = data[0];

// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(status) && data[2] == 0)
status -= 0x10;

uint8_t midi_buf[4] = { 0, status, data[2], data[3] };
osc_send_midi(nullptr, midi_buf);
}
}
}

private:
@@ -292,7 +575,11 @@ private:
LV2UI_Widget widget;
const LV2UI_Descriptor* descriptor;
LV2_Feature* features[lv2_feature_count+1];
bool resizable;

const LV2_RDF_Descriptor* rdf_descriptor;
const LV2_RDF_UI* rdf_ui_descriptor;

const LV2_Programs_UI_Interface* programs;

#ifdef BRIDGE_LV2_X11
QDialog* x11_widget;
@@ -301,63 +588,53 @@ private:

int main(int argc, char* argv[])
{
if (argc != 7)
if (argc != 5)
{
qCritical("%s: bad arguments", argv[0]);
return 1;
}

const char* osc_url = argv[1];
const char* plugin_uri = argv[2];
const char* ui_uri = argv[3];
const char* ui_binary = argv[4];
const char* ui_bundle = argv[5];
const char* ui_title = argv[6];
const char* osc_url = argv[1];
const char* plugin_uri = argv[2];
const char* ui_uri = argv[3];
const char* ui_title = argv[4];

// Init toolkit
toolkit_init();

// Init LV2
ui = new Lv2UiData;
// Init LV2-UI
ui = new Lv2UiData(ui_title);

// Init OSC
osc_init("lv2-ui-bridge", osc_url);
osc_init(osc_url);

// Load UI
int ret;

if (ui->lib_open(ui_binary))
if (ui->init(plugin_uri, ui_uri))
{
if (ui->init(plugin_uri, ui_uri, ui_bundle, false) == false) // (strcmp(resizable, "true") == 0)
{
qCritical("Failed to load LV2 UI");
ui->lib_close();
osc_close();
return 1;
}
toolkit_loop();
ret = 0;
}
else
{
qCritical("Failed to load UI, error was:\n%s", ui->lib_error());
osc_close();
return 1;
qCritical("Failed to load LV2 UI");
ret = 1;
}

#ifdef BRIDGE_LV2_X11
bool reparent = false;
#else
bool reparent = true;
#endif

toolkit_loop(ui_title, reparent);
// Close OSC
osc_send_exiting(nullptr);
osc_close();

// Close LV2-UI
ui->close();
ui->lib_close();

osc_send_exiting();
osc_close();

toolkit_quit();
// Close toolkit
if (! ret)
toolkit_quit();

delete ui;
ui = nullptr;

return 0;
return ret;
}

+ 50
- 35
src/carla-bridge-ui/carla_bridge_ui.h View File

@@ -20,10 +20,11 @@

#include "carla_includes.h"

#include <pthread.h>
#include <cstring>
#include <QtCore/QMutex>

void toolkit_init();
void toolkit_loop(const char* ui_title, bool reparent);
void toolkit_loop();
void toolkit_quit();
void toolkit_window_show();
void toolkit_window_hide();
@@ -31,7 +32,7 @@ void toolkit_window_resize(int width, int height);

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

const unsigned int MAX_BRIDGE_MESSAGES = 256;
#define MAX_BRIDGE_MESSAGES 256

enum BridgeMessageType {
BRIDGE_MESSAGE_NULL = 0,
@@ -46,7 +47,6 @@ enum BridgeMessageType {
};

struct QuequeBridgeMessage {
bool valid;
BridgeMessageType type;
int value1;
int value2;
@@ -58,14 +58,13 @@ struct QuequeBridgeMessage {
class UiData
{
public:
UiData()
UiData(const char* ui_title)
{
m_lib = nullptr;
pthread_mutex_init(&m_lock, nullptr);
m_lib = nullptr;
m_title = strdup(ui_title);

for (unsigned int i=0; i < MAX_BRIDGE_MESSAGES; i++)
{
QuequeBridgeMessages[i].valid = false;
QuequeBridgeMessages[i].type = BRIDGE_MESSAGE_NULL;
QuequeBridgeMessages[i].value1 = 0;
QuequeBridgeMessages[i].value2 = 0;
@@ -75,17 +74,16 @@ public:

~UiData()
{
pthread_mutex_destroy(&m_lock);
free((void*)m_title);
}

void queque_message(BridgeMessageType type, int value1, int value2, double value3)
{
pthread_mutex_lock(&m_lock);
m_lock.lock();
for (unsigned int i=0; i<MAX_BRIDGE_MESSAGES; i++)
{
if (QuequeBridgeMessages[i].valid == false)
if (QuequeBridgeMessages[i].type == BRIDGE_MESSAGE_NULL)
{
QuequeBridgeMessages[i].valid = true;
QuequeBridgeMessages[i].type = type;
QuequeBridgeMessages[i].value1 = value1;
QuequeBridgeMessages[i].value2 = value2;
@@ -93,36 +91,34 @@ public:
break;
}
}
pthread_mutex_unlock(&m_lock);
m_lock.unlock();
}

bool run_messages()
{
pthread_mutex_lock(&m_lock);
m_lock.lock();
for (unsigned int i=0; i < MAX_BRIDGE_MESSAGES; i++)
{
if (QuequeBridgeMessages[i].valid)
if (QuequeBridgeMessages[i].type != BRIDGE_MESSAGE_NULL)
{
QuequeBridgeMessage* m = &QuequeBridgeMessages[i];
const QuequeBridgeMessage* const m = &QuequeBridgeMessages[i];

switch (m->type)
{
case BRIDGE_MESSAGE_NULL:
break;
case BRIDGE_MESSAGE_PARAMETER:
update_parameter(m->value1, m->value3);
set_parameter(m->value1, m->value3);
break;
case BRIDGE_MESSAGE_PROGRAM:
update_program(m->value1);
set_program(m->value1);
break;
case BRIDGE_MESSAGE_MIDI_PROGRAM:
update_midi_program(m->value1, m->value2);
set_midi_program(m->value1, m->value2);
break;
case BRIDGE_MESSAGE_NOTE_ON:
send_note_on(m->value1, m->value2);
//send_note_on(m->value1, m->value2);
break;
case BRIDGE_MESSAGE_NOTE_OFF:
send_note_off(m->value1);
//send_note_off(m->value1);
break;
case BRIDGE_MESSAGE_SHOW_GUI:
if (m->value1)
@@ -135,31 +131,45 @@ public:
break;
case BRIDGE_MESSAGE_QUIT:
toolkit_quit();
pthread_mutex_unlock(&m_lock);
m_lock.unlock();
return false;
default:
break;
}
m->valid = false;

QuequeBridgeMessages[i].type = BRIDGE_MESSAGE_NULL;
}
else
break;
}
pthread_mutex_unlock(&m_lock);
m_lock.unlock();
return true;
}

virtual bool init(const char*, const char*, const char*, bool) = 0;
const char* get_title() const
{
return m_title;
}

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

// initialization
virtual bool init(const char*, const char*) = 0;
virtual void close() = 0;

virtual void update_parameter(int index, double value) = 0;
virtual void update_program(int index) = 0;
virtual void update_midi_program(int bank, int program) = 0;
virtual void send_note_on(int note, int velocity) = 0;
virtual void send_note_off(int note) = 0;
// processing
virtual void set_parameter(int index, double value) = 0;
virtual void set_program(int index) = 0;
virtual void set_midi_program(int bank, int program) = 0;
//virtual void send_note_on(int note, int velocity) = 0;
//virtual void send_note_off(int note) = 0;

// gui
virtual bool has_parent() const = 0;
virtual bool is_resizable() const = 0;
virtual void* get_widget() const = 0;

virtual void* get_widget() = 0;
virtual bool is_resizable() = 0;
// ---------------------------------------------------------------------

bool lib_open(const char* filename)
{
@@ -214,9 +224,14 @@ public:
#endif
}

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

protected:
const char* m_title;

private:
void* m_lib;
pthread_mutex_t m_lock;
QMutex m_lock;
QuequeBridgeMessage QuequeBridgeMessages[MAX_BRIDGE_MESSAGES];
};



+ 14
- 9
src/carla-bridge-ui/qtcreator/carla-bridge-lv2-gtk2.pro View File

@@ -1,20 +1,28 @@
# QtCreator project file

CONFIG = warn_on qt release
QT = core

CONFIG += warn_on qt debug link_pkgconfig
PKGCONFIG = liblo gtk+-2.0

TEMPLATE = app
VERSION = 0.5.0
VERSION = 0.5.0

SOURCES = \
../carla_bridge_lv2.cpp \
../carla_bridge_gtk2.cpp \
../../carla-bridge/carla_osc.cpp
../../carla-bridge/carla_bridge_osc.cpp

HEADERS = \
../carla_bridge_ui.h \
../../carla-bridge/carla_osc.h
../../carla/carla_midi.h \
../../carla/lv2_rdf.h \
../../carla-bridge/carla_bridge_osc.h \
../../carla-includes/carla_includes.h \
../../carla-includes/carla_osc_includes.h

INCLUDEPATH = .. \
../../carla \
../../carla-bridge \
../../carla-includes

@@ -22,9 +30,6 @@ TARGET = carla-bridge-lv2-gtk2

DEFINES = BUILD_BRIDGE BUILD_BRIDGE_UI BRIDGE_LV2_GTK2

LIBS += -ldl -lpthread -llo
LIBS = ../../carla-lilv/carla_lilv.a -ldl

unix {
CONFIG += link_pkgconfig
PKGCONFIG += gtk+-2.0
}
QMAKE_CXXFLAGS *= -std=c++0x

src/carla-bridge/carla_osc.cpp → src/carla-bridge/carla_bridge_osc.cpp View File

@@ -15,20 +15,23 @@
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "carla_osc.h"
#include "carla_bridge_osc.h"
#include "carla_midi.h"

#ifdef BUILD_BRIDGE_UI
#include "carla_bridge_ui.h"
#else
// TODO
#include "carla_plugin.h"
extern void plugin_bridge_show_gui(bool yesno);
extern void plugin_bridge_quit();
//CarlaPlugin* plugin = CarlaPlugins[0];
#endif

#include <cstring>

size_t plugin_name_len = 0;
const char* plugin_name = nullptr;
size_t plugin_name_len = 13;
const char* plugin_name = "lv2-ui-bridge";

const char* global_osc_server_path = nullptr;
lo_server_thread global_osc_server_thread = nullptr;
@@ -36,11 +39,9 @@ OscData global_osc_data = { nullptr, nullptr, nullptr };

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

void osc_init(const char* osc_name, const char* osc_url)
void osc_init(const char* osc_url)
{
qDebug("osc_init(%s, %s)", osc_name, osc_url);
plugin_name = osc_name;
plugin_name_len = strlen(plugin_name);
qDebug("osc_init(%s)", osc_url);

const char* host = lo_url_get_hostname(osc_url);
const char* port = lo_url_get_port(osc_url);
@@ -55,21 +56,18 @@ void osc_init(const char* osc_name, const char* osc_url)
global_osc_server_thread = lo_server_thread_new(nullptr, osc_error_handler);

// get our full OSC server path
char* osc_thread_path = lo_server_thread_get_url(global_osc_server_thread);
char* this_thread_path = lo_server_thread_get_url(global_osc_server_thread);

char osc_path_tmp[strlen(osc_thread_path) + plugin_name_len + 1];
strcpy(osc_path_tmp, osc_thread_path);
char osc_path_tmp[strlen(this_thread_path) + plugin_name_len + 1];
strcpy(osc_path_tmp, this_thread_path);
strcat(osc_path_tmp, plugin_name);
free(osc_thread_path);
free(this_thread_path);

global_osc_server_path = strdup(osc_path_tmp);

// register message handler and start OSC thread
lo_server_thread_add_method(global_osc_server_thread, nullptr, nullptr, osc_message_handler, nullptr);
lo_server_thread_start(global_osc_server_thread);

// debug our server path just to make sure everything is ok
qDebug("carla-bridge OSC -> %s\n", global_osc_server_path);
}

void osc_close()
@@ -90,14 +88,16 @@ void osc_clear_data(OscData* osc_data)
{
qDebug("osc_clear_data(%p)", osc_data);

if (global_osc_data.path)
free((void*)global_osc_data.path);
// TODO - sync

if (global_osc_data.target)
lo_address_free(global_osc_data.target);
if (osc_data->path)
free((void*)osc_data->path);

global_osc_data.path = nullptr;
global_osc_data.target = nullptr;
if (osc_data->target)
lo_address_free(osc_data->target);

osc_data->path = nullptr;
osc_data->target = nullptr;
}

// -------------------------------------------------------------------------
@@ -111,24 +111,25 @@ int osc_message_handler(const char* path, const char* types, lo_arg** argv, int
{
qDebug("osc_message_handler(%s, %s, %p, %i, %p, %p)", path, types, argv, argc, data, user_data);

char method[32];
memset(method, 0, sizeof(char)*24);

unsigned int mindex = strlen(plugin_name)+2;
if (strlen(path) < plugin_name_len + 3)
{
qWarning("Got invalid OSC path '%s'", path);
return 1;
}

for (unsigned int i=mindex; i < strlen(path) && i-mindex < 24; i++)
method[i-mindex] = path[i];
char method[32] = { 0 };
memcpy(method, path + plugin_name_len + 2, 32);

if (strcmp(method, "control") == 0)
if (strcmp(method, "configure") == 0)
return osc_handle_configure(argv);
else if (strcmp(method, "control") == 0)
return osc_handle_control(argv);
else if (strcmp(method, "program") == 0)
return osc_handle_program(argv);
else if (strcmp(method, "midi_program") == 0)
return osc_handle_midi_program(argv);
// else if (strcmp(method, "note_on") == 0)
// return osc_note_on_handler(argv);
// else if (strcmp(method, "note_off") == 0)
// return osc_note_off_handler(argv);
else if (strcmp(method, "midi") == 0)
return osc_handle_midi(argv);
else if (strcmp(method, "show") == 0)
return osc_handle_show();
else if (strcmp(method, "hide") == 0)
@@ -149,6 +150,23 @@ int osc_message_handler(const char* path, const char* types, lo_arg** argv, int

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

int osc_handle_configure(lo_arg** argv)
{
const char* key = (const char*)&argv[0]->s;
const char* value = (const char*)&argv[1]->s;

#ifdef BUILD_BRIDGE_UI
// TODO
(void)key;
(void)value;
#else
if (CarlaPlugins[0])
CarlaPlugins[0]->set_custom_data(CUSTOM_DATA_STRING, key, value, false);
#endif

return 0;
}

int osc_handle_control(lo_arg** argv)
{
int index = argv[0]->i;
@@ -173,7 +191,7 @@ int osc_handle_program(lo_arg** argv)
if (ui && index >= 0)
ui->queque_message(BRIDGE_MESSAGE_PROGRAM, index, 0, 0.0);
#else
if (CarlaPlugins[0])
if (CarlaPlugins[0] && index >= 0)
CarlaPlugins[0]->set_program(index, false, true, true, true);
#endif

@@ -186,18 +204,50 @@ int osc_handle_midi_program(lo_arg** argv)
int program = argv[1]->i;

#ifdef BUILD_BRIDGE_UI
//if (ui && index >= 0)
// ui->queque_message(BRIDGE_MESSAGE_MIDI_PROGRAM, index, 0, 0.0);
(void)bank;
(void)program;
if (ui && bank >= 0 && program >= 0)
ui->queque_message(BRIDGE_MESSAGE_MIDI_PROGRAM, bank, program, 0.0);
#else
if (CarlaPlugins[0])
if (CarlaPlugins[0] && bank >= 0 && program >= 0)
CarlaPlugins[0]->set_midi_program_full(bank, program, false, true, true, true);
#endif

return 0;
}

int osc_handle_midi(lo_arg** argv)
{
uint8_t* data = argv[0]->m;
uint8_t status = data[1];

// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0)
status -= 0x10;

if (MIDI_IS_STATUS_NOTE_OFF(status))
{
uint8_t note = data[2];
#ifdef BUILD_BRIDGE_UI
if (ui)
ui->queque_message(BRIDGE_MESSAGE_NOTE_OFF, note, 0, 0.0);
#else
plugin->send_midi_note(false, note, 0, false, true, true);
#endif
}
else if (MIDI_IS_STATUS_NOTE_ON(status))
{
uint8_t note = data[2];
uint8_t velo = data[3];
#ifdef BUILD_BRIDGE_UI
if (ui)
ui->queque_message(BRIDGE_MESSAGE_NOTE_ON, note, velo, 0.0);
#else
plugin->send_midi_note(true, note, velo, false, true, true);
#endif
}

return 0;
}

int osc_handle_show()
{
#ifdef BUILD_BRIDGE_UI
@@ -236,9 +286,8 @@ int osc_handle_quit()

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

void osc_send_update()
void osc_send_update(OscData*)
{
qDebug("osc_send_update()");
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+8];
@@ -248,9 +297,63 @@ void osc_send_update()
}
}

void osc_send_exiting()
void osc_send_configure(OscData*, const char* key, const char* value)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+11];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/configure");
lo_send(global_osc_data.target, target_path, "ss", key, value);
}
}

void osc_send_control(OscData*, int param, double value)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+9];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/control");
lo_send(global_osc_data.target, target_path, "if", param, value);
}
}

void osc_send_program(OscData*, int program)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+9];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/program");
lo_send(global_osc_data.target, target_path, "i", program);
}
}

void osc_send_midi_program(OscData*, int bank, int program)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+14];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/midi_program");
lo_send(global_osc_data.target, target_path, "ii", bank, program);
}
}

void osc_send_midi(OscData*, uint8_t buf[4])
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+6];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/midi");
lo_send(global_osc_data.target, target_path, "m", buf);
}
}

void osc_send_exiting(OscData*)
{
qDebug("osc_send_exiting()");
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+9];
@@ -260,6 +363,9 @@ void osc_send_exiting()
}
}

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

#ifndef BUILD_BRIDGE_UI
void osc_send_bridge_ains_peak(int index, double value)
{
if (global_osc_data.target)
@@ -315,6 +421,28 @@ void osc_send_bridge_param_count(int ins, int outs, int total)
}
}

void osc_send_bridge_program_count(int count)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+22];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/bridge_program_count");
lo_send(global_osc_data.target, target_path, "i", count);
}
}

void osc_send_bridge_midi_program_count(int count)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+27];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/bridge_midi_program_count");
lo_send(global_osc_data.target, target_path, "i", count);
}
}

void osc_send_bridge_plugin_info(int type, int category, int hints, const char* name, const char* label, const char* maker, const char* copyright, long unique_id)
{
if (global_osc_data.target)
@@ -337,14 +465,14 @@ void osc_send_bridge_param_info(int index, const char* name, const char* unit)
}
}

void osc_send_bridge_param_data(int type, int index, int rindex, int hints, int midi_channel, int midi_cc)
void osc_send_bridge_param_data(int index, int type, int rindex, int hints, int midi_channel, int midi_cc)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+19];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/bridge_param_data");
lo_send(global_osc_data.target, target_path, "iiiiii", type, index, rindex, hints, midi_channel, midi_cc);
lo_send(global_osc_data.target, target_path, "iiiiii", index, type, rindex, hints, midi_channel, midi_cc);
}
}

@@ -359,51 +487,36 @@ void osc_send_bridge_param_ranges(int index, double def, double min, double max,
}
}

void osc_send_bridge_update()
void osc_send_bridge_program_info(int index, const char* name)
{
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+14];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/bridge_update");
lo_send(global_osc_data.target, target_path, "");
}
}

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

void osc_send_configure(OscData*, const char* key, const char* value)
{
qDebug("osc_send_configure(%s, %s)", key, value);
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+11];
char target_path[strlen(global_osc_data.path)+21];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/configure");
lo_send(global_osc_data.target, target_path, "ss", key, value);
strcat(target_path, "/bridge_program_info");
lo_send(global_osc_data.target, target_path, "is", index, name);
}
}

void osc_send_control(OscData*, int param, double value)
void osc_send_bridge_midi_program_info(int index, int bank, int program, const char* label)
{
qDebug("osc_send_control(%i, %f)", param, value);
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+9];
char target_path[strlen(global_osc_data.path)+26];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/control");
lo_send(global_osc_data.target, target_path, "if", param, value);
strcat(target_path, "/bridge_midi_program_info");
lo_send(global_osc_data.target, target_path, "iiis", index, bank, program, label);
}
}

void osc_send_program(OscData*, int program_id)
void osc_send_bridge_update()
{
qDebug("osc_send_program(%i)", program_id);
if (global_osc_data.target)
{
char target_path[strlen(global_osc_data.path)+9];
char target_path[strlen(global_osc_data.path)+15];
strcpy(target_path, global_osc_data.path);
strcat(target_path, "/program");
lo_send(global_osc_data.target, target_path, "i", program_id);
strcat(target_path, "/bridge_update");
lo_send(global_osc_data.target, target_path, "");
}
}
#endif

src/carla-bridge/carla_osc.h → src/carla-bridge/carla_bridge_osc.h View File

@@ -15,56 +15,37 @@
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_OSC_H
#define CARLA_OSC_H
#ifndef CARLA_BRIDGE_OSC_H
#define CARLA_BRIDGE_OSC_H

#include "carla_includes.h"
#include "carla_osc_includes.h"

#include <lo/lo.h>

struct OscData {
char* path;
lo_address source; // unused
lo_address target;
};

void osc_init(const char* osc_name, const char* osc_url);
void osc_close();
void osc_clear_data(OscData* osc_data);

void osc_error_handler(int num, const char* msg, const char* path);
int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data);

// common plugin handlers
// common handlers
int osc_handle_configure(lo_arg** argv);
int osc_handle_control(lo_arg** argv);
int osc_handle_program(lo_arg** argv);
int osc_handle_midi_program(lo_arg** argv);
int osc_handle_midi(lo_arg** argv);
int osc_handle_show();
int osc_handle_hide();
int osc_handle_quit();

#ifndef BUILD_BRIDGE_UI
// bridge only
void osc_send_update();
void osc_send_exiting();
void osc_send_bridge_ains_peak(int index, double value);
void osc_send_bridge_aouts_peak(int index, double value);
void osc_send_bridge_audio_count(int ins, int outs, int total);
void osc_send_bridge_midi_count(int ins, int outs, int total);
void osc_send_bridge_param_count(int ins, int outs, int total);
//void osc_send_bridge_program_count();
//void osc_send_bridge_midi_program_count();
void osc_send_bridge_program_count(int count);
void osc_send_bridge_midi_program_count(int count);
void osc_send_bridge_plugin_info(int type, int category, int hints, const char* name, const char* label, const char* maker, const char* copyright, long unique_id);
void osc_send_bridge_param_info(int index, const char* name, const char* unit);
void osc_send_bridge_param_data(int type, int index, int rindex, int hints, int midi_channel, int midi_cc);
void osc_send_bridge_param_data(int index, int type, int rindex, int hints, int midi_channel, int midi_cc);
void osc_send_bridge_param_ranges(int index, double def, double min, double max, double step, double step_small, double step_large);
//void osc_send_bridge_program_info();
//void osc_send_bridge_midi_program_info();
void osc_send_bridge_program_info(int index, const char* name);
void osc_send_bridge_midi_program_info(int index, int bank, int program, const char* label);
void osc_send_bridge_update();
#endif

// common plugin calls
void osc_send_configure(OscData* osc_data, const char* key, const char* value);
void osc_send_control(OscData* osc_data, int param_id, double value);
void osc_send_program(OscData* osc_data, int program_id);
// TODO - midi

#endif // CARLA_OSC_H
#endif // CARLA_BRIDGE_OSC_H

+ 52
- 0
src/carla-includes/carla_osc_includes.h View File

@@ -0,0 +1,52 @@
/*
* JACK Backend code for Carla
* Copyright (C) 2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_OSC_INCLUDES_H
#define CARLA_OSC_INCLUDES_H

#include "carla_includes.h"

#include <lo/lo.h>

struct OscData {
char* path;
lo_address source;
lo_address target;
};

void osc_init(const char*);
void osc_close();
void osc_clear_data(OscData*);

void osc_error_handler(int num, const char* msg, const char* path);
int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data);

void osc_send_update(OscData*);
void osc_send_configure(OscData*, const char* key, const char* value);
void osc_send_control(OscData*, int control, double value);
void osc_send_program(OscData*, int program);
void osc_send_midi_program(OscData*, int bank, int program);
void osc_send_midi(OscData*, uint8_t buf[4]);
#ifndef BUILD_BRIDGE_UI
void osc_send_show(OscData*);
void osc_send_hide(OscData*);
void osc_send_quit(OscData*);
#else
void osc_send_exiting(OscData*);
#endif

#endif // CARLA_OSC_INCLUDES_H

+ 3
- 3
src/carla-includes/lv2/lv2-midifunctions.h View File

@@ -33,7 +33,7 @@ typedef struct {
} LV2_MIDIState;


static double lv2midi_get_event(LV2_MIDIState* state,
inline double lv2midi_get_event(LV2_MIDIState* state,
double* timestamp,
uint32_t* size,
unsigned char** data) {
@@ -54,7 +54,7 @@ static double lv2midi_get_event(LV2_MIDIState* state,
}


static double lv2midi_step(LV2_MIDIState* state) {
inline double lv2midi_step(LV2_MIDIState* state) {

if (state->position >= state->midi->size) {
state->position = state->midi->size;
@@ -69,7 +69,7 @@ static double lv2midi_step(LV2_MIDIState* state) {
}


static void lv2midi_put_event(LV2_MIDIState* state,
inline void lv2midi_put_event(LV2_MIDIState* state,
double timestamp,
uint32_t size,
const unsigned char* data) {


+ 1
- 1
src/carla.py View File

@@ -2392,7 +2392,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget):
content += " <CustomData>\n"
content += " <type>%s</type>\n" % (custom_data['type'])
content += " <key>%s</key>\n" % (custom_data['key'])
if (custom_data['type'] in ("string", "binary")):
if (custom_data['type'] in ("string", "chunk", "binary")):
content += " <value>\n"
content += "%s\n" % (custom_data['value'])
content += " </value>\n"


+ 2
- 25
src/carla/carla_osc.h View File

@@ -18,25 +18,10 @@
#ifndef CARLA_OSC_H
#define CARLA_OSC_H

#include "carla_includes.h"

#include <lo/lo.h>
#include "carla_osc_includes.h"

class CarlaPlugin;

struct OscData {
char* path;
lo_address source;
lo_address target;
};

void osc_init();
void osc_close();
void osc_clear_data(OscData* osc_data);

void osc_error_handler(int num, const char* msg, const char* path);
int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data);

int osc_handle_register(lo_arg** argv, lo_address source);
int osc_handle_unregister();

@@ -45,6 +30,7 @@ int osc_handle_configure(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_control(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_program(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_program_as_midi(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_midi_program(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_midi(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_exiting(CarlaPlugin* plugin);

@@ -60,15 +46,6 @@ int osc_handle_note_off(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_bridge_ains_peak(CarlaPlugin* plugin, lo_arg** argv);
int osc_handle_bridge_aouts_peak(CarlaPlugin* plugin, lo_arg** argv);

void osc_send_configure(OscData* osc_data, const char* key, const char* value);
void osc_send_control(OscData* osc_data, int param_id, double value);
void osc_send_program(OscData* osc_data, int program_id);
void osc_send_program_as_midi(OscData* osc_data, int bank, int program);
void osc_send_midi_program(OscData* osc_data, int bank, int program);
void osc_send_show(OscData* osc_data);
void osc_send_hide(OscData* osc_data);
void osc_send_quit(OscData* osc_data);

bool osc_global_registered();
void osc_global_send_add_plugin(int plugin_id, const char* plugin_name);
void osc_global_send_remove_plugin(int plugin_id);


+ 69
- 110
src/carla/lv2.cpp View File

@@ -17,33 +17,6 @@

#include "carla_plugin.h"

#include "lv2/lv2.h"
#include "lv2/atom.h"
#include "lv2/atom-util.h"
#include "lv2/data-access.h"
#include "lv2/event.h"
#include "lv2/event-helpers.h"
#include "lv2/instance-access.h"
#include "lv2/log.h"
#include "lv2/midi.h"
#include "lv2/patch.h"
#include "lv2/port-props.h"
#include "lv2/presets.h"
#include "lv2/state.h"
#include "lv2/time.h"
#include "lv2/ui.h"
#include "lv2/units.h"
#include "lv2/uri-map.h"
#include "lv2/urid.h"
#include "lv2/worker.h"

#include "lv2/lv2dynparam.h"
#include "lv2/lv2-miditype.h"
#include "lv2/lv2-midifunctions.h"
#include "lv2/lv2_external_ui.h"
#include "lv2/lv2_programs.h"
#include "lv2/lv2_rtmempool.h"

#include "lv2_rdf.h"

extern "C" {
@@ -73,45 +46,44 @@ const unsigned int PARAMETER_IS_TRIGGER = 0x1000;
const unsigned int PARAMETER_IS_STRICT_BOUNDS = 0x2000;

// feature ids
const uint32_t lv2_feature_id_event = 0;
const uint32_t lv2_feature_id_logs = 1;
const uint32_t lv2_feature_id_state_make_path = 2;
const uint32_t lv2_feature_id_state_map_path = 3;
const uint32_t lv2_feature_id_uri_map = 4;
const uint32_t lv2_feature_id_urid_map = 5;
const uint32_t lv2_feature_id_urid_unmap = 6;
const uint32_t lv2_feature_id_worker = 7;
const uint32_t lv2_feature_id_programs = 8;
const uint32_t lv2_feature_id_rtmempool = 9;
const uint32_t lv2_feature_id_data_access = 10;
const uint32_t lv2_feature_id_instance_access = 11;
const uint32_t lv2_feature_id_ui_parent = 12;
const uint32_t lv2_feature_id_ui_port_map = 13;
const uint32_t lv2_feature_id_ui_resize = 14;
const uint32_t lv2_feature_id_external_ui = 15;
const uint32_t lv2_feature_id_external_ui_old = 16;
const uint32_t lv2_feature_count = 17;
const uint32_t lv2_feature_id_event = 0;
const uint32_t lv2_feature_id_logs = 1;
const uint32_t lv2_feature_id_programs = 2;
const uint32_t lv2_feature_id_rtmempool = 3;
const uint32_t lv2_feature_id_state_make_path = 4;
const uint32_t lv2_feature_id_state_map_path = 5;
const uint32_t lv2_feature_id_uri_map = 6;
const uint32_t lv2_feature_id_urid_map = 7;
const uint32_t lv2_feature_id_urid_unmap = 8;
const uint32_t lv2_feature_id_worker = 9;
const uint32_t lv2_feature_id_data_access = 10;
const uint32_t lv2_feature_id_instance_access = 11;
const uint32_t lv2_feature_id_ui_parent = 12;
const uint32_t lv2_feature_id_ui_port_map = 13;
const uint32_t lv2_feature_id_ui_resize = 14;
const uint32_t lv2_feature_id_external_ui = 15;
const uint32_t lv2_feature_id_external_ui_old = 16;
const uint32_t lv2_feature_count = 17;

// event data/types
const unsigned int CARLA_EVENT_DATA_ATOM = 0x01;
const unsigned int CARLA_EVENT_DATA_EVENT = 0x02;
const unsigned int CARLA_EVENT_DATA_MIDI_LL = 0x04;
const unsigned int CARLA_EVENT_TYPE_MESSAGE = 0x10;
const unsigned int CARLA_EVENT_TYPE_MIDI = 0x20;
const unsigned int CARLA_EVENT_DATA_ATOM = 0x01;
const unsigned int CARLA_EVENT_DATA_EVENT = 0x02;
const unsigned int CARLA_EVENT_DATA_MIDI_LL = 0x04;
const unsigned int CARLA_EVENT_TYPE_MESSAGE = 0x10;
const unsigned int CARLA_EVENT_TYPE_MIDI = 0x20;

// pre-set uri[d] map ids
const uint32_t CARLA_URI_MAP_ID_NULL = 0;
const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1;
const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 2;
const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 3;
const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 4;
const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 5;
const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 6;
const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 7;
const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 8;
const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 9;
const uint32_t CARLA_URI_MAP_ID_TIME_POSITION = 10; // TODO - full timePos support
const uint32_t CARLA_URI_MAP_ID_COUNT = 11;
const uint32_t CARLA_URI_MAP_ID_NULL = 0;
const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1;
const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 2;
const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 3;
const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 4;
const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 5;
const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 6;
const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 7;
const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 8;
const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 9;
const uint32_t CARLA_URI_MAP_ID_COUNT = 10;

enum Lv2ParameterDataType {
LV2_PARAMETER_TYPE_CONTROL,
@@ -2374,6 +2346,10 @@ public:
Log_Feature->printf = carla_lv2_log_printf;
Log_Feature->vprintf = carla_lv2_log_vprintf;

LV2_Programs_Host* Programs_Feature = new LV2_Programs_Host;
Programs_Feature->handle = this;
Programs_Feature->program_changed = carla_lv2_program_changed;

LV2_State_Make_Path* State_MakePath_Feature = new LV2_State_Make_Path;
State_MakePath_Feature->handle = this;
State_MakePath_Feature->path = carla_lv2_state_make_path;
@@ -2399,10 +2375,6 @@ public:
Worker_Feature->handle = this;
Worker_Feature->schedule_work = carla_lv2_worker_schedule;

LV2_Programs_Host* Programs_Feature = new LV2_Programs_Host;
Programs_Feature->handle = this;
Programs_Feature->program_changed = carla_lv2_program_changed;

lv2_rtsafe_memory_pool_provider* RT_MemPool_Feature = new lv2_rtsafe_memory_pool_provider;
rtmempool_allocator_init(RT_MemPool_Feature);

@@ -2414,6 +2386,14 @@ public:
features[lv2_feature_id_logs]->URI = LV2_LOG__log;
features[lv2_feature_id_logs]->data = Log_Feature;

features[lv2_feature_id_programs] = new LV2_Feature;
features[lv2_feature_id_programs]->URI = LV2_PROGRAMS__Host;
features[lv2_feature_id_programs]->data = Programs_Feature;

features[lv2_feature_id_rtmempool] = new LV2_Feature;
features[lv2_feature_id_rtmempool]->URI = LV2_RTSAFE_MEMORY_POOL_URI;
features[lv2_feature_id_rtmempool]->data = RT_MemPool_Feature;

features[lv2_feature_id_state_make_path] = new LV2_Feature;
features[lv2_feature_id_state_make_path]->URI = LV2_STATE__makePath;
features[lv2_feature_id_state_make_path]->data = State_MakePath_Feature;
@@ -2438,14 +2418,6 @@ public:
features[lv2_feature_id_worker]->URI = LV2_WORKER__schedule;
features[lv2_feature_id_worker]->data = Worker_Feature;

features[lv2_feature_id_programs] = new LV2_Feature;
features[lv2_feature_id_programs]->URI = LV2_PROGRAMS__Host;
features[lv2_feature_id_programs]->data = Programs_Feature;

features[lv2_feature_id_rtmempool] = new LV2_Feature;
features[lv2_feature_id_rtmempool]->URI = LV2_RTSAFE_MEMORY_POOL_URI;
features[lv2_feature_id_rtmempool]->data = RT_MemPool_Feature;

handle = descriptor->instantiate(descriptor, get_sample_rate(), rdf_descriptor->Bundle, features);

if (handle)
@@ -2762,6 +2734,9 @@ public:
#endif
}

// ----------------- DynParam Feature ------------------------------------------------
// TODO

// ----------------- Event Feature ---------------------------------------------------
static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
{
@@ -2819,6 +2794,18 @@ public:
return ret;
}

// ----------------- Programs Feature ------------------------------------------------
static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
{
qDebug("Lv2Plugin::carla_lv2_program_changed(%p, %i)", handle, index);

if (handle)
{
Lv2Plugin* plugin = (Lv2Plugin*)handle;
plugin->update_program(index);
}
}

// ----------------- State Feature ---------------------------------------------------
static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
{
@@ -2996,17 +2983,8 @@ public:
{
qDebug("Lv2Plugin::carla_lv2_uri_to_id(%p, %s, %s)", data, map, uri);

// Event types
if (map && strcmp(map, LV2_EVENT_URI) == 0)
{
if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
return CARLA_URI_MAP_ID_MIDI_EVENT;
else if (strcmp(uri, LV2_TIME__Position) == 0)
return CARLA_URI_MAP_ID_TIME_POSITION;
}

// Atom types
else if (strcmp(uri, LV2_ATOM__Chunk) == 0)
if (strcmp(uri, LV2_ATOM__Chunk) == 0)
return CARLA_URI_MAP_ID_ATOM_CHUNK;
else if (strcmp(uri, LV2_ATOM__Path) == 0)
return CARLA_URI_MAP_ID_ATOM_PATH;
@@ -3025,7 +3003,9 @@ public:
else if (strcmp(uri, LV2_LOG__Warning) == 0)
return CARLA_URI_MAP_ID_LOG_WARNING;

// TODO - position types
// Others
else if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
return CARLA_URI_MAP_ID_MIDI_EVENT;

// Custom types
if (data)
@@ -3042,14 +3022,8 @@ public:
{
qDebug("Lv2Plugin::carla_lv2_urid_map(%p, %s)", handle, uri);

// Event types
if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
return CARLA_URI_MAP_ID_MIDI_EVENT;
else if (strcmp(uri, LV2_TIME__Position) == 0)
return CARLA_URI_MAP_ID_TIME_POSITION;

// Atom types
else if (strcmp(uri, LV2_ATOM__Chunk) == 0)
if (strcmp(uri, LV2_ATOM__Chunk) == 0)
return CARLA_URI_MAP_ID_ATOM_CHUNK;
else if (strcmp(uri, LV2_ATOM__Path) == 0)
return CARLA_URI_MAP_ID_ATOM_PATH;
@@ -3068,7 +3042,9 @@ public:
else if (strcmp(uri, LV2_LOG__Warning) == 0)
return CARLA_URI_MAP_ID_LOG_WARNING;

// TODO - position types
// Others
else if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
return CARLA_URI_MAP_ID_MIDI_EVENT;

// Custom types
if (handle)
@@ -3087,8 +3063,6 @@ public:
// Event types
if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
return LV2_MIDI__MidiEvent;
else if (urid == CARLA_URI_MAP_ID_TIME_POSITION)
return LV2_TIME__Position;

// Atom types
else if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
@@ -3166,21 +3140,6 @@ public:
return LV2_WORKER_ERR_UNKNOWN;
}

// ----------------- DynParam Feature ------------------------------------------------
// TODO

// ----------------- Programs Feature ------------------------------------------------
static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
{
qDebug("Lv2Plugin::carla_lv2_program_changed(%p, %i)", handle, index);

if (handle)
{
Lv2Plugin* plugin = (Lv2Plugin*)handle;
plugin->update_program(index);
}
}

// ----------------- UI Port-Map Feature ---------------------------------------------
static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
{


+ 58
- 4
src/carla/lv2_rdf.h View File

@@ -20,6 +20,33 @@

#include <cstdint>

#include "lv2/lv2.h"
#include "lv2/atom.h"
#include "lv2/atom-util.h"
#include "lv2/data-access.h"
#include "lv2/event.h"
#include "lv2/event-helpers.h"
#include "lv2/instance-access.h"
#include "lv2/log.h"
#include "lv2/midi.h"
#include "lv2/patch.h"
#include "lv2/port-props.h"
#include "lv2/presets.h"
#include "lv2/state.h"
#include "lv2/time.h"
#include "lv2/ui.h"
#include "lv2/units.h"
#include "lv2/uri-map.h"
#include "lv2/urid.h"
#include "lv2/worker.h"

#include "lv2/lv2dynparam.h"
#include "lv2/lv2-miditype.h"
#include "lv2/lv2-midifunctions.h"
#include "lv2/lv2_external_ui.h"
#include "lv2/lv2_programs.h"
#include "lv2/lv2_rtmempool.h"

// Base Types
typedef float LV2_Data;
typedef const char* LV2_URI;
@@ -147,7 +174,6 @@ struct LV2_RDF_PortScalePoint {
// Port Support Types
#define LV2_PORT_SUPPORTS_MIDI_EVENT 0x1000
#define LV2_PORT_SUPPORTS_PATCH_MESSAGE 0x2000
//#define LV2_PORT_SUPPORTS_TIME 0x4000 // TODO

#define LV2_IS_PORT_INPUT(x) ((x) & LV2_PORT_INPUT)
#define LV2_IS_PORT_OUTPUT(x) ((x) & LV2_PORT_OUTPUT)
@@ -190,9 +216,29 @@ struct LV2_RDF_PortScalePoint {
#define LV2_IS_PORT_TRIGGER(x) ((x) & LV2_PORT_TRIGGER)

// Port Designation
#define LV2_PORT_LATENCY 0x1

#define LV2_IS_PORT_LATENCY(x) ((x) & LV2_PORT_LATENCY)
#define LV2_PORT_LATENCY 0x1
#define LV2_PORT_TIME_BAR 0x2
#define LV2_PORT_TIME_BAR_BEAT 0x3
#define LV2_PORT_TIME_BEAT 0x4
#define LV2_PORT_TIME_BEAT_UNIT 0x5
#define LV2_PORT_TIME_BEATS_PER_BAR 0x6
#define LV2_PORT_TIME_BEATS_PER_MINUTE 0x7
#define LV2_PORT_TIME_FRAMES 0x8
#define LV2_PORT_TIME_FRAMES_PER_SECOND 0x9
#define LV2_PORT_TIME_POSITION 0xA
#define LV2_PORT_TIME_SPEED 0xB

#define LV2_IS_PORT_LATENCY(x) ((x) == LV2_PORT_LATENCY)
#define LV2_IS_PORT_TIME_BAR(x) ((x) == LV2_PORT_TIME_BAR)
#define LV2_IS_PORT_TIME_BAR_BEAT(x) ((x) == LV2_PORT_TIME_BAR_BEAT)
#define LV2_IS_PORT_TIME_BEAT(x) ((x) == LV2_PORT_TIME_BEAT)
#define LV2_IS_PORT_TIME_BEAT_UNIT(x) ((x) == LV2_PORT_TIME_BEAT_UNIT)
#define LV2_IS_PORT_TIME_BEATS_PER_BAR(x) ((x) == LV2_PORT_TIME_BEATS_PER_BAR)
#define LV2_IS_PORT_TIME_BEATS_PER_MINUTE(x) ((x) == LV2_PORT_TIME_BEATS_PER_MINUTE)
#define LV2_IS_PORT_TIME_FRAMES(x) ((x) == LV2_PORT_TIME_FRAMES)
#define LV2_IS_PORT_TIME_FRAMES_PER_SECOND(x) ((x) == LV2_PORT_TIME_FRAMES_PER_SECOND)
#define LV2_IS_PORT_TIME_POSITION(x) ((x) == LV2_PORT_TIME_POSITION)
#define LV2_IS_PORT_TIME_SPEED(x) ((x) == LV2_PORT_TIME_SPEED)

// Port
struct LV2_RDF_Port {
@@ -1724,12 +1770,16 @@ inline bool is_lv2_feature_supported(const char* uri)
return true;
else if (strcmp(uri, LV2_URID__unmap) == 0)
return true;
#ifndef BUILD_BRIDGE_UI
else if (strcmp(uri, LV2_WORKER__schedule) == 0)
return true;
#endif
else if (strcmp(uri, LV2_PROGRAMS__Host) == 0)
return true;
#ifndef BUILD_BRIDGE_UI
else if (strcmp(uri, LV2_RTSAFE_MEMORY_POOL_URI) == 0)
return true;
#endif
else
return false;
}
@@ -1741,10 +1791,12 @@ inline bool is_lv2_ui_feature_supported(const char* uri)
#endif
if (is_lv2_feature_supported(uri))
return true;
#ifndef BUILD_BRIDGE_UI
else if (strcmp(uri, LV2_DATA_ACCESS_URI) == 0)
return true;
else if (strcmp(uri, LV2_INSTANCE_ACCESS_URI) == 0)
return true;
#endif
else if (strcmp(uri, LV2_UI__noUserResize) == 0)
return true;
else if (strcmp(uri, LV2_UI__fixedSize) == 0)
@@ -1761,10 +1813,12 @@ inline bool is_lv2_ui_feature_supported(const char* uri)
return false; // TODO
else if (strcmp(uri, LV2_UI_PREFIX "makeResident") == 0)
return true;
#ifndef BUILD_BRIDGE_UI
else if (strcmp(uri, LV2_EXTERNAL_UI_URI) == 0)
return true;
else if (strcmp(uri, LV2_EXTERNAL_UI_DEPRECATED_URI) == 0)
return true;
#endif
else
return false;
}


Loading…
Cancel
Save