| @@ -27,7 +27,7 @@ | |||
| CARLA_BRIDGE_START_NAMESPACE | |||
| // forward declarations of commonly used Carla-Bridge classes | |||
| class CarlaBridgeClient; | |||
| class CarlaBridgeUI; | |||
| class CarlaBridgeToolkit; | |||
| 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: | |||
| 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 quit() = 0; | |||
| virtual void show() = 0; | |||
| virtual void focus() = 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* getContainerId2() const { return nullptr; } | |||
| static CarlaBridgeToolkit* createNew(CarlaBridgeClient* const client, const char* const windowTitle); | |||
| static CarlaBridgeToolkit* createNew(CarlaBridgeUI* const ui); | |||
| 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() {} | |||
| 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. | |||
| */ | |||
| #include "CarlaBridgeClient.hpp" | |||
| #include "CarlaBridgeToolkit.hpp" | |||
| #include "CarlaBridgeUI.hpp" | |||
| #include <gtk/gtk.h> | |||
| @@ -36,8 +35,8 @@ static char** gargv = nullptr; | |||
| class CarlaBridgeToolkitGtk : public CarlaBridgeToolkit | |||
| { | |||
| public: | |||
| CarlaBridgeToolkitGtk(CarlaBridgeClient* const client, const char* const windowTitle) | |||
| : CarlaBridgeToolkit(client, windowTitle), | |||
| CarlaBridgeToolkitGtk(CarlaBridgeUI* const ui) | |||
| : CarlaBridgeToolkit(ui), | |||
| fNeedsShow(false), | |||
| fWindow(nullptr), | |||
| fLastX(0), | |||
| @@ -55,32 +54,38 @@ public: | |||
| 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()"); | |||
| gtk_init(&gargc, &gargv); | |||
| fWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |||
| CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr, false); | |||
| gtk_window_resize(GTK_WINDOW(fWindow), 30, 30); | |||
| gtk_widget_hide(fWindow); | |||
| return true; | |||
| } | |||
| 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_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI)); | |||
| const CarlaBridgeUI::Options& options(ui->getOptions()); | |||
| GtkWindow* const gtkWindow(GTK_WINDOW(fWindow)); | |||
| 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_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) | |||
| { | |||
| @@ -122,6 +127,11 @@ public: | |||
| gtk_widget_show_all(fWindow); | |||
| } | |||
| void focus() override | |||
| { | |||
| carla_debug("CarlaBridgeToolkitGtk::focus()"); | |||
| } | |||
| void hide() override | |||
| { | |||
| carla_debug("CarlaBridgeToolkitGtk::hide()"); | |||
| @@ -132,7 +142,7 @@ public: | |||
| 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_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height); | |||
| @@ -140,6 +150,14 @@ public: | |||
| 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: | |||
| @@ -177,13 +195,14 @@ protected: | |||
| 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; | |||
| } | |||
| @@ -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. | |||
| */ | |||
| #include "CarlaBridgeClient.hpp" | |||
| #include "CarlaBridgeUI.hpp" | |||
| #include "CarlaBridgeToolkit.hpp" | |||
| #include "CarlaPluginUI.hpp" | |||
| @@ -34,13 +34,13 @@ class CarlaBridgeToolkitPlugin : public CarlaBridgeToolkit, | |||
| private CarlaPluginUI::CloseCallback | |||
| { | |||
| public: | |||
| CarlaBridgeToolkitPlugin(CarlaBridgeClient* const client, const char* const windowTitle) | |||
| : CarlaBridgeToolkit(client, windowTitle), | |||
| CarlaBridgeToolkitPlugin(CarlaBridgeUI* const ui) | |||
| : CarlaBridgeToolkit(ui), | |||
| fUI(nullptr), | |||
| fIdling(false), | |||
| leakDetector_CarlaBridgeToolkitPlugin() | |||
| { | |||
| carla_debug("CarlaBridgeToolkitPlugin::CarlaBridgeToolkitPlugin(%p, \"%s\")", client, windowTitle); | |||
| carla_debug("CarlaBridgeToolkitPlugin::CarlaBridgeToolkitPlugin(%p)", ui); | |||
| } | |||
| ~CarlaBridgeToolkitPlugin() override | |||
| @@ -49,26 +49,31 @@ public: | |||
| 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()"); | |||
| const CarlaBridgeUI::Options& options(ui->getOptions()); | |||
| #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) | |||
| fUI = CarlaPluginUI::newWindows(this, 0); | |||
| fUI = CarlaPluginUI::newWindows(this, 0, options.isResizable); | |||
| #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 | |||
| 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 | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(ui != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| carla_debug("CarlaBridgeToolkitPlugin::exec(%s)", bool2str(showUI)); | |||
| @@ -86,10 +91,11 @@ public: | |||
| for (; fIdling;) | |||
| { | |||
| 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 (MessageManager* const msgMgr = MessageManager::getInstance()) | |||
| @@ -119,6 +125,14 @@ public: | |||
| fUI->show(); | |||
| } | |||
| void focus() override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| carla_debug("CarlaBridgeToolkitPlugin::focus()"); | |||
| fUI->focus(); | |||
| } | |||
| void hide() override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| @@ -127,14 +141,22 @@ public: | |||
| 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(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); | |||
| 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 | |||
| @@ -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. | |||
| */ | |||
| #include "CarlaBridgeClient.hpp" | |||
| #include "CarlaBridgeUI.hpp" | |||
| #include "CarlaBridgeToolkit.hpp" | |||
| #include "CarlaStyle.hpp" | |||
| @@ -50,9 +50,9 @@ class CarlaBridgeToolkitQt: public QObject, | |||
| Q_OBJECT | |||
| public: | |||
| CarlaBridgeToolkitQt(CarlaBridgeClient* const client, const char* const windowTitle) | |||
| CarlaBridgeToolkitQt(CarlaBridgeUI* const ui) | |||
| : QObject(nullptr), | |||
| CarlaBridgeToolkit(client, windowTitle), | |||
| CarlaBridgeToolkit(ui), | |||
| fApp(nullptr), | |||
| fWindow(nullptr), | |||
| fMsgTimer(0), | |||
| @@ -72,11 +72,11 @@ public: | |||
| 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()"); | |||
| fApp = new QApplication(qargc, qargv); | |||
| @@ -84,16 +84,20 @@ public: | |||
| fWindow = new QMainWindow(nullptr); | |||
| fWindow->resize(30, 30); | |||
| fWindow->hide(); | |||
| return true; | |||
| } | |||
| 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(fWindow != nullptr,); | |||
| 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->adjustSize(); | |||
| @@ -101,7 +105,7 @@ public: | |||
| widget->setParent(fWindow); | |||
| widget->show(); | |||
| if (! kClient->isResizable()) | |||
| if (! options.isResizable) | |||
| { | |||
| fWindow->setFixedSize(fWindow->width(), fWindow->height()); | |||
| #ifdef CARLA_OS_WIN | |||
| @@ -110,18 +114,13 @@ public: | |||
| } | |||
| 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) | |||
| 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 | |||
| } | |||
| } | |||
| if (showUI || fNeedsShow) | |||
| @@ -141,7 +140,7 @@ public: | |||
| 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(fWindow != nullptr,); | |||
| carla_debug("CarlaBridgeToolkitQt::quit()"); | |||
| @@ -180,6 +179,11 @@ public: | |||
| fWindow->show(); | |||
| } | |||
| void focus() override | |||
| { | |||
| carla_debug("CarlaBridgeToolkitQt::focus()"); | |||
| } | |||
| void hide() override | |||
| { | |||
| carla_debug("CarlaBridgeToolkitQt::hide()"); | |||
| @@ -190,13 +194,27 @@ public: | |||
| 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(height > 0,); | |||
| 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: | |||
| @@ -208,21 +226,21 @@ protected: | |||
| 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: | |||
| void timerEvent(QTimerEvent* const ev) | |||
| void timerEvent(QTimerEvent* const ev) override | |||
| { | |||
| if (ev->timerId() == fMsgTimer) | |||
| handleTimeout(); | |||
| @@ -230,21 +248,6 @@ private: | |||
| 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 | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitQt) | |||
| #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. | |||
| */ | |||
| #include "CarlaBridgeClient.hpp" | |||
| #include "CarlaBase64Utils.hpp" | |||
| #include "CarlaBridgeUI.hpp" | |||
| #include "CarlaLibUtils.hpp" | |||
| #include "CarlaLv2Utils.hpp" | |||
| #include "CarlaMIDI.h" | |||
| #include "LinkedList.hpp" | |||
| @@ -185,23 +185,18 @@ struct Lv2PluginOptions { | |||
| // ------------------------------------------------------------------------- | |||
| class CarlaLv2Client : public CarlaBridgeClient | |||
| class CarlaLv2Client : public CarlaBridgeUI | |||
| { | |||
| public: | |||
| CarlaLv2Client(const char* const uiTitle) | |||
| : CarlaBridgeClient(uiTitle), | |||
| CarlaLv2Client() | |||
| : CarlaBridgeUI(), | |||
| fHandle(nullptr), | |||
| fWidget(nullptr), | |||
| fDescriptor(nullptr), | |||
| fRdfDescriptor(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(), | |||
| fExt(), | |||
| leakDetector_CarlaLv2Client() | |||
| @@ -214,9 +209,9 @@ public: | |||
| // --------------------------------------------------------------- | |||
| // initialize options | |||
| fOptions.minBufferSize = gBufferSizei; | |||
| fOptions.maxBufferSize = gBufferSizei; | |||
| fOptions.sampleRate = gSampleRate; | |||
| fLv2Options.minBufferSize = gBufferSizei; | |||
| fLv2Options.maxBufferSize = gBufferSizei; | |||
| fLv2Options.sampleRate = gSampleRate; | |||
| // --------------------------------------------------------------- | |||
| // initialize features (part 1) | |||
| @@ -269,7 +264,7 @@ public: | |||
| fFeatures[kFeatureIdLogs]->data = logFt; | |||
| fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options; | |||
| fFeatures[kFeatureIdOptions]->data = fOptions.opts; | |||
| fFeatures[kFeatureIdOptions]->data = fLv2Options.opts; | |||
| fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host; | |||
| fFeatures[kFeatureIdPrograms]->data = programsFt; | |||
| @@ -319,8 +314,19 @@ public: | |||
| ~CarlaLv2Client() override | |||
| { | |||
| if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr) | |||
| { | |||
| fDescriptor->cleanup(fHandle); | |||
| fHandle = nullptr; | |||
| } | |||
| if (fRdfDescriptor != nullptr) | |||
| { | |||
| delete fRdfDescriptor; | |||
| fRdfDescriptor = nullptr; | |||
| } | |||
| fRdfUiDescriptor = nullptr; | |||
| delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->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()) | |||
| { | |||
| const char* const uri(it.getValue()); | |||
| const char* const uri(it.getValue(nullptr)); | |||
| if (uri != nullptr) | |||
| 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) | |||
| fRdfDescriptor = lv2_rdf_new(pluginURI, true); | |||
| if (fRdfDescriptor == nullptr) | |||
| return false; | |||
| CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false); | |||
| // ----------------------------------------------------------------- | |||
| // 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 | |||
| 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; | |||
| } | |||
| // ----------------------------------------------------------------- | |||
| // 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) | |||
| return false; | |||
| @@ -440,26 +445,21 @@ public: | |||
| // initialize UI | |||
| #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11) | |||
| fFeatures[kFeatureIdUiParent]->data = getContainerId(); | |||
| fFeatures[kFeatureIdUiParent]->data = fToolkit->getContainerId(); | |||
| #endif | |||
| 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 | |||
| 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 || | |||
| std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__noUserResize) == 0) | |||
| { | |||
| fIsResizable = false; | |||
| fUiOptions.isResizable = false; | |||
| break; | |||
| } | |||
| } | |||
| @@ -483,57 +483,44 @@ public: | |||
| return true; | |||
| } | |||
| void uiIdle() override | |||
| void idleUI() override | |||
| { | |||
| if (fHandle != nullptr && fExt.idle != nullptr) | |||
| 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; | |||
| } | |||
| 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(fDescriptor != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(rindex >= 0,) | |||
| if (fDescriptor->port_event == nullptr) | |||
| 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,) | |||
| @@ -543,7 +530,11 @@ public: | |||
| 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(fDescriptor != nullptr,); | |||
| @@ -554,42 +545,31 @@ public: | |||
| 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_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[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); | |||
| } | |||
| 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(fDescriptor != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); | |||
| if (fDescriptor->port_event == nullptr) | |||
| 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)); | |||
| } | |||
| if (isOscControlRegistered()) | |||
| sendOscLv2UridMap(urid, uri); | |||
| if (isPipeRunning()) | |||
| sendURID(urid, uri); | |||
| return urid; | |||
| } | |||
| @@ -637,8 +617,8 @@ public: | |||
| void handleProgramChanged(const int32_t /*index*/) | |||
| { | |||
| if (isOscControlRegistered()) | |||
| sendOscConfigure("reloadprograms", ""); | |||
| if (isPipeRunning()) | |||
| sendConfigure("reloadprograms", ""); | |||
| } | |||
| uint32_t handleUiPortMap(const char* const symbol) | |||
| @@ -657,11 +637,12 @@ public: | |||
| 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(height > 0, 1); | |||
| carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height); | |||
| toolkitResize(width, height); | |||
| fToolkit->setSize(static_cast<uint>(width), static_cast<uint>(height)); | |||
| return 0; | |||
| } | |||
| @@ -674,30 +655,21 @@ public: | |||
| 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); | |||
| 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) | |||
| { | |||
| 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 | |||
| { | |||
| @@ -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: | |||
| LV2UI_Handle fHandle; | |||
| LV2UI_Widget fWidget; | |||
| @@ -772,10 +687,9 @@ private: | |||
| const LV2UI_Descriptor* fDescriptor; | |||
| const LV2_RDF_Descriptor* fRdfDescriptor; | |||
| const LV2_RDF_UI* fRdfUiDescriptor; | |||
| Lv2PluginOptions fOptions; | |||
| Lv2PluginOptions fLv2Options; | |||
| bool fIsReady; | |||
| bool fIsResizable; | |||
| Options fUiOptions; | |||
| LinkedList<const char*> fCustomURIDs; | |||
| struct Extensions { | |||
| @@ -1182,90 +1096,37 @@ private: | |||
| 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 | |||
| int main(int argc, char* argv[]) | |||
| // ----------------------------------------------------------------------- | |||
| int main(int argc, const char* argv[]) | |||
| { | |||
| 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; | |||
| } | |||
| 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 | |||
| if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE")) | |||
| gSampleRate = std::atof(sampleRateStr); | |||
| // Init LV2 client | |||
| CarlaLv2Client client(uiTitle); | |||
| // Init OSC | |||
| if (useOsc) | |||
| { | |||
| client.oscInit(oscUrl); | |||
| client.waitForOscURIs(); | |||
| } | |||
| CarlaLv2Client client; | |||
| // Load UI | |||
| int ret; | |||
| if (client.uiInit(pluginURI, uiURI, uiBundle)) | |||
| if (client.init(argc, argv)) | |||
| { | |||
| client.toolkitExec(!useOsc); | |||
| client.exec(testingModeOnly); | |||
| ret = 0; | |||
| } | |||
| else | |||
| @@ -1273,12 +1134,7 @@ int main(int argc, char* argv[]) | |||
| ret = 1; | |||
| } | |||
| // Close OSC | |||
| if (useOsc) | |||
| client.oscClose(); | |||
| // Close LV2 client | |||
| client.uiClose(); | |||
| return ret; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -15,8 +15,7 @@ | |||
| * 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 "CarlaMIDI.h" | |||
| @@ -28,11 +27,11 @@ CARLA_BRIDGE_START_NAMESPACE | |||
| uint32_t bufferSize = 512; | |||
| double sampleRate = 44100.0; | |||
| class CarlaVstClient : public CarlaBridgeClient | |||
| class CarlaVstClient : public CarlaBridgeUI | |||
| { | |||
| public: | |||
| CarlaVstClient(const char* const uiTitle) | |||
| : CarlaBridgeClient(uiTitle), | |||
| CarlaVstClient() | |||
| : CarlaBridgeUI(), | |||
| unique1(0), | |||
| effect(nullptr), | |||
| needIdle(false), | |||
| @@ -58,7 +57,7 @@ public: | |||
| // ----------------------------------------------------------------- | |||
| // init | |||
| CarlaBridgeClient::uiInit(binary, nullptr, nullptr); | |||
| CarlaBridgeUI::uiInit(binary, nullptr, nullptr); | |||
| // ----------------------------------------------------------------- | |||
| // open DLL | |||
| @@ -155,7 +154,7 @@ public: | |||
| effect = nullptr; | |||
| } | |||
| CarlaBridgeClient::uiClose(); | |||
| CarlaBridgeUI::uiClose(); | |||
| 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 += $(LIBLO_FLAGS) | |||
| BUILD_LV2_FLAGS = $(BUILD_CXX_FLAGS) -DBRIDGE_LV2 | |||
| BUILD_VST2_FLAGS = $(BUILD_CXX_FLAGS) -DBRIDGE_VST2 | |||
| @@ -33,7 +32,6 @@ BUILD_VST2_FLAGS += -DVESTIGE_HEADER | |||
| endif | |||
| 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-cocoa: $(BINDIR)/$(MODULENAME)-lv2-cocoa | |||
| ui_lv2-windows: $(BINDIR)/$(MODULENAME)-lv2-windows.exe | |||
| ui_vst2-x11: $(BINDIR)/$(MODULENAME)-vst2-x11 | |||
| ui_vst2-x11: #$(BINDIR)/$(MODULENAME)-vst2-x11 | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| # Common libs | |||
| @@ -169,10 +167,9 @@ $(OBJDIR)/%.cpp.vst2.o: %.cpp | |||
| # ui_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) | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -190,10 +187,9 @@ $(OBJDIR)/%.cpp.lv2-gtk2.o: %.cpp | |||
| # ui_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) | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -211,10 +207,9 @@ $(OBJDIR)/%.cpp.lv2-gtk3.o: %.cpp | |||
| # ui_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 | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -242,10 +237,9 @@ $(OBJDIR)/resources.qt4.cpp: ../../resources/resources-theme.qrc | |||
| # ui_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 | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -273,10 +267,9 @@ $(OBJDIR)/resources.qt5.cpp: ../../resources/resources-theme.qrc | |||
| # ui_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) | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -294,10 +287,9 @@ $(OBJDIR)/%.cpp.lv2-x11.o: %.cpp | |||
| # ui_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) | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -315,10 +307,9 @@ $(OBJDIR)/%.cpp.lv2-cocoa.o: %.cpp | |||
| # ui_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) | |||
| -@mkdir -p $(BINDIR) | |||
| @@ -336,10 +327,9 @@ $(OBJDIR)/%.cpp.lv2-windows.o: %.cpp | |||
| # ui_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) | |||
| -@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(),); | |||
| @@ -108,7 +108,7 @@ protected: | |||
| 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,); | |||
| @@ -133,7 +133,7 @@ protected: | |||
| 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(value != nullptr,); | |||
| @@ -403,15 +403,15 @@ struct CarlaPipeCommon::PrivateData { | |||
| int pipeSend; | |||
| #endif | |||
| // read functions must only be called in context of idle() | |||
| // read functions must only be called in context of idlePipe() | |||
| bool isReading; | |||
| // common write lock | |||
| 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 | |||
| #ifdef CARLA_OS_WIN | |||
| @@ -527,14 +527,14 @@ void CarlaPipeCommon::unlockPipe() const noexcept | |||
| pData->writeLock.unlock(); | |||
| } | |||
| CarlaMutex& CarlaPipeCommon::getPipeLock() noexcept | |||
| CarlaMutex& CarlaPipeCommon::getPipeLock() const noexcept | |||
| { | |||
| return pData->writeLock; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| bool CarlaPipeCommon::readNextLineAsBool(bool& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsBool(bool& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -548,7 +548,26 @@ bool CarlaPipeCommon::readNextLineAsBool(bool& value) noexcept | |||
| 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); | |||
| @@ -562,7 +581,7 @@ bool CarlaPipeCommon::readNextLineAsInt(int32_t& value) noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsUInt(uint32_t& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsUInt(uint32_t& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -581,7 +600,7 @@ bool CarlaPipeCommon::readNextLineAsUInt(uint32_t& value) noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsLong(int64_t& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsLong(int64_t& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -595,7 +614,7 @@ bool CarlaPipeCommon::readNextLineAsLong(int64_t& value) noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsULong(uint64_t& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsULong(uint64_t& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -614,7 +633,7 @@ bool CarlaPipeCommon::readNextLineAsULong(uint64_t& value) noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsFloat(float& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsFloat(float& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -628,7 +647,7 @@ bool CarlaPipeCommon::readNextLineAsFloat(float& value) noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsDouble(double& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsDouble(double& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -642,7 +661,7 @@ bool CarlaPipeCommon::readNextLineAsDouble(double& value) noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsString(const char*& value) noexcept | |||
| bool CarlaPipeCommon::readNextLineAsString(const char*& value) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| @@ -741,7 +760,7 @@ bool CarlaPipeCommon::flushMessages() const noexcept | |||
| // ------------------------------------------------------------------- | |||
| // internal | |||
| const char* CarlaPipeCommon::_readline() noexcept | |||
| const char* CarlaPipeCommon::_readline() const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->pipeRecv != INVALID_PIPE_VALUE, nullptr); | |||
| @@ -797,7 +816,7 @@ const char* CarlaPipeCommon::_readline() noexcept | |||
| 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); | |||
| @@ -87,7 +87,7 @@ public: | |||
| /*! | |||
| * Get the pipe write lock. | |||
| */ | |||
| CarlaMutex& getPipeLock() noexcept; | |||
| CarlaMutex& getPipeLock() const noexcept; | |||
| // ------------------------------------------------------------------- | |||
| // read lines, must only be called in the context of msgReceived() | |||
| @@ -95,43 +95,48 @@ public: | |||
| /*! | |||
| * 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. | |||
| */ | |||
| bool readNextLineAsInt(int32_t& value) noexcept; | |||
| bool readNextLineAsInt(int32_t& value) const noexcept; | |||
| /*! | |||
| * 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. | |||
| */ | |||
| bool readNextLineAsLong(int64_t& value) noexcept; | |||
| bool readNextLineAsLong(int64_t& value) const noexcept; | |||
| /*! | |||
| * 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). | |||
| */ | |||
| bool readNextLineAsFloat(float& value) noexcept; | |||
| bool readNextLineAsFloat(float& value) const noexcept; | |||
| /*! | |||
| * 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. | |||
| * @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 | |||
| @@ -167,10 +172,10 @@ protected: | |||
| // ------------------------------------------------------------------- | |||
| /*! @internal */ | |||
| const char* _readline() noexcept; | |||
| const char* _readline() const noexcept; | |||
| /*! @internal */ | |||
| const char* _readlineblock(const uint32_t timeOutMilliseconds = 50) noexcept; | |||
| const char* _readlineblock(const uint32_t timeOutMilliseconds = 50) const noexcept; | |||
| /*! @internal */ | |||
| 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); | |||
| #ifdef CARLA_OS_MAC | |||
| static CarlaPluginUI* newCocoa(CloseCallback*, uintptr_t); | |||
| static CarlaPluginUI* newCocoa(CloseCallback*, uintptr_t, bool); | |||
| #endif | |||
| #ifdef CARLA_OS_WIN | |||
| static CarlaPluginUI* newWindows(CloseCallback*, uintptr_t); | |||
| static CarlaPluginUI* newWindows(CloseCallback*, uintptr_t, bool); | |||
| #endif | |||
| #ifdef HAVE_X11 | |||
| static CarlaPluginUI* newX11(CloseCallback*, uintptr_t, bool); | |||