Browse Source

Carla: Fix for plugin bridges, can now show UI and save data

tags/v0.9.0
falkTX 12 years ago
parent
commit
a7f44dd9fe
15 changed files with 219 additions and 84 deletions
  1. +13
    -0
      c++/carla-backend/carla_backend.h
  2. +77
    -16
      c++/carla-backend/carla_bridge.cpp
  3. +44
    -0
      c++/carla-backend/carla_engine.cpp
  4. +4
    -3
      c++/carla-backend/carla_engine.h
  5. +2
    -14
      c++/carla-backend/carla_osc.cpp
  6. +2
    -8
      c++/carla-backend/carla_plugin.h
  7. +3
    -3
      c++/carla-bridge/Makefile
  8. +2
    -2
      c++/carla-bridge/Makefile.dbg
  9. +2
    -0
      c++/carla-bridge/carla_bridge_client.h
  10. +0
    -4
      c++/carla-bridge/carla_bridge_osc.cpp
  11. +59
    -31
      c++/carla-bridge/carla_bridge_plugin.cpp
  12. +2
    -1
      c++/carla-bridge/qtcreator/carla-bridge-lv2-gtk2.pro
  13. +2
    -1
      c++/carla-bridge/qtcreator/carla-bridge-lv2-qt4.pro
  14. +2
    -1
      c++/carla-bridge/qtcreator/carla-bridge-lv2-x11.pro
  15. +5
    -0
      c++/carla-includes/carla_osc_includes.h

+ 13
- 0
c++/carla-backend/carla_backend.h View File

@@ -78,6 +78,19 @@ const unsigned int PARAMETER_USES_SCALEPOINTS = 0x40; //!< Parameter uses scalep
const unsigned int PARAMETER_USES_CUSTOM_TEXT = 0x80; //!< Parameter uses custom text for displaying its value.\see CarlaPlugin::getParameterText()
/**@}*/

/*!
* @defgroup BridgeMessages Bridge Messages
*
* Various bridge related messages, used as configure(<message>, value).
* @{
*/
const char* const CARLA_BRIDGE_MSG_HIDE_GUI = "CarlaBridgeHideGUI"; //!< Plugin -> Host call, tells host GUI is now hidden
const char* const CARLA_BRIDGE_MSG_SAVED = "CarlaBridgeSaved"; //!< Plugin -> Host call, tells host state is saved
const char* const CARLA_BRIDGE_MSG_SAVE_NOW = "CarlaBridgeSaveNow"; //!< Host -> Plugin call, tells plugin to save state now
const char* const CARLA_BRIDGE_MSG_SET_CHUNK = "CarlaBridgeSetChunk"; //!< Host -> Plugin call, tells plugin to set chunk in file \a value
const char* const CARLA_BRIDGE_MSG_SET_CUSTOM = "CarlaBridgeSetCustom"; //!< Host -> Plugin call, tells plugin to set a custom data set using \a value ("type·key·rvalue").\n If \a type is 'chunk' or 'binary' \a rvalue refers to chunk file.
/**@}*/

/*!
* The binary type of a plugin.
*/


+ 77
- 16
c++/carla-backend/carla_bridge.cpp View File

@@ -17,7 +17,9 @@

#include "carla_plugin.h"

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>

#define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
@@ -533,6 +535,28 @@ public:
break;
}

case PluginBridgeConfigure:
{
CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");

const char* const key = (const char*)&argv[0]->s;
const char* const value = (const char*)&argv[1]->s;

Q_ASSERT(key);
Q_ASSERT(value);

if (strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
{
x_engine->callback(CALLBACK_SHOW_GUI, m_id, 0, 0, 0.0);
}
else if (strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
{
m_saved = true;
}

break;
}

case PluginBridgeSetParameterValue:
{
CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
@@ -552,7 +576,6 @@ public:
const int32_t index = argv[0]->i;
const double value = argv[1]->d;


Q_ASSERT(index >= 0 && index < (int32_t)param.count);

if (index >= 0 && index < (int32_t)param.count)
@@ -585,25 +608,67 @@ public:

case PluginBridgeSetCustomData:
{
// const char* stype = (const char*)&argv[0]->s;
// const char* key = (const char*)&argv[1]->s;
// const char* value = (const char*)&argv[2]->s;
CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");

// setCustomData(getCustomDataStringType(stype), key, value, false);
const char* const stype = (const char*)&argv[0]->s;
const char* const key = (const char*)&argv[1]->s;
const char* const value = (const char*)&argv[2]->s;

Q_ASSERT(stype);
Q_ASSERT(key);
Q_ASSERT(value);

setCustomData(getCustomDataStringType(stype), key, value, false);

break;
}

case PluginBridgeSetChunkData:
{
// const char* const filePath = (const char*)&argv[0]->s;
// QFile file(filePath);
CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");

const char* const chunkFileChar = (const char*)&argv[0]->s;

Q_ASSERT(chunkFileChar);

// if (file.open(QIODevice::ReadOnly))
// {
// info.chunk = file.readAll();
// file.remove();
// }
QString chunkFileStr(chunkFileChar);

#ifndef Q_OS_WIN
// Using Wine, fix temp dir
if (m_binary == BINARY_WIN32 || m_binary == BINARY_WIN64)
{
// Get WINEPREFIX
QString wineDir;
if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
wineDir = QString(WINEPREFIX);
else
wineDir = QDir::homePath() + "/.wine";

QStringList chunkFileStrSplit1 = chunkFileStr.split(":/");
QStringList chunkFileStrSplit2 = chunkFileStrSplit1.at(1).split("\\");

QString wineDrive = chunkFileStrSplit1.at(0).toLower();
QString wineTMP = chunkFileStrSplit2.at(0);
QString baseName = chunkFileStrSplit2.at(1);

chunkFileStr = wineDir;
chunkFileStr += "/drive_";
chunkFileStr += wineDrive;
chunkFileStr += "/";
chunkFileStr += wineTMP;
chunkFileStr += "/";
chunkFileStr += baseName;
chunkFileStr = QDir::toNativeSeparators(chunkFileStr);
}
#endif

QFile chunkFile(chunkFileStr);

if (chunkFile.open(QIODevice::ReadOnly))
{
info.chunk = chunkFile.readAll();
chunkFile.remove();
}

break;
}
@@ -611,10 +676,6 @@ public:
case PluginBridgeUpdateNow:
m_initiated = true;
break;

case PluginBridgeSaved:
m_saved = true;
break;
}

return 0;


+ 44
- 0
c++/carla-backend/carla_engine.cpp View File

@@ -1685,6 +1685,22 @@ void CarlaEngine::osc_send_bridge_midi_program_info(const int32_t index, const i
}
}

void CarlaEngine::osc_send_bridge_configure(const char* const key, const char* const value)
{
qDebug("CarlaEngine::osc_send_bridge_configure(\"%s\", \"%s\")", key, value);
Q_ASSERT(m_oscData);
Q_ASSERT(key);
Q_ASSERT(value);

if (m_oscData && m_oscData->target)
{
char target_path[strlen(m_oscData->path)+18];
strcpy(target_path, m_oscData->path);
strcat(target_path, "/bridge_configure");
lo_send(m_oscData->target, target_path, "ss", key, value);
}
}

void CarlaEngine::osc_send_bridge_set_parameter_value(const int32_t index, const double value)
{
qDebug("CarlaEngine::osc_send_bridge_set_parameter_value(%i, %g)", index, value);
@@ -1741,6 +1757,34 @@ void CarlaEngine::osc_send_bridge_set_midi_program(const int32_t index)
}
}

void CarlaEngine::osc_send_bridge_set_custom_data(const char* const stype, const char* const key, const char* const value)
{
qDebug("CarlaEngine::osc_send_bridge_set_custom_data(\"%s\", \"%s\", \"%s\")", stype, key, value);
Q_ASSERT(m_oscData);

if (m_oscData && m_oscData->target)
{
char target_path[strlen(m_oscData->path)+24];
strcpy(target_path, m_oscData->path);
strcat(target_path, "/bridge_set_custom_data");
lo_send(m_oscData->target, target_path, "sss", stype, key, value);
}
}

void CarlaEngine::osc_send_bridge_set_chunk_data(const char* const chunkFile)
{
qDebug("CarlaEngine::osc_send_bridge_set_chunk_data(\"%s\")", chunkFile);
Q_ASSERT(m_oscData);

if (m_oscData && m_oscData->target)
{
char target_path[strlen(m_oscData->path)+23];
strcpy(target_path, m_oscData->path);
strcat(target_path, "/bridge_set_chunk_data");
lo_send(m_oscData->target, target_path, "s", chunkFile);
}
}

void CarlaEngine::osc_send_bridge_set_input_peak_value(const int32_t portId, const double value)
{
Q_ASSERT(m_oscData);


+ 4
- 3
c++/carla-backend/carla_engine.h View File

@@ -109,7 +109,7 @@ struct CarlaTimeInfoBBT {
float beat_type;
double ticks_per_beat;
double beats_per_minute;
CarlaTimeInfoBBT()
: bar(0),
beat(0),
@@ -279,14 +279,15 @@ public:
void osc_send_bridge_parameter_ranges(const int32_t index, const double def, const double min, const double max, const double step, const double stepSmall, const double stepLarge);
void osc_send_bridge_program_info(const int32_t index, const char* const name);
void osc_send_bridge_midi_program_info(const int32_t index, const int32_t bank, const int32_t program, const char* const label);
void osc_send_bridge_configure(const char* const key, const char* const value);
void osc_send_bridge_set_parameter_value(const int32_t index, const double value);
void osc_send_bridge_set_default_value(const int32_t index, const double value);
void osc_send_bridge_set_program(const int32_t index);
void osc_send_bridge_set_midi_program(const int32_t index);
void osc_send_bridge_set_custom_data(const char* const stype, const char* const key, const char* const value);
void osc_send_bridge_set_chunk_data(const char* const chunkFile);
void osc_send_bridge_set_input_peak_value(const int32_t portId, const double value);
void osc_send_bridge_set_output_peak_value(const int32_t portId, const double value);
//void osc_send_bridge_custom_data(const char* const stype, const char* const key, const char* const value);
//void osc_send_bridge_chunk_data(const char* const stringData);
#else
void osc_send_control_add_plugin(const int32_t pluginId, const char* const pluginName);
void osc_send_control_remove_plugin(const int32_t pluginId);


+ 2
- 14
c++/carla-backend/carla_osc.cpp View File

@@ -224,6 +224,8 @@ int CarlaOsc::handleMessage(const char* const path, const int argc, const lo_arg
return plugin->setOscBridgeInfo(PluginBridgeProgramInfo, argc, argv, types);
if (strcmp(method, "/bridge_midi_program_info") == 0)
return plugin->setOscBridgeInfo(PluginBridgeMidiProgramInfo, argc, argv, types);
if (strcmp(method, "/bridge_configure") == 0)
return plugin->setOscBridgeInfo(PluginBridgeConfigure, argc, argv, types);
if (strcmp(method, "/bridge_set_parameter_value") == 0)
return plugin->setOscBridgeInfo(PluginBridgeSetParameterValue, argc, argv, types);
if (strcmp(method, "/bridge_set_default_value") == 0)
@@ -322,20 +324,6 @@ int CarlaOsc::handle_configure(CARLA_OSC_HANDLE_ARGS2)
const char* const key = (const char*)&argv[0]->s;
const char* const value = (const char*)&argv[1]->s;

// if (plugin->hints() & PLUGIN_IS_BRIDGE)
// {
// if (strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
// {
// engine->callback(CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0);
// return 0;
// }

// if (strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
// {
// return plugin->setOscBridgeInfo(PluginBridgeSaved, nullptr);
// }
// }

plugin->setCustomData(CUSTOM_DATA_STRING, key, value, false);

return 0;


+ 2
- 8
c++/carla-backend/carla_plugin.h View File

@@ -49,12 +49,6 @@ CARLA_BACKEND_START_NAMESPACE
const unsigned short MAX_MIDI_EVENTS = 512;
const unsigned short MAX_POST_EVENTS = 152;

const char* const CARLA_BRIDGE_MSG_HIDE_GUI = "CarlaBridgeHideGUI"; //!< Plugin -> Host call, tells host GUI is now hidden
const char* const CARLA_BRIDGE_MSG_SAVED = "CarlaBridgeSaved"; //!< Plugin -> Host call, tells host state is saved
const char* const CARLA_BRIDGE_MSG_SAVE_NOW = "CarlaBridgeSaveNow"; //!< Host -> Plugin call, tells plugin to save state now
const char* const CARLA_BRIDGE_MSG_SET_CHUNK = "CarlaBridgeSetChunk"; //!< Host -> Plugin call, tells plugin to set chunk in file \a value
const char* const CARLA_BRIDGE_MSG_SET_CUSTOM = "CarlaBridgeSetCustom"; //!< Host -> Plugin call, tells plugin to set a custom data set using \a value ("type·key·rvalue").\n If \a type is 'chunk' or 'binary' \a rvalue refers to chunk file.

#ifndef BUILD_BRIDGE
enum PluginBridgeInfoType {
PluginBridgeAudioCount,
@@ -68,14 +62,14 @@ enum PluginBridgeInfoType {
PluginBridgeParameterRanges,
PluginBridgeProgramInfo,
PluginBridgeMidiProgramInfo,
PluginBridgeConfigure,
PluginBridgeSetParameterValue,
PluginBridgeSetDefaultValue,
PluginBridgeSetProgram,
PluginBridgeSetMidiProgram,
PluginBridgeSetCustomData,
PluginBridgeSetChunkData,
PluginBridgeUpdateNow,
PluginBridgeSaved
PluginBridgeUpdateNow
};
#endif



+ 3
- 3
c++/carla-bridge/Makefile View File

@@ -4,8 +4,8 @@
# Created by falkTX
#

CXX ?= g++
STRIP ?= strip
CXX ?= g++
STRIP ?= strip

BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse -mfpmath=sse -Wall

@@ -416,6 +416,6 @@ doc: carla_bridge.doxygen
doxygen $<

clean:
rm -f *.o *.dll *.so *.exe
rm -f *.o *.so *.exe
rm -f carla-bridge-lv2-gtk2 carla-bridge-lv2-gtk3 carla-bridge-lv2-qt4 carla-bridge-lv2-x11 carla-bridge-vst-x11
rm -f carla-bridge-posix32 carla-bridge-posix64

+ 2
- 2
c++/carla-bridge/Makefile.dbg View File

@@ -4,7 +4,7 @@
# Created by falkTX
#

CXX ?= g++
CXX ?= g++

BASE_FLAGS = -O0 -g

@@ -415,6 +415,6 @@ doc: carla_bridge.doxygen
doxygen $<

clean:
rm -f *.o *.dll *.so *.exe
rm -f *.o *.so *.exe
rm -f carla-bridge-lv2-gtk2 carla-bridge-lv2-gtk3 carla-bridge-lv2-qt4 carla-bridge-lv2-x11 carla-bridge-vst-x11
rm -f carla-bridge-posix32 carla-bridge-posix64

+ 2
- 0
c++/carla-bridge/carla_bridge_client.h View File

@@ -328,6 +328,8 @@ private:
#ifdef BUILD_BRIDGE_UI
char* m_filename;
void* m_lib;
#else
friend class CarlaPluginClient;
#endif
};



+ 0
- 4
c++/carla-bridge/carla_bridge_osc.cpp View File

@@ -19,10 +19,6 @@
#include "carla_bridge_client.h"
#include "carla_midi.h"

#ifdef BUILD_BRIDGE_PLUGIN
#include "carla_plugin.h" // FIXME - put msg defines somewhere else
#endif

#include <QtCore/QString>
#include <QtCore/QStringList>



+ 59
- 31
c++/carla-bridge/carla_bridge_plugin.cpp View File

@@ -20,6 +20,7 @@
#include "carla_bridge_client.h"
#include "carla_plugin.h"

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QTimerEvent>
#include <QtGui/QApplication>
@@ -187,29 +188,34 @@ public:
{
qDebug("CarlaPluginClient::saveNow()");
Q_ASSERT(plugin);
Q_ASSERT(engine);

if (! plugin)
if (! (plugin && engine))
return;

plugin->prepareForSave();

#if 0
for (uint32_t i=0; i < CARLA_PLUGIN->customDataCount(); i++)
for (uint32_t i=0; i < plugin->customDataCount(); i++)
{
const CustomData* const cdata = CARLA_PLUGIN->customData(i);
osc_send_bridge_custom_data(customdatatype2str(cdata->type), cdata->key, cdata->value);
const CarlaBackend::CustomData* const cdata = plugin->customData(i);
engine->osc_send_bridge_set_custom_data(CarlaBackend::getCustomDataTypeString(cdata->type), cdata->key, cdata->value);
}

if (CARLA_PLUGIN->hints() & PLUGIN_USES_CHUNKS)
if (plugin->hints() & CarlaBackend::PLUGIN_USES_CHUNKS)
{
void* data = nullptr;
int32_t dataSize = CARLA_PLUGIN->chunkData(&data);
int32_t dataSize = plugin->chunkData(&data);

if (data && dataSize >= 4)
{
QString filePath;
filePath += "/tmp/.CarlaChunk_";
filePath += CARLA_PLUGIN->name();
filePath = QDir::tempPath();
#ifdef Q_OS_WIN
filePath += "\\.CarlaChunk_";
#else
filePath += "/.CarlaChunk_";
#endif
filePath += plugin->name();

QFile file(filePath);

@@ -218,13 +224,12 @@ public:
QByteArray chunk((const char*)data, dataSize);
file.write(chunk);
file.close();
osc_send_bridge_chunk_data(filePath.toUtf8().constData());
engine->osc_send_bridge_set_chunk_data(filePath.toUtf8().constData());
}
}
}

osc_send_configure(CARLA_BRIDGE_MSG_SAVED, "");
#endif
engine->osc_send_bridge_configure(CarlaBackend::CARLA_BRIDGE_MSG_SAVED, "");
}

void setCustomData(const char* const type, const char* const key, const char* const value)
@@ -267,7 +272,6 @@ public:
return;

plugin->idleGui();
//plugin->showGui(true);
}

void showGui(const bool yesNo)
@@ -287,42 +291,49 @@ public:
void handleCallback(const CarlaBackend::CallbackType action, const int value1, const int value2, const double value3)
{
qDebug("CarlaPluginClient::handleCallback(%s, %i, %i, %g)", CarlaBackend::CallbackType2str(action), value1, value2, value3);
Q_ASSERT(engine);

if (! engine)
return;

// FIXME - those OSC calls should be on the engine
switch (action)
{
case CarlaBackend::CALLBACK_PARAMETER_VALUE_CHANGED:
engine->osc_send_bridge_set_parameter_value(value1, value3);
break;

case CarlaBackend::CALLBACK_PROGRAM_CHANGED:
engine->osc_send_bridge_set_program(value1);
break;

case CarlaBackend::CALLBACK_MIDI_PROGRAM_CHANGED:
engine->osc_send_bridge_set_midi_program(value1);
break;

case CarlaBackend::CALLBACK_NOTE_ON:
{
//uint8_t mdata[4] = { 0, MIDI_STATUS_NOTE_ON, (uint8_t)value1, (uint8_t)value2 };
//osc_send_midi(mdata);
break;
}

case CarlaBackend::CALLBACK_NOTE_OFF:
{
//uint8_t mdata[4] = { 0, MIDI_STATUS_NOTE_OFF, (uint8_t)value1, (uint8_t)value2 };
//osc_send_midi(mdata);
break;
}

case CarlaBackend::CALLBACK_SHOW_GUI:
//if (value1 == 0)
//sendOscConfigure(CarlaBackend::CARLA_BRIDGE_MSG_HIDE_GUI, "");
//quequeMessage(MESSAGE_QUIT, 0, 0, 0.0);
if (value1 == 0)
engine->osc_send_bridge_configure(CarlaBackend::CARLA_BRIDGE_MSG_HIDE_GUI, "");
break;

case CarlaBackend::CALLBACK_RESIZE_GUI:
qDebug("resize callback-------------------------------------------------------------------------------");
quequeMessage(MESSAGE_RESIZE_GUI, value1, value2, 0.0);
//if (m_toolkit)
// m_toolkit->resize(value1, value2);
if (m_toolkit)
m_toolkit->resize(value1, value2);
break;

case CarlaBackend::CALLBACK_RELOAD_PARAMETERS:
//if (CARLA_PLUGIN)
//{
@@ -332,14 +343,14 @@ public:
// }
//}
break;

case CarlaBackend::CALLBACK_QUIT:
//quequeMessage(MESSAGE_QUIT, 0, 0, 0.0);
break;

default:
break;
}
Q_UNUSED(value1);
Q_UNUSED(value2);
Q_UNUSED(value3);
}

@@ -382,6 +393,14 @@ public:
QApplication::exec();
}

void killMsgTimer()
{
Q_ASSERT(msgTimer != 0);

killTimer(msgTimer);
msgTimer = 0;
}

protected:
void timerEvent(QTimerEvent* const event)
{
@@ -395,7 +414,10 @@ protected:
m_client->idle();

if (! m_client->runMessages())
killTimer(msgTimer);
{
msgTimer = 0;
return;
}
}
}

@@ -449,6 +471,7 @@ public:
{
m_client->sendOscUpdate();
m_client->sendOscBridgeUpdate();
app->setQuitOnLastWindowClosed(false);
}

app->exec((CarlaPluginClient*)client);
@@ -469,6 +492,8 @@ public:

if (app)
{
app->killMsgTimer();

if (! app->closingDown())
app->quit();

@@ -492,11 +517,11 @@ public:
{
qDebug("CarlaToolkitPlugin::hide()");

if (dialog)
dialog->hide();

if (m_client)
((CarlaPluginClient*)m_client)->showGui(false);

if (dialog)
dialog->show();
}

void resize(int width, int height)
@@ -674,15 +699,18 @@ int main(int argc, char* argv[])
engine.removeAllPlugins();
engine.close();

// Close OSC
if (useOsc)
{
// Close OSC
client.sendOscExiting();
client.oscClose();
// toolkit can't be closed manually, only by host
}
else
{
// Close toolkit
toolkit.quit();
}

// Close toolkit
toolkit.quit();

return ret;
}


+ 2
- 1
c++/carla-bridge/qtcreator/carla-bridge-lv2-gtk2.pro View File

@@ -30,7 +30,8 @@ INCLUDEPATH = .. \
../../carla-includes

LIBS = \
../../carla-lilv/carla_lilv.a
../../carla-lilv/carla_lilv.a \
../../carla-rtmempool/carla_rtmempool.a

DEFINES = QTCREATOR_TEST
DEFINES += BUILD_BRIDGE BUILD_BRIDGE_UI BRIDGE_LV2 BRIDGE_LV2_GTK2


+ 2
- 1
c++/carla-bridge/qtcreator/carla-bridge-lv2-qt4.pro View File

@@ -30,7 +30,8 @@ INCLUDEPATH = .. \
../../carla-includes

LIBS = \
../../carla-lilv/carla_lilv.a
../../carla-lilv/carla_lilv.a \
../../carla-rtmempool/carla_rtmempool.a

DEFINES = DEBUG
DEFINES += BUILD_BRIDGE BUILD_BRIDGE_UI BRIDGE_LV2 BRIDGE_LV2_QT4


+ 2
- 1
c++/carla-bridge/qtcreator/carla-bridge-lv2-x11.pro View File

@@ -30,7 +30,8 @@ INCLUDEPATH = .. \
../../carla-includes

LIBS = \
../../carla-lilv/carla_lilv.a
../../carla-lilv/carla_lilv.a \
../../carla-rtmempool/carla_rtmempool.a

DEFINES = DEBUG
DEFINES += BUILD_BRIDGE BUILD_BRIDGE_UI BRIDGE_LV2 BRIDGE_LV2_X11


+ 5
- 0
c++/carla-includes/carla_osc_includes.h View File

@@ -30,6 +30,11 @@ struct CarlaOscData {
const char* path;
lo_address source;
lo_address target;

CarlaOscData()
: path(nullptr),
source(nullptr),
target(nullptr) {}
};

static inline


Loading…
Cancel
Save