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_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_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 {
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__
#define __CARLA_BRIDGE_HPP__

#include "CarlaUtils.hpp"

#include <semaphore.h>

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

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

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

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__

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

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

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

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

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

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

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

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

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

public:
#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_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);


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

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

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* 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();
#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__

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

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

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

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

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

uint32_t CarlaEngineEventPort::getEventCount()
{
CARLA_ASSERT(kIsInput);
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)
return 0;
if (fBuffer == nullptr)
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;

uint32_t count = 0;
@@ -162,14 +163,14 @@ const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index)
{
CARLA_ASSERT(kIsInput);
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);

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

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;
#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);
#endif
setLastError("Bridged plugins are not implemented yet");
}
else
#endif // BUILD_BRIDGE
@@ -1207,13 +1192,6 @@ void CarlaEngine::setAboutToClose()
// -----------------------------------------------------------------------
// Global options

#ifndef BUILD_BRIDGE

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

#define CARLA_ENGINE_SET_OPTION_RUNNING_CHECK \
if (isRunning()) \
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:
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);

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:
// FIXME: Always enable JACK transport for now
#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);

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

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

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

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

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

CARLA_BACKEND_END_NAMESPACE

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

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

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

#include "jackbridge/jackbridge.h"

#include <ctime>

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

CARLA_BACKEND_START_NAMESPACE

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

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

class CarlaEngineBridge : public CarlaEngine
class CarlaEngineBridge : public CarlaEngine,
public CarlaThread
{
public:
CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName)
: CarlaEngine()
: CarlaEngine(),
fIsRunning(false),
fQuitNow(false)
{
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()
@@ -56,11 +70,14 @@ public:
{
carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);

char tmpFileBase[60];

// 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);
#endif

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

// 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);
#endif

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

if (! carla_shm_map<ShmControl>(fShmControl.shm, fShmControl.data))
if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
{
_cleanup();
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;
}

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

fQuitNow = true;
CarlaThread::stop();

_cleanup();

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

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

bool isOffline() const
@@ -118,16 +156,113 @@ public:
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:
struct BridgeAudioPool {
CarlaString filename;
float* data;
size_t size;
shm_t shm;

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

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

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

} fShmControl;

bool fIsRunning;
bool fQuitNow;

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

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

// and again
fShmControl.data = nullptr;

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
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;
}
#endif


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

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

fName = clientName;
fName.toBasic();

CarlaEngine::init(fName);
CarlaEngine::init(clientName);
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

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



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

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

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

while (true)
{
for (int c = size - 6; c < size; c++)
@@ -136,28 +134,24 @@ public:
kData->singleMutex.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;
}
#endif

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)
{
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)
{
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)
{
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)
{
CARLA_ASSERT(parameterId < param.count);
@@ -273,15 +257,6 @@ public:

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

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

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)
{
case PluginBridgeAudioCount:
case kPluginBridgeAudioCount:
{
CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");

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

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

break;
Q_UNUSED(aTotal);

// unused
(void)aTotal;
}

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

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

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

break;
Q_UNUSED(mTotal);

// unused
(void)mTotal;
}

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

break;
}
#endif

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

@@ -458,21 +438,23 @@ public:
CARLA_ASSERT(maker);
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;
}

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

break;
}
#endif

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

case PluginBridgeError:
case kPluginBridgeError:
{
CARLA_BRIDGE_CHECK_OSC_TYPES(1, "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;
}
}
#endif

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

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

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();
}
@@ -860,6 +842,131 @@ public:
// -------------------------------------------------------------------
// 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()
{
m_saved = false;
@@ -877,93 +984,125 @@ public:
else
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

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;
if (! osc.data.target)
if (kData->osc.data.target == nullptr)
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)
{
CARLA_ASSERT(index < prog.count);
CARLA_ASSERT(index < kData->prog.count);

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

osc_send_program(&osc.data, index);
osc_send_program(&kData->osc.data, 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;
if (! osc.data.target)
if (kData->osc.data.target == nullptr)
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)
{
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;

uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_ON + channel;
midiData[2] = note;
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)
{
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;

uint8_t midiData[4] = { 0 };
midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
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;

// ---------------------------------------------------------------
// 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
{
char tmpFileBase[60];

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

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

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

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

CARLA_ASSERT(fShmControl.data != nullptr);

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)
{
@@ -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)
fHints |= PLUGIN_IS_BRIDGE;
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++)
{
@@ -1079,7 +1252,9 @@ public:
// unregister so it gets handled properly
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?)");
return false;
}
@@ -1093,10 +1268,16 @@ public:
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;
}


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

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

@@ -1163,12 +1399,12 @@ CARLA_BACKEND_END_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");
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);

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

// unused
(void)bridgeBinary;
#endif
}

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



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

@@ -64,11 +64,12 @@ void CarlaPluginThread::setMode(const CarlaPluginThread::Mode 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;
fLabel = label;
fExtra = extra;
fExtra1 = extra1;
fExtra2 = extra2;
}

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

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

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

switch (fMode)
{
case PLUGIN_THREAD_NULL:
break;

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();
/* label */ arguments << (const char*)fLabel;
/* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
break;

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;
/* ui-URI */ arguments << (const char*)fExtra;
/* ui-URI */ arguments << (const char*)fExtra1;
/* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
break;

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();
/* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
break;

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();
/* name */ arguments << name;
/* label */ arguments << (const char*)fLabel;
/* SHM ids */ arguments << (const char*)fExtra2;
break;
}



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

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

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:
void run();
@@ -53,7 +53,8 @@ private:
Mode fMode;
CarlaString fBinary;
CarlaString fLabel;
CarlaString fExtra;
CarlaString fExtra1;
CarlaString fExtra2;
QProcess* fProcess;
};



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

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

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

} standalone;

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

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

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

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

#if 0
static bool sigInfoInitiated = false;

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

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

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

#ifndef BUILD_BRIDGE
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);

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

switch (option)
{
@@ -493,6 +476,7 @@ void carla_set_engine_option(CarlaBackend::OptionsType option, int value, const
#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
//def QTCREATOR_TEST



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

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

const CarlaOscData* fOscData;


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

@@ -115,17 +115,21 @@ class CarlaPluginClient : public CarlaBridgeClient,
public QObject
{
public:
CarlaPluginClient(const char* const name)
CarlaPluginClient(const bool useBridge, const char* const driverName, const char* audioBaseName, const char* controlBaseName)
: CarlaBridgeClient(nullptr),
QObject(nullptr),
fEngine(nullptr),
fPlugin(nullptr),
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);
}

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

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

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

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

if (kClient == nullptr)
return 1;

gCloseNow = true;

return 0;
@@ -473,7 +482,7 @@ int main(int argc, char* argv[])
{
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]);
return 1;
@@ -485,11 +494,21 @@ int main(int argc, char* argv[])
const char* name = argv[4];
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)
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;

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

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

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

// TESTING!!
carla_set_active(0, true);
carla_show_gui(0, true);
}
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 += -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 += $(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)

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

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

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

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

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

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

# carla-plugin
OBJS_WIN64 += \


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

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

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

LIBS = -ldl \


+ 1
- 0
source/carla_shared.py View File

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

# Set BINARY_NATIVE
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_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_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



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

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

#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, ...)
@@ -279,3 +284,30 @@ void jackbridge_transport_stop(jack_client_t* client)
jack_transport_stop(client);
#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
# define GNU_WIN32 // fix jack threads, always use pthread
# include <sys/time.h>
#endif

#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_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
}
#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_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_H__

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

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

#ifdef CARLA_OS_WIN
# include <vector>
# 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
# include <fcntl.h>
# include <sys/mman.h>
@@ -49,7 +47,7 @@ void carla_shm_init(shm_t& shm)
{
#ifdef CARLA_OS_WIN
shm.shm = nullptr;
shm.maps.clear();
shm.map = nullptr;
#else
shm = -1;
#endif
@@ -67,6 +65,7 @@ shm_t carla_shm_attach_linux(const char* const name)

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

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

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

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

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

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

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

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

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

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

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

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(ptr != nullptr);
CARLA_ASSERT(size > 0);

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

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

template<typename T>
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);
}

template<typename T>
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;
}



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

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

CARLA_PREVENT_HEAP_ALLOCATION
//CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
};



Loading…
Cancel
Save