| @@ -27,7 +27,7 @@ | |||||
| CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
| // forward declarations of commonly used Carla-Bridge classes | // forward declarations of commonly used Carla-Bridge classes | ||||
| class CarlaBridgeClient; | |||||
| class CarlaBridgeUI; | |||||
| class CarlaBridgeToolkit; | class CarlaBridgeToolkit; | ||||
| CARLA_BRIDGE_END_NAMESPACE | CARLA_BRIDGE_END_NAMESPACE | ||||
| @@ -1,257 +0,0 @@ | |||||
| /* | |||||
| * Carla Bridge Client | |||||
| * Copyright (C) 2011-2014 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 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 doc/GPL.txt file. | |||||
| */ | |||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaLibUtils.hpp" | |||||
| CARLA_BRIDGE_START_NAMESPACE | |||||
| // --------------------------------------------------------------------- | |||||
| CarlaBridgeClient::CarlaBridgeClient(const char* const uiTitle) | |||||
| : fOsc(this), | |||||
| fOscData(fOsc.getControlData()), | |||||
| fUI(CarlaBridgeToolkit::createNew(this, uiTitle)), | |||||
| leakDetector_CarlaBridgeClient() | |||||
| { | |||||
| CARLA_ASSERT(uiTitle != nullptr && uiTitle[0] != '\0'); | |||||
| carla_debug("CarlaBridgeClient::CarlaBridgeClient(\"%s\")", uiTitle); | |||||
| } | |||||
| CarlaBridgeClient::~CarlaBridgeClient() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::~CarlaBridgeClient()"); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // ui initialization | |||||
| bool CarlaBridgeClient::uiInit(const char*, const char* const, const char* const) | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::uiInit()"); | |||||
| fUI.init(); | |||||
| return true; | |||||
| } | |||||
| void CarlaBridgeClient::uiClose() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::uiClose()"); | |||||
| if (isOscControlRegistered() && ! fUI.quit) | |||||
| sendOscExiting(); | |||||
| fUI.close(); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // ui toolkit | |||||
| void CarlaBridgeClient::toolkitShow() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeClient::toolkitShow()"); | |||||
| fUI.toolkit->show(); | |||||
| } | |||||
| void CarlaBridgeClient::toolkitHide() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeClient::toolkitHide()"); | |||||
| fUI.toolkit->hide(); | |||||
| } | |||||
| void CarlaBridgeClient::toolkitResize(const int width, const int height) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeClient::toolkitResize(%i, %i)", width, height); | |||||
| fUI.toolkit->resize(width, height); | |||||
| } | |||||
| void CarlaBridgeClient::toolkitExec(const bool showGui) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeClient::toolkitExec(%s)", bool2str(showGui)); | |||||
| fUI.toolkit->exec(showGui); | |||||
| } | |||||
| void CarlaBridgeClient::toolkitQuit() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::toolkitQuit()"); | |||||
| fUI.quit = true; | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // osc stuff | |||||
| void CarlaBridgeClient::oscInit(const char* const url) | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::oscInit(\"%s\")", url); | |||||
| fOsc.init(url); | |||||
| } | |||||
| bool CarlaBridgeClient::oscIdle(const bool onlyOnce) const | |||||
| { | |||||
| if (onlyOnce) | |||||
| fOsc.idleOnce(); | |||||
| else | |||||
| fOsc.idle(); | |||||
| return ! fUI.quit; | |||||
| } | |||||
| void CarlaBridgeClient::oscClose() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::oscClose()"); | |||||
| fOsc.close(); | |||||
| } | |||||
| bool CarlaBridgeClient::isOscControlRegistered() const noexcept | |||||
| { | |||||
| return fOsc.isControlRegistered(); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscUpdate() const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscUpdate()"); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_update(fOscData, fOsc.getServerPath()); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| void CarlaBridgeClient::sendOscConfigure(const char* const key, const char* const value) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscConfigure(\"%s\", \"%s\")", key, value); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_configure(fOscData, key, value); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscControl(const int32_t index, const float value) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscControl(%i, %f)", index, value); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_control(fOscData, index, value); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscProgram(const uint32_t index) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscProgram(%i)", index); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_program(fOscData, index); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscMidiProgram(const uint32_t index) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscMidiProgram(%i)", index); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_midi_program(fOscData, index); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscMidi(const uint8_t midiBuf[4]) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscMidi(%p)", midiBuf); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_midi(fOscData, midiBuf); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscExiting() const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscExiting()"); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_exiting(fOscData); | |||||
| } | |||||
| #ifdef BRIDGE_LV2 | |||||
| void CarlaBridgeClient::sendOscLv2AtomTransfer(const uint32_t portIndex, const char* const atomBuf) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscLv2TransferAtom(%i, \"%s\")", portIndex, atomBuf); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_lv2_atom_transfer(fOscData, portIndex, atomBuf); | |||||
| } | |||||
| void CarlaBridgeClient::sendOscLv2UridMap(const uint32_t urid, const char* const uri) const | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::sendOscLv2UridMap(%i, \"%s\")", urid, uri); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_lv2_urid_map(fOscData, urid, uri); | |||||
| } | |||||
| #endif | |||||
| // --------------------------------------------------------------------- | |||||
| void* CarlaBridgeClient::getContainerId() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::getContainerId()"); | |||||
| return fUI.toolkit->getContainerId(); | |||||
| } | |||||
| void* CarlaBridgeClient::getContainerId2() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::getContainerId2()"); | |||||
| return fUI.toolkit->getContainerId2(); | |||||
| } | |||||
| bool CarlaBridgeClient::uiLibOpen(const char* const filename) | |||||
| { | |||||
| CARLA_ASSERT(fUI.lib == nullptr); | |||||
| CARLA_ASSERT(filename != nullptr); | |||||
| carla_debug("CarlaBridgeClient::uiLibOpen(\"%s\")", filename); | |||||
| fUI.lib = lib_open(filename); | |||||
| fUI.filename = filename; | |||||
| return (fUI.lib != nullptr); | |||||
| } | |||||
| bool CarlaBridgeClient::uiLibClose() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.lib != nullptr, false); | |||||
| carla_debug("CarlaBridgeClient::uiLibClose()"); | |||||
| const bool closed = lib_close(fUI.lib); | |||||
| fUI.lib = nullptr; | |||||
| return closed; | |||||
| } | |||||
| const char* CarlaBridgeClient::uiLibError() | |||||
| { | |||||
| carla_debug("CarlaBridgeClient::uiLibError()"); | |||||
| return lib_error(fUI.filename); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | |||||
| @@ -1,162 +0,0 @@ | |||||
| /* | |||||
| * Carla Bridge Client | |||||
| * Copyright (C) 2011-2014 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 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 doc/GPL.txt file. | |||||
| */ | |||||
| #ifndef CARLA_BRIDGE_CLIENT_HPP_INCLUDED | |||||
| #define CARLA_BRIDGE_CLIENT_HPP_INCLUDED | |||||
| #include "CarlaBridgeOsc.hpp" | |||||
| #include "CarlaBridgeToolkit.hpp" | |||||
| #include "CarlaLibUtils.hpp" | |||||
| CARLA_BRIDGE_START_NAMESPACE | |||||
| // ----------------------------------------------------------------------- | |||||
| class CarlaBridgeClient | |||||
| { | |||||
| public: | |||||
| CarlaBridgeClient(const char* const uiTitle); | |||||
| virtual ~CarlaBridgeClient(); | |||||
| // --------------------------------------------------------------------- | |||||
| // ui initialization | |||||
| virtual bool uiInit(const char*, const char* const, const char* const); | |||||
| virtual void uiIdle() {} | |||||
| virtual void uiClose(); | |||||
| // --------------------------------------------------------------------- | |||||
| // ui management | |||||
| virtual void* getWidget() const = 0; | |||||
| virtual bool isResizable() const = 0; | |||||
| // --------------------------------------------------------------------- | |||||
| // ui processing | |||||
| virtual void setParameter(const int32_t rindex, const float value) = 0; | |||||
| virtual void setProgram(const uint32_t index) = 0; | |||||
| virtual void setMidiProgram(const uint32_t bank, const uint32_t program) = 0; | |||||
| virtual void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) = 0; | |||||
| virtual void noteOff(const uint8_t channel, const uint8_t note) = 0; | |||||
| // --------------------------------------------------------------------- | |||||
| // ui toolkit | |||||
| void toolkitShow(); | |||||
| void toolkitHide(); | |||||
| void toolkitResize(const int width, const int height); | |||||
| void toolkitExec(const bool showGui); | |||||
| void toolkitQuit(); | |||||
| // --------------------------------------------------------------------- | |||||
| // osc stuff | |||||
| void oscInit(const char* const url); | |||||
| bool oscIdle(const bool onlyOnce = false) const; | |||||
| void oscClose(); | |||||
| bool isOscControlRegistered() const noexcept; | |||||
| void sendOscUpdate() const; | |||||
| // --------------------------------------------------------------------- | |||||
| protected: | |||||
| void sendOscConfigure(const char* const key, const char* const value) const; | |||||
| void sendOscControl(const int32_t index, const float value) const; | |||||
| void sendOscProgram(const uint32_t index) const; | |||||
| void sendOscMidiProgram(const uint32_t index) const; | |||||
| void sendOscMidi(const uint8_t midiBuf[4]) const; | |||||
| void sendOscExiting() const; | |||||
| #ifdef BRIDGE_LV2 | |||||
| void sendOscLv2AtomTransfer(const uint32_t portIndex, const char* const atomBuf) const; | |||||
| void sendOscLv2UridMap(const uint32_t urid, const char* const uri) const; | |||||
| #endif | |||||
| // --------------------------------------------------------------------- | |||||
| void* getContainerId(); | |||||
| void* getContainerId2(); | |||||
| // --------------------------------------------------------------------- | |||||
| bool uiLibOpen(const char* const filename); | |||||
| bool uiLibClose(); | |||||
| const char* uiLibError(); | |||||
| template<typename Func> | |||||
| Func uiLibSymbol(const char* const symbol) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.lib != nullptr, nullptr); | |||||
| carla_debug("CarlaBridgeClient::uiLibSymbol(\"%s\")", symbol); | |||||
| return lib_symbol<Func>(fUI.lib, symbol); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| private: | |||||
| CarlaBridgeOsc fOsc; | |||||
| const CarlaOscData& fOscData; | |||||
| struct UI { | |||||
| CarlaBridgeToolkit* const toolkit; | |||||
| CarlaString filename; | |||||
| lib_t lib; | |||||
| bool quit; | |||||
| UI(CarlaBridgeToolkit* const toolkit_) | |||||
| : toolkit(toolkit_), | |||||
| filename(), | |||||
| lib(nullptr), | |||||
| quit(false) | |||||
| { | |||||
| CARLA_ASSERT(toolkit != nullptr); | |||||
| } | |||||
| ~UI() | |||||
| { | |||||
| delete toolkit; | |||||
| } | |||||
| void init() | |||||
| { | |||||
| toolkit->init(); | |||||
| quit = false; | |||||
| } | |||||
| void close() | |||||
| { | |||||
| quit = true; | |||||
| toolkit->quit(); | |||||
| } | |||||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||||
| UI() = delete; | |||||
| CARLA_DECLARE_NON_COPY_STRUCT(UI) | |||||
| #endif | |||||
| } fUI; | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeClient) | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | |||||
| #endif // CARLA_BRIDGE_CLIENT_HPP_INCLUDED | |||||
| @@ -1,337 +0,0 @@ | |||||
| /* | |||||
| * Carla Bridge OSC | |||||
| * Copyright (C) 2011-2014 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 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 doc/GPL.txt file. | |||||
| */ | |||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaMIDI.h" | |||||
| CARLA_BRIDGE_START_NAMESPACE | |||||
| // ----------------------------------------------------------------------- | |||||
| CarlaBridgeOsc::CarlaBridgeOsc(CarlaBridgeClient* const client) | |||||
| : kClient(client), | |||||
| fControlData(), | |||||
| fName(), | |||||
| fServerPath(), | |||||
| fServer(nullptr), | |||||
| leakDetector_CarlaBridgeOsc() | |||||
| { | |||||
| CARLA_ASSERT(client != nullptr); | |||||
| carla_debug("CarlaBridgeOsc::CarlaBridgeOsc(%p)", client); | |||||
| } | |||||
| CarlaBridgeOsc::~CarlaBridgeOsc() | |||||
| { | |||||
| CARLA_ASSERT(fControlData.source == nullptr); // must never be used | |||||
| CARLA_ASSERT(fName.isEmpty()); | |||||
| CARLA_ASSERT(fServerPath.isEmpty()); | |||||
| CARLA_ASSERT(fServer == nullptr); | |||||
| carla_debug("CarlaBridgeOsc::~CarlaBridgeOsc()"); | |||||
| } | |||||
| void CarlaBridgeOsc::init(const char* const url) | |||||
| { | |||||
| CARLA_ASSERT(fName.isEmpty()); | |||||
| CARLA_ASSERT(fServerPath.isEmpty()); | |||||
| CARLA_ASSERT(fServer == nullptr); | |||||
| CARLA_ASSERT(url != nullptr); | |||||
| carla_debug("CarlaBridgeOsc::init(\"%s\")", url); | |||||
| std::srand((uint)(uintptr_t)this); | |||||
| std::srand((uint)(uintptr_t)&url); | |||||
| fName = "ui-"; | |||||
| fName += CarlaString(std::rand() % 99999); | |||||
| fServer = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler); | |||||
| CARLA_SAFE_ASSERT_RETURN(fServer != nullptr,) | |||||
| { | |||||
| char* const host = lo_url_get_hostname(url); | |||||
| char* const port = lo_url_get_port(url); | |||||
| fControlData.path = carla_strdup_free(lo_url_get_path(url)); | |||||
| fControlData.target = lo_address_new_with_proto(LO_UDP, host, port); | |||||
| std::free(host); | |||||
| std::free(port); | |||||
| } | |||||
| if (char* const tmpServerPath = lo_server_get_url(fServer)) | |||||
| { | |||||
| fServerPath = tmpServerPath; | |||||
| fServerPath += fName; | |||||
| std::free(tmpServerPath); | |||||
| } | |||||
| lo_server_add_method(fServer, nullptr, nullptr, osc_message_handler, this); | |||||
| CARLA_ASSERT(fName.isNotEmpty()); | |||||
| CARLA_ASSERT(fServerPath.isNotEmpty()); | |||||
| } | |||||
| void CarlaBridgeOsc::idle() const | |||||
| { | |||||
| if (fServer == nullptr) | |||||
| return; | |||||
| for (; lo_server_recv_noblock(fServer, 0) != 0;) {} | |||||
| } | |||||
| void CarlaBridgeOsc::idleOnce() const | |||||
| { | |||||
| if (fServer == nullptr) | |||||
| return; | |||||
| lo_server_recv_noblock(fServer, 0); | |||||
| } | |||||
| void CarlaBridgeOsc::close() | |||||
| { | |||||
| CARLA_ASSERT(fControlData.source == nullptr); // must never be used | |||||
| CARLA_ASSERT(fName.isNotEmpty()); | |||||
| CARLA_ASSERT(fServerPath.isNotEmpty()); | |||||
| CARLA_ASSERT(fServer != nullptr); | |||||
| carla_debug("CarlaBridgeOsc::close()"); | |||||
| fName.clear(); | |||||
| if (fServer != nullptr) | |||||
| { | |||||
| lo_server_del_method(fServer, nullptr, nullptr); | |||||
| lo_server_free(fServer); | |||||
| fServer = nullptr; | |||||
| } | |||||
| fServerPath.clear(); | |||||
| fControlData.clear(); | |||||
| CARLA_ASSERT(fName.isEmpty()); | |||||
| CARLA_ASSERT(fServerPath.isEmpty()); | |||||
| CARLA_ASSERT(fServer == nullptr); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| int CarlaBridgeOsc::handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fName.isNotEmpty(), 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(fServerPath.isNotEmpty(), 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(fServer != nullptr, 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(path != nullptr, 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(msg != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMessage(\"%s\", %i, %p, \"%s\", %p)", path, argc, argv, types, msg); | |||||
| const size_t nameSize(fName.length()); | |||||
| // Check if message is for this client | |||||
| if (std::strlen(path) <= nameSize || std::strncmp(path+1, fName, nameSize) != 0) | |||||
| { | |||||
| carla_stderr("CarlaBridgeOsc::handleMessage() - message not for this client -> '%s' != '/%s/'", path, fName.buffer()); | |||||
| return 1; | |||||
| } | |||||
| // Get method from path | |||||
| char method[32+1] = { '\0' }; | |||||
| std::strncpy(method, path + (nameSize + 2), 32); | |||||
| if (method[0] == '\0') | |||||
| { | |||||
| carla_stderr("CarlaBridgeOsc::handleMessage(\"%s\", ...) - received message without method", path); | |||||
| return 1; | |||||
| } | |||||
| // Common methods | |||||
| if (std::strcmp(method, "show") == 0) | |||||
| return handleMsgShow(); | |||||
| if (std::strcmp(method, "hide") == 0) | |||||
| return handleMsgHide(); | |||||
| if (std::strcmp(method, "quit") == 0) | |||||
| return handleMsgQuit(); | |||||
| // UI methods | |||||
| if (std::strcmp(method, "configure") == 0) | |||||
| return handleMsgConfigure(argc, argv, types); | |||||
| if (std::strcmp(method, "control") == 0) | |||||
| return handleMsgControl(argc, argv, types); | |||||
| if (std::strcmp(method, "program") == 0) | |||||
| return handleMsgProgram(argc, argv, types); | |||||
| if (std::strcmp(method, "midi-program") == 0) | |||||
| return handleMsgMidiProgram(argc, argv, types); | |||||
| if (std::strcmp(method, "midi") == 0) | |||||
| return handleMsgMidi(argc, argv, types); | |||||
| if (std::strcmp(method, "sample-rate") == 0) | |||||
| return 0; // unused | |||||
| // special | |||||
| if (std::strcmp(method, "update_url") == 0) | |||||
| return handleMsgUpdateURL(argc, argv, types); | |||||
| #ifdef BRIDGE_LV2 | |||||
| // LV2 methods | |||||
| if (std::strcmp(method, "lv2_atom_transfer") == 0) | |||||
| return handleMsgLv2AtomTransfer(argc, argv, types); | |||||
| if (std::strcmp(method, "lv2_urid_map") == 0) | |||||
| return handleMsgLv2UridMap(argc, argv, types); | |||||
| #endif | |||||
| carla_stderr("CarlaBridgeOsc::handleMessage(\"%s\", ...) - received unsupported OSC method '%s'", path, method); | |||||
| return 1; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgShow() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgShow()"); | |||||
| kClient->toolkitShow(); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgHide() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgHide()"); | |||||
| kClient->toolkitHide(); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgQuit() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgQuit()"); | |||||
| kClient->toolkitQuit(); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgConfigure(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ss"); | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgConfigure()"); | |||||
| // nothing here for now | |||||
| return 0; | |||||
| // unused | |||||
| (void)argv; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgControl(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "if"); | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgControl()"); | |||||
| const int32_t index = argv[0]->i; | |||||
| const float value = argv[1]->f; | |||||
| CARLA_SAFE_ASSERT_RETURN(index != -1, 1); | |||||
| kClient->setParameter(index, value); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(1, "i"); | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgProgram()"); | |||||
| const int32_t index = argv[0]->i; | |||||
| CARLA_SAFE_ASSERT_RETURN(index >= 0, 1); | |||||
| kClient->setProgram(static_cast<uint32_t>(index)); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgMidiProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii"); | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgMidiProgram()"); | |||||
| const int32_t bank = argv[0]->i; | |||||
| const int32_t program = argv[1]->i; | |||||
| CARLA_SAFE_ASSERT_RETURN(bank >= 0, 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(program >= 0, 1); | |||||
| kClient->setMidiProgram(static_cast<uint32_t>(bank), static_cast<uint32_t>(program)); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgMidi(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(1, "m"); | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgMidi()"); | |||||
| const uint8_t* const data = argv[0]->m; | |||||
| uint8_t status = data[1]; | |||||
| uint8_t channel = status & MIDI_CHANNEL_BIT; | |||||
| // Fix bad note-off | |||||
| if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0) | |||||
| status = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); | |||||
| if (MIDI_IS_STATUS_NOTE_OFF(status)) | |||||
| { | |||||
| const uint8_t note = data[2]; | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, 1); | |||||
| kClient->noteOff(channel, note); | |||||
| } | |||||
| else if (MIDI_IS_STATUS_NOTE_ON(status)) | |||||
| { | |||||
| const uint8_t note = data[2]; | |||||
| const uint8_t velo = data[3]; | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE, 1); | |||||
| kClient->noteOn(channel, note, velo); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgUpdateURL(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(1, "s"); | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr, 1); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgUpdateURL()"); | |||||
| const char* const url = (const char*)&argv[0]->s; | |||||
| fControlData.setNewURL(url); | |||||
| return 0; | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | |||||
| @@ -1,131 +0,0 @@ | |||||
| /* | |||||
| * Carla Bridge OSC | |||||
| * Copyright (C) 2011-2014 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 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 doc/GPL.txt file. | |||||
| */ | |||||
| #ifndef CARLA_BRIDGE_OSC_HPP_INCLUDED | |||||
| #define CARLA_BRIDGE_OSC_HPP_INCLUDED | |||||
| #include "CarlaBridge.hpp" | |||||
| #include "CarlaOscUtils.hpp" | |||||
| #include "CarlaString.hpp" | |||||
| #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) \ | |||||
| /* check argument count */ \ | |||||
| if (argc != argcToCompare) \ | |||||
| { \ | |||||
| carla_stderr("CarlaBridgeOsc::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \ | |||||
| return 1; \ | |||||
| } \ | |||||
| if (argc > 0) \ | |||||
| { \ | |||||
| /* check for nullness */ \ | |||||
| if (types == nullptr || typesToCompare == nullptr) \ | |||||
| { \ | |||||
| carla_stderr("CarlaBridgeOsc::%s() - argument types are null", __FUNCTION__); \ | |||||
| return 1; \ | |||||
| } \ | |||||
| /* check argument types */ \ | |||||
| if (std::strcmp(types, typesToCompare) != 0) \ | |||||
| { \ | |||||
| carla_stderr("CarlaBridgeOsc::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \ | |||||
| return 1; \ | |||||
| } \ | |||||
| } | |||||
| CARLA_BRIDGE_START_NAMESPACE | |||||
| // ----------------------------------------------------------------------- | |||||
| class CarlaBridgeOsc | |||||
| { | |||||
| public: | |||||
| CarlaBridgeOsc(CarlaBridgeClient* const client); | |||||
| ~CarlaBridgeOsc(); | |||||
| void init(const char* const url); | |||||
| void idle() const; | |||||
| void idleOnce() const; | |||||
| void close(); | |||||
| // ------------------------------------------------------------------- | |||||
| bool isControlRegistered() const noexcept | |||||
| { | |||||
| return (fControlData.target != nullptr); | |||||
| } | |||||
| const CarlaOscData& getControlData() const noexcept | |||||
| { | |||||
| return fControlData; | |||||
| } | |||||
| const char* getServerPath() const noexcept | |||||
| { | |||||
| return fServerPath; | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| private: | |||||
| CarlaBridgeClient* const kClient; | |||||
| CarlaOscData fControlData; | |||||
| CarlaString fName; | |||||
| CarlaString fServerPath; | |||||
| lo_server fServer; | |||||
| // ------------------------------------------------------------------- | |||||
| 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 handleMsgControl(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| int handleMsgProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| int handleMsgMidiProgram(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| int handleMsgMidi(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| int handleMsgUpdateURL(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| int handleMsgShow(); | |||||
| int handleMsgHide(); | |||||
| int handleMsgQuit(); | |||||
| #ifdef BRIDGE_LV2 | |||||
| int handleMsgLv2AtomTransfer(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| int handleMsgLv2UridMap(CARLA_BRIDGE_OSC_HANDLE_ARGS); | |||||
| #endif | |||||
| // ------------------------------------------------------------------- | |||||
| static int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* userData) | |||||
| { | |||||
| return ((CarlaBridgeOsc*)userData)->handleMessage(path, argc, argv, types, msg); | |||||
| } | |||||
| static void osc_error_handler(int num, const char* msg, const char* path) | |||||
| { | |||||
| carla_stderr("CarlaBridgeOsc::osc_error_handler(%i, \"%s\", \"%s\")", num, msg, path); | |||||
| } | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeOsc) | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | |||||
| #endif // CARLA_BRIDGE_OSC_HPP_INCLUDED | |||||
| @@ -30,26 +30,26 @@ class CarlaBridgeToolkit | |||||
| public: | public: | ||||
| virtual ~CarlaBridgeToolkit() {} | virtual ~CarlaBridgeToolkit() {} | ||||
| virtual void init() = 0; | |||||
| virtual bool init(const int argc, const char* argv[]) = 0; | |||||
| virtual void exec(const bool showUI) = 0; | virtual void exec(const bool showUI) = 0; | ||||
| virtual void quit() = 0; | virtual void quit() = 0; | ||||
| virtual void show() = 0; | virtual void show() = 0; | ||||
| virtual void focus() = 0; | |||||
| virtual void hide() = 0; | virtual void hide() = 0; | ||||
| virtual void resize(const int width, const int height) = 0; | |||||
| virtual void setSize(const uint width, const uint height) = 0; | |||||
| virtual void setTitle(const char* const title) = 0; | |||||
| virtual void* getContainerId() const { return nullptr; } | virtual void* getContainerId() const { return nullptr; } | ||||
| virtual void* getContainerId2() const { return nullptr; } | virtual void* getContainerId2() const { return nullptr; } | ||||
| static CarlaBridgeToolkit* createNew(CarlaBridgeClient* const client, const char* const windowTitle); | |||||
| static CarlaBridgeToolkit* createNew(CarlaBridgeUI* const ui); | |||||
| protected: | protected: | ||||
| CarlaBridgeClient* const kClient; | |||||
| const CarlaString kWindowTitle; | |||||
| CarlaBridgeUI* const ui; | |||||
| CarlaBridgeToolkit(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| : kClient(client), | |||||
| kWindowTitle(windowTitle), | |||||
| CarlaBridgeToolkit(CarlaBridgeUI* const u) | |||||
| : ui(u), | |||||
| leakDetector_CarlaBridgeToolkit() {} | leakDetector_CarlaBridgeToolkit() {} | ||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkit) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkit) | ||||
| @@ -15,8 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaBridgeToolkit.hpp" | |||||
| #include "CarlaBridgeUI.hpp" | |||||
| #include <gtk/gtk.h> | #include <gtk/gtk.h> | ||||
| @@ -36,8 +35,8 @@ static char** gargv = nullptr; | |||||
| class CarlaBridgeToolkitGtk : public CarlaBridgeToolkit | class CarlaBridgeToolkitGtk : public CarlaBridgeToolkit | ||||
| { | { | ||||
| public: | public: | ||||
| CarlaBridgeToolkitGtk(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| : CarlaBridgeToolkit(client, windowTitle), | |||||
| CarlaBridgeToolkitGtk(CarlaBridgeUI* const ui) | |||||
| : CarlaBridgeToolkit(ui), | |||||
| fNeedsShow(false), | fNeedsShow(false), | ||||
| fWindow(nullptr), | fWindow(nullptr), | ||||
| fLastX(0), | fLastX(0), | ||||
| @@ -55,32 +54,38 @@ public: | |||||
| carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()"); | carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()"); | ||||
| } | } | ||||
| void init() override | |||||
| bool init(const int /*argc*/, const char** /*argv[]*/) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr, false); | |||||
| carla_debug("CarlaBridgeToolkitGtk::init()"); | carla_debug("CarlaBridgeToolkitGtk::init()"); | ||||
| gtk_init(&gargc, &gargv); | gtk_init(&gargc, &gargv); | ||||
| fWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); | fWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr, false); | |||||
| gtk_window_resize(GTK_WINDOW(fWindow), 30, 30); | gtk_window_resize(GTK_WINDOW(fWindow), 30, 30); | ||||
| gtk_widget_hide(fWindow); | gtk_widget_hide(fWindow); | ||||
| return true; | |||||
| } | } | ||||
| void exec(const bool showUI) override | void exec(const bool showUI) override | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | ||||
| carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI)); | carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI)); | ||||
| const CarlaBridgeUI::Options& options(ui->getOptions()); | |||||
| GtkWindow* const gtkWindow(GTK_WINDOW(fWindow)); | GtkWindow* const gtkWindow(GTK_WINDOW(fWindow)); | ||||
| CARLA_SAFE_ASSERT_RETURN(gtkWindow != nullptr,); | CARLA_SAFE_ASSERT_RETURN(gtkWindow != nullptr,); | ||||
| GtkWidget* const widget((GtkWidget*)kClient->getWidget()); | |||||
| GtkWidget* const widget((GtkWidget*)ui->getWidget()); | |||||
| gtk_container_add(GTK_CONTAINER(fWindow), widget); | gtk_container_add(GTK_CONTAINER(fWindow), widget); | ||||
| gtk_window_set_resizable(gtkWindow, kClient->isResizable()); | |||||
| gtk_window_set_title(gtkWindow, kWindowTitle); | |||||
| gtk_window_set_resizable(gtkWindow, options.isResizable); | |||||
| gtk_window_set_title(gtkWindow, options.windowTitle); | |||||
| if (showUI || fNeedsShow) | if (showUI || fNeedsShow) | ||||
| { | { | ||||
| @@ -122,6 +127,11 @@ public: | |||||
| gtk_widget_show_all(fWindow); | gtk_widget_show_all(fWindow); | ||||
| } | } | ||||
| void focus() override | |||||
| { | |||||
| carla_debug("CarlaBridgeToolkitGtk::focus()"); | |||||
| } | |||||
| void hide() override | void hide() override | ||||
| { | { | ||||
| carla_debug("CarlaBridgeToolkitGtk::hide()"); | carla_debug("CarlaBridgeToolkitGtk::hide()"); | ||||
| @@ -132,7 +142,7 @@ public: | |||||
| gtk_widget_hide(fWindow); | gtk_widget_hide(fWindow); | ||||
| } | } | ||||
| void resize(int width, int height) override | |||||
| void setSize(const uint width, const uint height) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | ||||
| carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height); | carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height); | ||||
| @@ -140,6 +150,14 @@ public: | |||||
| gtk_window_resize(GTK_WINDOW(fWindow), width, height); | gtk_window_resize(GTK_WINDOW(fWindow), width, height); | ||||
| } | } | ||||
| void setTitle(const char* const title) override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
| carla_debug("CarlaBridgeToolkitGtk::setTitle(\"%s\")", title); | |||||
| gtk_window_set_title(GTK_WINDOW(fWindow), title); | |||||
| } | |||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| protected: | protected: | ||||
| @@ -177,13 +195,14 @@ protected: | |||||
| gtk_window_get_size(GTK_WINDOW(fWindow), &fLastWidth, &fLastHeight); | gtk_window_get_size(GTK_WINDOW(fWindow), &fLastWidth, &fLastHeight); | ||||
| } | } | ||||
| kClient->uiIdle(); | |||||
| ui->idlePipe(); | |||||
| ui->idleUI(); | |||||
| if (! kClient->oscIdle()) | |||||
| { | |||||
| gtk_main_quit_if_needed(); | |||||
| return false; | |||||
| } | |||||
| // if (! fUi) | |||||
| // { | |||||
| // gtk_main_quit_if_needed(); | |||||
| // return false; | |||||
| // } | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -254,9 +273,9 @@ private: | |||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeUI* const ui) | |||||
| { | { | ||||
| return new CarlaBridgeToolkitGtk(client, windowTitle); | |||||
| return new CarlaBridgeToolkitGtk(ui); | |||||
| } | } | ||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| @@ -15,7 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaBridgeUI.hpp" | |||||
| #include "CarlaBridgeToolkit.hpp" | #include "CarlaBridgeToolkit.hpp" | ||||
| #include "CarlaPluginUI.hpp" | #include "CarlaPluginUI.hpp" | ||||
| @@ -34,13 +34,13 @@ class CarlaBridgeToolkitPlugin : public CarlaBridgeToolkit, | |||||
| private CarlaPluginUI::CloseCallback | private CarlaPluginUI::CloseCallback | ||||
| { | { | ||||
| public: | public: | ||||
| CarlaBridgeToolkitPlugin(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| : CarlaBridgeToolkit(client, windowTitle), | |||||
| CarlaBridgeToolkitPlugin(CarlaBridgeUI* const ui) | |||||
| : CarlaBridgeToolkit(ui), | |||||
| fUI(nullptr), | fUI(nullptr), | ||||
| fIdling(false), | fIdling(false), | ||||
| leakDetector_CarlaBridgeToolkitPlugin() | leakDetector_CarlaBridgeToolkitPlugin() | ||||
| { | { | ||||
| carla_debug("CarlaBridgeToolkitPlugin::CarlaBridgeToolkitPlugin(%p, \"%s\")", client, windowTitle); | |||||
| carla_debug("CarlaBridgeToolkitPlugin::CarlaBridgeToolkitPlugin(%p)", ui); | |||||
| } | } | ||||
| ~CarlaBridgeToolkitPlugin() override | ~CarlaBridgeToolkitPlugin() override | ||||
| @@ -49,26 +49,31 @@ public: | |||||
| carla_debug("CarlaBridgeToolkitPlugin::~CarlaBridgeToolkitPlugin()"); | carla_debug("CarlaBridgeToolkitPlugin::~CarlaBridgeToolkitPlugin()"); | ||||
| } | } | ||||
| void init() override | |||||
| bool init(const int /*argc*/, const char** /*argv[]*/) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fUI == nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI == nullptr, false); | |||||
| carla_debug("CarlaBridgeToolkitPlugin::init()"); | carla_debug("CarlaBridgeToolkitPlugin::init()"); | ||||
| const CarlaBridgeUI::Options& options(ui->getOptions()); | |||||
| #if defined(CARLA_OS_MAC) && defined(BRIDGE_COCOA) | #if defined(CARLA_OS_MAC) && defined(BRIDGE_COCOA) | ||||
| fUI = CarlaPluginUI::newCocoa(this, 0); | |||||
| fUI = CarlaPluginUI::newCocoa(this, 0, options.isResizable); | |||||
| #elif defined(CARLA_OS_WIN) && defined(BRIDGE_HWND) | #elif defined(CARLA_OS_WIN) && defined(BRIDGE_HWND) | ||||
| fUI = CarlaPluginUI::newWindows(this, 0); | |||||
| fUI = CarlaPluginUI::newWindows(this, 0, options.isResizable); | |||||
| #elif defined(HAVE_X11) && defined(BRIDGE_X11) | #elif defined(HAVE_X11) && defined(BRIDGE_X11) | ||||
| fUI = CarlaPluginUI::newX11(this, 0, false); // TODO: check if UI is resizable | |||||
| fUI = CarlaPluginUI::newX11(this, 0, options.isResizable); | |||||
| #endif | #endif | ||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr, false); | |||||
| fUI->setTitle(options.windowTitle); | |||||
| fUI->setTransientWinId(options.transientWindowId); | |||||
| fUI->setTitle(kWindowTitle); | |||||
| return true; | |||||
| } | } | ||||
| void exec(const bool showUI) override | void exec(const bool showUI) override | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | ||||
| carla_debug("CarlaBridgeToolkitPlugin::exec(%s)", bool2str(showUI)); | carla_debug("CarlaBridgeToolkitPlugin::exec(%s)", bool2str(showUI)); | ||||
| @@ -86,10 +91,11 @@ public: | |||||
| for (; fIdling;) | for (; fIdling;) | ||||
| { | { | ||||
| fUI->idle(); | fUI->idle(); | ||||
| kClient->uiIdle(); | |||||
| ui->idlePipe(); | |||||
| ui->idleUI(); | |||||
| if (! kClient->oscIdle()) | |||||
| break; | |||||
| //if (! kClient->oscIdle()) | |||||
| // break; | |||||
| #if defined(CARLA_OS_WIN) || defined(CARLA_OS_MAC) | #if defined(CARLA_OS_WIN) || defined(CARLA_OS_MAC) | ||||
| if (MessageManager* const msgMgr = MessageManager::getInstance()) | if (MessageManager* const msgMgr = MessageManager::getInstance()) | ||||
| @@ -119,6 +125,14 @@ public: | |||||
| fUI->show(); | fUI->show(); | ||||
| } | } | ||||
| void focus() override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||||
| carla_debug("CarlaBridgeToolkitPlugin::focus()"); | |||||
| fUI->focus(); | |||||
| } | |||||
| void hide() override | void hide() override | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | ||||
| @@ -127,14 +141,22 @@ public: | |||||
| fUI->hide(); | fUI->hide(); | ||||
| } | } | ||||
| void resize(int width, int height) override | |||||
| void setSize(const uint width, const uint height) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(width >= 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(height >= 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(width > 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(height > 0,); | |||||
| carla_debug("CarlaBridgeToolkitPlugin::resize(%i, %i)", width, height); | carla_debug("CarlaBridgeToolkitPlugin::resize(%i, %i)", width, height); | ||||
| fUI->setSize(static_cast<uint>(width), static_cast<uint>(height), false); | |||||
| fUI->setSize(width, height, false); | |||||
| } | |||||
| void setTitle(const char* const title) override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||||
| carla_debug("CarlaBridgeToolkitPlugin::setTitle(\"%s\")", title); | |||||
| fUI->setTitle(title); | |||||
| } | } | ||||
| void* getContainerId() const override | void* getContainerId() const override | ||||
| @@ -180,9 +202,9 @@ private: | |||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeUI* const ui) | |||||
| { | { | ||||
| return new CarlaBridgeToolkitPlugin(client, windowTitle); | |||||
| return new CarlaBridgeToolkitPlugin(ui); | |||||
| } | } | ||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| @@ -15,7 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaBridgeUI.hpp" | |||||
| #include "CarlaBridgeToolkit.hpp" | #include "CarlaBridgeToolkit.hpp" | ||||
| #include "CarlaStyle.hpp" | #include "CarlaStyle.hpp" | ||||
| @@ -50,9 +50,9 @@ class CarlaBridgeToolkitQt: public QObject, | |||||
| Q_OBJECT | Q_OBJECT | ||||
| public: | public: | ||||
| CarlaBridgeToolkitQt(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| CarlaBridgeToolkitQt(CarlaBridgeUI* const ui) | |||||
| : QObject(nullptr), | : QObject(nullptr), | ||||
| CarlaBridgeToolkit(client, windowTitle), | |||||
| CarlaBridgeToolkit(ui), | |||||
| fApp(nullptr), | fApp(nullptr), | ||||
| fWindow(nullptr), | fWindow(nullptr), | ||||
| fMsgTimer(0), | fMsgTimer(0), | ||||
| @@ -72,11 +72,11 @@ public: | |||||
| carla_debug("CarlaBridgeToolkitQt::~CarlaBridgeToolkitQt()"); | carla_debug("CarlaBridgeToolkitQt::~CarlaBridgeToolkitQt()"); | ||||
| } | } | ||||
| void init() override | |||||
| bool init(const int /*argc*/, const char** /*argv[]*/) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fApp == nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fMsgTimer == 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fApp == nullptr, false); | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr, false); | |||||
| CARLA_SAFE_ASSERT_RETURN(fMsgTimer == 0, false); | |||||
| carla_debug("CarlaBridgeToolkitQt::init()"); | carla_debug("CarlaBridgeToolkitQt::init()"); | ||||
| fApp = new QApplication(qargc, qargv); | fApp = new QApplication(qargc, qargv); | ||||
| @@ -84,16 +84,20 @@ public: | |||||
| fWindow = new QMainWindow(nullptr); | fWindow = new QMainWindow(nullptr); | ||||
| fWindow->resize(30, 30); | fWindow->resize(30, 30); | ||||
| fWindow->hide(); | fWindow->hide(); | ||||
| return true; | |||||
| } | } | ||||
| void exec(const bool showUI) override | void exec(const bool showUI) override | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | ||||
| carla_debug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showUI)); | carla_debug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showUI)); | ||||
| QWidget* const widget((QWidget*)kClient->getWidget()); | |||||
| const CarlaBridgeUI::Options& options(ui->getOptions()); | |||||
| QWidget* const widget((QWidget*)ui->getWidget()); | |||||
| fWindow->setCentralWidget(widget); | fWindow->setCentralWidget(widget); | ||||
| fWindow->adjustSize(); | fWindow->adjustSize(); | ||||
| @@ -101,7 +105,7 @@ public: | |||||
| widget->setParent(fWindow); | widget->setParent(fWindow); | ||||
| widget->show(); | widget->show(); | ||||
| if (! kClient->isResizable()) | |||||
| if (! options.isResizable) | |||||
| { | { | ||||
| fWindow->setFixedSize(fWindow->width(), fWindow->height()); | fWindow->setFixedSize(fWindow->width(), fWindow->height()); | ||||
| #ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
| @@ -110,18 +114,13 @@ public: | |||||
| } | } | ||||
| fWindow->setWindowIcon(QIcon::fromTheme("carla", QIcon(":/scalable/carla.svg"))); | fWindow->setWindowIcon(QIcon::fromTheme("carla", QIcon(":/scalable/carla.svg"))); | ||||
| fWindow->setWindowTitle(kWindowTitle.buffer()); | |||||
| fWindow->setWindowTitle(options.windowTitle); | |||||
| if (const char* const winIdStr = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) | |||||
| if (options.transientWindowId != 0) | |||||
| { | { | ||||
| if (const long long winId = std::strtoll(winIdStr, nullptr, 16)) | |||||
| { | |||||
| #if defined(CARLA_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | #if defined(CARLA_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | ||||
| XSetTransientForHint(QX11Info::display(), static_cast<::Window>(fWindow->winId()), static_cast<::Window>(winId)); | |||||
| #else | |||||
| (void)winId; | |||||
| XSetTransientForHint(QX11Info::display(), static_cast<::Window>(fWindow->winId()), static_cast<::Window>(options.transientWindowId)); | |||||
| #endif | #endif | ||||
| } | |||||
| } | } | ||||
| if (showUI || fNeedsShow) | if (showUI || fNeedsShow) | ||||
| @@ -141,7 +140,7 @@ public: | |||||
| void quit() override | void quit() override | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | ||||
| carla_debug("CarlaBridgeToolkitQt::quit()"); | carla_debug("CarlaBridgeToolkitQt::quit()"); | ||||
| @@ -180,6 +179,11 @@ public: | |||||
| fWindow->show(); | fWindow->show(); | ||||
| } | } | ||||
| void focus() override | |||||
| { | |||||
| carla_debug("CarlaBridgeToolkitQt::focus()"); | |||||
| } | |||||
| void hide() override | void hide() override | ||||
| { | { | ||||
| carla_debug("CarlaBridgeToolkitQt::hide()"); | carla_debug("CarlaBridgeToolkitQt::hide()"); | ||||
| @@ -190,13 +194,27 @@ public: | |||||
| fWindow->hide(); | fWindow->hide(); | ||||
| } | } | ||||
| void resize(const int width, const int height) override | |||||
| void setSize(const uint width, const uint height) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(width > 0,); | CARLA_SAFE_ASSERT_RETURN(width > 0,); | ||||
| CARLA_SAFE_ASSERT_RETURN(height > 0,); | CARLA_SAFE_ASSERT_RETURN(height > 0,); | ||||
| carla_debug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height); | carla_debug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height); | ||||
| emit setSizeSafeSignal(static_cast<uint>(width), static_cast<uint>(height)); | |||||
| if (ui->getOptions().isResizable) | |||||
| fWindow->resize(width, height); | |||||
| else | |||||
| fWindow->setFixedSize(width, height); | |||||
| } | |||||
| void setTitle(const char* const title) override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0',); | |||||
| carla_debug("CarlaBridgeToolkitQt::setTitle(\"%s\")", title); | |||||
| fWindow->setWindowTitle(title); | |||||
| } | } | ||||
| protected: | protected: | ||||
| @@ -208,21 +226,21 @@ protected: | |||||
| void handleTimeout() | void handleTimeout() | ||||
| { | { | ||||
| if (kClient == nullptr) | |||||
| return; | |||||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||||
| kClient->uiIdle(); | |||||
| ui->idlePipe(); | |||||
| ui->idleUI(); | |||||
| if (! kClient->oscIdle()) | |||||
| { | |||||
| killTimer(fMsgTimer); | |||||
| fMsgTimer = 0; | |||||
| fApp->quit(); | |||||
| } | |||||
| // if (! kClient->oscIdle()) | |||||
| // { | |||||
| // killTimer(fMsgTimer); | |||||
| // fMsgTimer = 0; | |||||
| // fApp->quit(); | |||||
| // } | |||||
| } | } | ||||
| private: | private: | ||||
| void timerEvent(QTimerEvent* const ev) | |||||
| void timerEvent(QTimerEvent* const ev) override | |||||
| { | { | ||||
| if (ev->timerId() == fMsgTimer) | if (ev->timerId() == fMsgTimer) | ||||
| handleTimeout(); | handleTimeout(); | ||||
| @@ -230,21 +248,6 @@ private: | |||||
| QObject::timerEvent(ev); | QObject::timerEvent(ev); | ||||
| } | } | ||||
| signals: | |||||
| void setSizeSafeSignal(int, int); | |||||
| private slots: | |||||
| void setSizeSafeSlot(uint width, uint height) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
| if (kClient->isResizable()) | |||||
| fWindow->resize(width, height); | |||||
| else | |||||
| fWindow->setFixedSize(width, height); | |||||
| } | |||||
| #ifndef MOC_PARSING | #ifndef MOC_PARSING | ||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitQt) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitQt) | ||||
| #endif | #endif | ||||
| @@ -258,9 +261,9 @@ private slots: | |||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const windowTitle) | |||||
| CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeUI* const ui) | |||||
| { | { | ||||
| return new CarlaBridgeToolkitQt(client, windowTitle); | |||||
| return new CarlaBridgeToolkitQt(ui); | |||||
| } | } | ||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| @@ -15,8 +15,8 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaBase64Utils.hpp" | |||||
| #include "CarlaBridgeUI.hpp" | |||||
| #include "CarlaLibUtils.hpp" | |||||
| #include "CarlaLv2Utils.hpp" | #include "CarlaLv2Utils.hpp" | ||||
| #include "CarlaMIDI.h" | #include "CarlaMIDI.h" | ||||
| #include "LinkedList.hpp" | #include "LinkedList.hpp" | ||||
| @@ -185,23 +185,18 @@ struct Lv2PluginOptions { | |||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| class CarlaLv2Client : public CarlaBridgeClient | |||||
| class CarlaLv2Client : public CarlaBridgeUI | |||||
| { | { | ||||
| public: | public: | ||||
| CarlaLv2Client(const char* const uiTitle) | |||||
| : CarlaBridgeClient(uiTitle), | |||||
| CarlaLv2Client() | |||||
| : CarlaBridgeUI(), | |||||
| fHandle(nullptr), | fHandle(nullptr), | ||||
| fWidget(nullptr), | fWidget(nullptr), | ||||
| fDescriptor(nullptr), | fDescriptor(nullptr), | ||||
| fRdfDescriptor(nullptr), | fRdfDescriptor(nullptr), | ||||
| fRdfUiDescriptor(nullptr), | fRdfUiDescriptor(nullptr), | ||||
| fOptions(), | |||||
| fIsReady(false), | |||||
| #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11) | |||||
| fIsResizable(false), | |||||
| #else | |||||
| fIsResizable(true), | |||||
| #endif | |||||
| fLv2Options(), | |||||
| fUiOptions(), | |||||
| fCustomURIDs(), | fCustomURIDs(), | ||||
| fExt(), | fExt(), | ||||
| leakDetector_CarlaLv2Client() | leakDetector_CarlaLv2Client() | ||||
| @@ -214,9 +209,9 @@ public: | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // initialize options | // initialize options | ||||
| fOptions.minBufferSize = gBufferSizei; | |||||
| fOptions.maxBufferSize = gBufferSizei; | |||||
| fOptions.sampleRate = gSampleRate; | |||||
| fLv2Options.minBufferSize = gBufferSizei; | |||||
| fLv2Options.maxBufferSize = gBufferSizei; | |||||
| fLv2Options.sampleRate = gSampleRate; | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // initialize features (part 1) | // initialize features (part 1) | ||||
| @@ -269,7 +264,7 @@ public: | |||||
| fFeatures[kFeatureIdLogs]->data = logFt; | fFeatures[kFeatureIdLogs]->data = logFt; | ||||
| fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options; | fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options; | ||||
| fFeatures[kFeatureIdOptions]->data = fOptions.opts; | |||||
| fFeatures[kFeatureIdOptions]->data = fLv2Options.opts; | |||||
| fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host; | fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host; | ||||
| fFeatures[kFeatureIdPrograms]->data = programsFt; | fFeatures[kFeatureIdPrograms]->data = programsFt; | ||||
| @@ -319,8 +314,19 @@ public: | |||||
| ~CarlaLv2Client() override | ~CarlaLv2Client() override | ||||
| { | { | ||||
| if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr) | |||||
| { | |||||
| fDescriptor->cleanup(fHandle); | |||||
| fHandle = nullptr; | |||||
| } | |||||
| if (fRdfDescriptor != nullptr) | if (fRdfDescriptor != nullptr) | ||||
| { | |||||
| delete fRdfDescriptor; | delete fRdfDescriptor; | ||||
| fRdfDescriptor = nullptr; | |||||
| } | |||||
| fRdfUiDescriptor = nullptr; | |||||
| delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data; | delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data; | ||||
| delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data; | delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data; | ||||
| @@ -343,7 +349,7 @@ public: | |||||
| for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next()) | for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next()) | ||||
| { | { | ||||
| const char* const uri(it.getValue()); | |||||
| const char* const uri(it.getValue(nullptr)); | |||||
| if (uri != nullptr) | if (uri != nullptr) | ||||
| delete[] uri; | delete[] uri; | ||||
| @@ -353,37 +359,40 @@ public: | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| // ui initialization | |||||
| // UI initialization | |||||
| bool uiInit(const char* pluginURI, const char* uiURI, const char* uiBundle) override | |||||
| bool init(const int argc, const char* argv[]) override | |||||
| { | { | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // load bundle | |||||
| // init UI | |||||
| Lv2WorldClass& lv2World(Lv2WorldClass::getInstance()); | |||||
| if (! CarlaBridgeUI::init(argc, argv)) | |||||
| return false; | |||||
| Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, uiBundle)); | |||||
| CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(), false); | |||||
| const char* pluginURI = argv[1]; | |||||
| const char* uiURI = argv[2]; | |||||
| CarlaString sBundle(bundleNode.as_uri()); | |||||
| // ----------------------------------------------------------------- | |||||
| // load plugin | |||||
| if (! sBundle.endsWith("/")) | |||||
| sBundle += "/"; | |||||
| Lv2WorldClass& lv2World(Lv2WorldClass::getInstance()); | |||||
| lv2World.initIfNeeded(std::getenv("LV2_PATH")); | |||||
| lv2World.load_bundle(sBundle); | |||||
| //Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, uiBundle)); | |||||
| //CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(), false); | |||||
| // ----------------------------------------------------------------- | |||||
| // init | |||||
| //CarlaString sBundle(bundleNode.as_uri()); | |||||
| CarlaBridgeClient::uiInit(pluginURI, uiURI, uiBundle); | |||||
| //if (! sBundle.endsWith("/")) | |||||
| // sBundle += "/"; | |||||
| //lv2World.load_bundle(sBundle); | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // get plugin from lv2_rdf (lilv) | // get plugin from lv2_rdf (lilv) | ||||
| fRdfDescriptor = lv2_rdf_new(pluginURI, true); | fRdfDescriptor = lv2_rdf_new(pluginURI, true); | ||||
| if (fRdfDescriptor == nullptr) | |||||
| return false; | |||||
| CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // find requested UI | // find requested UI | ||||
| @@ -397,25 +406,21 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| if (fRdfUiDescriptor == nullptr) | |||||
| { | |||||
| carla_stderr("Failed to find requested UI"); | |||||
| return false; | |||||
| } | |||||
| CARLA_SAFE_ASSERT_RETURN(fRdfUiDescriptor != nullptr, false); | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // open DLL | // open DLL | ||||
| if (! uiLibOpen(fRdfUiDescriptor->Binary)) | |||||
| if (! libOpen(fRdfUiDescriptor->Binary)) | |||||
| { | { | ||||
| carla_stderr("Failed to load UI binary, error was:\n%s", uiLibError()); | |||||
| carla_stderr("Failed to load UI binary, error was:\n%s", libError()); | |||||
| return false; | return false; | ||||
| } | } | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // get DLL main entry | // get DLL main entry | ||||
| const LV2UI_DescriptorFunction ui_descFn = uiLibSymbol<LV2UI_DescriptorFunction>("lv2ui_descriptor"); | |||||
| const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)libSymbol("lv2ui_descriptor"); | |||||
| if (ui_descFn == nullptr) | if (ui_descFn == nullptr) | ||||
| return false; | return false; | ||||
| @@ -440,26 +445,21 @@ public: | |||||
| // initialize UI | // initialize UI | ||||
| #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11) | #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11) | ||||
| fFeatures[kFeatureIdUiParent]->data = getContainerId(); | |||||
| fFeatures[kFeatureIdUiParent]->data = fToolkit->getContainerId(); | |||||
| #endif | #endif | ||||
| fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures); | fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures); | ||||
| if (fHandle == nullptr) | |||||
| { | |||||
| carla_stderr("Failed to init UI"); | |||||
| return false; | |||||
| } | |||||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); | |||||
| // ----------------------------------------------------------- | // ----------------------------------------------------------- | ||||
| // check if not resizable | // check if not resizable | ||||
| for (uint32_t j=0; j < fRdfUiDescriptor->FeatureCount && fIsResizable; ++j) | |||||
| for (uint32_t j=0; j < fRdfUiDescriptor->FeatureCount; ++j) | |||||
| { | { | ||||
| if (std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__fixedSize ) == 0 || | if (std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__fixedSize ) == 0 || | ||||
| std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__noUserResize) == 0) | std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__noUserResize) == 0) | ||||
| { | { | ||||
| fIsResizable = false; | |||||
| fUiOptions.isResizable = false; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -483,57 +483,44 @@ public: | |||||
| return true; | return true; | ||||
| } | } | ||||
| void uiIdle() override | |||||
| void idleUI() override | |||||
| { | { | ||||
| if (fHandle != nullptr && fExt.idle != nullptr) | if (fHandle != nullptr && fExt.idle != nullptr) | ||||
| fExt.idle->idle(fHandle); | fExt.idle->idle(fHandle); | ||||
| } | } | ||||
| void uiClose() override | |||||
| { | |||||
| if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr) | |||||
| { | |||||
| fDescriptor->cleanup(fHandle); | |||||
| fHandle = nullptr; | |||||
| } | |||||
| CarlaBridgeClient::uiClose(); | |||||
| uiLibClose(); | |||||
| } | |||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| // ui management | |||||
| // UI management | |||||
| void* getWidget() const override | |||||
| void* getWidget() const noexcept override | |||||
| { | { | ||||
| return fWidget; | return fWidget; | ||||
| } | } | ||||
| bool isResizable() const override | |||||
| const Options& getOptions() const noexcept override | |||||
| { | { | ||||
| return fIsResizable; | |||||
| return fUiOptions; | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| // ui processing | |||||
| // DSP Callbacks | |||||
| void setParameter(const int32_t rindex, const float value) override | |||||
| void dspParameterChanged(const uint32_t index, const float value) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | ||||
| CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(rindex >= 0,) | |||||
| if (fDescriptor->port_event == nullptr) | if (fDescriptor->port_event == nullptr) | ||||
| return; | return; | ||||
| fDescriptor->port_event(fHandle, static_cast<uint32_t>(rindex), sizeof(float), CARLA_URI_MAP_ID_NULL, &value); | |||||
| fDescriptor->port_event(fHandle, index, sizeof(float), CARLA_URI_MAP_ID_NULL, &value); | |||||
| } | } | ||||
| void setProgram(const uint32_t) override | |||||
| void dspProgramChanged(const uint32_t) override | |||||
| { | { | ||||
| } | } | ||||
| void setMidiProgram(const uint32_t bank, const uint32_t program) override | |||||
| void dspMidiProgramChanged(const uint32_t bank, const uint32_t program) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | ||||
| @@ -543,7 +530,11 @@ public: | |||||
| fExt.programs->select_program(fHandle, bank, program); | fExt.programs->select_program(fHandle, bank, program); | ||||
| } | } | ||||
| void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override | |||||
| void dspStateChanged(const char* const, const char* const) override | |||||
| { | |||||
| } | |||||
| void dspNoteReceived(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | ||||
| CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | ||||
| @@ -554,42 +545,31 @@ public: | |||||
| LV2_Atom_MidiEvent midiEv; | LV2_Atom_MidiEvent midiEv; | ||||
| midiEv.atom.type = CARLA_URI_MAP_ID_MIDI_EVENT; | midiEv.atom.type = CARLA_URI_MAP_ID_MIDI_EVENT; | ||||
| midiEv.atom.size = 3; | midiEv.atom.size = 3; | ||||
| midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiEv.data[0] = uint8_t((onOff ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiEv.data[1] = note; | midiEv.data[1] = note; | ||||
| midiEv.data[2] = velo; | |||||
| midiEv.data[2] = velocity; | |||||
| fDescriptor->port_event(fHandle, /* TODO */ 0, lv2_atom_total_size(midiEv), CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv); | fDescriptor->port_event(fHandle, /* TODO */ 0, lv2_atom_total_size(midiEv), CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv); | ||||
| } | } | ||||
| void noteOff(const uint8_t channel, const uint8_t note) override | |||||
| void dspAtomReceived(const uint32_t portIndex, const LV2_Atom* const atom) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,) | ||||
| CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); | |||||
| if (fDescriptor->port_event == nullptr) | if (fDescriptor->port_event == nullptr) | ||||
| return; | return; | ||||
| LV2_Atom_MidiEvent midiEv; | |||||
| midiEv.atom.type = CARLA_URI_MAP_ID_MIDI_EVENT; | |||||
| midiEv.atom.size = 3; | |||||
| midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiEv.data[1] = note; | |||||
| midiEv.data[2] = 0; | |||||
| fDescriptor->port_event(fHandle, /* TODO */ 0, lv2_atom_total_size(midiEv), CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv); | |||||
| fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom); | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | |||||
| void waitForOscURIs() | |||||
| void dspURIDReceived(const LV2_URID urid, const char* const uri) | |||||
| { | { | ||||
| sendOscUpdate(); | |||||
| CARLA_SAFE_ASSERT_RETURN(urid == fCustomURIDs.count(),); | |||||
| CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); | |||||
| for (;;) | |||||
| { | |||||
| if (fIsReady || ! oscIdle(true)) | |||||
| return; | |||||
| } | |||||
| fCustomURIDs.append(carla_strdup(uri)); | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| @@ -618,8 +598,8 @@ public: | |||||
| fCustomURIDs.append(carla_strdup(uri)); | fCustomURIDs.append(carla_strdup(uri)); | ||||
| } | } | ||||
| if (isOscControlRegistered()) | |||||
| sendOscLv2UridMap(urid, uri); | |||||
| if (isPipeRunning()) | |||||
| sendURID(urid, uri); | |||||
| return urid; | return urid; | ||||
| } | } | ||||
| @@ -637,8 +617,8 @@ public: | |||||
| void handleProgramChanged(const int32_t /*index*/) | void handleProgramChanged(const int32_t /*index*/) | ||||
| { | { | ||||
| if (isOscControlRegistered()) | |||||
| sendOscConfigure("reloadprograms", ""); | |||||
| if (isPipeRunning()) | |||||
| sendConfigure("reloadprograms", ""); | |||||
| } | } | ||||
| uint32_t handleUiPortMap(const char* const symbol) | uint32_t handleUiPortMap(const char* const symbol) | ||||
| @@ -657,11 +637,12 @@ public: | |||||
| int handleUiResize(const int width, const int height) | int handleUiResize(const int width, const int height) | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, 1); | |||||
| CARLA_SAFE_ASSERT_RETURN(width > 0, 1); | CARLA_SAFE_ASSERT_RETURN(width > 0, 1); | ||||
| CARLA_SAFE_ASSERT_RETURN(height > 0, 1); | CARLA_SAFE_ASSERT_RETURN(height > 0, 1); | ||||
| carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height); | carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height); | ||||
| toolkitResize(width, height); | |||||
| fToolkit->setSize(static_cast<uint>(width), static_cast<uint>(height)); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -674,30 +655,21 @@ public: | |||||
| if (format == 0) | if (format == 0) | ||||
| { | { | ||||
| CARLA_ASSERT(buffer != nullptr); | |||||
| CARLA_ASSERT(bufferSize == sizeof(float)); | |||||
| if (bufferSize != sizeof(float)) | |||||
| return; | |||||
| if (buffer == nullptr || bufferSize != sizeof(float)) | |||||
| return; | |||||
| CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),); | |||||
| const float value(*(const float*)buffer); | const float value(*(const float*)buffer); | ||||
| if (isOscControlRegistered()) | |||||
| sendOscControl(static_cast<int32_t>(portIndex), value); | |||||
| if (isPipeRunning()) | |||||
| sendControl(portIndex, value); | |||||
| } | } | ||||
| else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT) | else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT) | ||||
| { | { | ||||
| CARLA_ASSERT(bufferSize != 0); | |||||
| CARLA_ASSERT(buffer != nullptr); | |||||
| CARLA_SAFE_ASSERT_RETURN(bufferSize >= sizeof(LV2_Atom),); | |||||
| if (bufferSize == 0 || buffer == nullptr) | |||||
| return; | |||||
| const LV2_Atom* const atom((const LV2_Atom*)buffer); | |||||
| if (isOscControlRegistered()) | |||||
| sendOscLv2AtomTransfer(portIndex, CarlaString::asBase64(buffer, bufferSize).buffer()); | |||||
| if (isPipeRunning()) | |||||
| sendAtom(portIndex, atom); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -707,63 +679,6 @@ public: | |||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| void handleAtomTransfer(const uint32_t portIndex, const LV2_Atom* const atom) | |||||
| { | |||||
| CARLA_ASSERT(atom != nullptr); | |||||
| carla_debug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom); | |||||
| if (atom != nullptr && fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr) | |||||
| fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom); | |||||
| } | |||||
| void handleUridMap(const LV2_URID urid, const char* const uri) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); | |||||
| carla_stdout("CarlaLv2Client::handleUridMap(%i, \"%s\")", urid, uri); | |||||
| if (urid == CARLA_URI_MAP_ID_NULL) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(std::strcmp(uri, "Complete") == 0,); | |||||
| carla_stdout("URID map from host complete"); | |||||
| fIsReady = true; | |||||
| return; | |||||
| } | |||||
| const uint32_t uridCount(static_cast<uint32_t>(fCustomURIDs.count())); | |||||
| if (urid < uridCount) | |||||
| { | |||||
| if (const char* const ourURI = carla_lv2_urid_unmap(this, urid)) | |||||
| { | |||||
| if (std::strcmp(ourURI, uri) != 0) | |||||
| carla_stderr2("UI :: wrong URI '%s' vs '%s'", ourURI, uri); | |||||
| } | |||||
| else | |||||
| { | |||||
| uint32_t i=0; | |||||
| for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next()) | |||||
| { | |||||
| if (i != urid) | |||||
| continue; | |||||
| CARLA_SAFE_ASSERT(it.getValue() == nullptr); | |||||
| it.setValue(carla_strdup(uri)); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| else if (urid > uridCount) | |||||
| { | |||||
| for (uint32_t i=uridCount; i < urid; ++i) | |||||
| fCustomURIDs.append(nullptr); | |||||
| fCustomURIDs.append(carla_strdup(uri)); | |||||
| } | |||||
| else // urid == uridCount | |||||
| { | |||||
| fCustomURIDs.append(carla_strdup(uri)); | |||||
| } | |||||
| } | |||||
| private: | private: | ||||
| LV2UI_Handle fHandle; | LV2UI_Handle fHandle; | ||||
| LV2UI_Widget fWidget; | LV2UI_Widget fWidget; | ||||
| @@ -772,10 +687,9 @@ private: | |||||
| const LV2UI_Descriptor* fDescriptor; | const LV2UI_Descriptor* fDescriptor; | ||||
| const LV2_RDF_Descriptor* fRdfDescriptor; | const LV2_RDF_Descriptor* fRdfDescriptor; | ||||
| const LV2_RDF_UI* fRdfUiDescriptor; | const LV2_RDF_UI* fRdfUiDescriptor; | ||||
| Lv2PluginOptions fOptions; | |||||
| Lv2PluginOptions fLv2Options; | |||||
| bool fIsReady; | |||||
| bool fIsResizable; | |||||
| Options fUiOptions; | |||||
| LinkedList<const char*> fCustomURIDs; | LinkedList<const char*> fCustomURIDs; | ||||
| struct Extensions { | struct Extensions { | ||||
| @@ -1182,90 +1096,37 @@ private: | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client) | ||||
| }; | }; | ||||
| #define lv2ClientPtr ((CarlaLv2Client*)kClient) | |||||
| int CarlaBridgeOsc::handleMsgLv2AtomTransfer(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is"); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgLv2AtomTransfer()"); | |||||
| if (kClient == nullptr) | |||||
| return 1; | |||||
| const int32_t portIndex = argv[0]->i; | |||||
| const char* const atomBuf = (const char*)&argv[1]->s; | |||||
| if (portIndex < 0) | |||||
| return 0; | |||||
| std::vector<uint8_t> chunk(carla_getChunkFromBase64String(atomBuf)); | |||||
| CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, 0); | |||||
| const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); | |||||
| lv2ClientPtr->handleAtomTransfer(static_cast<uint32_t>(portIndex), atom); | |||||
| return 0; | |||||
| } | |||||
| int CarlaBridgeOsc::handleMsgLv2UridMap(CARLA_BRIDGE_OSC_HANDLE_ARGS) | |||||
| { | |||||
| CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is"); | |||||
| carla_debug("CarlaBridgeOsc::handleMsgLv2UridMap()"); | |||||
| if (kClient == nullptr) | |||||
| return 1; | |||||
| const int32_t urid = argv[0]->i; | |||||
| const char* const uri = (const char*)&argv[1]->s; | |||||
| if (urid < 0) | |||||
| return 0; | |||||
| lv2ClientPtr->handleUridMap(static_cast<LV2_URID>(urid), uri); | |||||
| return 0; | |||||
| } | |||||
| #undef lv2ClientPtr | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | CARLA_BRIDGE_END_NAMESPACE | ||||
| int main(int argc, char* argv[]) | |||||
| // ----------------------------------------------------------------------- | |||||
| int main(int argc, const char* argv[]) | |||||
| { | { | ||||
| CARLA_BRIDGE_USE_NAMESPACE | CARLA_BRIDGE_USE_NAMESPACE | ||||
| if (argc != 6) | |||||
| if (argc < 3) | |||||
| { | { | ||||
| carla_stderr("usage: %s <osc-url|\"null\"><plugin-uri> <ui-uri> <ui-bundle> <ui-title>", argv[0]); | |||||
| carla_stderr("usage: %s <plugin-uri> <ui-uri>", argv[0]); | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| const char* oscUrl = argv[1]; | |||||
| const char* pluginURI = argv[2]; | |||||
| const char* uiURI = argv[3]; | |||||
| const char* uiBundle = argv[4]; | |||||
| const char* uiTitle = argv[5]; | |||||
| const bool useOsc(std::strcmp(oscUrl, "null") != 0); | |||||
| const bool testingModeOnly = (argc != 7); | |||||
| // try to get sampleRate value | // try to get sampleRate value | ||||
| if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE")) | if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE")) | ||||
| gSampleRate = std::atof(sampleRateStr); | gSampleRate = std::atof(sampleRateStr); | ||||
| // Init LV2 client | // Init LV2 client | ||||
| CarlaLv2Client client(uiTitle); | |||||
| // Init OSC | |||||
| if (useOsc) | |||||
| { | |||||
| client.oscInit(oscUrl); | |||||
| client.waitForOscURIs(); | |||||
| } | |||||
| CarlaLv2Client client; | |||||
| // Load UI | // Load UI | ||||
| int ret; | int ret; | ||||
| if (client.uiInit(pluginURI, uiURI, uiBundle)) | |||||
| if (client.init(argc, argv)) | |||||
| { | { | ||||
| client.toolkitExec(!useOsc); | |||||
| client.exec(testingModeOnly); | |||||
| ret = 0; | ret = 0; | ||||
| } | } | ||||
| else | else | ||||
| @@ -1273,12 +1134,7 @@ int main(int argc, char* argv[]) | |||||
| ret = 1; | ret = 1; | ||||
| } | } | ||||
| // Close OSC | |||||
| if (useOsc) | |||||
| client.oscClose(); | |||||
| // Close LV2 client | |||||
| client.uiClose(); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| // ----------------------------------------------------------------------- | |||||
| @@ -15,8 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaBridgeClient.hpp" | |||||
| #include "CarlaBridgeToolkit.hpp" | |||||
| #include "CarlaBridgeUI.hpp" | |||||
| #include "CarlaVstUtils.hpp" | #include "CarlaVstUtils.hpp" | ||||
| #include "CarlaMIDI.h" | #include "CarlaMIDI.h" | ||||
| @@ -28,11 +27,11 @@ CARLA_BRIDGE_START_NAMESPACE | |||||
| uint32_t bufferSize = 512; | uint32_t bufferSize = 512; | ||||
| double sampleRate = 44100.0; | double sampleRate = 44100.0; | ||||
| class CarlaVstClient : public CarlaBridgeClient | |||||
| class CarlaVstClient : public CarlaBridgeUI | |||||
| { | { | ||||
| public: | public: | ||||
| CarlaVstClient(const char* const uiTitle) | |||||
| : CarlaBridgeClient(uiTitle), | |||||
| CarlaVstClient() | |||||
| : CarlaBridgeUI(), | |||||
| unique1(0), | unique1(0), | ||||
| effect(nullptr), | effect(nullptr), | ||||
| needIdle(false), | needIdle(false), | ||||
| @@ -58,7 +57,7 @@ public: | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // init | // init | ||||
| CarlaBridgeClient::uiInit(binary, nullptr, nullptr); | |||||
| CarlaBridgeUI::uiInit(binary, nullptr, nullptr); | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // open DLL | // open DLL | ||||
| @@ -155,7 +154,7 @@ public: | |||||
| effect = nullptr; | effect = nullptr; | ||||
| } | } | ||||
| CarlaBridgeClient::uiClose(); | |||||
| CarlaBridgeUI::uiClose(); | |||||
| uiLibClose(); | uiLibClose(); | ||||
| } | } | ||||
| @@ -0,0 +1,674 @@ | |||||
| /* | |||||
| * Carla Bridge UI | |||||
| * Copyright (C) 2011-2014 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 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 doc/GPL.txt file. | |||||
| */ | |||||
| #include "CarlaBridgeUI.hpp" | |||||
| #include "CarlaMIDI.h" | |||||
| #include "CarlaBase64Utils.hpp" | |||||
| #ifdef BRIDGE_LV2 | |||||
| # undef NULL | |||||
| # define NULL nullptr | |||||
| # include "lv2/atom-util.h" | |||||
| #endif | |||||
| CARLA_BRIDGE_START_NAMESPACE | |||||
| // --------------------------------------------------------------------- | |||||
| CarlaBridgeUI::CarlaBridgeUI() noexcept | |||||
| : CarlaPipeClient(), | |||||
| fQuitReceived(false), | |||||
| #ifdef BRIDGE_LV2 | |||||
| fUridMapComplete(false), | |||||
| #endif | |||||
| fToolkit(nullptr), | |||||
| fLib(nullptr), | |||||
| fLibFilename(), | |||||
| leakDetector_CarlaBridgeUI() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::CarlaBridgeUI()"); | |||||
| try { | |||||
| fToolkit = CarlaBridgeToolkit::createNew(this); | |||||
| } CARLA_SAFE_EXCEPTION_RETURN("CarlaBridgeToolkit::createNew",); | |||||
| } | |||||
| CarlaBridgeUI::~CarlaBridgeUI() noexcept | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::~CarlaBridgeUI()"); | |||||
| if (fLib != nullptr) | |||||
| { | |||||
| lib_close(fLib); | |||||
| fLib = nullptr; | |||||
| } | |||||
| if (isPipeRunning() && ! fQuitReceived) | |||||
| { | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| writeMessage("exiting\n", 8); | |||||
| flushMessages(); | |||||
| } | |||||
| if (fToolkit != nullptr) | |||||
| { | |||||
| fToolkit->quit(); | |||||
| delete fToolkit; | |||||
| fToolkit = nullptr; | |||||
| } | |||||
| closePipeClient(); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // Host DSP State | |||||
| void CarlaBridgeUI::sendControl(const uint32_t index, const float value) const noexcept | |||||
| { | |||||
| char tmpBuf[0xff+1]; | |||||
| tmpBuf[0xff] = '\0'; | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| const ScopedLocale csl; | |||||
| writeMessage("control\n", 8); | |||||
| { | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", index); | |||||
| writeMessage(tmpBuf); | |||||
| std::snprintf(tmpBuf, 0xff, "%f\n", value); | |||||
| writeMessage(tmpBuf); | |||||
| } | |||||
| flushMessages(); | |||||
| } | |||||
| void CarlaBridgeUI::sendProgram(const uint32_t index) const noexcept | |||||
| { | |||||
| char tmpBuf[0xff+1]; | |||||
| tmpBuf[0xff] = '\0'; | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| writeMessage("program\n", 8); | |||||
| { | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", index); | |||||
| writeMessage(tmpBuf); | |||||
| } | |||||
| flushMessages(); | |||||
| } | |||||
| void CarlaBridgeUI::sendConfigure(const char* const key, const char* const value) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | |||||
| CARLA_SAFE_ASSERT_RETURN(value != nullptr,); | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| writeMessage("configure\n", 10); | |||||
| { | |||||
| writeAndFixMessage(key); | |||||
| writeAndFixMessage(value); | |||||
| } | |||||
| flushMessages(); | |||||
| } | |||||
| void CarlaBridgeUI::sendNote(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE,); | |||||
| char tmpBuf[0xff+1]; | |||||
| tmpBuf[0xff] = '\0'; | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| writeMessage("note\n", 5); | |||||
| { | |||||
| std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(onOff)); | |||||
| writeMessage(tmpBuf); | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", channel); | |||||
| writeMessage(tmpBuf); | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", note); | |||||
| writeMessage(tmpBuf); | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", velocity); | |||||
| writeMessage(tmpBuf); | |||||
| } | |||||
| flushMessages(); | |||||
| } | |||||
| #ifdef BRIDGE_LV2 | |||||
| void CarlaBridgeUI::sendAtom(const uint32_t index, const LV2_Atom* const atom) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); | |||||
| char tmpBuf[0xff+1]; | |||||
| tmpBuf[0xff] = '\0'; | |||||
| CarlaString base64atom(CarlaString::asBase64(atom, lv2_atom_total_size(atom))); | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| writeMessage("atom\n", 5); | |||||
| { | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", index); | |||||
| writeMessage(tmpBuf); | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", atom->size); | |||||
| writeMessage(tmpBuf); | |||||
| writeAndFixMessage(base64atom.buffer()); | |||||
| } | |||||
| flushMessages(); | |||||
| } | |||||
| void CarlaBridgeUI::sendURID(const LV2_URID urid, const char* const uri) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(urid != 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); | |||||
| char tmpBuf[0xff+1]; | |||||
| tmpBuf[0xff] = '\0'; | |||||
| const CarlaMutexLocker cml(getPipeLock()); | |||||
| writeMessage("urid\n", 5); | |||||
| { | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", urid); | |||||
| writeMessage(tmpBuf); | |||||
| writeAndFixMessage(uri); | |||||
| } | |||||
| flushMessages(); | |||||
| } | |||||
| #endif | |||||
| bool CarlaBridgeUI::libOpen(const char* const filename) noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fLib == nullptr, false); | |||||
| fLib = lib_open(filename); | |||||
| if (fLib != nullptr) | |||||
| { | |||||
| fLibFilename = filename; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| void* CarlaBridgeUI::libSymbol(const char* const symbol) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fLib != nullptr, nullptr); | |||||
| return lib_symbol<void*>(fLib, symbol); | |||||
| } | |||||
| const char* CarlaBridgeUI::libError() const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fLibFilename.isNotEmpty(), nullptr); | |||||
| return lib_error(fLibFilename); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| bool CarlaBridgeUI::msgReceived(const char* const msg) noexcept | |||||
| { | |||||
| #ifdef BRIDGE_LV2 | |||||
| if (! fUridMapComplete) { | |||||
| CARLA_SAFE_ASSERT_RETURN(std::strcmp(msg, "urid") == 0, true); | |||||
| } | |||||
| #endif | |||||
| if (std::strcmp(msg, "control") == 0) | |||||
| { | |||||
| uint32_t index; | |||||
| float value; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); | |||||
| dspParameterChanged(index, value); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "program") == 0) | |||||
| { | |||||
| uint32_t index; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||||
| dspProgramChanged(index); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "mprogram") == 0) | |||||
| { | |||||
| uint32_t bank, program; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(bank), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(program), true); | |||||
| dspMidiProgramChanged(bank, program); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "configure") == 0) | |||||
| { | |||||
| const char* key; | |||||
| const char* value; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value), true); | |||||
| dspStateChanged(key, value); | |||||
| delete[] key; | |||||
| delete[] value; | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "note") == 0) | |||||
| { | |||||
| bool onOff; | |||||
| uint8_t channel, note, velocity; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(channel), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(note), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(velocity), true); | |||||
| dspNoteReceived(onOff, channel, note, velocity); | |||||
| } | |||||
| #ifdef BRIDGE_LV2 | |||||
| if (std::strcmp(msg, "atom") == 0) | |||||
| { | |||||
| uint32_t index, size; | |||||
| const char* base64atom; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom), true); | |||||
| std::vector<uint8_t> chunk(carla_getChunkFromBase64String(base64atom)); | |||||
| delete[] base64atom; | |||||
| CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); | |||||
| const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); | |||||
| CARLA_SAFE_ASSERT_RETURN(atom->size == chunk.size(), true); | |||||
| dspAtomReceived(index, atom); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "urid") == 0) | |||||
| { | |||||
| uint32_t urid; | |||||
| const char* uri; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri), true); | |||||
| if (urid == 0) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(std::strcmp(uri, "Complete") == 0, true); | |||||
| fUridMapComplete = true; | |||||
| } | |||||
| else | |||||
| { | |||||
| dspURIDReceived(urid, uri); | |||||
| } | |||||
| delete[] uri; | |||||
| return true; | |||||
| } | |||||
| #endif | |||||
| CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, true); | |||||
| if (std::strcmp(msg, "show") == 0) | |||||
| { | |||||
| fToolkit->show(); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "focus") == 0) | |||||
| { | |||||
| fToolkit->focus(); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "hide") == 0) | |||||
| { | |||||
| fToolkit->hide(); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "quit") == 0) | |||||
| { | |||||
| fQuitReceived = true; | |||||
| fToolkit->quit(); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "uiTitle") == 0) | |||||
| { | |||||
| const char* title; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(title), true); | |||||
| fToolkit->setTitle(title); | |||||
| delete[] title; | |||||
| return true; | |||||
| } | |||||
| carla_stderr("CarlaBridgeUI::msgReceived : %s", msg); | |||||
| return false; | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| bool CarlaBridgeUI::init(const int argc, const char* argv[]) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, false); | |||||
| if (! fToolkit->init(argc, argv)) | |||||
| return false; | |||||
| if (argc == 7) | |||||
| { | |||||
| if (! initPipeClient(argv)) | |||||
| { | |||||
| fToolkit->quit(); | |||||
| delete fToolkit; | |||||
| fToolkit = nullptr; | |||||
| return false; | |||||
| } | |||||
| #ifdef BRIDGE_LV2 | |||||
| // wait for URID map to complete | |||||
| for (int i=0; i<20 && ! fUridMapComplete; ++i) | |||||
| { | |||||
| idlePipe(); | |||||
| carla_msleep(100); | |||||
| } | |||||
| if (! fUridMapComplete) | |||||
| { | |||||
| fToolkit->quit(); | |||||
| delete fToolkit; | |||||
| fToolkit = nullptr; | |||||
| closePipeClient(); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| return true; | |||||
| } | |||||
| void CarlaBridgeUI::exec(const bool showUI) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr,); | |||||
| fToolkit->exec(showUI); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | |||||
| #include "CarlaPipeUtils.cpp" | |||||
| // --------------------------------------------------------------------- | |||||
| #if 0 | |||||
| // --------------------------------------------------------------------- | |||||
| // ui initialization | |||||
| bool CarlaBridgeUI::uiInit(const char*, const char* const, const char* const) | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::uiInit()"); | |||||
| fUI.init(); | |||||
| return true; | |||||
| } | |||||
| void CarlaBridgeUI::uiClose() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::uiClose()"); | |||||
| if (isOscControlRegistered() && ! fUI.quit) | |||||
| sendOscExiting(); | |||||
| fUI.close(); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // ui toolkit | |||||
| void CarlaBridgeUI::toolkitShow() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeUI::toolkitShow()"); | |||||
| fUI.toolkit->show(); | |||||
| } | |||||
| void CarlaBridgeUI::toolkitHide() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeUI::toolkitHide()"); | |||||
| fUI.toolkit->hide(); | |||||
| } | |||||
| void CarlaBridgeUI::toolkitResize(const int width, const int height) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeUI::toolkitResize(%i, %i)", width, height); | |||||
| fUI.toolkit->resize(width, height); | |||||
| } | |||||
| void CarlaBridgeUI::toolkitExec(const bool showGui) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.toolkit != nullptr,); | |||||
| carla_debug("CarlaBridgeUI::toolkitExec(%s)", bool2str(showGui)); | |||||
| fUI.toolkit->exec(showGui); | |||||
| } | |||||
| void CarlaBridgeUI::toolkitQuit() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::toolkitQuit()"); | |||||
| fUI.quit = true; | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // osc stuff | |||||
| void CarlaBridgeUI::oscInit(const char* const url) | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::oscInit(\"%s\")", url); | |||||
| fOsc.init(url); | |||||
| } | |||||
| bool CarlaBridgeUI::oscIdle(const bool onlyOnce) const | |||||
| { | |||||
| if (onlyOnce) | |||||
| fOsc.idleOnce(); | |||||
| else | |||||
| fOsc.idle(); | |||||
| return ! fUI.quit; | |||||
| } | |||||
| void CarlaBridgeUI::oscClose() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::oscClose()"); | |||||
| fOsc.close(); | |||||
| } | |||||
| bool CarlaBridgeUI::isOscControlRegistered() const noexcept | |||||
| { | |||||
| return fOsc.isControlRegistered(); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscUpdate() const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscUpdate()"); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_update(fOscData, fOsc.getServerPath()); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| void CarlaBridgeUI::sendOscConfigure(const char* const key, const char* const value) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscConfigure(\"%s\", \"%s\")", key, value); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_configure(fOscData, key, value); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscControl(const int32_t index, const float value) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscControl(%i, %f)", index, value); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_control(fOscData, index, value); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscProgram(const uint32_t index) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscProgram(%i)", index); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_program(fOscData, index); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscMidiProgram(const uint32_t index) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscMidiProgram(%i)", index); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_midi_program(fOscData, index); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscMidi(const uint8_t midiBuf[4]) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscMidi(%p)", midiBuf); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_midi(fOscData, midiBuf); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscExiting() const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscExiting()"); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_exiting(fOscData); | |||||
| } | |||||
| #ifdef BRIDGE_LV2 | |||||
| void CarlaBridgeUI::sendOscLv2AtomTransfer(const uint32_t portIndex, const char* const atomBuf) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscLv2TransferAtom(%i, \"%s\")", portIndex, atomBuf); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_lv2_atom_transfer(fOscData, portIndex, atomBuf); | |||||
| } | |||||
| void CarlaBridgeUI::sendOscLv2UridMap(const uint32_t urid, const char* const uri) const | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::sendOscLv2UridMap(%i, \"%s\")", urid, uri); | |||||
| if (fOscData.target != nullptr) | |||||
| osc_send_lv2_urid_map(fOscData, urid, uri); | |||||
| } | |||||
| #endif | |||||
| // --------------------------------------------------------------------- | |||||
| void* CarlaBridgeUI::getContainerId() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::getContainerId()"); | |||||
| return fUI.toolkit->getContainerId(); | |||||
| } | |||||
| void* CarlaBridgeUI::getContainerId2() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::getContainerId2()"); | |||||
| return fUI.toolkit->getContainerId2(); | |||||
| } | |||||
| bool CarlaBridgeUI::uiLibOpen(const char* const filename) | |||||
| { | |||||
| CARLA_ASSERT(fUI.lib == nullptr); | |||||
| CARLA_ASSERT(filename != nullptr); | |||||
| carla_debug("CarlaBridgeUI::uiLibOpen(\"%s\")", filename); | |||||
| fUI.lib = lib_open(filename); | |||||
| fUI.filename = filename; | |||||
| return (fUI.lib != nullptr); | |||||
| } | |||||
| bool CarlaBridgeUI::uiLibClose() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.lib != nullptr, false); | |||||
| carla_debug("CarlaBridgeUI::uiLibClose()"); | |||||
| const bool closed = lib_close(fUI.lib); | |||||
| fUI.lib = nullptr; | |||||
| return closed; | |||||
| } | |||||
| const char* CarlaBridgeUI::uiLibError() | |||||
| { | |||||
| carla_debug("CarlaBridgeUI::uiLibError()"); | |||||
| return lib_error(fUI.filename); | |||||
| } | |||||
| #endif | |||||
| @@ -0,0 +1,279 @@ | |||||
| /* | |||||
| * Carla Bridge UI | |||||
| * Copyright (C) 2011-2014 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 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 doc/GPL.txt file. | |||||
| */ | |||||
| #ifndef CARLA_BRIDGE_UI_HPP_INCLUDED | |||||
| #define CARLA_BRIDGE_UI_HPP_INCLUDED | |||||
| #include "CarlaBridgeToolkit.hpp" | |||||
| #include "CarlaLibUtils.hpp" | |||||
| #include "CarlaPipeUtils.hpp" | |||||
| #ifdef BRIDGE_LV2 | |||||
| # include "lv2/atom.h" | |||||
| # include "lv2/urid.h" | |||||
| #endif | |||||
| //#include "CarlaBridgeToolkit.hpp" | |||||
| //#include "CarlaLibUtils.hpp" | |||||
| CARLA_BRIDGE_START_NAMESPACE | |||||
| /*! | |||||
| * @defgroup CarlaBridgeUIAPI Carla UI Bridge API | |||||
| * | |||||
| * The Carla UI Bridge API. | |||||
| * @{ | |||||
| */ | |||||
| // ----------------------------------------------------------------------- | |||||
| class CarlaBridgeUI : public CarlaPipeClient | |||||
| { | |||||
| protected: | |||||
| /*! | |||||
| * Constructor. | |||||
| */ | |||||
| CarlaBridgeUI() noexcept; | |||||
| /*! | |||||
| * Destructor. | |||||
| */ | |||||
| virtual ~CarlaBridgeUI() noexcept; | |||||
| // --------------------------------------------------------------------- | |||||
| // Host DSP State | |||||
| void sendControl(const uint32_t index, const float value) const noexcept; | |||||
| void sendProgram(const uint32_t index) const noexcept; | |||||
| void sendConfigure(const char* const key, const char* const value) const noexcept; | |||||
| void sendNote(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept; | |||||
| #ifdef BRIDGE_LV2 | |||||
| void sendAtom(const uint32_t index, const LV2_Atom* const atom) const noexcept; | |||||
| void sendURID(const LV2_URID urid, const char* const uri) const noexcept; | |||||
| #endif | |||||
| bool libOpen(const char* const filename) noexcept; | |||||
| void* libSymbol(const char* const symbol) const noexcept; | |||||
| const char* libError() const noexcept; | |||||
| // --------------------------------------------------------------------- | |||||
| // DSP Callbacks | |||||
| virtual void dspParameterChanged(const uint32_t index, const float value) = 0; | |||||
| virtual void dspProgramChanged(const uint32_t index) = 0; | |||||
| virtual void dspMidiProgramChanged(const uint32_t bank, const uint32_t program) = 0; | |||||
| virtual void dspStateChanged(const char* const key, const char* const value) = 0; | |||||
| virtual void dspNoteReceived(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) = 0; | |||||
| #ifdef BRIDGE_LV2 | |||||
| virtual void dspAtomReceived(const uint32_t index, const LV2_Atom* const atom) = 0; | |||||
| virtual void dspURIDReceived(const LV2_URID urid, const char* const uri) = 0; | |||||
| #endif | |||||
| public: | |||||
| // --------------------------------------------------------------------- | |||||
| // UI initialization | |||||
| virtual bool init(const int argc, const char* argv[]); | |||||
| virtual void exec(const bool showUI); | |||||
| virtual void idleUI() {} | |||||
| // --------------------------------------------------------------------- | |||||
| // UI management | |||||
| /*! | |||||
| * Get the widget associated with this UI. | |||||
| * This can be a Gtk widget, Qt widget or a native Window handle depending on the compile target. | |||||
| */ | |||||
| virtual void* getWidget() const noexcept = 0; | |||||
| /*! | |||||
| * Options. | |||||
| */ | |||||
| struct Options { | |||||
| /*! | |||||
| * UI is resizable by the user. | |||||
| * The UI can still sometimes resize itself internally if this is false. | |||||
| */ | |||||
| bool isResizable; | |||||
| /*! | |||||
| * Use the Carla PRO theme if possible. | |||||
| */ | |||||
| bool useTheme; | |||||
| /*! | |||||
| * Use the Carla PRO theme colors if possible. | |||||
| * This implies useTheme to be true. | |||||
| */ | |||||
| bool useThemeColors; | |||||
| /*! | |||||
| * Window title. | |||||
| */ | |||||
| const char* windowTitle; | |||||
| /*! | |||||
| * Transient window id (parent), null if zero. | |||||
| */ | |||||
| uintptr_t transientWindowId; | |||||
| /*! | |||||
| * Constructor for default options. | |||||
| */ | |||||
| Options() noexcept | |||||
| : isResizable(true), | |||||
| useTheme(true), | |||||
| useThemeColors(true), | |||||
| windowTitle(nullptr), | |||||
| transientWindowId(0) {} | |||||
| }; | |||||
| /*! | |||||
| * Get options associated with this UI. | |||||
| */ | |||||
| virtual const Options& getOptions() const noexcept = 0; | |||||
| // --------------------------------------------------------------------- | |||||
| protected: | |||||
| bool fQuitReceived; | |||||
| #ifdef BRIDGE_LV2 | |||||
| bool fUridMapComplete; | |||||
| #endif | |||||
| CarlaBridgeToolkit* fToolkit; | |||||
| lib_t fLib; | |||||
| CarlaString fLibFilename; | |||||
| /*! @internal */ | |||||
| bool msgReceived(const char* const msg) noexcept override; | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeUI) | |||||
| }; | |||||
| /**@}*/ | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BRIDGE_END_NAMESPACE | |||||
| #endif // CARLA_BRIDGE_UI_HPP_INCLUDED | |||||
| // ----------------------------------------------------------------------- | |||||
| #if 0 | |||||
| // --------------------------------------------------------------------- | |||||
| // ui initialization | |||||
| virtual bool uiInit(const char*, const char* const, const char* const); | |||||
| virtual void uiIdle() {} | |||||
| virtual void uiClose(); | |||||
| // --------------------------------------------------------------------- | |||||
| // ui toolkit | |||||
| void toolkitShow(); | |||||
| void toolkitHide(); | |||||
| void toolkitResize(const int width, const int height); | |||||
| void toolkitExec(const bool showGui); | |||||
| void toolkitQuit(); | |||||
| // --------------------------------------------------------------------- | |||||
| // osc stuff | |||||
| void oscInit(const char* const url); | |||||
| bool oscIdle(const bool onlyOnce = false) const; | |||||
| void oscClose(); | |||||
| bool isOscControlRegistered() const noexcept; | |||||
| void sendOscUpdate() const; | |||||
| // --------------------------------------------------------------------- | |||||
| protected: | |||||
| void sendOscConfigure(const char* const key, const char* const value) const; | |||||
| void sendOscControl(const int32_t index, const float value) const; | |||||
| void sendOscProgram(const uint32_t index) const; | |||||
| void sendOscMidiProgram(const uint32_t index) const; | |||||
| void sendOscMidi(const uint8_t midiBuf[4]) const; | |||||
| void sendOscExiting() const; | |||||
| #ifdef BRIDGE_LV2 | |||||
| void sendOscLv2AtomTransfer(const uint32_t portIndex, const char* const atomBuf) const; | |||||
| void sendOscLv2UridMap(const uint32_t urid, const char* const uri) const; | |||||
| #endif | |||||
| // --------------------------------------------------------------------- | |||||
| void* getContainerId(); | |||||
| void* getContainerId2(); | |||||
| // --------------------------------------------------------------------- | |||||
| const char* uiLibError(); | |||||
| template<typename Func> | |||||
| Func uiLibSymbol(const char* const symbol) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fUI.lib != nullptr, nullptr); | |||||
| carla_debug("CarlaBridgeUI::uiLibSymbol(\"%s\")", symbol); | |||||
| return lib_symbol<Func>(fUI.lib, symbol); | |||||
| } | |||||
| #endif | |||||
| #if 0 | |||||
| struct UI { | |||||
| CarlaBridgeToolkit* const toolkit; | |||||
| CarlaString filename; | |||||
| lib_t lib; | |||||
| bool quit; | |||||
| UI(CarlaBridgeToolkit* const toolkit_) | |||||
| : toolkit(toolkit_), | |||||
| filename(), | |||||
| lib(nullptr), | |||||
| quit(false) | |||||
| { | |||||
| CARLA_ASSERT(toolkit != nullptr); | |||||
| } | |||||
| ~UI() | |||||
| { | |||||
| delete toolkit; | |||||
| } | |||||
| void init() | |||||
| { | |||||
| toolkit->init(); | |||||
| quit = false; | |||||
| } | |||||
| void close() | |||||
| { | |||||
| quit = true; | |||||
| toolkit->quit(); | |||||
| } | |||||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||||
| UI() = delete; | |||||
| CARLA_DECLARE_NON_COPY_STRUCT(UI) | |||||
| #endif | |||||
| } fUI; | |||||
| #endif | |||||
| @@ -23,7 +23,6 @@ endif | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
| BUILD_CXX_FLAGS += -DBUILD_BRIDGE -I. -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/utils -isystem $(CWD)/modules | BUILD_CXX_FLAGS += -DBUILD_BRIDGE -I. -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/utils -isystem $(CWD)/modules | ||||
| BUILD_CXX_FLAGS += $(LIBLO_FLAGS) | |||||
| BUILD_LV2_FLAGS = $(BUILD_CXX_FLAGS) -DBRIDGE_LV2 | BUILD_LV2_FLAGS = $(BUILD_CXX_FLAGS) -DBRIDGE_LV2 | ||||
| BUILD_VST2_FLAGS = $(BUILD_CXX_FLAGS) -DBRIDGE_VST2 | BUILD_VST2_FLAGS = $(BUILD_CXX_FLAGS) -DBRIDGE_VST2 | ||||
| @@ -33,7 +32,6 @@ BUILD_VST2_FLAGS += -DVESTIGE_HEADER | |||||
| endif | endif | ||||
| LINK_FLAGS += $(JUCE_CORE_LIBS) | LINK_FLAGS += $(JUCE_CORE_LIBS) | ||||
| LINK_FLAGS += $(LIBLO_LIBS) | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -128,7 +126,7 @@ ui_lv2-qt5: $(BINDIR)/$(MODULENAME)-lv2-qt5 | |||||
| ui_lv2-x11: $(BINDIR)/$(MODULENAME)-lv2-x11 | ui_lv2-x11: $(BINDIR)/$(MODULENAME)-lv2-x11 | ||||
| ui_lv2-cocoa: $(BINDIR)/$(MODULENAME)-lv2-cocoa | ui_lv2-cocoa: $(BINDIR)/$(MODULENAME)-lv2-cocoa | ||||
| ui_lv2-windows: $(BINDIR)/$(MODULENAME)-lv2-windows.exe | ui_lv2-windows: $(BINDIR)/$(MODULENAME)-lv2-windows.exe | ||||
| ui_vst2-x11: $(BINDIR)/$(MODULENAME)-vst2-x11 | |||||
| ui_vst2-x11: #$(BINDIR)/$(MODULENAME)-vst2-x11 | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
| # Common libs | # Common libs | ||||
| @@ -169,10 +167,9 @@ $(OBJDIR)/%.cpp.vst2.o: %.cpp | |||||
| # ui_lv2-gtk2 | # ui_lv2-gtk2 | ||||
| OBJS_LV2_GTK2 = \ | OBJS_LV2_GTK2 = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitGtk.cpp.lv2-gtk2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-gtk2.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-gtk2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitGtk.cpp.lv2-gtk2.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-gtk2: $(OBJS_LV2_GTK2) $(LIBS_LV2) | $(BINDIR)/$(MODULENAME)-lv2-gtk2: $(OBJS_LV2_GTK2) $(LIBS_LV2) | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -190,10 +187,9 @@ $(OBJDIR)/%.cpp.lv2-gtk2.o: %.cpp | |||||
| # ui_lv2-gtk3 | # ui_lv2-gtk3 | ||||
| OBJS_LV2_GTK3 = \ | OBJS_LV2_GTK3 = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitGtk.cpp.lv2-gtk3.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-gtk3.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-gtk3.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitGtk.cpp.lv2-gtk3.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-gtk3: $(OBJS_LV2_GTK3) $(LIBS_LV2) | $(BINDIR)/$(MODULENAME)-lv2-gtk3: $(OBJS_LV2_GTK3) $(LIBS_LV2) | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -211,10 +207,9 @@ $(OBJDIR)/%.cpp.lv2-gtk3.o: %.cpp | |||||
| # ui_lv2-qt4 | # ui_lv2-qt4 | ||||
| OBJS_LV2_QT4 = \ | OBJS_LV2_QT4 = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitQt.cpp.lv2-qt4.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-qt4.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-qt4.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitQt.cpp.lv2-qt4.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-qt4: $(OBJS_LV2_QT4) $(LIBS_LV2) $(MODULEDIR)/theme.qt4.a | $(BINDIR)/$(MODULENAME)-lv2-qt4: $(OBJS_LV2_QT4) $(LIBS_LV2) $(MODULEDIR)/theme.qt4.a | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -242,10 +237,9 @@ $(OBJDIR)/resources.qt4.cpp: ../../resources/resources-theme.qrc | |||||
| # ui_lv2-qt5 | # ui_lv2-qt5 | ||||
| OBJS_LV2_QT5 = \ | OBJS_LV2_QT5 = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitQt.cpp.lv2-qt5.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-qt5.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-qt5.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitQt.cpp.lv2-qt5.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-qt5: $(OBJS_LV2_QT5) $(LIBS_LV2) $(MODULEDIR)/theme.qt5.a | $(BINDIR)/$(MODULENAME)-lv2-qt5: $(OBJS_LV2_QT5) $(LIBS_LV2) $(MODULEDIR)/theme.qt5.a | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -273,10 +267,9 @@ $(OBJDIR)/resources.qt5.cpp: ../../resources/resources-theme.qrc | |||||
| # ui_lv2-x11 | # ui_lv2-x11 | ||||
| OBJS_LV2_X11 = \ | OBJS_LV2_X11 = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.lv2-x11.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-x11.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-x11.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.lv2-x11.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-x11: $(OBJS_LV2_X11) $(LIBS_LV2) | $(BINDIR)/$(MODULENAME)-lv2-x11: $(OBJS_LV2_X11) $(LIBS_LV2) | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -294,10 +287,9 @@ $(OBJDIR)/%.cpp.lv2-x11.o: %.cpp | |||||
| # ui_lv2-cocoa | # ui_lv2-cocoa | ||||
| OBJS_LV2_COCOA = \ | OBJS_LV2_COCOA = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.lv2-cocoa.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-cocoa.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-cocoa.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.lv2-cocoa.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-cocoa: $(OBJS_LV2_COCOA) $(LIBS_LV2_JUCE) | $(BINDIR)/$(MODULENAME)-lv2-cocoa: $(OBJS_LV2_COCOA) $(LIBS_LV2_JUCE) | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -315,10 +307,9 @@ $(OBJDIR)/%.cpp.lv2-cocoa.o: %.cpp | |||||
| # ui_lv2-windows | # ui_lv2-windows | ||||
| OBJS_LV2_WINDOWS = \ | OBJS_LV2_WINDOWS = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.lv2-windows.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-windows.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.lv2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-LV2.cpp.lv2-windows.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.lv2-windows.o | |||||
| $(BINDIR)/$(MODULENAME)-lv2-windows.exe: $(OBJS_LV2_WINDOWS) $(LIBS_LV2_JUCE) | $(BINDIR)/$(MODULENAME)-lv2-windows.exe: $(OBJS_LV2_WINDOWS) $(LIBS_LV2_JUCE) | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -336,10 +327,9 @@ $(OBJDIR)/%.cpp.lv2-windows.o: %.cpp | |||||
| # ui_vst2-x11 | # ui_vst2-x11 | ||||
| OBJS_VST2_X11 = \ | OBJS_VST2_X11 = \ | ||||
| $(OBJDIR)/CarlaBridgeClient.cpp.vst2.o \ | |||||
| $(OBJDIR)/CarlaBridgeOsc.cpp.vst2.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.vst2-x11.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-VST2.cpp.vst2-x11.o | |||||
| $(OBJDIR)/CarlaBridgeUI.cpp.vst2.o \ | |||||
| $(OBJDIR)/CarlaBridgeUI-VST2.cpp.vst2-x11.o \ | |||||
| $(OBJDIR)/CarlaBridgeToolkitPlugin.cpp.vst2-x11.o | |||||
| $(BINDIR)/$(MODULENAME)-vst2-x11: $(OBJS_VST2_X11) $(LIBS_VST2) | $(BINDIR)/$(MODULENAME)-vst2-x11: $(OBJS_VST2_X11) $(LIBS_VST2) | ||||
| -@mkdir -p $(BINDIR) | -@mkdir -p $(BINDIR) | ||||
| @@ -85,7 +85,7 @@ protected: | |||||
| } | } | ||||
| } | } | ||||
| void uiSetParameterValue(const uint32_t index, const float value) override | |||||
| void uiSetParameterValue(const uint32_t index, const float value) noexcept override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),); | CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),); | ||||
| @@ -108,7 +108,7 @@ protected: | |||||
| flushMessages(); | flushMessages(); | ||||
| } | } | ||||
| void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override | |||||
| void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) noexcept override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | ||||
| @@ -133,7 +133,7 @@ protected: | |||||
| flushMessages(); | flushMessages(); | ||||
| } | } | ||||
| void uiSetCustomData(const char* const key, const char* const value) override | |||||
| void uiSetCustomData(const char* const key, const char* const value) noexcept override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | ||||
| CARLA_SAFE_ASSERT_RETURN(value != nullptr,); | CARLA_SAFE_ASSERT_RETURN(value != nullptr,); | ||||
| @@ -403,15 +403,15 @@ struct CarlaPipeCommon::PrivateData { | |||||
| int pipeSend; | int pipeSend; | ||||
| #endif | #endif | ||||
| // read functions must only be called in context of idle() | |||||
| // read functions must only be called in context of idlePipe() | |||||
| bool isReading; | bool isReading; | ||||
| // common write lock | // common write lock | ||||
| CarlaMutex writeLock; | CarlaMutex writeLock; | ||||
| // temporary buffers for readline() | |||||
| char tmpBuf[0xff+1]; | |||||
| CarlaString tmpStr; | |||||
| // temporary buffers for _readline() | |||||
| mutable char tmpBuf[0xff+1]; | |||||
| mutable CarlaString tmpStr; | |||||
| PrivateData() noexcept | PrivateData() noexcept | ||||
| #ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
| @@ -527,14 +527,14 @@ void CarlaPipeCommon::unlockPipe() const noexcept | |||||
| pData->writeLock.unlock(); | pData->writeLock.unlock(); | ||||
| } | } | ||||
| CarlaMutex& CarlaPipeCommon::getPipeLock() noexcept | |||||
| CarlaMutex& CarlaPipeCommon::getPipeLock() const noexcept | |||||
| { | { | ||||
| return pData->writeLock; | return pData->writeLock; | ||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| bool CarlaPipeCommon::readNextLineAsBool(bool& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsBool(bool& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -548,7 +548,26 @@ bool CarlaPipeCommon::readNextLineAsBool(bool& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsInt(int32_t& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsByte(uint8_t& value) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||||
| if (const char* const msg = _readlineblock()) | |||||
| { | |||||
| int tmp = std::atoi(msg); | |||||
| delete[] msg; | |||||
| if (tmp >= 0 && tmp <= 0xFF) | |||||
| { | |||||
| value = static_cast<uint8_t>(tmp); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool CarlaPipeCommon::readNextLineAsInt(int32_t& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -562,7 +581,7 @@ bool CarlaPipeCommon::readNextLineAsInt(int32_t& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsUInt(uint32_t& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsUInt(uint32_t& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -581,7 +600,7 @@ bool CarlaPipeCommon::readNextLineAsUInt(uint32_t& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsLong(int64_t& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsLong(int64_t& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -595,7 +614,7 @@ bool CarlaPipeCommon::readNextLineAsLong(int64_t& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsULong(uint64_t& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsULong(uint64_t& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -614,7 +633,7 @@ bool CarlaPipeCommon::readNextLineAsULong(uint64_t& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsFloat(float& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsFloat(float& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -628,7 +647,7 @@ bool CarlaPipeCommon::readNextLineAsFloat(float& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsDouble(double& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsDouble(double& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -642,7 +661,7 @@ bool CarlaPipeCommon::readNextLineAsDouble(double& value) noexcept | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool CarlaPipeCommon::readNextLineAsString(const char*& value) noexcept | |||||
| bool CarlaPipeCommon::readNextLineAsString(const char*& value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | ||||
| @@ -741,7 +760,7 @@ bool CarlaPipeCommon::flushMessages() const noexcept | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // internal | // internal | ||||
| const char* CarlaPipeCommon::_readline() noexcept | |||||
| const char* CarlaPipeCommon::_readline() const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pData->pipeRecv != INVALID_PIPE_VALUE, nullptr); | CARLA_SAFE_ASSERT_RETURN(pData->pipeRecv != INVALID_PIPE_VALUE, nullptr); | ||||
| @@ -797,7 +816,7 @@ const char* CarlaPipeCommon::_readline() noexcept | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| const char* CarlaPipeCommon::_readlineblock(const uint32_t timeOutMilliseconds) noexcept | |||||
| const char* CarlaPipeCommon::_readlineblock(const uint32_t timeOutMilliseconds) const noexcept | |||||
| { | { | ||||
| const uint32_t timeoutEnd(juce::Time::getMillisecondCounter() + timeOutMilliseconds); | const uint32_t timeoutEnd(juce::Time::getMillisecondCounter() + timeOutMilliseconds); | ||||
| @@ -87,7 +87,7 @@ public: | |||||
| /*! | /*! | ||||
| * Get the pipe write lock. | * Get the pipe write lock. | ||||
| */ | */ | ||||
| CarlaMutex& getPipeLock() noexcept; | |||||
| CarlaMutex& getPipeLock() const noexcept; | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // read lines, must only be called in the context of msgReceived() | // read lines, must only be called in the context of msgReceived() | ||||
| @@ -95,43 +95,48 @@ public: | |||||
| /*! | /*! | ||||
| * Read the next line as a boolean. | * Read the next line as a boolean. | ||||
| */ | */ | ||||
| bool readNextLineAsBool(bool& value) noexcept; | |||||
| bool readNextLineAsBool(bool& value) const noexcept; | |||||
| /*! | |||||
| * Read the next line as a byte. | |||||
| */ | |||||
| bool readNextLineAsByte(uint8_t& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as an integer. | * Read the next line as an integer. | ||||
| */ | */ | ||||
| bool readNextLineAsInt(int32_t& value) noexcept; | |||||
| bool readNextLineAsInt(int32_t& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as an unsigned integer. | * Read the next line as an unsigned integer. | ||||
| */ | */ | ||||
| bool readNextLineAsUInt(uint32_t& value) noexcept; | |||||
| bool readNextLineAsUInt(uint32_t& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as a long integer. | * Read the next line as a long integer. | ||||
| */ | */ | ||||
| bool readNextLineAsLong(int64_t& value) noexcept; | |||||
| bool readNextLineAsLong(int64_t& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as a long unsigned integer. | * Read the next line as a long unsigned integer. | ||||
| */ | */ | ||||
| bool readNextLineAsULong(uint64_t& value) noexcept; | |||||
| bool readNextLineAsULong(uint64_t& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as a floating point number (single precision). | * Read the next line as a floating point number (single precision). | ||||
| */ | */ | ||||
| bool readNextLineAsFloat(float& value) noexcept; | |||||
| bool readNextLineAsFloat(float& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as a floating point number (double precision). | * Read the next line as a floating point number (double precision). | ||||
| */ | */ | ||||
| bool readNextLineAsDouble(double& value) noexcept; | |||||
| bool readNextLineAsDouble(double& value) const noexcept; | |||||
| /*! | /*! | ||||
| * Read the next line as a string. | * Read the next line as a string. | ||||
| * @note: @a value must be deleted if valid. | * @note: @a value must be deleted if valid. | ||||
| */ | */ | ||||
| bool readNextLineAsString(const char*& value) noexcept; | |||||
| bool readNextLineAsString(const char*& value) const noexcept; | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // write messages, must be locked before calling | // write messages, must be locked before calling | ||||
| @@ -167,10 +172,10 @@ protected: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| /*! @internal */ | /*! @internal */ | ||||
| const char* _readline() noexcept; | |||||
| const char* _readline() const noexcept; | |||||
| /*! @internal */ | /*! @internal */ | ||||
| const char* _readlineblock(const uint32_t timeOutMilliseconds = 50) noexcept; | |||||
| const char* _readlineblock(const uint32_t timeOutMilliseconds = 50) const noexcept; | |||||
| /*! @internal */ | /*! @internal */ | ||||
| bool _writeMsgBuffer(const char* const msg, const std::size_t size) const noexcept; | bool _writeMsgBuffer(const char* const msg, const std::size_t size) const noexcept; | ||||
| @@ -48,10 +48,10 @@ public: | |||||
| static bool tryTransientWinIdMatch(const uintptr_t pid, const char* const uiTitle, const uintptr_t winId, const bool centerUI); | static bool tryTransientWinIdMatch(const uintptr_t pid, const char* const uiTitle, const uintptr_t winId, const bool centerUI); | ||||
| #ifdef CARLA_OS_MAC | #ifdef CARLA_OS_MAC | ||||
| static CarlaPluginUI* newCocoa(CloseCallback*, uintptr_t); | |||||
| static CarlaPluginUI* newCocoa(CloseCallback*, uintptr_t, bool); | |||||
| #endif | #endif | ||||
| #ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
| static CarlaPluginUI* newWindows(CloseCallback*, uintptr_t); | |||||
| static CarlaPluginUI* newWindows(CloseCallback*, uintptr_t, bool); | |||||
| #endif | #endif | ||||
| #ifdef HAVE_X11 | #ifdef HAVE_X11 | ||||
| static CarlaPluginUI* newX11(CloseCallback*, uintptr_t, bool); | static CarlaPluginUI* newX11(CloseCallback*, uintptr_t, bool); | ||||