@@ -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 |