@@ -0,0 +1,39 @@ | |||
#!/usr/bin/make -f | |||
# Makefile for Carla-Bridge # | |||
# ----------------------------------------- # | |||
# Created by falkTX | |||
# | |||
CXX ?= g++ | |||
WINECXX ?= wineg++ | |||
BASE_FLAGS = -DBUILD_BRIDGE -DBUILD_BRIDGE_UI -Wall -std=c++0x -I. ../carla-bridge -I../carla-includes -I../carla $(CXXFLAGS) | |||
BASE_FLAGS += `pkg-config --cflags --libs liblo QtCore` -ldl -lpthread $(LDFLAGS) | |||
#BASE_FLAGS += -DNDEBUG -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse | |||
BASE_FLAGS += -DDEBUG -O0 -g | |||
BASE_FLAGS += -DVESTIGE_HEADER -I../carla-includes/vestige # Comment this line to not use vestige header | |||
BRIDGE_LV2_X11_FLAGS = $(BASE_FLAGS) -DBRIDGE_LV2_X11 `pkg-config --cflags --libs QtGui` | |||
BRIDGE_LV2_GTK2_FLAGS = $(BASE_FLAGS) -DBRIDGE_LV2_GTK2 `pkg-config --cflags --libs gtk+-2.0` | |||
BRIDGE_LV2_QT4_FLAGS = $(BASE_FLAGS) -DBRIDGE_LV2_QT4 `pkg-config --cflags --libs QtGui` | |||
BRIDGE_VST_QT4_FLAGS = $(BASE_FLAGS) -DBRIDGE_VST_QT4 `pkg-config --cflags --libs QtGui` | |||
all: carla-bridge-lv2-gtk2 | |||
#carla-bridge-lv2-x11 carla-bridge-lv2-qt4 | |||
#carla-bridge-vst-qt4 | |||
# carla-bridge-lv2-x11: carla_bridge_lv2.cpp carla-bridge-x11.cpp osc.cpp carla-bridge.h bridge-includes.h osc.h | |||
# $(CXX) carla-bridge-lv2.cpp carla-bridge-x11.cpp osc.cpp $(BRIDGE_LV2_X11_FLAGS) -o $@ | |||
carla-bridge-lv2-gtk2: carla_bridge_lv2.cpp carla_bridge_gtk2.cpp ../carla-bridge/carla_osc.cpp | |||
$(CXX) carla_bridge_lv2.cpp carla_bridge_gtk2.cpp ../carla-bridge/carla_osc.cpp $(BRIDGE_LV2_GTK2_FLAGS) -o $@ | |||
# carla-bridge-lv2-qt4: carla-bridge-lv2.cpp carla-bridge-qt4.cpp osc.cpp carla-bridge.h bridge-includes.h osc.h | |||
# $(CXX) carla-bridge-lv2.cpp carla-bridge-qt4.cpp osc.cpp $(BRIDGE_LV2_QT4_FLAGS) -o $@ | |||
# carla-bridge-vst-qt4: carla-bridge-vst.cpp carla-bridge-qt4.cpp osc.cpp carla-bridge.h bridge-includes.h osc.h | |||
# $(CXX) carla-bridge-vst.cpp carla-bridge-qt4.cpp osc.cpp $(BRIDGE_VST_QT4_FLAGS) -o $@ | |||
clean: | |||
rm -f carla-bridge-* |
@@ -0,0 +1,93 @@ | |||
/* | |||
* Carla UI bridge code | |||
* Copyright (C) 2011-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 | |||
*/ | |||
#include "carla_bridge_ui.h" | |||
#include "../carla-bridge/carla_osc.h" | |||
#include <gtk/gtk.h> | |||
static GtkWidget* window; | |||
// ------------------------------------------------------------------------- | |||
gboolean gtk_ui_recheck(void*) | |||
{ | |||
return ui->run_messages(); | |||
} | |||
void gtk_ui_destroy(GtkWidget*, void*) | |||
{ | |||
window = nullptr; | |||
gtk_main_quit(); | |||
} | |||
// ------------------------------------------------------------------------- | |||
void toolkit_init() | |||
{ | |||
int argc = 0; | |||
char** argv = nullptr; | |||
gtk_init(&argc, &argv); | |||
} | |||
void toolkit_loop(const char* plugin_name, bool reparent) | |||
{ | |||
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(); | |||
} | |||
g_timeout_add(50, gtk_ui_recheck, 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), plugin_name); | |||
osc_send_update(); | |||
// Main loop | |||
gtk_main(); | |||
} | |||
void toolkit_quit() | |||
{ | |||
if (window) | |||
{ | |||
gtk_widget_destroy(window); | |||
gtk_main_quit(); | |||
} | |||
} | |||
void toolkit_window_show() | |||
{ | |||
gtk_widget_show_all(window); | |||
} | |||
void toolkit_window_hide() | |||
{ | |||
gtk_widget_hide_all(window); | |||
} | |||
void toolkit_window_resize(int width, int height) | |||
{ | |||
gtk_window_resize(GTK_WINDOW(window), width, height); | |||
} |
@@ -0,0 +1,353 @@ | |||
/* | |||
* Carla UI bridge code | |||
* Copyright (C) 2011-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 | |||
*/ | |||
#include "carla_bridge_ui.h" | |||
#include "../carla-bridge/carla_osc.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> | |||
// ------------------------------------------------------------------------- | |||
// 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_parent = 4; | |||
const uint32_t lv2_feature_id_ui_resize = 5; | |||
const uint32_t lv2_feature_count = 6; | |||
// 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); | |||
} | |||
} | |||
} | |||
// ------------------------------------------------------------------------- | |||
class Lv2UiData : public UiData | |||
{ | |||
public: | |||
Lv2UiData() : UiData() | |||
{ | |||
handle = nullptr; | |||
widget = nullptr; | |||
descriptor = nullptr; | |||
#ifdef BRIDGE_LV2_X11 | |||
x11_widget = new QDialog(); | |||
#endif | |||
// Initialize features | |||
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; | |||
LV2_URID_Map* URID_Map_Feature = new LV2_URID_Map; | |||
URID_Map_Feature->handle = this; | |||
URID_Map_Feature->map = carla_lv2_urid_map; | |||
LV2_URID_Unmap* URID_Unmap_Feature = new LV2_URID_Unmap; | |||
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_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_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_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_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_ui_parent] = new LV2_Feature; | |||
features[lv2_feature_id_ui_parent]->URI = LV2_UI__parent; | |||
features[lv2_feature_id_ui_parent]->data = nullptr; | |||
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_count] = nullptr; | |||
resizable = true; | |||
} | |||
~Lv2UiData() | |||
{ | |||
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_Resize*)features[lv2_feature_id_ui_resize]->data; | |||
for (uint32_t i=0; i < lv2_feature_count; i++) | |||
{ | |||
if (features[i]) | |||
delete features[i]; | |||
} | |||
#ifdef WANT_X11 | |||
//delete x11_widget; | |||
#endif | |||
} | |||
virtual bool init(const char* plugin_uri, const char* ui_uri, const char* ui_bundle, bool resizable_) | |||
{ | |||
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, | |||
ui_bundle, | |||
carla_lv2_ui_write_function, | |||
this, | |||
&widget, | |||
features); | |||
resizable = resizable_; | |||
return bool(handle); | |||
} | |||
} | |||
return false; | |||
} | |||
virtual void close() | |||
{ | |||
if (handle && descriptor && descriptor->cleanup) | |||
descriptor->cleanup(handle); | |||
} | |||
virtual void update_parameter(int index, double value) | |||
{ | |||
if (descriptor && descriptor->port_event) | |||
{ | |||
float fvalue = value; | |||
descriptor->port_event(handle, index, sizeof(float), 0, &fvalue); | |||
} | |||
} | |||
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) {} | |||
virtual void* get_widget() | |||
{ | |||
#ifdef BRIDGE_LV2_X11 | |||
return x11_widget; | |||
#else | |||
return widget; | |||
#endif | |||
} | |||
virtual bool is_resizable() | |||
{ | |||
return resizable; | |||
} | |||
private: | |||
LV2UI_Handle handle; | |||
LV2UI_Widget widget; | |||
const LV2UI_Descriptor* descriptor; | |||
LV2_Feature* features[lv2_feature_count+1]; | |||
bool resizable; | |||
#ifdef BRIDGE_LV2_X11 | |||
LV2UI_Widget x11_widget; | |||
#endif | |||
}; | |||
int main(int argc, char* argv[]) | |||
{ | |||
if (argc != 8) | |||
{ | |||
//std::cerr << argv[0] << " :: bad arguments" << std::endl; | |||
return 1; | |||
} | |||
const char* plugin_uri = argv[1]; | |||
const char* plugin_name = argv[2]; | |||
const char* ui_uri = argv[3]; | |||
const char* ui_binary = argv[4]; | |||
const char* ui_bundle = argv[5]; | |||
const char* osc_url = argv[6]; | |||
const char* resizable = argv[7]; | |||
// Init LV2 | |||
ui = new Lv2UiData; | |||
// Init toolkit | |||
toolkit_init(); | |||
// Init OSC | |||
osc_init("osc_name", "osc_url"); | |||
if (ui->lib_open(ui_binary)) | |||
{ | |||
if (ui->init(plugin_uri, ui_uri, ui_bundle, (strcmp(resizable, "true") == 0)) == false) | |||
{ | |||
qCritical("Failed to load LV2 UI"); | |||
ui->lib_close(); | |||
osc_close(); | |||
return 1; | |||
} | |||
} | |||
else | |||
{ | |||
qCritical("Failed to load UI, error was:\n%s", ui->lib_error()); | |||
osc_close(); | |||
return 1; | |||
} | |||
toolkit_loop(plugin_name, | |||
#ifdef BRIDGE_LV2_X11 | |||
false); | |||
#else | |||
true); | |||
#endif | |||
ui->close(); | |||
ui->lib_close(); | |||
osc_send_exiting(); | |||
osc_close(); | |||
toolkit_quit(); | |||
delete ui; | |||
ui = nullptr; | |||
return 0; | |||
} |
@@ -0,0 +1,227 @@ | |||
/* | |||
* Carla UI bridge code | |||
* Copyright (C) 2011-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_BRIDGE_UI_H | |||
#define CARLA_BRIDGE_UI_H | |||
#include "carla_includes.h" | |||
#include <pthread.h> | |||
void toolkit_init(); | |||
void toolkit_loop(const char* plugin_name, bool reparent); | |||
void toolkit_quit(); | |||
void toolkit_window_show(); | |||
void toolkit_window_hide(); | |||
void toolkit_window_resize(int width, int height); | |||
// ------------------------------------------------------------------------- | |||
const unsigned int MAX_BRIDGE_MESSAGES = 256; | |||
enum BridgeMessageType { | |||
BRIDGE_MESSAGE_NULL = 0, | |||
BRIDGE_MESSAGE_PARAMETER = 1, // index, 0, value | |||
BRIDGE_MESSAGE_PROGRAM = 2, // index, 0, 0 | |||
BRIDGE_MESSAGE_MIDI_PROGRAM = 3, // bank, program, 0 | |||
BRIDGE_MESSAGE_NOTE_ON = 4, // note, velocity, 0 | |||
BRIDGE_MESSAGE_NOTE_OFF = 5, // note, 0, 0 | |||
BRIDGE_MESSAGE_SHOW_GUI = 6, // show, 0, 0 | |||
BRIDGE_MESSAGE_RESIZE_GUI = 7, // width, height, 0 | |||
BRIDGE_MESSAGE_QUIT = 8 | |||
}; | |||
struct QuequeBridgeMessage { | |||
bool valid; | |||
BridgeMessageType type; | |||
int value1; | |||
int value2; | |||
double value3; | |||
}; | |||
// ------------------------------------------------------------------------- | |||
class UiData | |||
{ | |||
public: | |||
UiData() | |||
{ | |||
m_lib = nullptr; | |||
pthread_mutex_init(&m_lock, nullptr); | |||
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; | |||
QuequeBridgeMessages[i].value3 = 0.0; | |||
} | |||
} | |||
~UiData() | |||
{ | |||
pthread_mutex_destroy(&m_lock); | |||
} | |||
void queque_message(BridgeMessageType type, int value1, int value2, double value3) | |||
{ | |||
pthread_mutex_lock(&m_lock); | |||
for (unsigned int i=0; i<MAX_BRIDGE_MESSAGES; i++) | |||
{ | |||
if (QuequeBridgeMessages[i].valid == false) | |||
{ | |||
QuequeBridgeMessages[i].valid = true; | |||
QuequeBridgeMessages[i].type = type; | |||
QuequeBridgeMessages[i].value1 = value1; | |||
QuequeBridgeMessages[i].value2 = value2; | |||
QuequeBridgeMessages[i].value3 = value3; | |||
break; | |||
} | |||
} | |||
pthread_mutex_unlock(&m_lock); | |||
} | |||
bool run_messages() | |||
{ | |||
pthread_mutex_lock(&m_lock); | |||
for (unsigned int i=0; i < MAX_BRIDGE_MESSAGES; i++) | |||
{ | |||
if (QuequeBridgeMessages[i].valid) | |||
{ | |||
QuequeBridgeMessage* m = &QuequeBridgeMessages[i]; | |||
switch (m->type) | |||
{ | |||
case BRIDGE_MESSAGE_NULL: | |||
break; | |||
case BRIDGE_MESSAGE_PARAMETER: | |||
update_parameter(m->value1, m->value3); | |||
break; | |||
case BRIDGE_MESSAGE_PROGRAM: | |||
update_program(m->value1); | |||
break; | |||
case BRIDGE_MESSAGE_MIDI_PROGRAM: | |||
update_midi_program(m->value1, m->value2); | |||
break; | |||
case BRIDGE_MESSAGE_NOTE_ON: | |||
send_note_on(m->value1, m->value2); | |||
break; | |||
case BRIDGE_MESSAGE_NOTE_OFF: | |||
send_note_off(m->value1); | |||
break; | |||
case BRIDGE_MESSAGE_SHOW_GUI: | |||
if (m->value1) | |||
toolkit_window_show(); | |||
else | |||
toolkit_window_hide(); | |||
break; | |||
case BRIDGE_MESSAGE_RESIZE_GUI: | |||
toolkit_window_resize(m->value1, m->value2); | |||
break; | |||
case BRIDGE_MESSAGE_QUIT: | |||
toolkit_quit(); | |||
pthread_mutex_unlock(&m_lock); | |||
return false; | |||
default: | |||
break; | |||
} | |||
m->valid = false; | |||
} | |||
else | |||
break; | |||
} | |||
pthread_mutex_unlock(&m_lock); | |||
return true; | |||
} | |||
virtual bool init(const char*, const char*, const char*, bool) = 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; | |||
virtual void* get_widget() = 0; | |||
virtual bool is_resizable() = 0; | |||
bool lib_open(const char* filename) | |||
{ | |||
#ifdef Q_OS_WIN | |||
m_lib = LoadLibraryA(filename); | |||
#else | |||
m_lib = dlopen(filename, RTLD_NOW); | |||
#endif | |||
return bool(m_lib); | |||
} | |||
bool lib_close() | |||
{ | |||
if (m_lib) | |||
#ifdef Q_OS_WIN | |||
return FreeLibrary((HMODULE)m_lib) != 0; | |||
#else | |||
return dlclose(m_lib) != 0; | |||
#endif | |||
else | |||
return false; | |||
} | |||
void* lib_symbol(const char* symbol) | |||
{ | |||
if (m_lib) | |||
#ifdef Q_OS_WIN | |||
return (void*)GetProcAddress((HMODULE)m_lib, symbol); | |||
#else | |||
return dlsym(m_lib, symbol); | |||
#endif | |||
else | |||
return nullptr; | |||
} | |||
const char* lib_error() | |||
{ | |||
#ifdef Q_OS_WIN | |||
static char libError[2048]; | |||
memset(libError, 0, sizeof(char)*2048); | |||
LPVOID winErrorString; | |||
DWORD winErrorCode = GetLastError(); | |||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr); | |||
snprintf(libError, 2048, "%s: error code %i: %s", m_filename, winErrorCode, (const char*)winErrorString); | |||
LocalFree(winErrorString); | |||
return libError; | |||
#else | |||
return dlerror(); | |||
#endif | |||
} | |||
private: | |||
void* m_lib; | |||
pthread_mutex_t m_lock; | |||
QuequeBridgeMessage QuequeBridgeMessages[MAX_BRIDGE_MESSAGES]; | |||
}; | |||
// ------------------------------------------------------------------------- | |||
static UiData* ui = nullptr; | |||
#endif // CARLA_BRIDGE_UI_H |
@@ -0,0 +1,31 @@ | |||
# QtCreator project file | |||
CONFIG = warn_on qt release | |||
TEMPLATE = app | |||
VERSION = 0.5 | |||
TARGET = carla-bridge-lv2-gtk2 | |||
SOURCES = \ | |||
../carla_bridge_lv2.cpp \ | |||
../carla_bridge_gtk2.cpp \ | |||
../../carla-bridge/carla_osc.cpp | |||
HEADERS = \ | |||
../carla_bridge_ui.h \ | |||
../../carla-bridge/carla_osc.h \ | |||
../../carla-includes/carla_includes.h | |||
INCLUDEPATH = .. \ | |||
../../carla-bridge \ | |||
../../carla-includes | |||
LIBS += -ldl -lpthread -llo | |||
DEFINES = BUILD_BRIDGE BUILD_BRIDGE_UI | |||
unix { | |||
CONFIG += link_pkgconfig | |||
PKGCONFIG += gtk+-2.0 | |||
} |
@@ -0,0 +1,93 @@ | |||
/* | |||
* JACK Backend code for Carla | |||
* Copyright (C) 2011-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_INCLUDES_H | |||
#define CARLA_INCLUDES_H | |||
#ifdef __WINE__ | |||
#define __socklen_t_defined | |||
#define __WINE_WINSOCK2__ | |||
#define HRESULT LONG | |||
#define Q_CORE_EXPORT | |||
#define Q_GUI_EXPORT | |||
#define QT_NO_STL | |||
//#define _WIN32_X11_ | |||
#endif | |||
#include <stdint.h> | |||
#include <Qt> | |||
#if defined (__GXX_EXPERIMENTAL_CXX0X__) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
// nullptr is available | |||
#else | |||
#define nullptr (0) | |||
#endif | |||
#ifdef Q_OS_WIN | |||
# include <windows.h> | |||
# define carla_sleep(t) Sleep(t * 1000) | |||
# define carla_msleep(t) Sleep(t) | |||
# define carla_usleep(t) Sleep(t / 1000) | |||
#else | |||
# include <dlfcn.h> | |||
# include <unistd.h> | |||
# define carla_sleep(t) sleep(t) | |||
# define carla_msleep(t) usleep(t * 1000) | |||
# define carla_usleep(t) usleep(t) | |||
# ifndef __cdecl | |||
# define __cdecl | |||
# endif | |||
#endif | |||
// needed for qDebug/Warning/Critical sections | |||
#if __WORDSIZE == 64 | |||
# define P_INTPTR "%li" | |||
# define P_SIZE "%lu" | |||
#else | |||
# define P_INTPTR "%i" | |||
# define P_SIZE "%u" | |||
#endif | |||
// set native binary type | |||
#if defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) | |||
# if __LP64__ | |||
# define BINARY_NATIVE BINARY_UNIX64 | |||
# else | |||
# define BINARY_NATIVE BINARY_UNIX32 | |||
# endif | |||
#elif defined(Q_OS_WIN) | |||
# ifdef Q_OS_WIN64 | |||
# define BINARY_NATIVE BINARY_WIN64 | |||
# else | |||
# define BINARY_NATIVE BINARY_WIN32 | |||
# endif | |||
#else | |||
# error Invalid build type | |||
#endif | |||
// export symbols if needed | |||
#ifdef BUILD_BRIDGE | |||
# define CARLA_EXPORT | |||
#else | |||
# if defined(Q_OS_WIN) && !defined(__WINE__) | |||
# define CARLA_EXPORT extern "C" __declspec (dllexport) | |||
# else | |||
# define CARLA_EXPORT extern "C" __attribute__ ((visibility("default"))) | |||
# endif | |||
#endif | |||
#endif // CARLA_INCLUDES_H |