@@ -18,16 +18,12 @@ | |||
#include "carla_bridge_client.hpp" | |||
#include "carla_bridge_toolkit.hpp" | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
# include "carla_engine.hpp" | |||
#else | |||
#ifdef BUILD_BRIDGE_UI | |||
# include "carla_lib_utils.hpp" | |||
#endif | |||
#include <cmath> | |||
#include <cstdio> | |||
#include <cstdint> | |||
#include <cstdlib> | |||
#include <cstring> | |||
CARLA_BRIDGE_START_NAMESPACE | |||
@@ -46,8 +42,6 @@ CarlaBridgeClient::CarlaBridgeClient(const char* const uiTitle) | |||
m_uiLib = nullptr; | |||
m_uiQuit = false; | |||
#endif | |||
m_toolkit->init(); | |||
} | |||
CarlaBridgeClient::~CarlaBridgeClient() | |||
@@ -58,6 +52,8 @@ CarlaBridgeClient::~CarlaBridgeClient() | |||
if (m_uiFilename) | |||
free(m_uiFilename); | |||
#endif | |||
delete m_toolkit; | |||
} | |||
#ifdef BUILD_BRIDGE_UI | |||
@@ -68,7 +64,17 @@ bool CarlaBridgeClient::init(const char* const, const char* const) | |||
{ | |||
qDebug("CarlaBridgeClient::init()"); | |||
// Test for single init | |||
{ | |||
static bool initiated = false; | |||
CARLA_ASSERT(! initiated); | |||
initiated = true; | |||
} | |||
m_uiQuit = false; | |||
m_toolkit->init(); | |||
return false; | |||
} | |||
@@ -95,7 +101,7 @@ bool CarlaBridgeClient::oscInit(const char* const url) | |||
{ | |||
qDebug("CarlaBridgeClient::oscInit(\"%s\")", url); | |||
bool ret = m_osc.init(url); | |||
const bool ret = m_osc.init(url); | |||
m_oscData = m_osc.getControlData(); | |||
return ret; | |||
@@ -103,7 +109,7 @@ bool CarlaBridgeClient::oscInit(const char* const url) | |||
bool CarlaBridgeClient::oscIdle() | |||
{ | |||
m_osc .idle(); | |||
m_osc.idle(); | |||
#ifdef BUILD_BRIDGE_UI | |||
return ! m_uiQuit; | |||
@@ -136,6 +142,15 @@ void CarlaBridgeClient::sendOscUpdate() | |||
} | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
void CarlaBridgeClient::registerOscEngine(CarlaBackend::CarlaEngine* const engine) | |||
{ | |||
qDebug("CarlaBridgeClient::registerOscEngine(%p)", engine); | |||
CARLA_ASSERT(engine); | |||
if (engine) | |||
engine->setOscBridgeData(m_oscData); | |||
} | |||
void CarlaBridgeClient::sendOscBridgeError(const char* const error) | |||
{ | |||
qDebug("CarlaBridgeClient::sendOscBridgeError(\"%s\")", error); | |||
@@ -145,12 +160,6 @@ void CarlaBridgeClient::sendOscBridgeError(const char* const error) | |||
if (m_oscData && m_oscData->target) | |||
osc_send_bridge_error(m_oscData, error); | |||
} | |||
void CarlaBridgeClient::registerOscEngine(CarlaBackend::CarlaEngine* const engine) | |||
{ | |||
qDebug("CarlaBridgeClient::registerOscEngine(%p)", engine); | |||
engine->setOscBridgeData(m_oscData); | |||
} | |||
#endif | |||
// --------------------------------------------------------------------- | |||
@@ -250,18 +259,6 @@ void CarlaBridgeClient::sendOscExiting() | |||
osc_send_exiting(m_oscData); | |||
} | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
void CarlaBridgeClient::sendOscBridgeUpdate() | |||
{ | |||
qDebug("CarlaBridgeClient::sendOscBridgeUpdate()"); | |||
CARLA_ASSERT(m_oscData); | |||
CARLA_ASSERT(m_oscData->target && m_osc.m_serverPath); | |||
if (m_oscData && m_oscData->target && m_osc.m_serverPath) | |||
osc_send_bridge_update(m_oscData, m_osc.m_serverPath); | |||
} | |||
#endif | |||
#ifdef BRIDGE_LV2 | |||
void CarlaBridgeClient::sendOscLv2TransferAtom(const int32_t portIndex, const char* const typeStr, const char* const atomBuf) | |||
{ | |||
@@ -282,6 +279,18 @@ void CarlaBridgeClient::sendOscLv2TransferEvent(const int32_t portIndex, const c | |||
} | |||
#endif | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
void CarlaBridgeClient::sendOscBridgeUpdate() | |||
{ | |||
qDebug("CarlaBridgeClient::sendOscBridgeUpdate()"); | |||
CARLA_ASSERT(m_oscData); | |||
CARLA_ASSERT(m_oscData->target && m_osc.m_serverPath); | |||
if (m_oscData && m_oscData->target && m_osc.m_serverPath) | |||
osc_send_bridge_update(m_oscData, m_osc.m_serverPath); | |||
} | |||
#endif | |||
// --------------------------------------------------------------------- | |||
#ifdef BUILD_BRIDGE_UI | |||
@@ -292,6 +301,7 @@ void* CarlaBridgeClient::getContainerId() | |||
bool CarlaBridgeClient::uiLibOpen(const char* const filename) | |||
{ | |||
CARLA_ASSERT(! m_uiLib); | |||
CARLA_ASSERT(filename); | |||
if (m_uiFilename) | |||
@@ -305,6 +315,8 @@ bool CarlaBridgeClient::uiLibOpen(const char* const filename) | |||
bool CarlaBridgeClient::uiLibClose() | |||
{ | |||
CARLA_ASSERT(m_uiLib); | |||
if (m_uiLib) | |||
{ | |||
const bool closed = lib_close(m_uiLib); | |||
@@ -317,6 +329,8 @@ bool CarlaBridgeClient::uiLibClose() | |||
void* CarlaBridgeClient::uiLibSymbol(const char* const symbol) | |||
{ | |||
CARLA_ASSERT(m_uiLib); | |||
if (m_uiLib) | |||
return lib_symbol(m_uiLib, symbol); | |||
@@ -20,8 +20,6 @@ | |||
#include "carla_bridge_osc.hpp" | |||
#include <QtCore/QMutex> | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
namespace CarlaBackend { | |||
class CarlaEngine; | |||
@@ -98,8 +96,8 @@ public: | |||
void sendOscUpdate(); | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
void sendOscBridgeError(const char* const error); | |||
void registerOscEngine(CarlaBackend::CarlaEngine* const engine); | |||
void sendOscBridgeError(const char* const error); | |||
#endif | |||
// --------------------------------------------------------------------- | |||
@@ -121,15 +119,15 @@ protected: | |||
void sendOscMidi(const uint8_t midiBuf[4]); | |||
void sendOscExiting(); | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
void sendOscBridgeUpdate(); | |||
#endif | |||
#ifdef BRIDGE_LV2 | |||
void sendOscLv2TransferAtom(const int32_t portIndex, const char* const typeStr, const char* const atomBuf); | |||
void sendOscLv2TransferEvent(const int32_t portIndex, const char* const typeStr, const char* const atomBuf); | |||
#endif | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
void sendOscBridgeUpdate(); | |||
#endif | |||
// --------------------------------------------------------------------- | |||
#ifdef BUILD_BRIDGE_UI | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Bridge OSC | |||
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.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 | |||
@@ -234,6 +234,16 @@ int CarlaBridgeOsc::handleMessage(const char* const path, const int argc, const | |||
return handleMsgLv2TransferEvent(argc, argv, types); | |||
#endif | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
// Plugin methods | |||
if (strcmp(method, "plugin_save_now") == 0) | |||
return handleMsgPluginSaveNow(); | |||
if (strcmp(method, "plugin_set_chunk") == 0) | |||
return handleMsgPluginSetChunk(argc, argv, types); | |||
if (strcmp(method, "plugin_set_custom_data") == 0) | |||
return handleMsgPluginSetCustomData(argc, argv, types); | |||
#endif | |||
#if 0 | |||
// TODO | |||
else if (strcmp(method, "set_parameter_midi_channel") == 0) | |||
@@ -254,36 +264,11 @@ int CarlaBridgeOsc::handleMsgConfigure(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
if (! client) | |||
return 1; | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
const char* const key = (const char*)&argv[0]->s; | |||
const char* const value = (const char*)&argv[1]->s; | |||
// nothing here for now | |||
if (strcmp(key, CarlaBackend::CARLA_BRIDGE_MSG_SAVE_NOW) == 0) | |||
{ | |||
client->saveNow(); | |||
} | |||
else if (strcmp(key, CarlaBackend::CARLA_BRIDGE_MSG_SET_CHUNK) == 0) | |||
{ | |||
client->setChunkData(value); | |||
} | |||
else if (strcmp(key, CarlaBackend::CARLA_BRIDGE_MSG_SET_CUSTOM) == 0) | |||
{ | |||
QStringList vList = QString(value).split("·", QString::KeepEmptyParts); | |||
if (vList.size() == 3) | |||
{ | |||
const char* const cType = vList.at(0).toUtf8().constData(); | |||
const char* const cKey = vList.at(1).toUtf8().constData(); | |||
const char* const cValue = vList.at(2).toUtf8().constData(); | |||
return 0; | |||
client->setCustomData(cType, cKey, cValue); | |||
} | |||
} | |||
#else | |||
Q_UNUSED(argv); | |||
#endif | |||
return 0; | |||
} | |||
int CarlaBridgeOsc::handleMsgControl(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
@@ -296,6 +281,7 @@ int CarlaBridgeOsc::handleMsgControl(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
const int32_t index = argv[0]->i; | |||
const float value = argv[1]->f; | |||
client->setParameter(index, value); | |||
return 0; | |||
@@ -310,34 +296,44 @@ int CarlaBridgeOsc::handleMsgProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
return 1; | |||
const int32_t index = argv[0]->i; | |||
client->setProgram(index); | |||
return 0; | |||
} | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
int CarlaBridgeOsc::handleMsgMidiProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
{ | |||
qDebug("CarlaBridgeOsc::handleMsgMidiProgram()"); | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(1, "i"); | |||
#else | |||
CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii"); | |||
#endif | |||
if (! client) | |||
return 1; | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
const int32_t index = argv[0]->i; | |||
client->setMidiProgram(index); | |||
return 0; | |||
} | |||
#else | |||
int CarlaBridgeOsc::handleMsgMidiProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
{ | |||
qDebug("CarlaBridgeOsc::handleMsgMidiProgram()"); | |||
CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii"); | |||
if (! client) | |||
return 1; | |||
const int32_t bank = argv[0]->i; | |||
const int32_t program = argv[1]->i; | |||
client->setMidiProgram(bank, program); | |||
#endif | |||
return 0; | |||
} | |||
#endif | |||
int CarlaBridgeOsc::handleMsgMidi(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
{ | |||
@@ -359,13 +355,15 @@ int CarlaBridgeOsc::handleMsgMidi(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||
if (MIDI_IS_STATUS_NOTE_OFF(status)) | |||
{ | |||
uint8_t note = data[2]; | |||
const uint8_t note = data[2]; | |||
client->noteOff(channel, note); | |||
} | |||
else if (MIDI_IS_STATUS_NOTE_ON(status)) | |||
{ | |||
uint8_t note = data[2]; | |||
uint8_t velo = data[3]; | |||
const uint8_t note = data[2]; | |||
const uint8_t velo = data[3]; | |||
client->noteOn(channel, note, velo); | |||
} | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Bridge OSC | |||
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.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 | |||
@@ -110,6 +110,12 @@ private: | |||
int handleMsgLv2TransferEvent(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||
#endif | |||
#ifdef BUILD_BRIDGE_PLUGIN | |||
int handleMsgPluginSaveNow(); | |||
int handleMsgPluginSetChunk(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||
int handleMsgPluginSetCustomData(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||
#endif | |||
// ------------------------------------------------------------------- | |||
static void osc_error_handler(const int num, const char* const msg, const char* const path) | |||
@@ -53,13 +53,18 @@ public: | |||
window = nullptr; | |||
lastX = lastY = 0; | |||
lastWidth = lastHeight = 0; | |||
lastX = 0; | |||
lastY = 0; | |||
lastWidth = 0; | |||
lastHeight = 0; | |||
} | |||
~CarlaToolkitGtk() | |||
{ | |||
qDebug("CarlaToolkitGtk::~CarlaToolkitGtk()"); | |||
if (window) | |||
gtk_widget_destroy(window); | |||
} | |||
void init() | |||
@@ -68,44 +73,61 @@ public: | |||
CARLA_ASSERT(! window); | |||
gtk_init(&gargc, &gargv); | |||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |||
gtk_window_resize(GTK_WINDOW(window), 30, 30); | |||
gtk_widget_hide(window); | |||
} | |||
void exec(const bool showGui) | |||
{ | |||
qDebug("CarlaToolkitGtk::exec(%s)", bool2str(showGui)); | |||
CARLA_ASSERT(window); | |||
CARLA_ASSERT(client); | |||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |||
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)client->getWidget()); | |||
GtkWidget* const widget = (GtkWidget*)client->getWidget(); | |||
gtk_container_add(GTK_CONTAINER(window), widget); | |||
gtk_window_set_resizable(GTK_WINDOW(window), client->isResizable()); | |||
gtk_window_set_title(GTK_WINDOW(window), uiTitle); | |||
gtk_window_get_position(GTK_WINDOW(window), &lastX, &lastY); | |||
gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | |||
if (settings.contains(QString("%1/pos_x").arg(uiTitle))) | |||
{ | |||
lastX = settings.value(QString("%1/pos_x").arg(uiTitle), lastX).toInt(); | |||
lastY = settings.value(QString("%1/pos_y").arg(uiTitle), lastY).toInt(); | |||
gtk_window_move(GTK_WINDOW(window), lastX, lastY); | |||
gtk_window_get_position(GTK_WINDOW(window), &lastX, &lastY); | |||
bool hasX, hasY; | |||
lastX = settings.value(QString("%1/pos_x").arg(uiTitle), lastX).toInt(&hasX); | |||
lastY = settings.value(QString("%1/pos_y").arg(uiTitle), lastY).toInt(&hasY); | |||
if (hasX && hasY) | |||
gtk_window_move(GTK_WINDOW(window), lastX, lastY); | |||
if (client->isResizable()) | |||
{ | |||
lastWidth = settings.value(QString("%1/width").arg(uiTitle), lastWidth).toInt(); | |||
lastHeight = settings.value(QString("%1/height").arg(uiTitle), lastHeight).toInt(); | |||
gtk_window_resize(GTK_WINDOW(window), lastWidth, lastHeight); | |||
gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | |||
bool hasWidth, hasHeight; | |||
lastWidth = settings.value(QString("%1/width").arg(uiTitle), lastWidth).toInt(&hasWidth); | |||
lastHeight = settings.value(QString("%1/height").arg(uiTitle), lastHeight).toInt(&hasHeight); | |||
if (hasWidth && hasHeight) | |||
gtk_window_resize(GTK_WINDOW(window), lastWidth, lastHeight); | |||
} | |||
} | |||
g_timeout_add(50, gtk_ui_timeout, this); | |||
g_signal_connect(window, "destroy", G_CALLBACK(gtk_ui_destroy), this); | |||
if (showGui) | |||
show(); | |||
else | |||
client->sendOscUpdate(); | |||
// Timer | |||
g_timeout_add(50, gtk_ui_timeout, this); | |||
g_signal_connect(window, "destroy", G_CALLBACK(gtk_ui_destroy), this); | |||
// First idle | |||
handleTimeout(); | |||
// Main loop | |||
gtk_main(); | |||
} | |||
@@ -159,6 +181,11 @@ public: | |||
// --------------------------------------------------------------------- | |||
protected: | |||
GtkWidget* window; | |||
QSettings settings; | |||
gint lastX, lastY, lastWidth, lastHeight; | |||
void handleDestroy() | |||
{ | |||
qDebug("CarlaToolkitGtk::handleDestroy()"); | |||
@@ -180,30 +207,31 @@ protected: | |||
gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | |||
} | |||
// FIXME | |||
// FIXME? | |||
return client->isOscControlRegistered() ? client->oscIdle() : false; | |||
} | |||
// --------------------------------------------------------------------- | |||
private: | |||
GtkWidget* window; | |||
QSettings settings; | |||
gint lastX, lastY, lastWidth, lastHeight; | |||
static void gtk_ui_destroy(GtkWidget*, gpointer data) | |||
{ | |||
CarlaToolkitGtk* const _this_ = (CarlaToolkitGtk*)data; | |||
_this_->handleDestroy(); | |||
CARLA_ASSERT(data); | |||
if (CarlaToolkitGtk* const _this_ = (CarlaToolkitGtk*)data) | |||
_this_->handleDestroy(); | |||
gtk_main_quit(); | |||
} | |||
static gboolean gtk_ui_timeout(gpointer data) | |||
{ | |||
CarlaToolkitGtk* const _this_ = (CarlaToolkitGtk*)data; | |||
return _this_->handleTimeout(); | |||
CARLA_ASSERT(data); | |||
if (CarlaToolkitGtk* const _this_ = (CarlaToolkitGtk*)data) | |||
return _this_->handleTimeout(); | |||
return false; | |||
} | |||
}; | |||
@@ -184,6 +184,9 @@ public: | |||
// Timer | |||
msgTimer = startTimer(50); | |||
// First idle | |||
handleTimeout(); | |||
// Main loop | |||
app->exec(); | |||
} | |||
@@ -201,14 +204,11 @@ public: | |||
if (window) | |||
{ | |||
if (client) | |||
{ | |||
settings.setValue(QString("%1/pos_x").arg(uiTitle), window->x()); | |||
settings.setValue(QString("%1/pos_y").arg(uiTitle), window->y()); | |||
settings.setValue(QString("%1/width").arg(uiTitle), window->width()); | |||
settings.setValue(QString("%1/height").arg(uiTitle), window->height()); | |||
settings.sync(); | |||
} | |||
settings.setValue(QString("%1/pos_x").arg(uiTitle), window->x()); | |||
settings.setValue(QString("%1/pos_y").arg(uiTitle), window->y()); | |||
settings.setValue(QString("%1/width").arg(uiTitle), window->width()); | |||
settings.setValue(QString("%1/height").arg(uiTitle), window->height()); | |||
settings.sync(); | |||
window->close(); | |||
@@ -300,22 +300,29 @@ protected: | |||
QEmbedContainer* embedContainer; | |||
#endif | |||
void timerEvent(QTimerEvent* const event) | |||
void handleTimeout() | |||
{ | |||
if (event->timerId() == msgTimer && client) | |||
if (! client) | |||
return; | |||
if (needsResize) | |||
{ | |||
if (needsResize) | |||
{ | |||
client->toolkitResize(nextWidth, nextHeight); | |||
needsResize = false; | |||
} | |||
client->toolkitResize(nextWidth, nextHeight); | |||
needsResize = false; | |||
} | |||
if (client->isOscControlRegistered() && ! client->oscIdle()) | |||
{ | |||
killTimer(msgTimer); | |||
msgTimer = 0; | |||
} | |||
if (client->isOscControlRegistered() && ! client->oscIdle()) | |||
{ | |||
killTimer(msgTimer); | |||
msgTimer = 0; | |||
} | |||
} | |||
private: | |||
void timerEvent(QTimerEvent* const event) | |||
{ | |||
if (event->timerId() == msgTimer) | |||
handleTimeout(); | |||
QObject::timerEvent(event); | |||
} | |||
@@ -26,7 +26,7 @@ CARLA_BRIDGE_START_NAMESPACE | |||
CarlaBridgeToolkit::CarlaBridgeToolkit(CarlaBridgeClient* const client_, const char* const newTitle) | |||
: client(client_) | |||
{ | |||
qDebug("CarlaBridgeToolkit::CarlaBridgeToolkit(\"%s\")", newTitle); | |||
qDebug("CarlaBridgeToolkit::CarlaBridgeToolkit(%p, \"%s\")", client, newTitle); | |||
CARLA_ASSERT(client); | |||
CARLA_ASSERT(newTitle); | |||
@@ -618,7 +618,8 @@ public: | |||
void handleProgramChanged(int32_t /*index*/) | |||
{ | |||
sendOscConfigure("reloadprograms", ""); | |||
if (isOscControlRegistered()) | |||
sendOscConfigure("reloadprograms", ""); | |||
} | |||
uint32_t handleUiPortMap(const char* const symbol) | |||
@@ -651,10 +652,9 @@ public: | |||
return 0; | |||
} | |||
void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer) | |||
{ | |||
if (! buffer) | |||
if (! (buffer && isOscControlRegistered())) | |||
return; | |||
if (format == 0) | |||
@@ -35,6 +35,11 @@ struct CarlaOscData { | |||
source(nullptr), | |||
target(nullptr) {} | |||
~CarlaOscData() | |||
{ | |||
free(); | |||
} | |||
void free() | |||
{ | |||
if (path) | |||
@@ -300,6 +305,7 @@ void osc_send_bridge_error(const CarlaOscData* const oscData, const char* const | |||
} | |||
#endif | |||
#if defined(BRIDGE_LV2) || defined(WANT_LV2) | |||
static inline | |||
void osc_send_lv2_transfer_atom(const CarlaOscData* const oscData, const int32_t portIndex, const char* const typeStr, const char* const atomBuf) | |||
{ | |||
@@ -335,6 +341,7 @@ void osc_send_lv2_transfer_event(const CarlaOscData* const oscData, const int32_ | |||
lo_send(oscData->target, targetPath, "iss", portIndex, typeStr, atomBuf); | |||
} | |||
} | |||
#endif | |||
// ------------------------------------------------------------------------------------------------ | |||