(needed later for plugin bridges)tags/v0.9.0
| @@ -20,50 +20,11 @@ | |||||
| #include "carla_includes.h" | #include "carla_includes.h" | ||||
| #include <cstdint> | |||||
| #define CARLA_BRIDGE_START_NAMESPACE namespace CarlaBridge { | #define CARLA_BRIDGE_START_NAMESPACE namespace CarlaBridge { | ||||
| #define CARLA_BRIDGE_END_NAMESPACE } | #define CARLA_BRIDGE_END_NAMESPACE } | ||||
| CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
| /*! | |||||
| * @defgroup CarlaBridgeAPI Carla Bridge API | |||||
| * | |||||
| * The Carla Bridge API | |||||
| * @{ | |||||
| */ | |||||
| #define MAX_BRIDGE_MESSAGES 256 //!< Maximum number of messages per client | |||||
| enum MessageType { | |||||
| MESSAGE_NULL = 0, | |||||
| MESSAGE_PARAMETER, // index, 0, value | |||||
| MESSAGE_PROGRAM, // index, 0, 0 | |||||
| MESSAGE_MIDI_PROGRAM, // index, 0, 0 | bank, program, 0 | |||||
| MESSAGE_NOTE_ON, // note, velocity, 0 | |||||
| MESSAGE_NOTE_OFF, // note, 0, 0 | |||||
| MESSAGE_SHOW_GUI, // show, 0, 0 | |||||
| MESSAGE_RESIZE_GUI, // width, height, 0 | |||||
| MESSAGE_SAVE_NOW, | |||||
| MESSAGE_QUIT | |||||
| }; | |||||
| struct Message { | |||||
| MessageType type; | |||||
| int32_t value1; | |||||
| int32_t value2; | |||||
| double value3; | |||||
| Message() | |||||
| : type(MESSAGE_NULL), | |||||
| value1(0), | |||||
| value2(0), | |||||
| value3(0.0) {} | |||||
| }; | |||||
| /**@}*/ | |||||
| class CarlaClient; | class CarlaClient; | ||||
| class CarlaToolkit; | class CarlaToolkit; | ||||
| @@ -56,7 +56,9 @@ public: | |||||
| #ifdef BUILD_BRIDGE_UI | #ifdef BUILD_BRIDGE_UI | ||||
| m_filename = nullptr; | m_filename = nullptr; | ||||
| m_lib = nullptr; | m_lib = nullptr; | ||||
| m_quit = false; | |||||
| #endif | #endif | ||||
| m_toolkit->m_client = this; | |||||
| } | } | ||||
| virtual ~CarlaClient() | virtual ~CarlaClient() | ||||
| @@ -69,6 +71,7 @@ public: | |||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| #if 0 | |||||
| void quequeMessage(const MessageType type, const int32_t value1, const int32_t value2, const double value3) | void quequeMessage(const MessageType type, const int32_t value1, const int32_t value2, const double value3) | ||||
| { | { | ||||
| const QMutexLocker locker(&m_messages.lock); | const QMutexLocker locker(&m_messages.lock); | ||||
| @@ -152,13 +155,26 @@ public: | |||||
| return true; | return true; | ||||
| } | } | ||||
| #endif | |||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| #ifdef BUILD_BRIDGE_UI | #ifdef BUILD_BRIDGE_UI | ||||
| // ui initialization | // ui initialization | ||||
| virtual bool init(const char* const, const char* const) = 0; | |||||
| virtual void close() = 0; | |||||
| virtual bool init(const char* const, const char* const) | |||||
| { | |||||
| m_quit = false; | |||||
| return false; | |||||
| } | |||||
| virtual void close() | |||||
| { | |||||
| if (! m_quit) | |||||
| { | |||||
| m_quit = true; | |||||
| sendOscExiting(); | |||||
| } | |||||
| } | |||||
| // ui management | // ui management | ||||
| virtual void* getWidget() const = 0; | virtual void* getWidget() const = 0; | ||||
| @@ -193,12 +209,55 @@ public: | |||||
| return m_osc.init(url); | return m_osc.init(url); | ||||
| } | } | ||||
| bool oscIdle() | |||||
| { | |||||
| if (m_osc.m_server) | |||||
| while (lo_server_recv_noblock(m_osc.m_server, 0) != 0) {} | |||||
| return ! m_quit; | |||||
| } | |||||
| void oscClose() | void oscClose() | ||||
| { | { | ||||
| qDebug("CarlaClient::oscClose()"); | qDebug("CarlaClient::oscClose()"); | ||||
| m_osc.close(); | m_osc.close(); | ||||
| } | } | ||||
| void sendOscUpdate() | |||||
| { | |||||
| qDebug("CarlaClient::sendOscUpdate()"); | |||||
| CARLA_ASSERT(m_osc.m_controlData.target); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_update(&m_osc.m_controlData, m_osc.m_serverPath); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| void toolkitShow() | |||||
| { | |||||
| m_toolkit->show(); | |||||
| } | |||||
| void toolkitHide() | |||||
| { | |||||
| m_toolkit->hide(); | |||||
| } | |||||
| void toolkitResize(int width, int height) | |||||
| { | |||||
| m_toolkit->resize(width, height); | |||||
| } | |||||
| void toolkitQuit() | |||||
| { | |||||
| m_quit = true; | |||||
| m_toolkit->quit(); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| protected: | |||||
| #ifdef BUILD_BRIDGE_PLUGIN | #ifdef BUILD_BRIDGE_PLUGIN | ||||
| void registerOscEngine(CarlaBackend::CarlaEngine* const engine) | void registerOscEngine(CarlaBackend::CarlaEngine* const engine) | ||||
| { | { | ||||
| @@ -210,56 +269,69 @@ public: | |||||
| void sendOscConfigure(const char* const key, const char* const value) | void sendOscConfigure(const char* const key, const char* const value) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscConfigure(\"%s\", \"%s\")", key, value); | qDebug("CarlaClient::sendOscConfigure(\"%s\", \"%s\")", key, value); | ||||
| m_osc.sendOscConfigure(key, value); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_configure(&m_osc.m_controlData, key, value); | |||||
| } | } | ||||
| void sendOscControl(const int32_t index, const float value) | void sendOscControl(const int32_t index, const float value) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscControl(%i, %f)", index, value); | qDebug("CarlaClient::sendOscControl(%i, %f)", index, value); | ||||
| m_osc.sendOscControl(index, value); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_control(&m_osc.m_controlData, index, value); | |||||
| } | } | ||||
| void sendOscProgram(const int32_t index) | void sendOscProgram(const int32_t index) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscProgram(%i)", index); | qDebug("CarlaClient::sendOscProgram(%i)", index); | ||||
| m_osc.sendOscProgram(index); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_program(&m_osc.m_controlData, index); | |||||
| } | } | ||||
| void sendOscMidiProgram(const int32_t index) | void sendOscMidiProgram(const int32_t index) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscMidiProgram(%i)", index); | qDebug("CarlaClient::sendOscMidiProgram(%i)", index); | ||||
| m_osc.sendOscMidiProgram(index); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_midi_program(&m_osc.m_controlData, index); | |||||
| } | } | ||||
| void sendOscMidi(const uint8_t midiBuf[4]) | void sendOscMidi(const uint8_t midiBuf[4]) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscMidi(%p)", midiBuf); | qDebug("CarlaClient::sendOscMidi(%p)", midiBuf); | ||||
| m_osc.sendOscMidi(midiBuf); | |||||
| } | |||||
| void sendOscUpdate() | |||||
| { | |||||
| qDebug("CarlaClient::sendOscUpdate()"); | |||||
| m_osc.sendOscUpdate(); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_midi(&m_osc.m_controlData, midiBuf); | |||||
| } | } | ||||
| void sendOscExiting() | void sendOscExiting() | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscExiting()"); | qDebug("CarlaClient::sendOscExiting()"); | ||||
| m_osc.sendOscExiting(); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_exiting(&m_osc.m_controlData); | |||||
| } | } | ||||
| #ifdef BUILD_BRIDGE_PLUGIN | #ifdef BUILD_BRIDGE_PLUGIN | ||||
| void sendOscBridgeUpdate() | void sendOscBridgeUpdate() | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscBridgeUpdate()"); | qDebug("CarlaClient::sendOscBridgeUpdate()"); | ||||
| m_osc.sendOscBridgeUpdate(); | |||||
| CARLA_ASSERT(m_osc.m_controlData.target && m_serverPath); | |||||
| if (m_osc.m_controlData.target && m_osc.m_serverPath) | |||||
| osc_send_bridge_update(&m_osc.m_controlData, m_osc.m_serverPath); | |||||
| } | } | ||||
| void sendOscBridgeError(const char* const error) | void sendOscBridgeError(const char* const error) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscBridgeError(\"%s\")", error); | qDebug("CarlaClient::sendOscBridgeError(\"%s\")", error); | ||||
| m_osc.sendOscBridgeError(error); | |||||
| CARLA_ASSERT(m_osc.m_controlData.target); | |||||
| CARLA_ASSERT(error); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_bridge_error(&m_osc.m_controlData, error); | |||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -267,20 +339,28 @@ public: | |||||
| void sendOscLv2TransferAtom(const int32_t portIndex, const char* const typeStr, const char* const atomBuf) | void sendOscLv2TransferAtom(const int32_t portIndex, const char* const typeStr, const char* const atomBuf) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscLv2TransferAtom(%i, \"%s\", \"%s\")", portIndex, typeStr, atomBuf); | qDebug("CarlaClient::sendOscLv2TransferAtom(%i, \"%s\", \"%s\")", portIndex, typeStr, atomBuf); | ||||
| m_osc.sendOscLv2TransferAtom(portIndex, typeStr, atomBuf); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_lv2_transfer_atom(&m_osc.m_controlData, portIndex, typeStr, atomBuf); | |||||
| } | } | ||||
| void sendOscLv2TransferEvent(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) | ||||
| { | { | ||||
| qDebug("CarlaClient::sendOscLv2TransferEvent(%i, \"%s\", \"%s\")", portIndex, typeStr, atomBuf); | qDebug("CarlaClient::sendOscLv2TransferEvent(%i, \"%s\", \"%s\")", portIndex, typeStr, atomBuf); | ||||
| m_osc.sendOscLv2TransferEvent(portIndex, typeStr, atomBuf); | |||||
| if (m_osc.m_controlData.target) | |||||
| osc_send_lv2_transfer_event(&m_osc.m_controlData, portIndex, typeStr, atomBuf); | |||||
| } | } | ||||
| #endif | #endif | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| #ifdef BUILD_BRIDGE_UI | #ifdef BUILD_BRIDGE_UI | ||||
| protected: | |||||
| void* getContainerId() | |||||
| { | |||||
| return m_toolkit->getContainerId(); | |||||
| } | |||||
| bool libOpen(const char* const filename) | bool libOpen(const char* const filename) | ||||
| { | { | ||||
| CARLA_ASSERT(filename); | CARLA_ASSERT(filename); | ||||
| @@ -326,14 +406,10 @@ private: | |||||
| CarlaBridgeOsc m_osc; | CarlaBridgeOsc m_osc; | ||||
| CarlaToolkit* const m_toolkit; | CarlaToolkit* const m_toolkit; | ||||
| struct { | |||||
| Message data[MAX_BRIDGE_MESSAGES]; | |||||
| QMutex lock; | |||||
| } m_messages; | |||||
| #ifdef BUILD_BRIDGE_UI | #ifdef BUILD_BRIDGE_UI | ||||
| char* m_filename; | char* m_filename; | ||||
| void* m_lib; | void* m_lib; | ||||
| bool m_quit; | |||||
| #endif | #endif | ||||
| }; | }; | ||||
| @@ -43,8 +43,8 @@ CarlaBridgeOsc::CarlaBridgeOsc(CarlaClient* const client_, const char* const nam | |||||
| CARLA_ASSERT(client); | CARLA_ASSERT(client); | ||||
| CARLA_ASSERT(name); | CARLA_ASSERT(name); | ||||
| m_server = nullptr; | |||||
| m_serverPath = nullptr; | m_serverPath = nullptr; | ||||
| m_serverThread = nullptr; | |||||
| m_controlData.path = nullptr; | m_controlData.path = nullptr; | ||||
| m_controlData.source = nullptr; // unused | m_controlData.source = nullptr; // unused | ||||
| m_controlData.target = nullptr; | m_controlData.target = nullptr; | ||||
| @@ -64,8 +64,8 @@ CarlaBridgeOsc::~CarlaBridgeOsc() | |||||
| bool CarlaBridgeOsc::init(const char* const url) | bool CarlaBridgeOsc::init(const char* const url) | ||||
| { | { | ||||
| qDebug("CarlaBridgeOsc::init(\"%s\")", url); | qDebug("CarlaBridgeOsc::init(\"%s\")", url); | ||||
| CARLA_ASSERT(! m_server); | |||||
| CARLA_ASSERT(! m_serverPath); | CARLA_ASSERT(! m_serverPath); | ||||
| CARLA_ASSERT(! m_serverThread); | |||||
| CARLA_ASSERT(url); | CARLA_ASSERT(url); | ||||
| char* host = lo_url_get_hostname(url); | char* host = lo_url_get_hostname(url); | ||||
| @@ -84,16 +84,15 @@ bool CarlaBridgeOsc::init(const char* const url) | |||||
| } | } | ||||
| // create new OSC thread | // create new OSC thread | ||||
| m_serverThread = lo_server_thread_new_with_proto(nullptr, LO_TCP, osc_error_handler); | |||||
| m_server = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handler); | |||||
| // get our full OSC server path | // get our full OSC server path | ||||
| char* const threadPath = lo_server_thread_get_url(m_serverThread); | |||||
| char* const threadPath = lo_server_get_url(m_server); | |||||
| m_serverPath = strdup(QString("%1%2").arg(threadPath).arg(m_name).toUtf8().constData()); | m_serverPath = strdup(QString("%1%2").arg(threadPath).arg(m_name).toUtf8().constData()); | ||||
| free(threadPath); | free(threadPath); | ||||
| // register message handler and start OSC thread | |||||
| lo_server_thread_add_method(m_serverThread, nullptr, nullptr, osc_message_handler, this); | |||||
| lo_server_thread_start(m_serverThread); | |||||
| // register message handler | |||||
| lo_server_add_method(m_server, nullptr, nullptr, osc_message_handler, this); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -101,14 +100,13 @@ bool CarlaBridgeOsc::init(const char* const url) | |||||
| void CarlaBridgeOsc::close() | void CarlaBridgeOsc::close() | ||||
| { | { | ||||
| qDebug("CarlaBridgeOsc::close()"); | qDebug("CarlaBridgeOsc::close()"); | ||||
| CARLA_ASSERT(m_server); | |||||
| CARLA_ASSERT(m_serverPath); | CARLA_ASSERT(m_serverPath); | ||||
| CARLA_ASSERT(m_serverThread); | |||||
| osc_clear_data(&m_controlData); | osc_clear_data(&m_controlData); | ||||
| lo_server_thread_stop(m_serverThread); | |||||
| lo_server_thread_del_method(m_serverThread, nullptr, nullptr); | |||||
| lo_server_thread_free(m_serverThread); | |||||
| lo_server_del_method(m_server, nullptr, nullptr); | |||||
| lo_server_free(m_server); | |||||
| free((void*)m_serverPath); | free((void*)m_serverPath); | ||||
| m_serverPath = nullptr; | m_serverPath = nullptr; | ||||
| @@ -119,8 +117,8 @@ void CarlaBridgeOsc::close() | |||||
| int CarlaBridgeOsc::handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg) | int CarlaBridgeOsc::handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg) | ||||
| { | { | ||||
| qDebug("CarlaBridgeOsc::handleMessage(\"%s\", %i, %p, \"%s\", %p)", path, argc, argv, types, msg); | qDebug("CarlaBridgeOsc::handleMessage(\"%s\", %i, %p, \"%s\", %p)", path, argc, argv, types, msg); | ||||
| CARLA_ASSERT(m_server); | |||||
| CARLA_ASSERT(m_serverPath); | CARLA_ASSERT(m_serverPath); | ||||
| CARLA_ASSERT(m_serverThread); | |||||
| CARLA_ASSERT(path); | CARLA_ASSERT(path); | ||||
| // Check if message is for this client | // Check if message is for this client | ||||
| @@ -147,7 +145,7 @@ int CarlaBridgeOsc::handleMessage(const char* const path, const int argc, const | |||||
| return handleMsgMidiProgram(argc, argv, types); | return handleMsgMidiProgram(argc, argv, types); | ||||
| if (strcmp(method, "/midi") == 0) | if (strcmp(method, "/midi") == 0) | ||||
| return handleMsgMidi(argc, argv, types); | return handleMsgMidi(argc, argv, types); | ||||
| if (strcmp(method, "/sample_rate") == 0) | |||||
| if (strcmp(method, "/sample-rate") == 0) | |||||
| return 0; // unused | return 0; // unused | ||||
| if (strcmp(method, "/show") == 0) | if (strcmp(method, "/show") == 0) | ||||
| return handleMsgShow(); | return handleMsgShow(); | ||||
| @@ -224,7 +222,7 @@ int CarlaBridgeOsc::handleMsgControl(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| const int32_t index = argv[0]->i; | const int32_t index = argv[0]->i; | ||||
| const float value = argv[1]->f; | const float value = argv[1]->f; | ||||
| client->quequeMessage(MESSAGE_PARAMETER, index, 0, value); | |||||
| client->setParameter(index, value); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -238,7 +236,7 @@ int CarlaBridgeOsc::handleMsgProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| return 1; | return 1; | ||||
| const int32_t index = argv[0]->i; | const int32_t index = argv[0]->i; | ||||
| client->quequeMessage(MESSAGE_PROGRAM, index, 0, 0.0); | |||||
| client->setProgram(index); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -257,11 +255,11 @@ int CarlaBridgeOsc::handleMsgMidiProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| #ifdef BUILD_BRIDGE_PLUGIN | #ifdef BUILD_BRIDGE_PLUGIN | ||||
| const int32_t index = argv[0]->i; | const int32_t index = argv[0]->i; | ||||
| client->quequeMessage(MESSAGE_MIDI_PROGRAM, index, 0, 0.0); | |||||
| client->setProgram(index); | |||||
| #else | #else | ||||
| const int32_t bank = argv[0]->i; | const int32_t bank = argv[0]->i; | ||||
| const int32_t program = argv[1]->i; | const int32_t program = argv[1]->i; | ||||
| client->quequeMessage(MESSAGE_MIDI_PROGRAM, bank, program, 0.0); | |||||
| client->setMidiProgram(bank, program); | |||||
| #endif | #endif | ||||
| return 0; | return 0; | ||||
| @@ -275,8 +273,8 @@ int CarlaBridgeOsc::handleMsgMidi(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| if (! client) | if (! client) | ||||
| return 1; | return 1; | ||||
| const uint8_t* const mdata = argv[0]->m; | |||||
| const uint8_t data[4] = { mdata[0], mdata[1], mdata[2], mdata[3] }; | |||||
| const uint8_t* const mdata = argv[0]->m; | |||||
| const uint8_t data[4] = { mdata[0], mdata[1], mdata[2], mdata[3] }; | |||||
| uint8_t status = data[1]; | uint8_t status = data[1]; | ||||
| uint8_t channel = status & 0x0F; | uint8_t channel = status & 0x0F; | ||||
| @@ -288,13 +286,13 @@ int CarlaBridgeOsc::handleMsgMidi(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| if (MIDI_IS_STATUS_NOTE_OFF(status)) | if (MIDI_IS_STATUS_NOTE_OFF(status)) | ||||
| { | { | ||||
| uint8_t note = data[2]; | uint8_t note = data[2]; | ||||
| client->quequeMessage(MESSAGE_NOTE_OFF, channel, note, 0); | |||||
| client->noteOff(channel, note); | |||||
| } | } | ||||
| 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]; | ||||
| client->quequeMessage(MESSAGE_NOTE_ON, channel, note, velo); | |||||
| client->noteOn(channel, note, velo); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -307,7 +305,7 @@ int CarlaBridgeOsc::handleMsgShow() | |||||
| if (! client) | if (! client) | ||||
| return 1; | return 1; | ||||
| client->quequeMessage(MESSAGE_SHOW_GUI, 1, 0, 0.0); | |||||
| client->toolkitShow(); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -319,7 +317,7 @@ int CarlaBridgeOsc::handleMsgHide() | |||||
| if (! client) | if (! client) | ||||
| return 1; | return 1; | ||||
| client->quequeMessage(MESSAGE_SHOW_GUI, 0, 0, 0.0); | |||||
| client->toolkitHide(); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -331,7 +329,7 @@ int CarlaBridgeOsc::handleMsgQuit() | |||||
| if (! client) | if (! client) | ||||
| return 1; | return 1; | ||||
| client->quequeMessage(MESSAGE_QUIT, 0, 0, 0.0); | |||||
| client->toolkitQuit(); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -24,8 +24,8 @@ | |||||
| #define CARLA_BRIDGE_OSC_HANDLE_ARGS const int argc, const lo_arg* const* const argv, const char* const types | #define CARLA_BRIDGE_OSC_HANDLE_ARGS const int argc, const lo_arg* const* const argv, const char* const types | ||||
| #define CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | #define CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | ||||
| CARLA_ASSERT(m_server); \ | |||||
| CARLA_ASSERT(m_serverPath); \ | CARLA_ASSERT(m_serverPath); \ | ||||
| CARLA_ASSERT(m_serverThread); \ | |||||
| /* check argument count */ \ | /* check argument count */ \ | ||||
| if (argc != argcToCompare) \ | if (argc != argcToCompare) \ | ||||
| { \ | { \ | ||||
| @@ -68,106 +68,6 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| const CarlaOscData* getControllerData() const | |||||
| { | |||||
| return &m_controlData; | |||||
| } | |||||
| void sendOscConfigure(const char* const key, const char* const value) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_configure(&m_controlData, key, value); | |||||
| } | |||||
| void sendOscControl(const int32_t index, const float value) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_control(&m_controlData, index, value); | |||||
| } | |||||
| void sendOscProgram(const int32_t index) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_program(&m_controlData, index); | |||||
| } | |||||
| void sendOscMidiProgram(const int32_t index) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_midi_program(&m_controlData, index); | |||||
| } | |||||
| void sendOscMidi(const uint8_t midiBuf[4]) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_midi(&m_controlData, midiBuf); | |||||
| } | |||||
| void sendOscUpdate() | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_update(&m_controlData, m_serverPath); | |||||
| } | |||||
| void sendOscExiting() | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_exiting(&m_controlData); | |||||
| } | |||||
| #ifdef BUILD_BRIDGE_PLUGIN | |||||
| void sendOscBridgeUpdate() | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target && m_serverPath); | |||||
| if (m_controlData.target && m_serverPath) | |||||
| osc_send_bridge_update(&m_controlData, m_serverPath); | |||||
| } | |||||
| void sendOscBridgeError(const char* const error) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target && m_serverPath); | |||||
| CARLA_ASSERT(error); | |||||
| if (m_controlData.target && m_serverPath) | |||||
| osc_send_bridge_error(&m_controlData, error); | |||||
| } | |||||
| #endif | |||||
| #ifdef BRIDGE_LV2 | |||||
| void sendOscLv2TransferAtom(const int32_t portIndex, const char* const typeStr, const char* const atomBuf) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_lv2_transfer_atom(&m_controlData, portIndex, typeStr, atomBuf); | |||||
| } | |||||
| void sendOscLv2TransferEvent(const int32_t portIndex, const char* const typeStr, const char* const atomBuf) | |||||
| { | |||||
| CARLA_ASSERT(m_controlData.target); | |||||
| if (m_controlData.target) | |||||
| osc_send_lv2_transfer_event(&m_controlData, portIndex, typeStr, atomBuf); | |||||
| } | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| protected: | protected: | ||||
| int handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg); | int handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg); | ||||
| int handleMsgConfigure(CARLA_BRIDGE_OSC_HANDLE_ARGS); | int handleMsgConfigure(CARLA_BRIDGE_OSC_HANDLE_ARGS); | ||||
| @@ -189,8 +89,8 @@ protected: | |||||
| private: | private: | ||||
| CarlaClient* const client; | CarlaClient* const client; | ||||
| const char* m_serverPath; | |||||
| lo_server_thread m_serverThread; | |||||
| lo_server m_server; | |||||
| const char* m_serverPath; | |||||
| CarlaOscData m_controlData; | CarlaOscData m_controlData; | ||||
| char* m_name; | char* m_name; | ||||
| @@ -204,6 +104,8 @@ private: | |||||
| CarlaBridgeOsc* const _this_ = (CarlaBridgeOsc*)user_data; | CarlaBridgeOsc* const _this_ = (CarlaBridgeOsc*)user_data; | ||||
| return _this_->handleMessage(path, argc, argv, types, msg); | return _this_->handleMessage(path, argc, argv, types, msg); | ||||
| } | } | ||||
| friend class CarlaClient; | |||||
| }; | }; | ||||
| /**@}*/ | /**@}*/ | ||||
| @@ -166,7 +166,7 @@ protected: | |||||
| gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | ||||
| } | } | ||||
| return m_client ? m_client->runMessages() : false; | |||||
| return m_client ? m_client->oscIdle() : false; | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| @@ -166,7 +166,7 @@ protected: | |||||
| gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight); | ||||
| } | } | ||||
| return m_client ? m_client->runMessages() : false; | |||||
| return m_client ? m_client->oscIdle() : false; | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| @@ -22,13 +22,17 @@ | |||||
| #include <QtCore/QTimerEvent> | #include <QtCore/QTimerEvent> | ||||
| #include <QtGui/QApplication> | #include <QtGui/QApplication> | ||||
| #include <QtGui/QDialog> | |||||
| #include <QtGui/QMainWindow> | |||||
| #include <QtGui/QVBoxLayout> | #include <QtGui/QVBoxLayout> | ||||
| #ifdef Q_WS_X11 | |||||
| # include <QtGui/QX11EmbedContainer> | |||||
| #endif | |||||
| CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
| static int qargc = 0; | static int qargc = 0; | ||||
| static char* qargv[] = { nullptr }; | |||||
| static char* qargv[0] = {}; | |||||
| class BridgeApplication : public QApplication | class BridgeApplication : public QApplication | ||||
| { | { | ||||
| @@ -53,7 +57,7 @@ protected: | |||||
| { | { | ||||
| if (event->timerId() == msgTimer) | if (event->timerId() == msgTimer) | ||||
| { | { | ||||
| if (m_client && ! m_client->runMessages()) | |||||
| if (m_client && ! m_client->oscIdle()) | |||||
| killTimer(msgTimer); | killTimer(msgTimer); | ||||
| } | } | ||||
| @@ -86,20 +90,35 @@ public: | |||||
| app = nullptr; | app = nullptr; | ||||
| window = nullptr; | window = nullptr; | ||||
| #ifdef Q_WS_X11 | |||||
| x11Container = nullptr; | |||||
| #endif | |||||
| } | } | ||||
| ~CarlaToolkitQt4() | ~CarlaToolkitQt4() | ||||
| { | { | ||||
| qDebug("CarlaToolkitQt4::~CarlaToolkitQt4()"); | qDebug("CarlaToolkitQt4::~CarlaToolkitQt4()"); | ||||
| CARLA_ASSERT(! app); | CARLA_ASSERT(! app); | ||||
| if (window) | |||||
| { | |||||
| window->close(); | |||||
| delete window; | |||||
| } | |||||
| } | } | ||||
| void init() | void init() | ||||
| { | { | ||||
| qDebug("CarlaToolkitQt4::init()"); | qDebug("CarlaToolkitQt4::init()"); | ||||
| CARLA_ASSERT(! app); | CARLA_ASSERT(! app); | ||||
| CARLA_ASSERT(! window); | |||||
| app = new BridgeApplication; | app = new BridgeApplication; | ||||
| window = new QMainWindow(nullptr); | |||||
| window->resize(10, 10); | |||||
| window->hide(); | |||||
| } | } | ||||
| void exec(CarlaClient* const client, const bool showGui) | void exec(CarlaClient* const client, const bool showGui) | ||||
| @@ -108,27 +127,15 @@ public: | |||||
| CARLA_ASSERT(app); | CARLA_ASSERT(app); | ||||
| CARLA_ASSERT(client); | CARLA_ASSERT(client); | ||||
| m_client = client; | |||||
| #ifndef BRIDGE_LV2_X11 | |||||
| QWidget* const widget = (QWidget*)client->getWidget(); | |||||
| if (client->needsReparent()) | |||||
| { | |||||
| window = (QDialog*)client->getWidget(); | |||||
| window->resize(10, 10); | |||||
| } | |||||
| else | |||||
| { | |||||
| // TODO - window->setCentralWidget(widget); or other simpler method | |||||
| window = new QDialog(nullptr); | |||||
| window->resize(10, 10); | |||||
| window->setLayout(new QVBoxLayout(window)); | |||||
| QWidget* const widget = (QWidget*)client->getWidget(); | |||||
| window->layout()->addWidget(widget); | |||||
| window->layout()->setContentsMargins(0, 0, 0, 0); | |||||
| window->adjustSize(); | |||||
| widget->setParent(window); | |||||
| widget->show(); | |||||
| } | |||||
| window->setCentralWidget(widget); | |||||
| window->adjustSize(); | |||||
| widget->setParent(window); | |||||
| widget->show(); | |||||
| #endif | |||||
| if (! client->isResizable()) | if (! client->isResizable()) | ||||
| window->setFixedSize(window->width(), window->height()); | window->setFixedSize(window->width(), window->height()); | ||||
| @@ -149,8 +156,6 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| app->connect(window, SIGNAL(finished(int)), app, SLOT(quit())); | |||||
| if (showGui) | if (showGui) | ||||
| show(); | show(); | ||||
| else | else | ||||
| @@ -219,12 +224,41 @@ public: | |||||
| if (window) | if (window) | ||||
| window->setFixedSize(width, height); | window->setFixedSize(width, height); | ||||
| #ifdef BRIDGE_LV2_X11 | |||||
| if (x11Container) | |||||
| x11Container->setFixedSize(width, height); | |||||
| #endif | |||||
| } | |||||
| void* getContainerId() | |||||
| { | |||||
| #ifdef Q_WS_X11 | |||||
| if (! x11Container) | |||||
| { | |||||
| x11Container = new QX11EmbedContainer(window); | |||||
| window->setCentralWidget(x11Container); | |||||
| window->adjustSize(); | |||||
| x11Container->setParent(window); | |||||
| x11Container->show(); | |||||
| } | |||||
| return (void*)x11Container->winId(); | |||||
| #else | |||||
| return nullptr; | |||||
| #endif | |||||
| } | } | ||||
| private: | private: | ||||
| BridgeApplication* app; | BridgeApplication* app; | ||||
| QDialog* window; | |||||
| QMainWindow* window; | |||||
| QSettings settings; | QSettings settings; | ||||
| #ifdef Q_WS_X11 | |||||
| QX11EmbedContainer* x11Container; | |||||
| #endif | |||||
| }; | }; | ||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| @@ -58,12 +58,18 @@ public: | |||||
| virtual void resize(int width, int height) = 0; | virtual void resize(int width, int height) = 0; | ||||
| #if BUILD_BRIDGE_UI | #if BUILD_BRIDGE_UI | ||||
| virtual void* getContainerId() | |||||
| { | |||||
| return nullptr; | |||||
| } | |||||
| static CarlaToolkit* createNew(const char* const title); | static CarlaToolkit* createNew(const char* const title); | ||||
| #endif | #endif | ||||
| protected: | protected: | ||||
| char* m_title; | char* m_title; | ||||
| CarlaClient* m_client; | CarlaClient* m_client; | ||||
| friend class CarlaClient; | |||||
| }; | }; | ||||
| /**@}*/ | /**@}*/ | ||||
| @@ -25,10 +25,6 @@ | |||||
| #include <vector> | #include <vector> | ||||
| #include <QtCore/QDir> | #include <QtCore/QDir> | ||||
| #ifdef BRIDGE_LV2_X11 | |||||
| # include <QtGui/QDialog> | |||||
| #endif | |||||
| CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| @@ -119,7 +115,6 @@ public: | |||||
| #ifdef BRIDGE_LV2_X11 | #ifdef BRIDGE_LV2_X11 | ||||
| m_resizable = false; | m_resizable = false; | ||||
| x11_widget = new QDialog; | |||||
| #else | #else | ||||
| m_resizable = true; | m_resizable = true; | ||||
| #endif | #endif | ||||
| @@ -276,7 +271,7 @@ public: | |||||
| features[lv2_feature_id_ui_parent] = new LV2_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]->URI = LV2_UI__parent; | ||||
| #ifdef BRIDGE_LV2_X11 | #ifdef BRIDGE_LV2_X11 | ||||
| features[lv2_feature_id_ui_parent]->data = (void*)x11_widget->winId(); | |||||
| features[lv2_feature_id_ui_parent]->data = getContainerId(); | |||||
| #else | #else | ||||
| features[lv2_feature_id_ui_parent]->data = nullptr; | features[lv2_feature_id_ui_parent]->data = nullptr; | ||||
| #endif | #endif | ||||
| @@ -330,6 +325,11 @@ public: | |||||
| bool init(const char* pluginURI, const char* uiURI) | bool init(const char* pluginURI, const char* uiURI) | ||||
| { | { | ||||
| // ----------------------------------------------------------------- | |||||
| // init | |||||
| CarlaClient::init(pluginURI, uiURI); | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // get plugin from lv2_rdf (lilv) | // get plugin from lv2_rdf (lilv) | ||||
| @@ -423,8 +423,16 @@ public: | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool idle() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| void close() | void close() | ||||
| { | { | ||||
| CarlaClient::close(); | |||||
| if (handle && descriptor && descriptor->cleanup) | if (handle && descriptor && descriptor->cleanup) | ||||
| descriptor->cleanup(handle); | descriptor->cleanup(handle); | ||||
| @@ -436,11 +444,7 @@ public: | |||||
| void* getWidget() const | void* getWidget() const | ||||
| { | { | ||||
| #ifdef BRIDGE_LV2_X11 | |||||
| return x11_widget; | |||||
| #else | |||||
| return widget; | return widget; | ||||
| #endif | |||||
| } | } | ||||
| bool isResizable() const | bool isResizable() const | ||||
| @@ -648,7 +652,7 @@ public: | |||||
| if (width <= 0 || height <= 0) | if (width <= 0 || height <= 0) | ||||
| return 1; | return 1; | ||||
| quequeMessage(MESSAGE_RESIZE_GUI, width, height, 0.0); | |||||
| toolkitResize(width, height); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1002,10 +1006,6 @@ private: | |||||
| const LV2_Programs_UI_Interface* programs; | const LV2_Programs_UI_Interface* programs; | ||||
| #ifdef BRIDGE_LV2_X11 | |||||
| QDialog* x11_widget; | |||||
| #endif | |||||
| bool m_resizable; | bool m_resizable; | ||||
| std::vector<const char*> customURIDs; | std::vector<const char*> customURIDs; | ||||
| }; | }; | ||||
| @@ -1115,7 +1115,6 @@ int main(int argc, char* argv[]) | |||||
| // Close OSC | // Close OSC | ||||
| if (useOsc) | if (useOsc) | ||||
| { | { | ||||
| client.sendOscExiting(); | |||||
| client.oscClose(); | client.oscClose(); | ||||
| } | } | ||||
| @@ -44,7 +44,6 @@ public: | |||||
| QObject(nullptr) | QObject(nullptr) | ||||
| { | { | ||||
| effect = nullptr; | effect = nullptr; | ||||
| widget = new QDialog(nullptr); | |||||
| idleTimer = 0; | idleTimer = 0; | ||||
| @@ -113,8 +112,11 @@ public: | |||||
| effect->dispatcher(effect, effSetBlockSize, 0, bufferSize, nullptr, 0.0f); | effect->dispatcher(effect, effSetBlockSize, 0, bufferSize, nullptr, 0.0f); | ||||
| effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f); | effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f); | ||||
| if (effect->dispatcher(effect, effEditOpen, 0, value, (void*)widget->winId(), 0.0f) != 1) | |||||
| if (effect->dispatcher(effect, effEditOpen, 0, value, getContainerId(), 0.0f) != 1) | |||||
| { | |||||
| effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f); | |||||
| return false; | return false; | ||||
| } | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // initialize gui stuff | // initialize gui stuff | ||||
| @@ -128,7 +130,7 @@ public: | |||||
| int height = vstRect->bottom - vstRect->top; | int height = vstRect->bottom - vstRect->top; | ||||
| if (width > 0 && height > 0) | if (width > 0 && height > 0) | ||||
| widget->setFixedSize(width, height); | |||||
| toolkitResize(width, height); | |||||
| } | } | ||||
| idleTimer = startTimer(50); | idleTimer = startTimer(50); | ||||
| @@ -150,7 +152,7 @@ public: | |||||
| void* getWidget() const | void* getWidget() const | ||||
| { | { | ||||
| return widget; | |||||
| return nullptr; // VST always uses reparent | |||||
| } | } | ||||
| bool isResizable() const | bool isResizable() const | ||||
| @@ -230,9 +232,7 @@ public: | |||||
| intptr_t handleAdioMasterSizeWindow(int32_t width, int32_t height) | intptr_t handleAdioMasterSizeWindow(int32_t width, int32_t height) | ||||
| { | { | ||||
| CARLA_ASSERT(widget); | |||||
| widget->setFixedSize(width, height); | |||||
| toolkitResize(width, height); | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| @@ -435,7 +435,6 @@ protected: | |||||
| private: | private: | ||||
| int unique1; | int unique1; | ||||
| AEffect* effect; | AEffect* effect; | ||||
| QDialog* widget; | |||||
| int idleTimer; | int idleTimer; | ||||
| int unique2; | int unique2; | ||||
| }; | }; | ||||
| @@ -496,7 +495,6 @@ int main(int argc, char* argv[]) | |||||
| // Close OSC | // Close OSC | ||||
| if (useOsc) | if (useOsc) | ||||
| { | { | ||||
| client.sendOscExiting(); | |||||
| client.oscClose(); | client.oscClose(); | ||||
| } | } | ||||