Browse Source

More work for plugin-bridge support

tags/1.9.4
falkTX 11 years ago
parent
commit
467ec8a84d
24 changed files with 892 additions and 308 deletions
  1. +3
    -2
      source/backend/CarlaBackend.hpp
  2. +152
    -2
      source/backend/CarlaBridge.hpp
  3. +2
    -12
      source/backend/CarlaEngine.hpp
  4. +1
    -1
      source/backend/CarlaPlugin.hpp
  5. +5
    -0
      source/backend/CarlaStandalone.hpp
  6. +20
    -56
      source/backend/engine/CarlaEngine.cpp
  7. +152
    -18
      source/backend/engine/CarlaEngineBridge.cpp
  8. +2
    -2
      source/backend/engine/CarlaEngineInternal.hpp
  9. +1
    -4
      source/backend/engine/CarlaEnginePlugin.cpp
  10. +1
    -5
      source/backend/engine/CarlaEngineThread.cpp
  11. +362
    -123
      source/backend/plugin/BridgePlugin.cpp
  12. +14
    -9
      source/backend/plugin/CarlaPluginThread.cpp
  13. +3
    -2
      source/backend/plugin/CarlaPluginThread.hpp
  14. +63
    -20
      source/backend/standalone/CarlaStandalone.cpp
  15. +2
    -0
      source/bridges/CarlaBridgeClient.hpp
  16. +33
    -10
      source/bridges/CarlaBridgePlugin.cpp
  17. +10
    -7
      source/bridges/Makefile
  18. +3
    -1
      source/bridges/qtcreator/carla-bridge-plugin.pro
  19. +1
    -0
      source/carla_shared.py
  20. +1
    -1
      source/libs/jackbridge/Makefile
  21. +32
    -0
      source/libs/jackbridge/jackbridge.c
  22. +9
    -0
      source/libs/jackbridge/jackbridge.h
  23. +19
    -32
      source/utils/CarlaShmUtils.hpp
  24. +1
    -1
      source/utils/CarlaThread.hpp

+ 3
- 2
source/backend/CarlaBackend.hpp View File

@@ -619,7 +619,7 @@ enum ProcessMode {
PROCESS_MODE_MULTIPLE_CLIENTS = 1, //!< Multiple client mode (1 master client + 1 client per plugin) PROCESS_MODE_MULTIPLE_CLIENTS = 1, //!< Multiple client mode (1 master client + 1 client per plugin)
PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, 'rack' mode. Processes plugins in order of id, with forced stereo. PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, 'rack' mode. Processes plugins in order of id, with forced stereo.
PROCESS_MODE_PATCHBAY = 3, //!< Single client, 'patchbay' mode. PROCESS_MODE_PATCHBAY = 3, //!< Single client, 'patchbay' mode.
PROCESS_MODE_BRIDGE = 4 //!< Special mode, used in plugin-bridges only. RT buffers come from shared memory in a separate host app.
PROCESS_MODE_BRIDGE = 4 //!< Special mode, used in plugin-bridges only.
}; };


/*! /*!
@@ -627,7 +627,8 @@ enum ProcessMode {
*/ */
enum TransportMode { enum TransportMode {
TRANSPORT_MODE_INTERNAL = 0, //!< Internal transport mode. TRANSPORT_MODE_INTERNAL = 0, //!< Internal transport mode.
TRANSPORT_MODE_JACK = 1 //!< JACK transport, only available if driver name is "JACK"
TRANSPORT_MODE_JACK = 1, //!< JACK transport, only available if driver name is "JACK"
TRANSPORT_MODE_BRIDGE = 2 //!< Special mode, used in plugin-bridges only.
}; };


/*! /*!


+ 152
- 2
source/backend/CarlaBridge.hpp View File

@@ -18,6 +18,8 @@
#ifndef __CARLA_BRIDGE_HPP__ #ifndef __CARLA_BRIDGE_HPP__
#define __CARLA_BRIDGE_HPP__ #define __CARLA_BRIDGE_HPP__


#include "CarlaUtils.hpp"

#include <semaphore.h> #include <semaphore.h>


#define BRIDGE_SHM_RING_BUFFER_SIZE 2048 #define BRIDGE_SHM_RING_BUFFER_SIZE 2048
@@ -50,6 +52,14 @@ enum PluginBridgeInfoType {
}; };
#endif #endif


enum PluginBridgeOpcode {
kPluginBridgeOpcodeNull = 0,
kPluginBridgeOpcodeReadyWait = 1,
kPluginBridgeOpcodeBufferSize = 2,
kPluginBridgeOpcodeSampleRate = 3,
kPluginBridgeOpcodeProcess = 4
};

/*! /*!
* TODO. * TODO.
*/ */
@@ -69,14 +79,154 @@ struct BridgeShmControl {
// Let's make sure there's plenty of room for either one. // Let's make sure there's plenty of room for either one.
union { union {
sem_t runServer; sem_t runServer;
char _alignServer[32];
char _alignServer[64];
}; };
union { union {
sem_t runClient; sem_t runClient;
char _alignClient[32];
char _alignClient[64];
}; };


BridgeRingBuffer ringBuffer; BridgeRingBuffer ringBuffer;
}; };


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

static inline
void rdwr_tryRead(BridgeRingBuffer* const ringbuf, void* const buf, const size_t size)
{
char* const charbuf = static_cast<char*>(buf);

size_t tail = ringbuf->tail;
size_t head = ringbuf->head;
size_t wrap = 0;

if (head <= tail) {
wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
}
if (head - tail + wrap < size) {
return;
}

size_t readto = tail + size;

if (readto >= BRIDGE_SHM_RING_BUFFER_SIZE)
{
readto -= BRIDGE_SHM_RING_BUFFER_SIZE;
size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - tail;
std::memcpy(charbuf, ringbuf->buf + tail, firstpart);
std::memcpy(charbuf + firstpart, ringbuf->buf, readto);
}
else
{
std::memcpy(charbuf, ringbuf->buf + tail, size);
}

ringbuf->tail = readto;
}

static inline
void rdwr_tryWrite(BridgeRingBuffer* const ringbuf, const void* const buf, const size_t size)
{
const char* const charbuf = static_cast<const char*>(buf);

size_t written = ringbuf->written;
size_t tail = ringbuf->tail;
size_t wrap = 0;

if (tail <= written)
{
wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
}
if (tail - written + wrap < size)
{
carla_stderr2("Operation ring buffer full! Dropping events.");
ringbuf->invalidateCommit = true;
return;
}

size_t writeto = written + size;

if (writeto >= BRIDGE_SHM_RING_BUFFER_SIZE)
{
writeto -= BRIDGE_SHM_RING_BUFFER_SIZE;
size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - written;
std::memcpy(ringbuf->buf + written, charbuf, firstpart);
std::memcpy(ringbuf->buf, charbuf + firstpart, writeto);
}
else
{
std::memcpy(ringbuf->buf + written, charbuf, size);
}

ringbuf->written = writeto;
}

static inline
void rdwr_commitWrite(BridgeRingBuffer* const ringbuf)
{
if (ringbuf->invalidateCommit)
{
ringbuf->written = ringbuf->head;
ringbuf->invalidateCommit = false;
}
else
{
ringbuf->head = ringbuf->written;
}
}

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

static inline
bool rdwr_dataAvailable(BridgeRingBuffer* const ringbuf)
{
return (ringbuf->tail != ringbuf->head);
}

static inline
PluginBridgeOpcode rdwr_readOpcode(BridgeRingBuffer* const ringbuf)
{
PluginBridgeOpcode code = kPluginBridgeOpcodeNull;
rdwr_tryRead(ringbuf, &code, sizeof(PluginBridgeOpcode));
return code;
}

static inline
int rdwr_readInt(BridgeRingBuffer* const ringbuf)
{
int i = 0;
rdwr_tryRead(ringbuf, &i, sizeof(int));
return i;
}

static inline
float rdwr_readFloat(BridgeRingBuffer* const ringbuf)
{
float f = 0.0f;
rdwr_tryRead(ringbuf, &f, sizeof(float));
return f;
}

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

static inline
void rdwr_writeOpcode(BridgeRingBuffer* const ringbuf, const PluginBridgeOpcode opcode)
{
rdwr_tryWrite(ringbuf, &opcode, sizeof(PluginBridgeOpcode));
}

static inline
void rdwr_writeInt(BridgeRingBuffer* const ringbuf, const int value)
{
rdwr_tryWrite(ringbuf, &value, sizeof(int));
}

static inline
void rdwr_writeFloat(BridgeRingBuffer* const ringbuf, const float value)
{
rdwr_tryWrite(ringbuf, &value, sizeof(float));
}

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

#endif // __CARLA_BRIDGE_HPP__ #endif // __CARLA_BRIDGE_HPP__

+ 2
- 12
source/backend/CarlaEngine.hpp View File

@@ -23,8 +23,6 @@


#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
struct CarlaOscData; struct CarlaOscData;
#else
class QProcessEnvironment;
#endif #endif


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE
@@ -913,20 +911,13 @@ public:
*/ */
void setAboutToClose(); void setAboutToClose();


#ifndef BUILD_BRIDGE
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Options // Options


/*!
* Get the engine options as process environment.
*/
const QProcessEnvironment& getOptionsAsProcessEnvironment() const;

/*! /*!
* Set the engine option \a option. * Set the engine option \a option.
*/ */
void setOption(const OptionsType option, const int value, const char* const valueStr); void setOption(const OptionsType option, const int value, const char* const valueStr);
#endif


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// OSC Stuff // OSC Stuff
@@ -1013,9 +1004,6 @@ protected:
#endif #endif


private: private:
#ifdef BUILD_BRIDGE
static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName);
#endif
#ifdef WANT_JACK #ifdef WANT_JACK
static CarlaEngine* newJack(); static CarlaEngine* newJack();
#endif #endif
@@ -1038,6 +1026,8 @@ private:


public: public:
#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName);

void osc_send_bridge_audio_count(const int32_t ins, const int32_t outs, const int32_t total); void osc_send_bridge_audio_count(const int32_t ins, const int32_t outs, const int32_t total);
void osc_send_bridge_midi_count(const int32_t ins, const int32_t outs, const int32_t total); void osc_send_bridge_midi_count(const int32_t ins, const int32_t outs, const int32_t total);
void osc_send_bridge_parameter_count(const int32_t ins, const int32_t outs, const int32_t total); void osc_send_bridge_parameter_count(const int32_t ins, const int32_t outs, const int32_t total);


+ 1
- 1
source/backend/CarlaPlugin.hpp View File

@@ -804,7 +804,7 @@ public:
static const PluginDescriptor* getNativePluginDescriptor(const size_t index); static const PluginDescriptor* getNativePluginDescriptor(const size_t index);


static CarlaPlugin* newNative(const Initializer& init); static CarlaPlugin* newNative(const Initializer& init);
static CarlaPlugin* newBridge(const Initializer& init, const BinaryType btype, const PluginType ptype, const char* const bridgeFilename);
static CarlaPlugin* newBridge(const Initializer& init, const BinaryType btype, const PluginType ptype, const char* const bridgeBinary);


static CarlaPlugin* newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor); static CarlaPlugin* newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor);
static CarlaPlugin* newDSSI(const Initializer& init, const char* const guiFilename); static CarlaPlugin* newDSSI(const Initializer& init, const char* const guiFilename);


+ 5
- 0
source/backend/CarlaStandalone.hpp View File

@@ -250,6 +250,11 @@ CARLA_EXPORT void carla_nsm_reply_open();
CARLA_EXPORT void carla_nsm_reply_save(); CARLA_EXPORT void carla_nsm_reply_save();
#endif #endif


#ifdef BUILD_BRIDGE
CARLA_EXPORT bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName);
CARLA_EXPORT CarlaBackend::CarlaEngine* carla_get_standalone_engine();
#endif

/**@}*/ /**@}*/


#endif // __CARLA_STANDALONE_HPP__ #endif // __CARLA_STANDALONE_HPP__

+ 20
- 56
source/backend/engine/CarlaEngine.cpp View File

@@ -101,7 +101,7 @@ CarlaEngineEventPort::CarlaEngineEventPort(const bool isInput, const ProcessMode
{ {
carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode)); carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode));


if (kProcessMode == PROCESS_MODE_PATCHBAY)
if (kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE)
fBuffer = new EngineEvent[PATCHBAY_EVENT_COUNT]; fBuffer = new EngineEvent[PATCHBAY_EVENT_COUNT];
} }


@@ -109,7 +109,7 @@ CarlaEngineEventPort::~CarlaEngineEventPort()
{ {
carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()");


if (kProcessMode == PROCESS_MODE_PATCHBAY)
if (kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE)
{ {
CARLA_ASSERT(fBuffer != nullptr); CARLA_ASSERT(fBuffer != nullptr);


@@ -128,22 +128,23 @@ void CarlaEngineEventPort::initBuffer(CarlaEngine* const engine)
#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK) if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK)
fBuffer = engine->getRackEventBuffer(kIsInput); fBuffer = engine->getRackEventBuffer(kIsInput);
else if (kProcessMode == PROCESS_MODE_PATCHBAY && ! kIsInput)
carla_zeroMem(fBuffer, sizeof(EngineEvent)*PATCHBAY_EVENT_COUNT);
else
#endif #endif
if ((kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE) && ! kIsInput)
carla_zeroMem(fBuffer, sizeof(EngineEvent)*PATCHBAY_EVENT_COUNT);
} }


uint32_t CarlaEngineEventPort::getEventCount() uint32_t CarlaEngineEventPort::getEventCount()
{ {
CARLA_ASSERT(kIsInput); CARLA_ASSERT(kIsInput);
CARLA_ASSERT(fBuffer != nullptr); CARLA_ASSERT(fBuffer != nullptr);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE);


if (! kIsInput) if (! kIsInput)
return 0; return 0;
if (fBuffer == nullptr) if (fBuffer == nullptr)
return 0; return 0;
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY)
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY && kProcessMode != PROCESS_MODE_BRIDGE)
return 0; return 0;


uint32_t count = 0; uint32_t count = 0;
@@ -162,14 +163,14 @@ const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index)
{ {
CARLA_ASSERT(kIsInput); CARLA_ASSERT(kIsInput);
CARLA_ASSERT(fBuffer != nullptr); CARLA_ASSERT(fBuffer != nullptr);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE);
CARLA_ASSERT(index < kMaxEventCount); CARLA_ASSERT(index < kMaxEventCount);


if (! kIsInput) if (! kIsInput)
return kFallbackEngineEvent; return kFallbackEngineEvent;
if (fBuffer == nullptr) if (fBuffer == nullptr)
return kFallbackEngineEvent; return kFallbackEngineEvent;
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY)
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY && kProcessMode != PROCESS_MODE_BRIDGE)
return kFallbackEngineEvent; return kFallbackEngineEvent;
if (index >= kMaxEventCount) if (index >= kMaxEventCount)
return kFallbackEngineEvent; return kFallbackEngineEvent;
@@ -181,7 +182,7 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t
{ {
CARLA_ASSERT(! kIsInput); CARLA_ASSERT(! kIsInput);
CARLA_ASSERT(fBuffer != nullptr); CARLA_ASSERT(fBuffer != nullptr);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE);
CARLA_ASSERT(type != kEngineControlEventTypeNull); CARLA_ASSERT(type != kEngineControlEventTypeNull);
CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
CARLA_SAFE_ASSERT(value >= 0.0 && value <= 1.0); CARLA_SAFE_ASSERT(value >= 0.0 && value <= 1.0);
@@ -190,7 +191,7 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t
return; return;
if (fBuffer == nullptr) if (fBuffer == nullptr)
return; return;
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY)
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY && kProcessMode != PROCESS_MODE_BRIDGE)
return; return;
if (type == kEngineControlEventTypeNull) if (type == kEngineControlEventTypeNull)
return; return;
@@ -224,7 +225,7 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha
{ {
CARLA_ASSERT(! kIsInput); CARLA_ASSERT(! kIsInput);
CARLA_ASSERT(fBuffer != nullptr); CARLA_ASSERT(fBuffer != nullptr);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY);
CARLA_ASSERT(kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY || kProcessMode == PROCESS_MODE_BRIDGE);
CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
CARLA_ASSERT(data != nullptr); CARLA_ASSERT(data != nullptr);
CARLA_ASSERT(size > 0); CARLA_ASSERT(size > 0);
@@ -233,7 +234,7 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha
return; return;
if (fBuffer == nullptr) if (fBuffer == nullptr)
return; return;
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY)
if (kProcessMode != PROCESS_MODE_CONTINUOUS_RACK && kProcessMode != PROCESS_MODE_PATCHBAY && kProcessMode != PROCESS_MODE_BRIDGE)
return; return;
if (channel >= MAX_MIDI_CHANNELS) if (channel >= MAX_MIDI_CHANNELS)
return; return;
@@ -641,7 +642,7 @@ bool CarlaEngine::close()
void CarlaEngine::idle() void CarlaEngine::idle()
{ {
CARLA_ASSERT(kData->plugins != nullptr); CARLA_ASSERT(kData->plugins != nullptr);
CARLA_ASSERT(isRunning());
//CARLA_ASSERT(isRunning());


for (unsigned int i=0; i < kData->curPluginCount; i++) for (unsigned int i=0; i < kData->curPluginCount; i++)
{ {
@@ -714,26 +715,10 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, cons
bridgeBinary = (const char*)fOptions.bridge_native; bridgeBinary = (const char*)fOptions.bridge_native;
#endif #endif


if (fOptions.preferPluginBridges && bridgeBinary != nullptr)
if (true)
//if (fOptions.preferPluginBridges && bridgeBinary != nullptr)
{ {
// TODO
if (fOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
{
setLastError("Can only use bridged plugins in JACK Multi-Client mode");
return -1;
}

// TODO
if (type() != kEngineTypeJack)
{
setLastError("Can only use bridged plugins with JACK backend");
return -1;
}

#if 0
plugin = CarlaPlugin::newBridge(init, btype, ptype, bridgeBinary); plugin = CarlaPlugin::newBridge(init, btype, ptype, bridgeBinary);
#endif
setLastError("Bridged plugins are not implemented yet");
} }
else else
#endif // BUILD_BRIDGE #endif // BUILD_BRIDGE
@@ -1207,13 +1192,6 @@ void CarlaEngine::setAboutToClose()
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Global options // Global options


#ifndef BUILD_BRIDGE

const QProcessEnvironment& CarlaEngine::getOptionsAsProcessEnvironment() const
{
return kData->procEnv;
}

#define CARLA_ENGINE_SET_OPTION_RUNNING_CHECK \ #define CARLA_ENGINE_SET_OPTION_RUNNING_CHECK \
if (isRunning()) \ if (isRunning()) \
return carla_stderr("CarlaEngine::setOption(%s, %i, \"%s\") - Cannot set this option while engine is running!", OptionsType2Str(option), value, valueStr); return carla_stderr("CarlaEngine::setOption(%s, %i, \"%s\") - Cannot set this option while engine is running!", OptionsType2Str(option), value, valueStr);
@@ -1231,7 +1209,7 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha
case OPTION_PROCESS_MODE: case OPTION_PROCESS_MODE:
CARLA_ENGINE_SET_OPTION_RUNNING_CHECK CARLA_ENGINE_SET_OPTION_RUNNING_CHECK


if (value < PROCESS_MODE_SINGLE_CLIENT || value > PROCESS_MODE_PATCHBAY)
if (value < PROCESS_MODE_SINGLE_CLIENT || value > PROCESS_MODE_BRIDGE)
return carla_stderr("CarlaEngine::setOption(%s, %i, \"%s\") - invalid value", OptionsType2Str(option), value, valueStr); return carla_stderr("CarlaEngine::setOption(%s, %i, \"%s\") - invalid value", OptionsType2Str(option), value, valueStr);


fOptions.processMode = static_cast<ProcessMode>(value); fOptions.processMode = static_cast<ProcessMode>(value);
@@ -1240,7 +1218,7 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha
case OPTION_TRANSPORT_MODE: case OPTION_TRANSPORT_MODE:
// FIXME: Always enable JACK transport for now // FIXME: Always enable JACK transport for now
#if 0 #if 0
if (value < CarlaBackend::TRANSPORT_MODE_INTERNAL || value > CarlaBackend::TRANSPORT_MODE_JACK)
if (value < CarlaBackend::TRANSPORT_MODE_INTERNAL || value > CarlaBackend::TRANSPORT_MODE_BRIDGE)
return carla_stderr2("carla_set_engine_option(OPTION_TRANSPORT_MODE, %i, \"%s\") - invalid value", value, valueStr); return carla_stderr2("carla_set_engine_option(OPTION_TRANSPORT_MODE, %i, \"%s\") - invalid value", value, valueStr);


fOptions.transportMode = static_cast<CarlaBackend::TransportMode>(value); fOptions.transportMode = static_cast<CarlaBackend::TransportMode>(value);
@@ -1293,6 +1271,7 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha
fOptions.oscUiTimeout = static_cast<uint>(value); fOptions.oscUiTimeout = static_cast<uint>(value);
break; break;


#ifndef BUILD_BRIDGE
case OPTION_PATH_BRIDGE_NATIVE: case OPTION_PATH_BRIDGE_NATIVE:
fOptions.bridge_native = valueStr; fOptions.bridge_native = valueStr;
break; break;
@@ -1308,6 +1287,7 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha
case OPTION_PATH_BRIDGE_WIN64: case OPTION_PATH_BRIDGE_WIN64:
fOptions.bridge_win64 = valueStr; fOptions.bridge_win64 = valueStr;
break; break;
#endif


#ifdef WANT_LV2 #ifdef WANT_LV2
case OPTION_PATH_BRIDGE_LV2_GTK2: case OPTION_PATH_BRIDGE_LV2_GTK2:
@@ -1346,7 +1326,6 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha
#endif #endif
} }
} }
#endif


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// OSC Stuff // OSC Stuff
@@ -2167,21 +2146,6 @@ void CarlaEngine::osc_send_bridge_set_chunk_data(const char* const chunkFile)
lo_send(kData->oscData->target, targetPath, "s", chunkFile); lo_send(kData->oscData->target, targetPath, "s", chunkFile);
} }
} }

void CarlaEngine::osc_send_bridge_set_peaks()
{
CARLA_ASSERT(kData->oscData != nullptr);

const EnginePluginData& pData = kData->plugins[0];

if (kData->oscData != nullptr && kData->oscData->target != nullptr)
{
char targetPath[std::strlen(kData->oscData->path)+22];
std::strcpy(targetPath, kData->oscData->path);
std::strcat(targetPath, "/bridge_set_peaks");
lo_send(kData->oscData->target, targetPath, "ffff", pData.insPeak[0], pData.insPeak[1], pData.outsPeak[0], pData.outsPeak[1]);
}
}
#endif #endif


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE

+ 152
- 18
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -21,9 +21,17 @@
#include "CarlaBackendUtils.hpp" #include "CarlaBackendUtils.hpp"
#include "CarlaMIDI.h" #include "CarlaMIDI.h"


#include "CarlaBridge.hpp"
#include "../CarlaBridge.hpp"
#include "CarlaShmUtils.hpp" #include "CarlaShmUtils.hpp"


#include "jackbridge/jackbridge.h"

#include <ctime>

//#ifdef CARLA_OS_WIN
//# include <sys/time.h>
//#endif

CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


#if 0 #if 0
@@ -32,16 +40,22 @@ CARLA_BACKEND_START_NAMESPACE


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


class CarlaEngineBridge : public CarlaEngine
class CarlaEngineBridge : public CarlaEngine,
public CarlaThread
{ {
public: public:
CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName) CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName)
: CarlaEngine()
: CarlaEngine(),
fIsRunning(false),
fQuitNow(false)
{ {
carla_debug("CarlaEngineBridge::CarlaEngineBridge()"); carla_debug("CarlaEngineBridge::CarlaEngineBridge()");


fShmAudioPool.filename = "/carla-bridge_shm_" + audioBaseName;
fShmControl.filename = "/carla-bridge_shc_" + controlBaseName;
fShmAudioPool.filename = "/carla-bridge_shm_";
fShmAudioPool.filename += audioBaseName;

fShmControl.filename = "/carla-bridge_shc_";
fShmControl.filename += controlBaseName;
} }


~CarlaEngineBridge() ~CarlaEngineBridge()
@@ -56,11 +70,14 @@ public:
{ {
carla_debug("CarlaEngineBridge::init(\"%s\")", clientName); carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);


char tmpFileBase[60];

// SHM Audio Pool // SHM Audio Pool
{ {
#ifdef CARLA_OS_WIN
// TESTING!
fShmAudioPool.shm = carla_shm_attach_linux((const char*)fShmAudioPool.filename);
#else
fShmAudioPool.shm = carla_shm_attach((const char*)fShmAudioPool.filename); fShmAudioPool.shm = carla_shm_attach((const char*)fShmAudioPool.filename);
#endif


if (! carla_is_shm_valid(fShmAudioPool.shm)) if (! carla_is_shm_valid(fShmAudioPool.shm))
{ {
@@ -72,7 +89,12 @@ public:


// SHM Control // SHM Control
{ {
#ifdef CARLA_OS_WIN
// TESTING!
fShmControl.shm = carla_shm_attach_linux((const char*)fShmControl.filename);
#else
fShmControl.shm = carla_shm_attach((const char*)fShmControl.filename); fShmControl.shm = carla_shm_attach((const char*)fShmControl.filename);
#endif


if (! carla_is_shm_valid(fShmControl.shm)) if (! carla_is_shm_valid(fShmControl.shm))
{ {
@@ -81,7 +103,7 @@ public:
return false; return false;
} }


if (! carla_shm_map<ShmControl>(fShmControl.shm, fShmControl.data))
if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
{ {
_cleanup(); _cleanup();
carla_stdout("Failed to mmap shared memory file"); carla_stdout("Failed to mmap shared memory file");
@@ -89,7 +111,20 @@ public:
} }
} }


CarlaEngine::init(fName);
// Read values from memory
CARLA_ASSERT(rdwr_readOpcode(&fShmControl.data->ringBuffer) == kPluginBridgeOpcodeBufferSize);
fBufferSize = rdwr_readInt(&fShmControl.data->ringBuffer);
carla_stderr("BufferSize: %i", fBufferSize);

CARLA_ASSERT(rdwr_readOpcode(&fShmControl.data->ringBuffer) == kPluginBridgeOpcodeSampleRate);
fSampleRate = rdwr_readFloat(&fShmControl.data->ringBuffer);
carla_stderr("SampleRate: %f", fSampleRate);

fQuitNow = false;
fIsRunning = true;

CarlaThread::start();
CarlaEngine::init(clientName);
return true; return true;
} }


@@ -98,6 +133,9 @@ public:
carla_debug("CarlaEnginePlugin::close()"); carla_debug("CarlaEnginePlugin::close()");
CarlaEngine::close(); CarlaEngine::close();


fQuitNow = true;
CarlaThread::stop();

_cleanup(); _cleanup();


return true; return true;
@@ -105,7 +143,7 @@ public:


bool isRunning() const bool isRunning() const
{ {
return true;
return fIsRunning;
} }


bool isOffline() const bool isOffline() const
@@ -118,16 +156,113 @@ public:
return kEngineTypeBridge; return kEngineTypeBridge;
} }


// -------------------------------------
// CarlaThread virtual calls

void run()
{
// TODO - set RT permissions

const int timeout = 50;

while (! fQuitNow)
{
carla_debug("RUN 001");
timespec ts_timeout;
#if 0//def CARLA_OS_WIN
timeval now;
gettimeofday(&now, nullptr);
ts_timeout.tv_sec = now.tv_sec;
ts_timeout.tv_nsec = now.tv_usec * 1000;
#else
linux_clock_gettime_rt(&ts_timeout);
#endif

time_t seconds = timeout / 1000;
ts_timeout.tv_sec += seconds;
ts_timeout.tv_nsec += (timeout - seconds * 1000) * 1000000;
if (ts_timeout.tv_nsec >= 1000000000) {
ts_timeout.tv_nsec -= 1000000000;
ts_timeout.tv_sec++;
}

if (linux_sem_timedwait(&fShmControl.data->runServer, &ts_timeout))
{
if (errno == ETIMEDOUT)
{
continue;
}
else
{
fQuitNow = true;
break;
}
}

carla_debug("RUN 004");

while (rdwr_dataAvailable(&fShmControl.data->ringBuffer))
{
carla_debug("RUN 005");
const PluginBridgeOpcode opcode = rdwr_readOpcode(&fShmControl.data->ringBuffer);

switch (opcode)
{
case kPluginBridgeOpcodeNull:
break;
case kPluginBridgeOpcodeReadyWait:
fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, rdwr_readInt(&fShmControl.data->ringBuffer));
break;
case kPluginBridgeOpcodeBufferSize:
bufferSizeChanged(rdwr_readInt(&fShmControl.data->ringBuffer));
break;
case kPluginBridgeOpcodeSampleRate:
sampleRateChanged(rdwr_readFloat(&fShmControl.data->ringBuffer));
break;
case kPluginBridgeOpcodeProcess:
{
CARLA_ASSERT(fShmAudioPool.data != nullptr);
CarlaPlugin* const plugin(getPluginUnchecked(0));
carla_debug("RUN 006");

if (plugin != nullptr && plugin->enabled() && plugin->tryLock())
{
const uint32_t inCount = plugin->audioInCount();
const uint32_t outCount = plugin->audioOutCount();

float* inBuffer[inCount];
float* outBuffer[outCount];

for (uint32_t i=0; i < inCount; i++)
inBuffer[i] = fShmAudioPool.data + i*fBufferSize;
for (uint32_t i=0; i < outCount; i++)
outBuffer[i] = fShmAudioPool.data + (i+inCount)*fBufferSize;

plugin->initBuffers();
plugin->setActive(true, false, false);
plugin->process(inBuffer, outBuffer, fBufferSize);
plugin->unlock();
}
break;
}
}
}

if (linux_sem_post(&fShmControl.data->runClient) != 0)
carla_stderr2("Could not post to semaphore");
}

fIsRunning = false;
}

private: private:
struct BridgeAudioPool { struct BridgeAudioPool {
CarlaString filename; CarlaString filename;
float* data; float* data;
size_t size;
shm_t shm; shm_t shm;


BridgeAudioPool() BridgeAudioPool()
: data(nullptr),
size(0)
: data(nullptr)
{ {
carla_shm_init(shm); carla_shm_init(shm);
} }
@@ -135,7 +270,7 @@ private:


struct BridgeControl { struct BridgeControl {
CarlaString filename; CarlaString filename;
ShmControl* data;
BridgeShmControl* data;
shm_t shm; shm_t shm;


BridgeControl() BridgeControl()
@@ -146,6 +281,9 @@ private:


} fShmControl; } fShmControl;


bool fIsRunning;
bool fQuitNow;

void _cleanup() void _cleanup()
{ {
if (fShmAudioPool.filename.isNotEmpty()) if (fShmAudioPool.filename.isNotEmpty())
@@ -154,11 +292,7 @@ private:
if (fShmControl.filename.isNotEmpty()) if (fShmControl.filename.isNotEmpty())
fShmControl.filename.clear(); fShmControl.filename.clear();


// delete data
fShmAudioPool.data = nullptr; fShmAudioPool.data = nullptr;
fShmAudioPool.size = 0;

// and again
fShmControl.data = nullptr; fShmControl.data = nullptr;


if (carla_is_shm_valid(fShmAudioPool.shm)) if (carla_is_shm_valid(fShmAudioPool.shm))


+ 2
- 2
source/backend/engine/CarlaEngineInternal.hpp View File

@@ -210,9 +210,9 @@ struct CarlaEngineProtectedData {
#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
static void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin) static void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin)
{ {
CARLA_ASSERT(id < engine->kData->curPluginCount);
CARLA_ASSERT(id == engine->kData->curPluginCount);


if (id < engine->kData->curPluginCount)
if (id == engine->kData->curPluginCount)
engine->kData->plugins[id].plugin = plugin; engine->kData->plugins[id].plugin = plugin;
} }
#endif #endif


+ 1
- 4
source/backend/engine/CarlaEnginePlugin.cpp View File

@@ -99,10 +99,7 @@ public:
fBufferSize = d_bufferSize(); fBufferSize = d_bufferSize();
fSampleRate = d_sampleRate(); fSampleRate = d_sampleRate();


fName = clientName;
fName.toBasic();

CarlaEngine::init(fName);
CarlaEngine::init(clientName);
return true; return true;
} }




+ 1
- 5
source/backend/engine/CarlaEngineThread.cpp View File

@@ -129,17 +129,13 @@ void CarlaEngineThread::run()
} }
} }


#ifndef BUILD_BRIDGE
// --------------------------------------------------- // ---------------------------------------------------
// Update OSC control client peaks // Update OSC control client peaks


if (oscRegisted) if (oscRegisted)
{
#ifdef BUILD_BRIDGE
kEngine->osc_send_bridge_set_peaks();
#else
kEngine->osc_send_control_set_peaks(i); kEngine->osc_send_control_set_peaks(i);
#endif #endif
}
} }
} }




+ 362
- 123
source/backend/plugin/BridgePlugin.cpp View File

@@ -84,8 +84,6 @@ shm_t shm_mkstemp(char* const fileBase)
return shm; return shm;
} }


std::srand(std::time(NULL));

while (true) while (true)
{ {
for (int c = size - 6; c < size; c++) for (int c = size - 6; c < size; c++)
@@ -136,28 +134,24 @@ public:
kData->singleMutex.lock(); kData->singleMutex.lock();
kData->masterMutex.lock(); kData->masterMutex.lock();


#if 0
if (osc.data.target)
_cleanup();

if (kData->osc.data.target != nullptr)
{ {
osc_send_hide(&osc.data);
osc_send_quit(&osc.data);
osc.data.free();
osc_send_hide(&kData->osc.data);
osc_send_quit(&kData->osc.data);
} }


if (osc.thread)
{
// Wait a bit first, try safe quit, then force kill
if (osc.thread->isRunning() && ! osc.thread->wait(3000))
{
carla_stderr("Failed to properly stop Plugin Bridge thread");
osc.thread->terminate();
}
kData->osc.data.free();


delete osc.thread;
// Wait a bit first, then force kill
if (kData->osc.thread.isRunning() && ! kData->osc.thread.stop(1000)) // kData->engine->getOptions().oscUiTimeout
{
carla_stderr("Failed to properly stop Plugin Bridge thread");
kData->osc.thread.terminate();
} }


info.chunk.clear();
#endif
//info.chunk.clear();
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -227,39 +221,29 @@ public:


return params[parameterId].value; return params[parameterId].value;
} }
#endif


void getLabel(char* const strBuf) void getLabel(char* const strBuf)
{ {
if (info.label)
strncpy(strBuf, info.label, STR_MAX);
else
CarlaPlugin::getLabel(strBuf);
std::strncpy(strBuf, (const char*)fInfo.label, STR_MAX);
} }


void getMaker(char* const strBuf) void getMaker(char* const strBuf)
{ {
if (info.maker)
strncpy(strBuf, info.maker, STR_MAX);
else
CarlaPlugin::getMaker(strBuf);
std::strncpy(strBuf, (const char*)fInfo.maker, STR_MAX);
} }


void getCopyright(char* const strBuf) void getCopyright(char* const strBuf)
{ {
if (info.copyright)
strncpy(strBuf, info.copyright, STR_MAX);
else
CarlaPlugin::getCopyright(strBuf);
std::strncpy(strBuf, (const char*)fInfo.copyright, STR_MAX);
} }


void getRealName(char* const strBuf) void getRealName(char* const strBuf)
{ {
if (info.name)
strncpy(strBuf, info.name, STR_MAX);
else
CarlaPlugin::getRealName(strBuf);
std::strncpy(strBuf, (const char*)fInfo.name, STR_MAX);
} }


#if 0
void getParameterName(const uint32_t parameterId, char* const strBuf) void getParameterName(const uint32_t parameterId, char* const strBuf)
{ {
CARLA_ASSERT(parameterId < param.count); CARLA_ASSERT(parameterId < param.count);
@@ -273,15 +257,6 @@ public:


strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX); strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX);
} }

void getGuiInfo(GuiType* const type, bool* const resizable)
{
if (m_hints & PLUGIN_HAS_GUI)
*type = GUI_EXTERNAL_OSC;
else
*type = GUI_NONE;
*resizable = false;
}
#endif #endif


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -289,12 +264,11 @@ public:


int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types) int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types)
{ {
carla_debug("setOscPluginBridgeInfo(%i, %i, %p, \"%s\")", type, argc, argv, types);
carla_stdout("setOscPluginBridgeInfo(%i, %i, %p, \"%s\")", type, argc, argv, types);


#if 0
switch (type) switch (type)
{ {
case PluginBridgeAudioCount:
case kPluginBridgeAudioCount:
{ {
CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii"); CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");


@@ -306,14 +280,16 @@ public:
CARLA_ASSERT(aOuts >= 0); CARLA_ASSERT(aOuts >= 0);
CARLA_ASSERT(aIns + aOuts == aTotal); CARLA_ASSERT(aIns + aOuts == aTotal);


info.aIns = aIns;
info.aOuts = aOuts;
fInfo.aIns = aIns;
fInfo.aOuts = aOuts;


break; break;
Q_UNUSED(aTotal);

// unused
(void)aTotal;
} }


case PluginBridgeMidiCount:
case kPluginBridgeMidiCount:
{ {
CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii"); CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");


@@ -325,13 +301,16 @@ public:
CARLA_ASSERT(mOuts >= 0); CARLA_ASSERT(mOuts >= 0);
CARLA_ASSERT(mIns + mOuts == mTotal); CARLA_ASSERT(mIns + mOuts == mTotal);


info.mIns = mIns;
info.mOuts = mOuts;
fInfo.mIns = mIns;
fInfo.mOuts = mOuts;


break; break;
Q_UNUSED(mTotal);

// unused
(void)mTotal;
} }


#if 0
case PluginBridgeParameterCount: case PluginBridgeParameterCount:
{ {
CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii"); CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
@@ -438,8 +417,9 @@ public:


break; break;
} }
#endif


case PluginBridgePluginInfo:
case kPluginBridgePluginInfo:
{ {
CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh"); CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh");


@@ -458,21 +438,23 @@ public:
CARLA_ASSERT(maker); CARLA_ASSERT(maker);
CARLA_ASSERT(copyright); CARLA_ASSERT(copyright);


m_hints = hints | PLUGIN_IS_BRIDGE;
info.category = (PluginCategory)category;
info.uniqueId = uniqueId;
fHints = hints | PLUGIN_IS_BRIDGE;


info.name = strdup(name);
info.label = strdup(label);
info.maker = strdup(maker);
info.copyright = strdup(copyright);
fInfo.category = static_cast<PluginCategory>(category);
fInfo.uniqueId = uniqueId;


if (! m_name)
m_name = x_engine->getUniquePluginName(name);
fInfo.name = name;
fInfo.label = label;
fInfo.maker = maker;
fInfo.copyright = copyright;

if (fName.isEmpty())
fName = kData->engine->getNewUniquePluginName(name);


break; break;
} }


#if 0
case PluginBridgeParameterInfo: case PluginBridgeParameterInfo:
{ {
CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss"); CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
@@ -753,30 +735,29 @@ public:


break; break;
} }
#endif


case PluginBridgeUpdateNow:
case kPluginBridgeUpdateNow:
{ {
m_initiated = true;
fInitiated = true;
break; break;
} }


case PluginBridgeError:
case kPluginBridgeError:
{ {
CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s"); CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");


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


CARLA_ASSERT(error);
CARLA_ASSERT(error != nullptr);


m_initiated = true;
m_initError = true;

x_engine->setLastError(error);
kData->engine->setLastError(error);


fInitError = true;
fInitiated = true;
break; break;
} }
} }
#endif


return 0; return 0;
} }
@@ -837,6 +818,7 @@ public:
osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData()); osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
} }
} }
#endif


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Set gui stuff // Set gui stuff
@@ -844,15 +826,15 @@ public:
void showGui(const bool yesNo) void showGui(const bool yesNo)
{ {
if (yesNo) if (yesNo)
osc_send_show(&osc.data);
osc_send_show(&kData->osc.data);
else else
osc_send_hide(&osc.data);
osc_send_hide(&kData->osc.data);
} }


void idleGui() void idleGui()
{ {
if (! osc.thread->isRunning())
carla_stderr("TESTING: Bridge has closed!");
if (! kData->osc.thread.isRunning())
carla_stderr2("TESTING: Bridge has closed!");


CarlaPlugin::idleGui(); CarlaPlugin::idleGui();
} }
@@ -860,6 +842,131 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Plugin state // Plugin state


void reload()
{
carla_debug("BridgePlugin::reload() - start");
CARLA_ASSERT(kData->engine != nullptr);

if (kData->engine == nullptr)
return;

const ProcessMode processMode(kData->engine->getProccessMode());

// Safely disable plugin for reload
const ScopedDisabler sd(this);

deleteBuffers();

bool needsCtrlIn, needsCtrlOut;
needsCtrlIn = needsCtrlOut = false;

if (fInfo.aIns > 0)
{
kData->audioIn.createNew(fInfo.aIns);
}

if (fInfo.aOuts > 0)
{
kData->audioOut.createNew(fInfo.aOuts);
needsCtrlIn = true;
}

if (fInfo.mIns > 0)
needsCtrlIn = true;

if (fInfo.mOuts > 0)
needsCtrlOut = true;

const uint portNameSize = kData->engine->maxPortNameSize();
CarlaString portName;

// Audio Ins
for (uint32_t j=0; j < fInfo.aIns; j++)
{
portName.clear();

if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{
portName = fName;
portName += ":";
}

if (fInfo.aIns > 1)
{
portName += "input_";
portName += CarlaString(j+1);
}
else
portName += "input";
portName.truncate(portNameSize);

kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
kData->audioIn.ports[j].rindex = j;
}

// Audio Outs
for (uint32_t j=0; j < fInfo.aOuts; j++)
{
portName.clear();

if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{
portName = fName;
portName += ":";
}

if (fInfo.aOuts > 1)
{
portName += "output_";
portName += CarlaString(j+1);
}
else
portName += "output";
portName.truncate(portNameSize);

kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
kData->audioOut.ports[j].rindex = j;
}

if (needsCtrlIn)
{
portName.clear();

if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{
portName = fName;
portName += ":";
}

portName += "event-in";
portName.truncate(portNameSize);

kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
}

if (needsCtrlOut)
{
portName.clear();

if (processMode == PROCESS_MODE_SINGLE_CLIENT)
{
portName = fName;
portName += ":";
}

portName += "event-out";
portName.truncate(portNameSize);

kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
}

//bufferSizeChanged(kData->engine->getBufferSize());
//reloadPrograms(true);

carla_debug("BridgePlugin::reload() - end");
}

#if 0
void prepareForSave() void prepareForSave()
{ {
m_saved = false; m_saved = false;
@@ -877,93 +984,125 @@ public:
else else
carla_debug("BridgePlugin::prepareForSave() - success!"); carla_debug("BridgePlugin::prepareForSave() - success!");
} }
#endif

// -------------------------------------------------------------------
// Plugin processing

void process(float** const inBuffer, float** const outBuffer, const uint32_t frames)
{
uint32_t i, k;

// --------------------------------------------------------------------------------------------------------
// Check if active

if (! kData->active)
{
// disable any output sound
for (i=0; i < kData->audioOut.count; i++)
carla_zeroFloat(outBuffer[i], frames);

kData->activeBefore = kData->active;
return;
}

for (i=0; i < fInfo.aIns; ++i)
carla_copyFloat(fShmAudioPool.data + i * frames, inBuffer[i], frames);

rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeProcess);
rdwr_commitWrite(&fShmControl.data->ringBuffer);

waitForServer();

for (i=0; i < fInfo.aOuts; ++i)
carla_copyFloat(outBuffer[i], fShmAudioPool.data + (i+fInfo.aIns) * frames, frames);
}


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Post-poned events // Post-poned events


void uiParameterChange(const uint32_t index, const double value)
void uiParameterChange(const uint32_t index, const float value)
{ {
CARLA_ASSERT(index < param.count);
CARLA_ASSERT(index < kData->param.count);


if (index >= param.count)
if (index >= kData->param.count)
return; return;
if (! osc.data.target)
if (kData->osc.data.target == nullptr)
return; return;


osc_send_control(&osc.data, param.data[index].rindex, value);
osc_send_control(&kData->osc.data, kData->param.data[index].rindex, value);
} }


void uiProgramChange(const uint32_t index) void uiProgramChange(const uint32_t index)
{ {
CARLA_ASSERT(index < prog.count);
CARLA_ASSERT(index < kData->prog.count);


if (index >= prog.count)
if (index >= kData->prog.count)
return; return;
if (! osc.data.target)
if (kData->osc.data.target == nullptr)
return; return;


osc_send_program(&osc.data, index);
osc_send_program(&kData->osc.data, index);
} }


void uiMidiProgramChange(const uint32_t index) void uiMidiProgramChange(const uint32_t index)
{ {
CARLA_ASSERT(index < midiprog.count);
CARLA_ASSERT(index < kData->midiprog.count);


if (index >= midiprog.count)
if (index >= kData->midiprog.count)
return; return;
if (! osc.data.target)
if (kData->osc.data.target == nullptr)
return; return;


osc_send_midi_program(&osc.data, index);
osc_send_midi_program(&kData->osc.data, index);
} }


void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
{ {
CARLA_ASSERT(channel < 16);
CARLA_ASSERT(note < 128);
CARLA_ASSERT(velo > 0 && velo < 128);
CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
CARLA_ASSERT(note < MAX_MIDI_NOTE);
CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);


if (! osc.data.target)
if (channel >= MAX_MIDI_CHANNELS)
return;
if (note >= MAX_MIDI_NOTE)
return;
if (velo >= MAX_MIDI_VALUE)
return;
if (kData->osc.data.target == nullptr)
return; return;


uint8_t midiData[4] = { 0 }; uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_ON + channel; midiData[1] = MIDI_STATUS_NOTE_ON + channel;
midiData[2] = note; midiData[2] = note;
midiData[3] = velo; midiData[3] = velo;
osc_send_midi(&osc.data, midiData);

osc_send_midi(&kData->osc.data, midiData);
} }


void uiNoteOff(const uint8_t channel, const uint8_t note) void uiNoteOff(const uint8_t channel, const uint8_t note)
{ {
CARLA_ASSERT(channel < 16);
CARLA_ASSERT(note < 128);
CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
CARLA_ASSERT(note < MAX_MIDI_NOTE);


if (! osc.data.target)
if (channel >= MAX_MIDI_CHANNELS)
return;
if (note >= MAX_MIDI_NOTE)
return;
if (kData->osc.data.target == nullptr)
return; return;


uint8_t midiData[4] = { 0 }; uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_OFF + channel; midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
midiData[2] = note; midiData[2] = note;
osc_send_midi(&osc.data, midiData);
}


// -------------------------------------------------------------------
// Cleanup
osc_send_midi(&kData->osc.data, midiData);
}


void deleteBuffers()
void bufferSizeChanged(const uint32_t newBufferSize)
{ {
carla_debug("BridgePlugin::delete_buffers() - start");

if (param.count > 0)
delete[] params;

params = nullptr;

CarlaPlugin::deleteBuffers();

carla_debug("BridgePlugin::delete_buffers() - end");
resizeAudioPool(newBufferSize);
} }
#endif


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


@@ -1001,11 +1140,23 @@ public:


fFilename = filename; fFilename = filename;


// ---------------------------------------------------------------
// register client

kData->client = kData->engine->addClient(this);

if (kData->client == nullptr || ! kData->client->isOk())
{
kData->engine->setLastError("Failed to register plugin client");
return false;
}

// --------------------------------------------------------------- // ---------------------------------------------------------------
// SHM Audio Pool // SHM Audio Pool
{ {
char tmpFileBase[60]; char tmpFileBase[60];


std::srand(std::time(NULL));
std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX"); std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");


fShmAudioPool.shm = shm_mkstemp(tmpFileBase); fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
@@ -1024,6 +1175,7 @@ public:
// SHM Control // SHM Control
{ {
char tmpFileBase[60]; char tmpFileBase[60];

std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX"); std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX");


fShmControl.shm = shm_mkstemp(tmpFileBase); fShmControl.shm = shm_mkstemp(tmpFileBase);
@@ -1044,7 +1196,10 @@ public:
return false; return false;
} }


CARLA_ASSERT(fShmControl.data != nullptr);

std::memset(fShmControl.data, 0, sizeof(BridgeShmControl)); std::memset(fShmControl.data, 0, sizeof(BridgeShmControl));
std::strcpy(fShmControl.data->ringBuffer.buf, "This thing is actually working!!!!");


if (sem_init(&fShmControl.data->runServer, 1, 0) != 0) if (sem_init(&fShmControl.data->runServer, 1, 0) != 0)
{ {
@@ -1061,11 +1216,29 @@ public:
} }
} }


// initial values
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeBufferSize);
rdwr_writeInt(&fShmControl.data->ringBuffer, kData->engine->getBufferSize());

rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSampleRate);
rdwr_writeFloat(&fShmControl.data->ringBuffer, kData->engine->getSampleRate());

rdwr_commitWrite(&fShmControl.data->ringBuffer);

// register plugin now so we can receive OSC (and wait for it) // register plugin now so we can receive OSC (and wait for it)
fHints |= PLUGIN_IS_BRIDGE;
registerEnginePlugin(kData->engine, fId, this); registerEnginePlugin(kData->engine, fId, this);


kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType));
kData->osc.thread.start();
// init OSC
{
char shmIdStr[12+1] = { 0 };
std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6);

kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
kData->osc.thread.start();
kData->osc.thread.waitForStarted();
}


for (int i=0; i < 200; i++) for (int i=0; i < 200; i++)
{ {
@@ -1079,7 +1252,9 @@ public:
// unregister so it gets handled properly // unregister so it gets handled properly
registerEnginePlugin(kData->engine, fId, nullptr); registerEnginePlugin(kData->engine, fId, nullptr);


kData->osc.thread.terminate();
if (kData->osc.thread.isRunning())
kData->osc.thread.terminate();

kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)"); kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
return false; return false;
} }
@@ -1093,10 +1268,16 @@ public:
return false; return false;
} }


resizeAudioPool(kData->engine->getBufferSize());

rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeReadyWait);
rdwr_writeInt(&fShmControl.data->ringBuffer, fShmAudioPool.size);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
waitForServer();

return true; return true;
} }



private: private:
const BinaryType fBinaryType; const BinaryType fBinaryType;
const PluginType fPluginType; const PluginType fPluginType;
@@ -1154,6 +1335,61 @@ private:


BridgeParamInfo* fParams; BridgeParamInfo* fParams;


void _cleanup()
{
if (fShmAudioPool.filename.isNotEmpty())
fShmAudioPool.filename.clear();

if (fShmControl.filename.isNotEmpty())
fShmControl.filename.clear();

if (fShmAudioPool.data != nullptr)
{
carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
fShmAudioPool.data = nullptr;
}

fShmAudioPool.size = 0;

// and again
if (fShmControl.data != nullptr)
{
carla_shm_unmap(fShmControl.shm, fShmControl.data, sizeof(BridgeShmControl));
fShmControl.data = nullptr;
}

if (carla_is_shm_valid(fShmAudioPool.shm))
carla_shm_close(fShmAudioPool.shm);

if (carla_is_shm_valid(fShmControl.shm))
carla_shm_close(fShmControl.shm);
}

void resizeAudioPool(const uint32_t bufferSize)
{
if (fShmAudioPool.data != nullptr)
carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);

fShmAudioPool.size = (fInfo.aIns+fInfo.aOuts)*bufferSize*sizeof(float);

if (fShmAudioPool.size > 0)
fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, fShmAudioPool.size);
else
fShmAudioPool.data = nullptr;
}

void waitForServer()
{
sem_post(&fShmControl.data->runServer);

timespec ts_timeout;
clock_gettime(CLOCK_REALTIME, &ts_timeout);
ts_timeout.tv_sec += 5;

if (sem_timedwait(&fShmControl.data->runClient, &ts_timeout) != 0)
kData->active = false; // TODO
}

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
}; };


@@ -1163,12 +1399,12 @@ CARLA_BACKEND_END_NAMESPACE


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const extra)
CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
{ {
carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s)", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype));
carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);


#if 1//ndef BUILD_BRIDGE
if (extra == nullptr)
#ifndef BUILD_BRIDGE
if (bridgeBinary == nullptr)
{ {
init.engine->setLastError("Bridge not possible, bridge-binary not found"); init.engine->setLastError("Bridge not possible, bridge-binary not found");
return nullptr; return nullptr;
@@ -1176,7 +1412,7 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P


BridgePlugin* const plugin = new BridgePlugin(init.engine, init.id, btype, ptype); BridgePlugin* const plugin = new BridgePlugin(init.engine, init.id, btype, ptype);


//if (! plugin->init(init.filename, init.name, init.label, (const char*)extra))
if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
{ {
delete plugin; delete plugin;
return nullptr; return nullptr;
@@ -1188,10 +1424,13 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P
#else #else
init.engine->setLastError("Plugin bridge support not available"); init.engine->setLastError("Plugin bridge support not available");
return nullptr; return nullptr;

// unused
(void)bridgeBinary;
#endif #endif
} }


#if 1//ndef BUILD_BRIDGE
#ifndef BUILD_BRIDGE
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Bridge Helper // Bridge Helper




+ 14
- 9
source/backend/plugin/CarlaPluginThread.cpp View File

@@ -64,11 +64,12 @@ void CarlaPluginThread::setMode(const CarlaPluginThread::Mode mode)
fMode = mode; fMode = mode;
} }


void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const extra)
void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const extra1, const char* const extra2)
{ {
fBinary = binary; fBinary = binary;
fLabel = label; fLabel = label;
fExtra = extra;
fExtra1 = extra1;
fExtra2 = extra2;
} }


void CarlaPluginThread::run() void CarlaPluginThread::run()
@@ -84,40 +85,44 @@ void CarlaPluginThread::run()
#endif #endif
} }


QString name(kPlugin->name() ? kPlugin->name() : "(none)");
QString name(kPlugin->name());
QStringList arguments; QStringList arguments;


if (name.isEmpty())
name = "(none)";

switch (fMode) switch (fMode)
{ {
case PLUGIN_THREAD_NULL: case PLUGIN_THREAD_NULL:
break; break;


case PLUGIN_THREAD_DSSI_GUI: case PLUGIN_THREAD_DSSI_GUI:
/* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathUDP()).arg(kPlugin->id());
/* osc-url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathUDP()).arg(kPlugin->id());
/* filename */ arguments << kPlugin->filename(); /* filename */ arguments << kPlugin->filename();
/* label */ arguments << (const char*)fLabel; /* label */ arguments << (const char*)fLabel;
/* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name()); /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
break; break;


case PLUGIN_THREAD_LV2_GUI: case PLUGIN_THREAD_LV2_GUI:
/* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
/* osc-url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
/* URI */ arguments << (const char*)fLabel; /* URI */ arguments << (const char*)fLabel;
/* ui-URI */ arguments << (const char*)fExtra;
/* ui-URI */ arguments << (const char*)fExtra1;
/* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name()); /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
break; break;


case PLUGIN_THREAD_VST_GUI: case PLUGIN_THREAD_VST_GUI:
/* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
/* osc-url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
/* filename */ arguments << kPlugin->filename(); /* filename */ arguments << kPlugin->filename();
/* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name()); /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
break; break;


case PLUGIN_THREAD_BRIDGE: case PLUGIN_THREAD_BRIDGE:
/* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
/* stype */ arguments << (const char*)fExtra;
/* osc-url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
/* stype */ arguments << (const char*)fExtra1;
/* filename */ arguments << kPlugin->filename(); /* filename */ arguments << kPlugin->filename();
/* name */ arguments << name; /* name */ arguments << name;
/* label */ arguments << (const char*)fLabel; /* label */ arguments << (const char*)fLabel;
/* SHM ids */ arguments << (const char*)fExtra2;
break; break;
} }




+ 3
- 2
source/backend/plugin/CarlaPluginThread.hpp View File

@@ -41,7 +41,7 @@ public:
~CarlaPluginThread(); ~CarlaPluginThread();


void setMode(const CarlaPluginThread::Mode mode); void setMode(const CarlaPluginThread::Mode mode);
void setOscData(const char* const binary, const char* const label, const char* const extra="");
void setOscData(const char* const binary, const char* const label, const char* const extra1="", const char* const extra2="");


protected: protected:
void run(); void run();
@@ -53,7 +53,8 @@ private:
Mode fMode; Mode fMode;
CarlaString fBinary; CarlaString fBinary;
CarlaString fLabel; CarlaString fLabel;
CarlaString fExtra;
CarlaString fExtra1;
CarlaString fExtra2;
QProcess* fProcess; QProcess* fProcess;
}; };




+ 63
- 20
source/backend/standalone/CarlaStandalone.cpp View File

@@ -46,7 +46,9 @@ struct CarlaBackendStandalone {
CarlaEngine* engine; CarlaEngine* engine;
CarlaString lastError; CarlaString lastError;
CarlaString procName; CarlaString procName;
#ifndef BUILD_BRIDGE
EngineOptions options; EngineOptions options;
#endif


QApplication* app; QApplication* app;
bool needsInit; bool needsInit;
@@ -85,14 +87,6 @@ struct CarlaBackendStandalone {


} standalone; } standalone;


// -------------------------------------------------------------------------------------------------------------------
// Helpers

CarlaEngine* carla_get_standalone_engine()
{
return standalone.engine;
}

// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
// API // API


@@ -232,16 +226,6 @@ bool carla_engine_init(const char* driverName, const char* clientName)
CARLA_ASSERT(driverName != nullptr); CARLA_ASSERT(driverName != nullptr);
CARLA_ASSERT(clientName != nullptr); CARLA_ASSERT(clientName != nullptr);


#if 0
static bool sigInfoInitiated = false;

if (! sigInfoInitiated)
{
setup_siginfo();
sigInfoInitiated = true;
}
#endif

standalone.engine = CarlaEngine::newDriverByName(driverName); standalone.engine = CarlaEngine::newDriverByName(driverName);


if (standalone.engine == nullptr) if (standalone.engine == nullptr)
@@ -377,14 +361,13 @@ void carla_set_engine_callback(CarlaBackend::CallbackFunc func, void* ptr)
standalone.engine->setCallback(func, ptr); standalone.engine->setCallback(func, ptr);
} }


#ifndef BUILD_BRIDGE
void carla_set_engine_option(CarlaBackend::OptionsType option, int value, const char* valueStr) void carla_set_engine_option(CarlaBackend::OptionsType option, int value, const char* valueStr)
{ {
carla_debug("carla_set_engine_option(%s, %i, \"%s\")", CarlaBackend::OptionsType2Str(option), value, valueStr); carla_debug("carla_set_engine_option(%s, %i, \"%s\")", CarlaBackend::OptionsType2Str(option), value, valueStr);


#ifndef BUILD_BRIDGE
if (standalone.engine != nullptr) if (standalone.engine != nullptr)
standalone.engine->setOption(option, value, valueStr); standalone.engine->setOption(option, value, valueStr);
#endif


switch (option) switch (option)
{ {
@@ -493,6 +476,7 @@ void carla_set_engine_option(CarlaBackend::OptionsType option, int value, const
#endif #endif
} }
} }
#endif


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


@@ -1853,6 +1837,65 @@ void carla_nsm_reply_save()


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


#ifdef BUILD_BRIDGE
bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName)
{
carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\")", audioBaseName, controlBaseName, clientName);
CARLA_ASSERT(standalone.engine == nullptr);
CARLA_ASSERT(audioBaseName != nullptr);
CARLA_ASSERT(controlBaseName != nullptr);
CARLA_ASSERT(clientName != nullptr);

standalone.engine = CarlaEngine::newBridge(audioBaseName, controlBaseName);

if (standalone.engine == nullptr)
{
standalone.lastError = "The seleted audio driver is not available!";
return false;
}

if (standalone.callback != nullptr)
standalone.engine->setCallback(standalone.callback, nullptr);

standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, CarlaBackend::PROCESS_MODE_BRIDGE, nullptr);
standalone.engine->setOption(CarlaBackend::OPTION_TRANSPORT_MODE, CarlaBackend::TRANSPORT_MODE_BRIDGE, nullptr);
standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr);
standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, false, nullptr);

// TODO - read from environment
#ifndef BUILD_BRIDGE
standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr);
# ifdef WANT_DSSI
standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr);
# endif
standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr);
#endif

const bool initiated = standalone.engine->init(clientName);

if (initiated)
{
standalone.lastError = "no error";
standalone.init();
}
else
{
standalone.lastError = standalone.engine->getLastError();
delete standalone.engine;
standalone.engine = nullptr;
}

return initiated;
}

CarlaEngine* carla_get_standalone_engine()
{
return standalone.engine;
}
#endif

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

#if 0 #if 0
//def QTCREATOR_TEST //def QTCREATOR_TEST




+ 2
- 0
source/bridges/CarlaBridgeClient.hpp View File

@@ -140,6 +140,8 @@ private:
const char* fUiFilename; const char* fUiFilename;
void* fUiLib; void* fUiLib;
bool fUiQuit; bool fUiQuit;
#else
friend class CarlaPluginClient;
#endif #endif


const CarlaOscData* fOscData; const CarlaOscData* fOscData;


+ 33
- 10
source/bridges/CarlaBridgePlugin.cpp View File

@@ -115,17 +115,21 @@ class CarlaPluginClient : public CarlaBridgeClient,
public QObject public QObject
{ {
public: public:
CarlaPluginClient(const char* const name)
CarlaPluginClient(const bool useBridge, const char* const driverName, const char* audioBaseName, const char* controlBaseName)
: CarlaBridgeClient(nullptr), : CarlaBridgeClient(nullptr),
QObject(nullptr), QObject(nullptr),
fEngine(nullptr), fEngine(nullptr),
fPlugin(nullptr), fPlugin(nullptr),
fTimerId(0) fTimerId(0)
{ {
CARLA_ASSERT(name != nullptr);
carla_debug("CarlaPluginClient::CarlaPluginClient()");
CARLA_ASSERT(driverName != nullptr);
carla_debug("CarlaPluginClient::CarlaPluginClient(%s, \"%s\", %s, %s)", bool2str(useBridge), driverName, audioBaseName, controlBaseName);

if (useBridge)
carla_engine_init_bridge(audioBaseName, controlBaseName, driverName);
else
carla_engine_init("JACK", driverName);


carla_engine_init("JACK", name);
carla_set_engine_callback(callback, this); carla_set_engine_callback(callback, this);
} }


@@ -138,6 +142,14 @@ public:
carla_engine_close(); carla_engine_close();
} }


void oscInit(const char* const url)
{
CarlaBridgeClient::oscInit(url);

fEngine = carla_get_standalone_engine();
fEngine->setOscBridgeData(fOscData);
}

void ready() void ready()
{ {
CARLA_ASSERT(fTimerId == 0); CARLA_ASSERT(fTimerId == 0);
@@ -405,9 +417,6 @@ int CarlaBridgeOsc::handleMsgQuit()
carla_debug("CarlaBridgeOsc::handleMsgQuit()"); carla_debug("CarlaBridgeOsc::handleMsgQuit()");
CARLA_ASSERT(kClient != nullptr); CARLA_ASSERT(kClient != nullptr);


if (kClient == nullptr)
return 1;

gCloseNow = true; gCloseNow = true;


return 0; return 0;
@@ -473,7 +482,7 @@ int main(int argc, char* argv[])
{ {
CARLA_BRIDGE_USE_NAMESPACE CARLA_BRIDGE_USE_NAMESPACE


if (argc != 6)
if (argc != 6 && argc != 7)
{ {
carla_stdout("usage: %s <osc-url|\"null\"> <type> <filename> <name|\"(none)\"> <label>", argv[0]); carla_stdout("usage: %s <osc-url|\"null\"> <type> <filename> <name|\"(none)\"> <label>", argv[0]);
return 1; return 1;
@@ -485,11 +494,21 @@ int main(int argc, char* argv[])
const char* name = argv[4]; const char* name = argv[4];
const char* const label = argv[5]; const char* const label = argv[5];


const bool useOsc = std::strcmp(oscUrl, "null");
const bool useBridge = (argc == 7);
const bool useOsc = std::strcmp(oscUrl, "null");


if (std::strcmp(name, "(none)") == 0) if (std::strcmp(name, "(none)") == 0)
name = nullptr; name = nullptr;


char bridgeBaseAudioName[6+1] = { 0 };
char bridgeBaseControlName[6+1] = { 0 };

if (useBridge)
{
std::strncpy(bridgeBaseAudioName, argv[6], 6);
std::strncpy(bridgeBaseControlName, argv[6]+6, 6);
}

CarlaBackend::PluginType itype; CarlaBackend::PluginType itype;


if (std::strcmp(stype, "LADSPA") == 0) if (std::strcmp(stype, "LADSPA") == 0)
@@ -512,7 +531,7 @@ int main(int argc, char* argv[])
app.setQuitOnLastWindowClosed(false); app.setQuitOnLastWindowClosed(false);


// Init Plugin client // Init Plugin client
CarlaPluginClient client(name ? name : label);
CarlaPluginClient client(useBridge, (name != nullptr) ? name : label, bridgeBaseAudioName, bridgeBaseControlName);


// Init OSC // Init OSC
if (useOsc) if (useOsc)
@@ -535,6 +554,10 @@ int main(int argc, char* argv[])
{ {
client.sendOscUpdate(); client.sendOscUpdate();
client.sendOscBridgeUpdate(); client.sendOscBridgeUpdate();

// TESTING!!
carla_set_active(0, true);
carla_show_gui(0, true);
} }
else else
{ {


+ 10
- 7
source/bridges/Makefile View File

@@ -31,7 +31,7 @@ LINK_FLAGS += $(shell pkg-config --libs liblo QtCore)


BUILD_PLUGIN_FLAGS = $(BUILD_CXX_FLAGS) BUILD_PLUGIN_FLAGS = $(BUILD_CXX_FLAGS)
BUILD_PLUGIN_FLAGS += -DBUILD_BRIDGE_PLUGIN -DBRIDGE_PLUGIN BUILD_PLUGIN_FLAGS += -DBUILD_BRIDGE_PLUGIN -DBRIDGE_PLUGIN
BUILD_PLUGIN_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST -DWANT_JACK
BUILD_PLUGIN_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
BUILD_PLUGIN_FLAGS += -I../backend/engine -I../backend/plugin -I../libs BUILD_PLUGIN_FLAGS += -I../backend/engine -I../backend/plugin -I../libs
BUILD_PLUGIN_FLAGS += $(QT_UI_FLAGS) $(shell pkg-config --cflags QtXml) BUILD_PLUGIN_FLAGS += $(QT_UI_FLAGS) $(shell pkg-config --cflags QtXml)


@@ -57,7 +57,7 @@ WIN_LINK_FLAGS = $(LINK_PLUGIN_FLAGS) -mwindows -lwinspool -lole32 -luuid -
# -------------------------------------------------------------- # --------------------------------------------------------------
# Plugin bridges (Native) # Plugin bridges (Native)


NATIVE_BUILD_FLAGS = $(POSIX_BUILD_FLAGS)
NATIVE_BUILD_FLAGS = $(POSIX_BUILD_FLAGS) -DWANT_JACK
NATIVE_LINK_FLAGS = $(POSIX_LINK_FLAGS) NATIVE_LINK_FLAGS = $(POSIX_LINK_FLAGS)


NATIVE_BUILD_FLAGS += -DWANT_NATIVE NATIVE_BUILD_FLAGS += -DWANT_NATIVE
@@ -288,7 +288,8 @@ OBJS_NATIVE += \
../backend/engine/CarlaEngine__native.o \ ../backend/engine/CarlaEngine__native.o \
../backend/engine/CarlaEngineOsc__native.o \ ../backend/engine/CarlaEngineOsc__native.o \
../backend/engine/CarlaEngineThread__native.o \ ../backend/engine/CarlaEngineThread__native.o \
../backend/engine/CarlaEngineJack__native.o
../backend/engine/CarlaEngineJack__native.o \
../backend/engine/CarlaEngineBridge__native.o


# carla-plugin # carla-plugin
OBJS_NATIVE += \ OBJS_NATIVE += \
@@ -332,7 +333,8 @@ OBJS_POSIX32 += \
../backend/engine/CarlaEngine__posix32.o \ ../backend/engine/CarlaEngine__posix32.o \
../backend/engine/CarlaEngineOsc__posix32.o \ ../backend/engine/CarlaEngineOsc__posix32.o \
../backend/engine/CarlaEngineThread__posix32.o \ ../backend/engine/CarlaEngineThread__posix32.o \
../backend/engine/CarlaEngineJack__posix32.o
../backend/engine/CarlaEngineJack__posix32.o \
../backend/engine/CarlaEngineBridge__posix32.o


# carla-plugin # carla-plugin
OBJS_POSIX32 += \ OBJS_POSIX32 += \
@@ -374,7 +376,8 @@ OBJS_POSIX64 += \
../backend/engine/CarlaEngine__posix64.o \ ../backend/engine/CarlaEngine__posix64.o \
../backend/engine/CarlaEngineOsc__posix64.o \ ../backend/engine/CarlaEngineOsc__posix64.o \
../backend/engine/CarlaEngineThread__posix64.o \ ../backend/engine/CarlaEngineThread__posix64.o \
../backend/engine/CarlaEngineJack__posix64.o
../backend/engine/CarlaEngineJack__posix64.o \
../backend/engine/CarlaEngineBridge__posix64.o


# carla-plugin # carla-plugin
OBJS_POSIX64 += \ OBJS_POSIX64 += \
@@ -416,7 +419,7 @@ OBJS_WIN32 += \
../backend/engine/CarlaEngine__win32.o \ ../backend/engine/CarlaEngine__win32.o \
../backend/engine/CarlaEngineOsc__win32.o \ ../backend/engine/CarlaEngineOsc__win32.o \
../backend/engine/CarlaEngineThread__win32.o \ ../backend/engine/CarlaEngineThread__win32.o \
../backend/engine/CarlaEngineJack__win32.o
../backend/engine/CarlaEngineBridge__win32.o


# carla-plugin # carla-plugin
OBJS_WIN32 += \ OBJS_WIN32 += \
@@ -458,7 +461,7 @@ OBJS_WIN64 += \
../backend/engine/CarlaEngine__win64.o \ ../backend/engine/CarlaEngine__win64.o \
../backend/engine/CarlaEngineOsc__win64.o \ ../backend/engine/CarlaEngineOsc__win64.o \
../backend/engine/CarlaEngineThread__win64.o \ ../backend/engine/CarlaEngineThread__win64.o \
../backend/engine/CarlaEngineJack__win64.o
../backend/engine/CarlaEngineBridge__win64.o


# carla-plugin # carla-plugin
OBJS_WIN64 += \ OBJS_WIN64 += \


+ 3
- 1
source/bridges/qtcreator/carla-bridge-plugin.pro View File

@@ -28,6 +28,7 @@ SOURCES += \
../../backend/engine/CarlaEngine.cpp \ ../../backend/engine/CarlaEngine.cpp \
../../backend/engine/CarlaEngineOsc.cpp \ ../../backend/engine/CarlaEngineOsc.cpp \
../../backend/engine/CarlaEngineThread.cpp \ ../../backend/engine/CarlaEngineThread.cpp \
../../backend/engine/CarlaEngineBridge.cpp \
../../backend/engine/CarlaEngineJack.cpp \ ../../backend/engine/CarlaEngineJack.cpp \
../../backend/engine/CarlaEnginePlugin.cpp \ ../../backend/engine/CarlaEnginePlugin.cpp \
../../backend/engine/CarlaEngineRtAudio.cpp ../../backend/engine/CarlaEngineRtAudio.cpp
@@ -88,6 +89,7 @@ HEADERS += \
../../utils/CarlaLibUtils.hpp \ ../../utils/CarlaLibUtils.hpp \
../../utils/CarlaLv2Utils.hpp \ ../../utils/CarlaLv2Utils.hpp \
../../utils/CarlaOscUtils.hpp \ ../../utils/CarlaOscUtils.hpp \
../../utils/CarlaShmUtils.hpp \
../../utils/CarlaStateUtils.hpp \ ../../utils/CarlaStateUtils.hpp \
../../utils/CarlaVstUtils.hpp \ ../../utils/CarlaVstUtils.hpp \
../../utils/CarlaUtils.hpp \ ../../utils/CarlaUtils.hpp \
@@ -114,7 +116,7 @@ DEFINES += DEBUG
DEFINES += BUILD_BRIDGE BUILD_BRIDGE_PLUGIN BRIDGE_PLUGIN DEFINES += BUILD_BRIDGE BUILD_BRIDGE_PLUGIN BRIDGE_PLUGIN


DEFINES += WANT_JACK DEFINES += WANT_JACK
DEFINES += WANT_NATIVE WANT_LADSPA WANT_DSSI WANT_LV2 WANT_VST WANT_VST3
DEFINES += WANT_LADSPA WANT_DSSI WANT_LV2 WANT_VST WANT_VST3
DEFINES += WANT_FLUIDSYNTH WANT_LINUXSAMPLER DEFINES += WANT_FLUIDSYNTH WANT_LINUXSAMPLER


LIBS = -ldl \ LIBS = -ldl \


+ 1
- 0
source/carla_shared.py View File

@@ -322,6 +322,7 @@ PROCESS_MODE_BRIDGE = 4
# Transport Mode # Transport Mode
TRANSPORT_MODE_INTERNAL = 0 TRANSPORT_MODE_INTERNAL = 0
TRANSPORT_MODE_JACK = 1 TRANSPORT_MODE_JACK = 1
TRANSPORT_MODE_BRIDGE = 2


# Set BINARY_NATIVE # Set BINARY_NATIVE
if HAIKU or LINUX or MACOS: if HAIKU or LINUX or MACOS:


+ 1
- 1
source/libs/jackbridge/Makefile View File

@@ -21,7 +21,7 @@ WIN_LINK_FLAGS = $(LINK_FLAGS)
WINE_BUILD_FLAGS = $(BUILD_C_FLAGS) -fPIC WINE_BUILD_FLAGS = $(BUILD_C_FLAGS) -fPIC
WINE_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine WINE_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine
WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine
WINE_LINK_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs jack) -ldl
WINE_LINK_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs jack) -lrt -lpthread


OBJS = jackbridge.c OBJS = jackbridge.c




+ 32
- 0
source/libs/jackbridge/jackbridge.c View File

@@ -16,6 +16,11 @@


#include "jackbridge.h" #include "jackbridge.h"


#ifndef JACKBRIDGE_DUMMY
# include <time.h>
# include <semaphore.h>
#endif

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


jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...) jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...)
@@ -279,3 +284,30 @@ void jackbridge_transport_stop(jack_client_t* client)
jack_transport_stop(client); jack_transport_stop(client);
#endif #endif
} }

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

void linux_clock_gettime_rt(struct timespec* ts)
{
#ifndef JACKBRIDGE_DUMMY
clock_gettime(CLOCK_REALTIME, ts);
#endif
}

int linux_sem_post(void* sem)
{
#ifndef JACKBRIDGE_DUMMY
return sem_post(sem);
#else
return 1;
#endif
}

int linux_sem_timedwait(void* sem, struct timespec* ts)
{
#ifndef JACKBRIDGE_DUMMY
return sem_timedwait(sem, ts);
#else
return 1;
#endif
}

+ 9
- 0
source/libs/jackbridge/jackbridge.h View File

@@ -27,6 +27,7 @@


#ifdef JACKBRIDGE_EXPORT #ifdef JACKBRIDGE_EXPORT
# define GNU_WIN32 // fix jack threads, always use pthread # define GNU_WIN32 // fix jack threads, always use pthread
# include <sys/time.h>
#endif #endif


#include <jack/jack.h> #include <jack/jack.h>
@@ -72,6 +73,10 @@ BRIDGE_EXPORT jack_transport_state_t jackbridge_transport_query(const jack_clien
BRIDGE_EXPORT void jackbridge_transport_start(jack_client_t* client); BRIDGE_EXPORT void jackbridge_transport_start(jack_client_t* client);
BRIDGE_EXPORT void jackbridge_transport_stop(jack_client_t* client); BRIDGE_EXPORT void jackbridge_transport_stop(jack_client_t* client);


BRIDGE_EXPORT void linux_clock_gettime_rt(struct timespec*);
BRIDGE_EXPORT int linux_sem_post(void*);
BRIDGE_EXPORT int linux_sem_timedwait(void*, struct timespec*);

#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -111,6 +116,10 @@ BRIDGE_EXPORT void jackbridge_transport_stop(jack_client_t* client);
#define jackbridge_transport_start jack_transport_start #define jackbridge_transport_start jack_transport_start
#define jackbridge_transport_stop jack_transport_stop #define jackbridge_transport_stop jack_transport_stop


#define linux_clock_gettime_rt(ts) clock_gettime(CLOCK_REALTIME, ts)
#define linux_sem_post sem_post
#define linux_sem_timedwait sem_timedwait

#endif // JACKBRIDGE_EXPORT #endif // JACKBRIDGE_EXPORT


#endif // __JACKBRIDGE_H__ #endif // __JACKBRIDGE_H__

+ 19
- 32
source/utils/CarlaShmUtils.hpp View File

@@ -21,10 +21,8 @@
#include "CarlaUtils.hpp" #include "CarlaUtils.hpp"


#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
# include <vector>
# include <windows.h> # include <windows.h>
struct map_t { HANDLE map; void* ptr; };
struct shm_t { HANDLE shm; std::vector<map_t> maps; };
struct shm_t { HANDLE shm; HANDLE map; };
#else #else
# include <fcntl.h> # include <fcntl.h>
# include <sys/mman.h> # include <sys/mman.h>
@@ -49,7 +47,7 @@ void carla_shm_init(shm_t& shm)
{ {
#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
shm.shm = nullptr; shm.shm = nullptr;
shm.maps.clear();
shm.map = nullptr;
#else #else
shm = -1; shm = -1;
#endif #endif
@@ -67,6 +65,7 @@ shm_t carla_shm_attach_linux(const char* const name)


shm_t ret; shm_t ret;
ret.shm = CreateFileA(shmName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); ret.shm = CreateFileA(shmName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
ret.map = nullptr;


return ret; return ret;
} }
@@ -94,7 +93,7 @@ void carla_shm_close(shm_t& shm)
CARLA_ASSERT(carla_is_shm_valid(shm)); CARLA_ASSERT(carla_is_shm_valid(shm));


#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
CARLA_ASSERT(shm.maps.empty());
CARLA_ASSERT(shm.map == nullptr);


CloseHandle(shm.shm); CloseHandle(shm.shm);
shm.shm = nullptr; shm.shm = nullptr;
@@ -111,6 +110,8 @@ void* carla_shm_map(shm_t& shm, const size_t size)
CARLA_ASSERT(size > 0); CARLA_ASSERT(size > 0);


#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
CARLA_ASSERT(shm.map == nullptr);

HANDLE map = CreateFileMapping(shm.shm, NULL, PAGE_READWRITE, size, size, NULL); HANDLE map = CreateFileMapping(shm.shm, NULL, PAGE_READWRITE, size, size, NULL);


if (map == nullptr) if (map == nullptr)
@@ -119,13 +120,12 @@ void* carla_shm_map(shm_t& shm, const size_t size)
HANDLE ptr = MapViewOfFile(map, FILE_MAP_COPY, 0, 0, size); HANDLE ptr = MapViewOfFile(map, FILE_MAP_COPY, 0, 0, size);


if (ptr == nullptr) if (ptr == nullptr)
{
CloseHandle(map);
return nullptr; return nullptr;
}


map_t newMap;
newMap.map = map;
newMap.ptr = ptr;

shm.maps.push_back(newMap);
shm.map = map;


return ptr; return ptr;
#else #else
@@ -135,31 +135,18 @@ void* carla_shm_map(shm_t& shm, const size_t size)
} }


static inline static inline
void carla_shm_unmap(const shm_t& shm, void* const ptr, const size_t size)
void carla_shm_unmap(shm_t& shm, void* const ptr, const size_t size)
{ {
CARLA_ASSERT(carla_is_shm_valid(shm)); CARLA_ASSERT(carla_is_shm_valid(shm));
CARLA_ASSERT(ptr != nullptr); CARLA_ASSERT(ptr != nullptr);
CARLA_ASSERT(size > 0); CARLA_ASSERT(size > 0);


#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
CARLA_ASSERT(! shm.maps.empty());

for (auto it = shm.maps.begin(); it != shm.maps.end(); ++it)
{
map_t map(*it);

if (map.ptr == ptr)
{
UnmapViewOfFile(ptr);
CloseHandle(map.map);

shm.maps.erase(it);
break;
}
}

CARLA_ASSERT(false);
CARLA_ASSERT(shm.map != nullptr);


UnmapViewOfFile(ptr);
CloseHandle(shm.map);
shm.map = nullptr;
return; return;


// unused // unused
@@ -178,17 +165,17 @@ void carla_shm_unmap(const shm_t& shm, void* const ptr, const size_t size)


template<typename T> template<typename T>
static inline static inline
bool carla_shm_map(shm_t& shm, T* value)
bool carla_shm_map(shm_t& shm, T*& value)
{ {
value = (T*)carla_shm_map(shm, sizeof(value));
value = (T*)carla_shm_map(shm, sizeof(T));
return (value != nullptr); return (value != nullptr);
} }


template<typename T> template<typename T>
static inline static inline
void carla_shm_unmap(const shm_t& shm, T* value)
void carla_shm_unmap(shm_t& shm, T*& value)
{ {
carla_shm_unmap(shm, value, sizeof(value));
carla_shm_unmap(shm, value, sizeof(T));
value = nullptr; value = nullptr;
} }




+ 1
- 1
source/utils/CarlaThread.hpp View File

@@ -263,7 +263,7 @@ private:
} }
#endif #endif


CARLA_PREVENT_HEAP_ALLOCATION
//CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
}; };




Loading…
Cancel
Save