Browse Source

Initial code rework to make ui-bridges use pipes instead of osc

tags/1.9.6
falkTX 10 years ago
parent
commit
7bd34192f5
18 changed files with 1281 additions and 1302 deletions
  1. +1
    -1
      source/bridges-ui/CarlaBridge.hpp
  2. +0
    -257
      source/bridges-ui/CarlaBridgeClient.cpp
  3. +0
    -162
      source/bridges-ui/CarlaBridgeClient.hpp
  4. +0
    -337
      source/bridges-ui/CarlaBridgeOsc.cpp
  5. +0
    -131
      source/bridges-ui/CarlaBridgeOsc.hpp
  6. +8
    -8
      source/bridges-ui/CarlaBridgeToolkit.hpp
  7. +38
    -19
      source/bridges-ui/CarlaBridgeToolkitGtk.cpp
  8. +43
    -21
      source/bridges-ui/CarlaBridgeToolkitPlugin.cpp
  9. +51
    -48
      source/bridges-ui/CarlaBridgeToolkitQt.cpp
  10. +101
    -245
      source/bridges-ui/CarlaBridgeUI-LV2.cpp
  11. +6
    -7
      source/bridges-ui/CarlaBridgeUI-VST2.cpp
  12. +674
    -0
      source/bridges-ui/CarlaBridgeUI.cpp
  13. +279
    -0
      source/bridges-ui/CarlaBridgeUI.hpp
  14. +25
    -35
      source/bridges-ui/Makefile
  15. +3
    -3
      source/includes/CarlaNativeExtUI.hpp
  16. +34
    -15
      source/utils/CarlaPipeUtils.cpp
  17. +16
    -11
      source/utils/CarlaPipeUtils.hpp
  18. +2
    -2
      source/utils/CarlaPluginUI.hpp

+ 1
- 1
source/bridges-ui/CarlaBridge.hpp View File

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


+ 0
- 257
source/bridges-ui/CarlaBridgeClient.cpp View File

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

+ 0
- 162
source/bridges-ui/CarlaBridgeClient.hpp View File

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

+ 0
- 337
source/bridges-ui/CarlaBridgeOsc.cpp View File

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

+ 0
- 131
source/bridges-ui/CarlaBridgeOsc.hpp View File

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

+ 8
- 8
source/bridges-ui/CarlaBridgeToolkit.hpp View File

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


+ 38
- 19
source/bridges-ui/CarlaBridgeToolkitGtk.cpp View File

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

// -------------------------------------------------------------------------


+ 43
- 21
source/bridges-ui/CarlaBridgeToolkitPlugin.cpp View File

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

// -------------------------------------------------------------------------


+ 51
- 48
source/bridges-ui/CarlaBridgeToolkitQt.cpp View File

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

// -------------------------------------------------------------------------


+ 101
- 245
source/bridges-ui/CarlaBridgeUI-LV2.cpp View File

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

// -----------------------------------------------------------------------

+ 6
- 7
source/bridges-ui/CarlaBridgeUI-VST2.cpp View File

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



+ 674
- 0
source/bridges-ui/CarlaBridgeUI.cpp View File

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

+ 279
- 0
source/bridges-ui/CarlaBridgeUI.hpp View File

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

+ 25
- 35
source/bridges-ui/Makefile View File

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


+ 3
- 3
source/includes/CarlaNativeExtUI.hpp View File

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


+ 34
- 15
source/utils/CarlaPipeUtils.cpp View File

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



+ 16
- 11
source/utils/CarlaPipeUtils.hpp View File

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


+ 2
- 2
source/utils/CarlaPluginUI.hpp View File

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


Loading…
Cancel
Save