Browse Source

carla-ui-bridges cleanup, will use same base for plugin-bridge

tags/v0.9.0
falkTX 13 years ago
parent
commit
c4489ddbe6
12 changed files with 286 additions and 292 deletions
  1. +2
    -4
      src/carla-backend/vst.cpp
  2. +23
    -10
      src/carla-bridge/carla_bridge.h
  3. +21
    -69
      src/carla-bridge/carla_bridge_osc.cpp
  4. +2
    -0
      src/carla-bridge/carla_bridge_osc.h
  5. +28
    -20
      src/carla-bridge/carla_bridge_ui-gtk2.cpp
  6. +101
    -79
      src/carla-bridge/carla_bridge_ui-lv2.cpp
  7. +35
    -26
      src/carla-bridge/carla_bridge_ui-qt4.cpp
  8. +69
    -79
      src/carla-bridge/carla_bridge_ui-vst.cpp
  9. +1
    -1
      src/carla-bridge/qtcreator/carla-bridge-lv2-gtk2.pro
  10. +1
    -1
      src/carla-bridge/qtcreator/carla-bridge-lv2-qt4.pro
  11. +1
    -1
      src/carla-bridge/qtcreator/carla-bridge-lv2-x11.pro
  12. +2
    -2
      src/carla-bridge/qtcreator/carla-bridge-vst-x11.pro

+ 2
- 4
src/carla-backend/vst.cpp View File

@@ -1270,13 +1270,11 @@ class VstPlugin : public CarlaPlugin


#ifdef VESTIGE_HEADER #ifdef VESTIGE_HEADER
if (effect && effect->ptr1) if (effect && effect->ptr1)
#else
if (effect && effect->resvd1)
#endif
{ {
#ifdef VESTIGE_HEADER
self = (VstPlugin*)effect->ptr1; self = (VstPlugin*)effect->ptr1;
#else #else
if (effect && effect->resvd1)
{
self = (VstPlugin*)get_pointer(effect->resvd1); self = (VstPlugin*)get_pointer(effect->resvd1);
#endif #endif
if (self->unique1 != self->unique2) if (self->unique1 != self->unique2)


src/carla-bridge/carla_bridge_ui.h → src/carla-bridge/carla_bridge.h View File

@@ -1,5 +1,5 @@
/* /*
* Carla UI bridge code
* Carla bridge code
* Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -15,11 +15,14 @@
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
*/ */


#ifndef CARLA_BRIDGE_UI_H
#define CARLA_BRIDGE_UI_H
#ifndef CARLA_BRIDGE_H
#define CARLA_BRIDGE_H


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

#ifdef BUILD_BRIDGE_UI
#include "carla_lib_includes.h" #include "carla_lib_includes.h"
#endif


#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@@ -58,12 +61,11 @@ struct QuequeBridgeMessage {


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


class UiData
class ClientData
{ {
public: public:
UiData(const char* ui_title)
ClientData(const char* ui_title)
{ {
m_lib = nullptr;
m_filename = nullptr; m_filename = nullptr;
m_title = strdup(ui_title); m_title = strdup(ui_title);


@@ -74,9 +76,13 @@ public:
QuequeBridgeMessages[i].value2 = 0; QuequeBridgeMessages[i].value2 = 0;
QuequeBridgeMessages[i].value3 = 0.0; QuequeBridgeMessages[i].value3 = 0.0;
} }

#ifdef BUILD_BRIDGE_UI
m_lib = nullptr;
#endif
} }


virtual ~UiData()
virtual ~ClientData()
{ {
if (m_filename) if (m_filename)
free(m_filename); free(m_filename);
@@ -170,13 +176,16 @@ public:
virtual void note_on(uint8_t note, uint8_t velocity) = 0; virtual void note_on(uint8_t note, uint8_t velocity) = 0;
virtual void note_off(uint8_t note) = 0; virtual void note_off(uint8_t note) = 0;


#ifdef BUILD_BRIDGE_UI
// gui // gui
virtual void* get_widget() const = 0; virtual void* get_widget() const = 0;
virtual bool is_resizable() const = 0; virtual bool is_resizable() const = 0;
virtual bool needs_reparent() const = 0; virtual bool needs_reparent() const = 0;
#endif


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


#ifdef BUILD_BRIDGE_UI
bool lib_open(const char* filename) bool lib_open(const char* filename)
{ {
m_lib = ::lib_open(filename); m_lib = ::lib_open(filename);
@@ -202,19 +211,23 @@ public:
{ {
return ::lib_error(m_filename ? m_filename : ""); return ::lib_error(m_filename ? m_filename : "");
} }
#endif


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


private: private:
void* m_lib;
char* m_filename; char* m_filename;
char* m_title; char* m_title;
QMutex m_lock; QMutex m_lock;
QuequeBridgeMessage QuequeBridgeMessages[MAX_BRIDGE_MESSAGES]; QuequeBridgeMessage QuequeBridgeMessages[MAX_BRIDGE_MESSAGES];

#ifdef BUILD_BRIDGE_UI
void* m_lib;
#endif
}; };


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


extern UiData* ui;
extern ClientData* client;


#endif // CARLA_BRIDGE_UI_H
#endif // CARLA_BRIDGE_H

+ 21
- 69
src/carla-bridge/carla_bridge_osc.cpp View File

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


#include "carla_bridge.h"
#include "carla_bridge_osc.h" #include "carla_bridge_osc.h"
#include "carla_midi.h" #include "carla_midi.h"


#include <QtCore/QString> #include <QtCore/QString>


#ifdef BUILD_BRIDGE_PLUGIN #ifdef BUILD_BRIDGE_PLUGIN
#include "carla_plugin.h"
extern void plugin_bridge_show_gui(bool yesno);
extern void plugin_bridge_quit();
static const size_t client_name_len = 13; static const size_t client_name_len = 13;
static const char* const client_name = "plugin-bridge"; static const char* const client_name = "plugin-bridge";
#define CARLA_PLUGIN CarlaBackend::CarlaPlugins[0]
#else #else
#include "carla_bridge_ui.h"
extern int osc_handle_lv2_event_transfer(lo_arg** argv);
static const size_t client_name_len = 13; static const size_t client_name_len = 13;
static const char* const client_name = "lv2-ui-bridge"; static const char* const client_name = "lv2-ui-bridge";
#endif #endif
@@ -168,8 +163,8 @@ int osc_handle_configure(lo_arg** argv)
const char* key = (const char*)&argv[0]->s; const char* key = (const char*)&argv[0]->s;
const char* value = (const char*)&argv[1]->s; const char* value = (const char*)&argv[1]->s;


if (CARLA_PLUGIN)
CARLA_PLUGIN->set_custom_data(CarlaBackend::CUSTOM_DATA_STRING, key, value, false);
//if (CARLA_PLUGIN)
// CARLA_PLUGIN->set_custom_data(CarlaBackend::CUSTOM_DATA_STRING, key, value, false);
#else #else
Q_UNUSED(argv); Q_UNUSED(argv);
#endif #endif
@@ -182,15 +177,8 @@ int osc_handle_control(lo_arg** argv)
int rindex = argv[0]->i; int rindex = argv[0]->i;
float value = argv[1]->f; float value = argv[1]->f;


qDebug("osc_handle_control(%i, %f)", rindex, value);

#ifdef BUILD_BRIDGE_PLUGIN
if (CARLA_PLUGIN)
CARLA_PLUGIN->set_parameter_value_by_rindex(rindex, value, true, true, false);
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_PARAMETER, rindex, 0, value);
#endif
if (client)
client->queque_message(BRIDGE_MESSAGE_PARAMETER, rindex, 0, value);


return 0; return 0;
} }
@@ -199,16 +187,8 @@ int osc_handle_program(lo_arg** argv)
{ {
int index = argv[0]->i; int index = argv[0]->i;


if (index >= 0)
{
#ifdef BUILD_BRIDGE_PLUGIN
if (CARLA_PLUGIN && index < (int32_t)CARLA_PLUGIN->prog_count())
CARLA_PLUGIN->set_program(index, false, true, true, true);
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_PROGRAM, index, 0, 0.0);
#endif
}
if (client)
client->queque_message(BRIDGE_MESSAGE_PROGRAM, index, 0, 0.0);


return 0; return 0;
} }
@@ -218,16 +198,8 @@ int osc_handle_midi_program(lo_arg** argv)
int bank = argv[0]->i; int bank = argv[0]->i;
int program = argv[1]->i; int program = argv[1]->i;


if (bank >= 0 && program >= 0)
{
#ifdef BUILD_BRIDGE_PLUGIN
if (CARLA_PLUGIN)
CARLA_PLUGIN->set_midi_program_by_id(bank, program, false, true, true, true);
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_MIDI_PROGRAM, bank, program, 0.0);
#endif
}
if (client)
client->queque_message(BRIDGE_MESSAGE_MIDI_PROGRAM, bank, program, 0.0);


return 0; return 0;
} }
@@ -244,25 +216,17 @@ int osc_handle_midi(lo_arg** argv)
if (MIDI_IS_STATUS_NOTE_OFF(status)) if (MIDI_IS_STATUS_NOTE_OFF(status))
{ {
uint8_t note = data[2]; uint8_t note = data[2];
#ifdef BUILD_BRIDGE_PLUGIN
if (CARLA_PLUGIN)
CARLA_PLUGIN->send_midi_note(false, note, 0, false, true, true);
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_NOTE_OFF, note, 0, 0.0);
#endif

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

if (client)
client->queque_message(BRIDGE_MESSAGE_NOTE_ON, note, velo, 0.0);
} }


return 0; return 0;
@@ -270,36 +234,24 @@ int osc_handle_midi(lo_arg** argv)


int osc_handle_show() int osc_handle_show()
{ {
#ifdef BUILD_BRIDGE_PLUGIN
plugin_bridge_show_gui(true);
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_SHOW_GUI, 1, 0, 0.0);
#endif
if (client)
client->queque_message(BRIDGE_MESSAGE_SHOW_GUI, 1, 0, 0.0);


return 0; return 0;
} }


int osc_handle_hide() int osc_handle_hide()
{ {
#ifdef BUILD_BRIDGE_PLUGIN
plugin_bridge_show_gui(false);
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_SHOW_GUI, 0, 0, 0.0);
#endif
if (client)
client->queque_message(BRIDGE_MESSAGE_SHOW_GUI, 0, 0, 0.0);


return 0; return 0;
} }


int osc_handle_quit() int osc_handle_quit()
{ {
#ifdef BUILD_BRIDGE_PLUGIN
plugin_bridge_quit();
#else
if (ui)
ui->queque_message(BRIDGE_MESSAGE_QUIT, 0, 0, 0.0);
#endif
if (client)
client->queque_message(BRIDGE_MESSAGE_QUIT, 0, 0, 0.0);


return 0; return 0;
} }


+ 2
- 0
src/carla-bridge/carla_bridge_osc.h View File

@@ -41,6 +41,8 @@ void osc_send_bridge_midi_program_info(int index, int bank, int program, const c
void osc_send_bridge_update(); void osc_send_bridge_update();
#else #else
// ui-bridge only // ui-bridge only
//int osc_handle_lv2_atom_transfer(lo_arg** argv);
int osc_handle_lv2_event_transfer(lo_arg** argv);
//void osc_send_lv2_atom_transfer(); //void osc_send_lv2_atom_transfer();
void osc_send_lv2_event_transfer(const char* type, const char* key, const char* value); void osc_send_lv2_event_transfer(const char* type, const char* key, const char* value);
#endif #endif


+ 28
- 20
src/carla-bridge/carla_bridge_ui-gtk2.cpp View File

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


#include "carla_bridge.h"
#include "carla_bridge_osc.h" #include "carla_bridge_osc.h"
#include "carla_bridge_ui.h"


#ifdef BRIDGE_LV2_X11 #ifdef BRIDGE_LV2_X11
#error X11 UI uses Qt4 #error X11 UI uses Qt4
@@ -26,7 +26,7 @@
#include <QtCore/QSettings> #include <QtCore/QSettings>


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


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


@@ -34,20 +34,27 @@ gint last_x, last_y, last_width, last_height;


void save_window_settings() 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);
settings.sync();
if (client)
{
settings.setValue(QString("%1/pos_x").arg(client->get_title()), last_x);
settings.setValue(QString("%1/pos_y").arg(client->get_title()), last_y);
settings.setValue(QString("%1/width").arg(client->get_title()), last_width);
settings.setValue(QString("%1/height").arg(client->get_title()), last_height);
settings.sync();
}
} }


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


gboolean gtk_ui_recheck(void*) 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();
if (window)
{
gtk_window_get_position(GTK_WINDOW(window), &last_x, &last_y);
gtk_window_get_size(GTK_WINDOW(window), &last_width, &last_height);
}

return client ? client->run_messages() : false;
} }


void gtk_ui_destroy(GtkWidget*, void*) void gtk_ui_destroy(GtkWidget*, void*)
@@ -67,27 +74,27 @@ void toolkit_init()
void toolkit_loop() void toolkit_loop()
{ {
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)ui->get_widget());
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)client->get_widget());


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


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


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


if (settings.contains(QString("%1/pos_x").arg(ui->get_title())))
if (settings.contains(QString("%1/pos_x").arg(client->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_x = settings.value(QString("%1/pos_x").arg(client->get_title()), last_x).toInt();
last_y = settings.value(QString("%1/pos_y").arg(client->get_title()), last_y).toInt();
gtk_window_move(GTK_WINDOW(window), last_x, last_y); gtk_window_move(GTK_WINDOW(window), last_x, last_y);


if (ui->is_resizable())
if (client->is_resizable())
{ {
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();
last_width = settings.value(QString("%1/width").arg(client->get_title()), last_width).toInt();
last_height = settings.value(QString("%1/height").arg(client->get_title()), last_height).toInt();
gtk_window_resize(GTK_WINDOW(window), last_width, last_height); gtk_window_resize(GTK_WINDOW(window), last_width, last_height);
} }
} }
@@ -100,9 +107,10 @@ void toolkit_loop()


void toolkit_quit() void toolkit_quit()
{ {
save_window_settings();

if (window) if (window)
{ {
save_window_settings();
gtk_widget_destroy(window); gtk_widget_destroy(window);
gtk_main_quit(); gtk_main_quit();
} }


+ 101
- 79
src/carla-bridge/carla_bridge_ui-lv2.cpp View File

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


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


#include "lv2_rdf.h" #include "lv2_rdf.h"
@@ -26,7 +26,7 @@
#include <QtGui/QDialog> #include <QtGui/QDialog>
#endif #endif


UiData* ui = nullptr;
ClientData* client = nullptr;


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


@@ -62,10 +62,10 @@ const uint32_t CARLA_URI_MAP_ID_COUNT = 12;


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


class Lv2UiData : public UiData
class Lv2UiData : public ClientData
{ {
public: public:
Lv2UiData(const char* ui_title) : UiData(ui_title)
Lv2UiData(const char* ui_title) : ClientData(ui_title)
{ {
handle = nullptr; handle = nullptr;
widget = nullptr; widget = nullptr;
@@ -89,7 +89,9 @@ public:
for (uint32_t i=0; i < lv2_feature_count+1; i++) for (uint32_t i=0; i < lv2_feature_count+1; i++)
features[i] = nullptr; features[i] = nullptr;


// Initialize features
// -----------------------------------------------------------------
// initialize features

LV2_Event_Feature* Event_Feature = new LV2_Event_Feature; LV2_Event_Feature* Event_Feature = new LV2_Event_Feature;
Event_Feature->callback_data = this; Event_Feature->callback_data = this;
Event_Feature->lv2_event_ref = carla_lv2_event_ref; Event_Feature->lv2_event_ref = carla_lv2_event_ref;
@@ -222,86 +224,95 @@ public:


bool init(const char* plugin_uri, const char* ui_uri) bool init(const char* plugin_uri, const char* ui_uri)
{ {
// -----------------------------------------------------------------
// get plugin from lv2_rdf (lilv)

Lv2World.init(); Lv2World.init();
rdf_descriptor = lv2_rdf_new(plugin_uri); rdf_descriptor = lv2_rdf_new(plugin_uri);


if (rdf_descriptor)
if (! rdf_descriptor)
return false;

// -----------------------------------------------------------------
// find requested UI

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

if (! rdf_ui_descriptor)
return false;

// -----------------------------------------------------------------
// open DLL

if (! lib_open(rdf_ui_descriptor->Binary))
return false;

// -----------------------------------------------------------------
// get DLL main entry

LV2UI_DescriptorFunction ui_descfn = (LV2UI_DescriptorFunction)lib_symbol("lv2ui_descriptor");

if (! ui_descfn)
return false;

// -----------------------------------------------------------
// get descriptor that matches URI

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

if (! descriptor)
return false;

// -----------------------------------------------------------
// initialize UI

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

if (! handle)
return false;

// -----------------------------------------------------------
// check if not resizable


if (rdf_ui_descriptor && lib_open(rdf_ui_descriptor->Binary))
#ifndef BRIDGE_LV2_X11
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)
{ {
LV2UI_DescriptorFunction ui_descfn = (LV2UI_DescriptorFunction)lib_symbol("lv2ui_descriptor");
m_resizable = false;
break;
}
}
#endif

// -----------------------------------------------------------
// check for programs extension


if (ui_descfn)
if (descriptor->extension_data)
{
for (uint32_t i=0; i < rdf_ui_descriptor->ExtensionCount; i++)
{
if (strcmp(rdf_ui_descriptor->Extensions[i], LV2_PROGRAMS__UIInterface) == 0)
{ {
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)
{
// Check if not resizable
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)
{
m_resizable = false;
break;
}
}

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

return true;
}
else
qCritical("Lv2UiData::init(%s, %s) - ui failed no initiliaze", plugin_uri, ui_uri);
}
else
qCritical("Lv2UiData::init(%s, %s) - ui descriptor mismatch", plugin_uri, ui_uri);
programs = (LV2_Programs_UI_Interface*)descriptor->extension_data(LV2_PROGRAMS__UIInterface);
break;
} }
else
qCritical("Lv2UiData::init(%s, %s) - Failed to find ui entry point", plugin_uri, ui_uri);
} }
else
qCritical("Lv2UiData::init(%s, %s) - Failed to find ui", plugin_uri, ui_uri);
} }
else
qCritical("Lv2UiData::init(%s, %s) - Failed to find plugin", plugin_uri, ui_uri);


return false;
return true;
} }


void close() void close()
@@ -447,7 +458,10 @@ public:
return nullptr; return nullptr;
} }


// TODO - finish lv2-features and import here from main backend code

// ----------------- Event Feature --------------------------------------------------- // ----------------- Event Feature ---------------------------------------------------

static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event) 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); qDebug("carla_lv2_event_ref(%p, %p)", callback_data, event);
@@ -461,6 +475,7 @@ public:
} }


// ----------------- Logs Feature ---------------------------------------------------- // ----------------- Logs Feature ----------------------------------------------------

static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap) 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); qDebug("carla_lv2_log_vprintf(%p, %i, %s, ...)", handle, type, fmt);
@@ -505,6 +520,7 @@ public:
} }


// ----------------- Programs Feature ------------------------------------------------ // ----------------- Programs Feature ------------------------------------------------

static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index) static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
{ {
qDebug("Lv2Plugin::carla_lv2_program_changed(%p, %i)", handle, index); qDebug("Lv2Plugin::carla_lv2_program_changed(%p, %i)", handle, index);
@@ -514,6 +530,7 @@ public:
} }


// ----------------- State Feature --------------------------------------------------- // ----------------- State Feature ---------------------------------------------------

static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path) 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); qDebug("carla_lv2_state_make_path(%p, %p)", handle, path);
@@ -533,6 +550,7 @@ public:
} }


// ----------------- URI-Map Feature --------------------------------------- // ----------------- URI-Map Feature ---------------------------------------

static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri) 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); qDebug("carla_lv2_uri_to_id(%p, %s, %s)", data, map, uri);
@@ -540,6 +558,7 @@ public:
} }


// ----------------- URID Feature ------------------------------------------ // ----------------- URID Feature ------------------------------------------

static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri) static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
{ {
qDebug("carla_lv2_urid_map(%p, %s)", handle, uri); qDebug("carla_lv2_urid_map(%p, %s)", handle, uri);
@@ -625,6 +644,7 @@ public:
} }


// ----------------- UI Port-Map Feature --------------------------------------------- // ----------------- UI Port-Map Feature ---------------------------------------------

static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol) static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
{ {
qDebug("Lv2Plugin::carla_lv2_ui_port_map(%p, %s)", handle, symbol); qDebug("Lv2Plugin::carla_lv2_ui_port_map(%p, %s)", handle, symbol);
@@ -644,6 +664,7 @@ public:
} }


// ----------------- UI Resize Feature ------------------------------------- // ----------------- UI Resize Feature -------------------------------------

static int carla_lv2_ui_resize(LV2UI_Feature_Handle data, int width, int height) 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); qDebug("carla_lv2_ui_resized(%p, %i, %i)", data, width, height);
@@ -659,6 +680,7 @@ public:
} }


// ----------------- UI Extension ------------------------------------------ // ----------------- 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) 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); qDebug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
@@ -729,7 +751,7 @@ int osc_handle_lv2_event_transfer(lo_arg** argv)
const char* type = (const char*)&argv[0]->s; const char* type = (const char*)&argv[0]->s;
const char* key = (const char*)&argv[1]->s; const char* key = (const char*)&argv[1]->s;
const char* value = (const char*)&argv[2]->s; const char* value = (const char*)&argv[2]->s;
((Lv2UiData*)ui)->handle_event_transfer(type, key, value);
((Lv2UiData*)client)->handle_event_transfer(type, key, value);
return 0; return 0;
} }


@@ -738,8 +760,8 @@ int main(int argc, char* argv[])
#if 1 #if 1
if (argc != 5) if (argc != 5)
{ {
qCritical("%s: bad arguments", argv[0]);
return 1;
qCritical("%s: bad arguments", argv[0]);
return 1;
} }


const char* osc_url = argv[1]; const char* osc_url = argv[1];
@@ -757,7 +779,7 @@ int main(int argc, char* argv[])
toolkit_init(); toolkit_init();


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


// Init OSC // Init OSC
osc_init(osc_url); osc_init(osc_url);
@@ -765,7 +787,7 @@ int main(int argc, char* argv[])
// Load UI // Load UI
int ret; int ret;


if (ui->init(plugin_uri, ui_uri))
if (client->init(plugin_uri, ui_uri))
{ {
toolkit_loop(); toolkit_loop();
ret = 0; ret = 0;
@@ -781,14 +803,14 @@ int main(int argc, char* argv[])
osc_close(); osc_close();


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


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


delete ui;
ui = nullptr;
delete client;
client = nullptr;


return ret; return ret;
} }

+ 35
- 26
src/carla-bridge/carla_bridge_ui-qt4.cpp View File

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


#include "carla_bridge.h"
#include "carla_bridge_osc.h" #include "carla_bridge_osc.h"
#include "carla_bridge_ui.h"


#include <QtCore/QSettings> #include <QtCore/QSettings>
#include <QtCore/QTimer> #include <QtCore/QTimer>
@@ -26,7 +26,11 @@
#include <QtGui/QVBoxLayout> #include <QtGui/QVBoxLayout>


static QDialog* window = nullptr; static QDialog* window = nullptr;
static QSettings settings("Cadence", "Carla-UIs");
#ifdef BRIDGE_LV2_X11
static QSettings settings("Cadence", "Carla-X11UIs");
#else
static QSettings settings("Cadence", "Carla-Qt4UIs");
#endif


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


@@ -40,8 +44,8 @@ public:


void timerEvent(QTimerEvent*) void timerEvent(QTimerEvent*)
{ {
if (ui)
ui->run_messages();
if (client)
client->run_messages();
} }
}; };


@@ -56,9 +60,9 @@ void toolkit_init()


void toolkit_loop() void toolkit_loop()
{ {
if (ui->needs_reparent())
if (client->needs_reparent())
{ {
window = (QDialog*)ui->get_widget();
window = (QDialog*)client->get_widget();
window->resize(10, 10); window->resize(10, 10);
} }
else else
@@ -67,7 +71,7 @@ void toolkit_loop()
window->resize(10, 10); window->resize(10, 10);
window->setLayout(new QVBoxLayout(window)); window->setLayout(new QVBoxLayout(window));


QWidget* widget = (QWidget*)ui->get_widget();
QWidget* widget = (QWidget*)client->get_widget();
window->layout()->addWidget(widget); window->layout()->addWidget(widget);
window->layout()->setContentsMargins(0, 0, 0, 0); window->layout()->setContentsMargins(0, 0, 0, 0);
window->adjustSize(); window->adjustSize();
@@ -79,21 +83,21 @@ void toolkit_loop()
checker.start(50); checker.start(50);
QObject::connect(window, SIGNAL(finished(int)), app, SLOT(quit())); QObject::connect(window, SIGNAL(finished(int)), app, SLOT(quit()));


if (! ui->is_resizable())
if (! client->is_resizable())
window->setFixedSize(window->width(), window->height()); window->setFixedSize(window->width(), window->height());


window->setWindowTitle(ui->get_title());
window->setWindowTitle(client->get_title());


if (settings.contains(QString("%1/pos_x").arg(ui->get_title())))
if (settings.contains(QString("%1/pos_x").arg(client->get_title())))
{ {
int pos_x = settings.value(QString("%1/pos_x").arg(ui->get_title()), window->x()).toInt();
int pos_y = settings.value(QString("%1/pos_y").arg(ui->get_title()), window->y()).toInt();
int pos_x = settings.value(QString("%1/pos_x").arg(client->get_title()), window->x()).toInt();
int pos_y = settings.value(QString("%1/pos_y").arg(client->get_title()), window->y()).toInt();
window->move(pos_x, pos_y); window->move(pos_x, pos_y);


if (ui->is_resizable())
if (client->is_resizable())
{ {
int width = settings.value(QString("%1/width").arg(ui->get_title()), window->width()).toInt();
int height = settings.value(QString("%1/height").arg(ui->get_title()), window->height()).toInt();
int width = settings.value(QString("%1/width").arg(client->get_title()), window->width()).toInt();
int height = settings.value(QString("%1/height").arg(client->get_title()), window->height()).toInt();
window->resize(width, height); window->resize(width, height);
} }
} }
@@ -108,24 +112,29 @@ void toolkit_quit()
{ {
if (window) if (window)
{ {
settings.setValue(QString("%1/pos_x").arg(ui->get_title()), window->x());
settings.setValue(QString("%1/pos_y").arg(ui->get_title()), window->y());
settings.setValue(QString("%1/width").arg(ui->get_title()), window->width());
settings.setValue(QString("%1/height").arg(ui->get_title()), window->height());
settings.sync();
if (client)
{
settings.setValue(QString("%1/pos_x").arg(client->get_title()), window->x());
settings.setValue(QString("%1/pos_y").arg(client->get_title()), window->y());
settings.setValue(QString("%1/width").arg(client->get_title()), window->width());
settings.setValue(QString("%1/height").arg(client->get_title()), window->height());
settings.sync();
}


window->close(); window->close();

delete window; delete window;
window = nullptr;
} }


if (app) if (app)
{ {
app->quit();
if (! app->closingDown())
app->quit();

delete app; delete app;
app = nullptr;
} }

app = nullptr;
window = nullptr;
} }


void toolkit_window_show() void toolkit_window_show()
@@ -142,9 +151,9 @@ void toolkit_window_hide()


void toolkit_window_resize(int width, int height) void toolkit_window_resize(int width, int height)
{ {
if (window)
if (client && window)
{ {
if (ui->is_resizable())
if (client->is_resizable())
window->resize(width, height); window->resize(width, height);
else else
window->setFixedSize(width, height); window->setFixedSize(width, height);


+ 69
- 79
src/carla-bridge/carla_bridge_ui-vst.cpp View File

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


#include "carla_vst_includes.h"

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


#include "carla_vst_includes.h"

#include <QtGui/QDialog> #include <QtGui/QDialog>


UiData* ui = nullptr;
ClientData* client = nullptr;


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


#define FAKE_SAMPLE_RATE 44100.0 #define FAKE_SAMPLE_RATE 44100.0
#define FAKE_BUFFER_SIZE 512 #define FAKE_BUFFER_SIZE 512


class VstUiData : public UiData
class VstUiData : public ClientData
{ {
public: public:
VstUiData(const char* ui_title) : UiData(ui_title)
VstUiData(const char* ui_title) : ClientData(ui_title)
{ {
effect = nullptr; effect = nullptr;
widget = new QDialog; widget = new QDialog;

// make UI valid
unique1 = unique2 = random();
} }


~VstUiData() ~VstUiData()
{ {
// UI is no longer valid
unique1 = 0;
unique2 = 1;
} }


// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@@ -54,48 +48,63 @@ public:


bool init(const char* binary, const char*) bool init(const char* binary, const char*)
{ {
if (lib_open(binary))
// -----------------------------------------------------------------
// open DLL

if ( !lib_open(binary))
return false;

// -----------------------------------------------------------------
// get DLL main entry

VST_Function vstfn = (VST_Function)lib_symbol("VSTPluginMain");

if (! vstfn)
{ {
VST_Function vstfn = (VST_Function)lib_symbol("VSTPluginMain");
vstfn = (VST_Function)lib_symbol("main");


if (! vstfn) if (! vstfn)
vstfn = (VST_Function)lib_symbol("main");
return false;
}


if (vstfn)
{
effect = vstfn(VstHostCallback);
// -----------------------------------------------------------------
// initialize plugin


if (effect && effect->magic == kEffectMagic)
{
effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
effect = vstfn(VstHostCallback);

if (! effect || effect->magic != kEffectMagic)
return false;

// -----------------------------------------------------------------
// initialize VST stuff

effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
#if ! VST_FORCE_DEPRECATED #if ! VST_FORCE_DEPRECATED
effect->dispatcher(effect, effSetBlockSizeAndSampleRate, 0, FAKE_BUFFER_SIZE, nullptr, FAKE_SAMPLE_RATE);
effect->dispatcher(effect, effSetBlockSizeAndSampleRate, 0, FAKE_BUFFER_SIZE, nullptr, FAKE_SAMPLE_RATE);
#endif #endif
effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, FAKE_SAMPLE_RATE);
effect->dispatcher(effect, effSetBlockSize, 0, FAKE_BUFFER_SIZE, nullptr, 0.0f);
effect->dispatcher(effect, effEditOpen, 0, 0, (void*)widget->winId(), 0.0f);
effect->user = this;

#ifndef ERect
struct ERect {
short top;
short left;
short bottom;
short right;
};
effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, FAKE_SAMPLE_RATE);
effect->dispatcher(effect, effSetBlockSize, 0, FAKE_BUFFER_SIZE, nullptr, 0.0f);
effect->dispatcher(effect, effEditOpen, 0, 0, (void*)widget->winId(), 0.0f);

#ifdef VESTIGE_HEADER
effect->ptr1 = this;
#else
effect->resvd1 = (intptr_t)this;
#endif #endif
ERect* vst_rect;

if (effect->dispatcher(effect, effEditGetRect, 0, 0, &vst_rect, 0.0f))
{
int width = vst_rect->right - vst_rect->left;
int height = vst_rect->bottom - vst_rect->top;
widget->setFixedSize(width, height);
return true;
}
}
}

// -----------------------------------------------------------------
// initialize gui stuff

ERect* vstRect;

if (effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0.0f))
{
int width = vstRect->right - vstRect->left;
int height = vstRect->bottom - vstRect->top;
widget->setFixedSize(width, height);
return true;
} }

return false; return false;
} }


@@ -147,20 +156,6 @@ public:


static intptr_t VstHostCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) static intptr_t VstHostCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
{ {
#if DEBUG
qDebug("VstHostCallback() - code: %s, index: %i, value: " P_INTPTR ", opt: %f", VstOpcode2str(opcode), index, value, opt);
#endif

// Check if 'user' points to this UI
VstUiData* self = nullptr;

if (effect && effect->user)
{
self = (VstUiData*)effect->user;
if (self->unique1 != self->unique2)
self = nullptr;
}

switch (opcode) switch (opcode)
{ {
case audioMasterAutomate: case audioMasterAutomate:
@@ -179,20 +174,17 @@ public:
break; break;


case audioMasterGetTime: case audioMasterGetTime:
{
static VstTimeInfo timeInfo;
memset(&timeInfo, 0, sizeof(VstTimeInfo));
timeInfo.sampleRate = 44100;
static VstTimeInfo_R timeInfo;
memset(&timeInfo, 0, sizeof(VstTimeInfo_R));
timeInfo.sampleRate = FAKE_SAMPLE_RATE;
return (intptr_t)&timeInfo; return (intptr_t)&timeInfo;
}


case audioMasterProcessEvents: case audioMasterProcessEvents:
if (self && ptr)
if (client && ptr)
{ {
int32_t i;
const VstEvents* const events = (VstEvents*)ptr; const VstEvents* const events = (VstEvents*)ptr;


for (i=0; i < events->numEvents; i++)
for (int32_t i=0; i < events->numEvents; i++)
{ {
const VstMidiEvent* const midi_event = (VstMidiEvent*)events->events[i]; const VstMidiEvent* const midi_event = (VstMidiEvent*)events->events[i];


@@ -218,8 +210,8 @@ public:
#endif #endif


case audioMasterSizeWindow: case audioMasterSizeWindow:
if (self)
self->queque_message(BRIDGE_MESSAGE_RESIZE_GUI, index, value, 0.0f);
if (client)
client->queque_message(BRIDGE_MESSAGE_RESIZE_GUI, index, value, 0.0f);
return 1; return 1;


case audioMasterGetSampleRate: case audioMasterGetSampleRate:
@@ -290,7 +282,7 @@ public:
return kVstLangEnglish; return kVstLangEnglish;


case audioMasterUpdateDisplay: case audioMasterUpdateDisplay:
osc_send_configure("reloadprograms", "");
//osc_send_configure("reloadprograms", "");
break; break;


default: default:
@@ -304,18 +296,16 @@ public:
} }


private: private:
long unique1;
AEffect* effect; AEffect* effect;
QDialog* widget; QDialog* widget;
long unique2;
}; };


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


const char* osc_url = argv[1]; const char* osc_url = argv[1];
@@ -326,7 +316,7 @@ int main(int argc, char* argv[])
toolkit_init(); toolkit_init();


// Init VST-UI // Init VST-UI
ui = new VstUiData(ui_title);
client = new VstUiData(ui_title);


// Init OSC // Init OSC
osc_init(osc_url); osc_init(osc_url);
@@ -334,7 +324,7 @@ int main(int argc, char* argv[])
// Load UI // Load UI
int ret; int ret;


if (ui->init(binary, nullptr))
if (client->init(binary, nullptr))
{ {
toolkit_loop(); toolkit_loop();
ret = 0; ret = 0;
@@ -350,14 +340,14 @@ int main(int argc, char* argv[])
osc_close(); osc_close();


// Close VST-UI // Close VST-UI
ui->close();
client->close();


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


delete ui;
ui = nullptr;
delete client;
client = nullptr;


return ret; return ret;
} }

+ 1
- 1
src/carla-bridge/qtcreator/carla-bridge-lv2-gtk2.pro View File

@@ -15,8 +15,8 @@ SOURCES = \
../carla_bridge_ui-gtk2.cpp ../carla_bridge_ui-gtk2.cpp


HEADERS = \ HEADERS = \
../carla_bridge.h \
../carla_bridge_osc.h \ ../carla_bridge_osc.h \
../carla_bridge_ui.h \
../../carla-backend/carla_midi.h \ ../../carla-backend/carla_midi.h \
../../carla-includes/carla_includes.h \ ../../carla-includes/carla_includes.h \
../../carla-includes/carla_lib_includes.h \ ../../carla-includes/carla_lib_includes.h \


+ 1
- 1
src/carla-bridge/qtcreator/carla-bridge-lv2-qt4.pro View File

@@ -15,8 +15,8 @@ SOURCES = \
../carla_bridge_ui-qt4.cpp ../carla_bridge_ui-qt4.cpp


HEADERS = \ HEADERS = \
../carla_bridge.h \
../carla_bridge_osc.h \ ../carla_bridge_osc.h \
../carla_bridge_ui.h \
../../carla-backend/carla_midi.h \ ../../carla-backend/carla_midi.h \
../../carla-includes/carla_includes.h \ ../../carla-includes/carla_includes.h \
../../carla-includes/carla_lib_includes.h \ ../../carla-includes/carla_lib_includes.h \


+ 1
- 1
src/carla-bridge/qtcreator/carla-bridge-lv2-x11.pro View File

@@ -15,8 +15,8 @@ SOURCES = \
../carla_bridge_ui-qt4.cpp ../carla_bridge_ui-qt4.cpp


HEADERS = \ HEADERS = \
../carla_bridge.h \
../carla_bridge_osc.h \ ../carla_bridge_osc.h \
../carla_bridge_ui.h \
../../carla-backend/carla_midi.h \ ../../carla-backend/carla_midi.h \
../../carla-includes/carla_includes.h \ ../../carla-includes/carla_includes.h \
../../carla-includes/carla_lib_includes.h \ ../../carla-includes/carla_lib_includes.h \


+ 2
- 2
src/carla-bridge/qtcreator/carla-bridge-vst-x11.pro View File

@@ -11,12 +11,12 @@ VERSION = 0.5.0


SOURCES = \ SOURCES = \
../carla_bridge_osc.cpp \ ../carla_bridge_osc.cpp \
../carla_bridge_ui-lv2.cpp \
../carla_bridge_ui-vst.cpp \
../carla_bridge_ui-qt4.cpp ../carla_bridge_ui-qt4.cpp


HEADERS = \ HEADERS = \
../carla_bridge.h \
../carla_bridge_osc.h \ ../carla_bridge_osc.h \
../carla_bridge_ui.h \
../../carla-backend/carla_midi.h \ ../../carla-backend/carla_midi.h \
../../carla-includes/carla_includes.h \ ../../carla-includes/carla_includes.h \
../../carla-includes/carla_lib_includes.h \ ../../carla-includes/carla_lib_includes.h \


Loading…
Cancel
Save