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