diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index a732dff0a..768a4464d 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -1167,7 +1167,7 @@ public: #ifdef BUILD_BRIDGE // Bridge - static CarlaEngine* newBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName); + static CarlaEngine* newBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName); #else # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) // Juce diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h index 93679e221..b57711547 100644 --- a/source/backend/CarlaHost.h +++ b/source/backend/CarlaHost.h @@ -423,7 +423,8 @@ CARLA_EXPORT bool carla_engine_init(const char* driverName, const char* clientNa /*! * Initialize the engine in bridged mode. */ -CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseName[6+1], const char nonRtBaseName[6+1], const char* clientName); +CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtClientBaseName[6+1], const char nonRtClientBaseName[6+1], + const char nonRtServerBaseName[6+1], const char* clientName); #endif /*! diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp index fa3de8d19..9dfd19a76 100644 --- a/source/backend/CarlaStandalone.cpp +++ b/source/backend/CarlaStandalone.cpp @@ -532,13 +532,15 @@ bool carla_engine_init(const char* driverName, const char* clientName) } #ifdef BUILD_BRIDGE -bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseName[6+1], const char nonRtBaseName[6+1], const char* clientName) +bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtClientBaseName[6+1], const char nonRtClientBaseName[6+1], + const char nonRtServerBaseName[6+1], const char* clientName) { CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false); - CARLA_SAFE_ASSERT_RETURN(rtBaseName != nullptr && rtBaseName[0] != '\0', false); - CARLA_SAFE_ASSERT_RETURN(nonRtBaseName != nullptr && nonRtBaseName[0] != '\0', false); + CARLA_SAFE_ASSERT_RETURN(rtClientBaseName != nullptr && rtClientBaseName[0] != '\0', false); + CARLA_SAFE_ASSERT_RETURN(nonRtClientBaseName != nullptr && nonRtClientBaseName[0] != '\0', false); + CARLA_SAFE_ASSERT_RETURN(nonRtServerBaseName != nullptr && nonRtServerBaseName[0] != '\0', false); CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false); - carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioBaseName, rtBaseName, nonRtBaseName, clientName); + carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\", \"%s\", \"%s\")", audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName); if (gStandalone.engine != nullptr) { @@ -547,7 +549,7 @@ bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseNa return false; } - gStandalone.engine = CarlaEngine::newBridge(audioBaseName, rtBaseName, nonRtBaseName); + gStandalone.engine = CarlaEngine::newBridge(audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); if (gStandalone.engine == nullptr) { diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index 8aac8738e..be80669f7 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -29,15 +29,10 @@ #include "jackbridge/JackBridge.hpp" -#include -#include - using juce::File; using juce::MemoryBlock; using juce::String; -// ------------------------------------------------------------------- - template bool jackbridge_shm_map2(char* shm, T*& value) noexcept { @@ -45,8 +40,6 @@ bool jackbridge_shm_map2(char* shm, T*& value) noexcept return (value != nullptr); } -// ------------------------------------------------------------------- - CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- @@ -72,34 +65,128 @@ struct BridgeAudioPool { clear(); } + void clear() noexcept + { + filename.clear(); + + if (! jackbridge_shm_is_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); + return; + } + + data = nullptr; + + jackbridge_shm_close(shm); + jackbridge_shm_init(shm); + } + bool attach() noexcept { + // must be invalid right now + CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); + jackbridge_shm_attach(shm, filename); return jackbridge_shm_is_valid(shm); } + CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) +}; + +// ------------------------------------------------------------------- + +struct BridgeRtClientControl : public CarlaRingBufferControl { + CarlaString filename; + BridgeRtClientData* data; + char shm[64]; + + BridgeRtClientControl() noexcept + : filename(), + data(nullptr) + { + carla_zeroChar(shm, 64); + jackbridge_shm_init(shm); + } + + ~BridgeRtClientControl() noexcept override + { + // should be cleared by now + CARLA_SAFE_ASSERT(data == nullptr); + + clear(); + } + void clear() noexcept { filename.clear(); + if (! jackbridge_shm_is_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); + return; + } + data = nullptr; - if (jackbridge_shm_is_valid(shm)) - jackbridge_shm_close(shm); + jackbridge_shm_close(shm); + jackbridge_shm_init(shm); } - CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) + bool attach() noexcept + { + // must be invalid right now + CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); + + jackbridge_shm_attach(shm, filename); + + return jackbridge_shm_is_valid(shm); + } + + bool mapData() noexcept + { + CARLA_SAFE_ASSERT(data == nullptr); + + if (jackbridge_shm_map2(shm, data)) + { + CARLA_SAFE_ASSERT(data->midiOut[0] == 0); + setRingBuffer(&data->ringBuffer, false); + return true; + } + + return false; + } + + bool postClient() noexcept + { + CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); + + return jackbridge_sem_post(&data->sem.client); + } + + bool waitForServer(const uint secs) noexcept + { + CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); + + return jackbridge_sem_timedwait(&data->sem.server, secs); + } + + PluginBridgeRtClientOpcode readOpcode() noexcept + { + return static_cast(readUInt()); + } + + CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl) }; // ------------------------------------------------------------------- -struct BridgeRtControl : public CarlaRingBufferControl { +struct BridgeNonRtClientControl : public CarlaRingBufferControl { CarlaString filename; - BridgeRtClientData* data; + BridgeNonRtClientData* data; char shm[64]; - BridgeRtControl() noexcept + BridgeNonRtClientControl() noexcept : filename(), data(nullptr) { @@ -107,7 +194,7 @@ struct BridgeRtControl : public CarlaRingBufferControl { jackbridge_shm_init(shm); } - ~BridgeRtControl() noexcept override + ~BridgeNonRtClientControl() noexcept override { // should be cleared by now CARLA_SAFE_ASSERT(data == nullptr); @@ -126,19 +213,24 @@ struct BridgeRtControl : public CarlaRingBufferControl { { filename.clear(); + if (! jackbridge_shm_is_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); + return; + } + data = nullptr; - if (jackbridge_shm_is_valid(shm)) - jackbridge_shm_close(shm); + jackbridge_shm_close(shm); + jackbridge_shm_init(shm); } bool mapData() noexcept { CARLA_SAFE_ASSERT(data == nullptr); - if (jackbridge_shm_map2(shm, data)) + if (jackbridge_shm_map2(shm, data)) { - CARLA_SAFE_ASSERT(data->midiOut[0] == 0); setRingBuffer(&data->ringBuffer, false); return true; } @@ -146,22 +238,22 @@ struct BridgeRtControl : public CarlaRingBufferControl { return false; } - PluginBridgeRtClientOpcode readOpcode() noexcept + PluginBridgeNonRtClientOpcode readOpcode() noexcept { - return static_cast(readInt()); + return static_cast(readUInt()); } - CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtControl) + CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl) }; // ------------------------------------------------------------------- -struct BridgeNonRtControl : public CarlaRingBufferControl { +struct BridgeNonRtServerControl : public CarlaRingBufferControl { CarlaString filename; - BridgeNonRtClientData* data; + BridgeNonRtServerData* data; char shm[64]; - BridgeNonRtControl() noexcept + BridgeNonRtServerControl() noexcept : filename(), data(nullptr) { @@ -169,7 +261,7 @@ struct BridgeNonRtControl : public CarlaRingBufferControl { jackbridge_shm_init(shm); } - ~BridgeNonRtControl() noexcept override + ~BridgeNonRtServerControl() noexcept override { // should be cleared by now CARLA_SAFE_ASSERT(data == nullptr); @@ -188,17 +280,23 @@ struct BridgeNonRtControl : public CarlaRingBufferControl { { filename.clear(); + if (! jackbridge_shm_is_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); + return; + } + data = nullptr; - if (jackbridge_shm_is_valid(shm)) - jackbridge_shm_close(shm); + jackbridge_shm_close(shm); + jackbridge_shm_init(shm); } bool mapData() noexcept { CARLA_SAFE_ASSERT(data == nullptr); - if (jackbridge_shm_map2(shm, data)) + if (jackbridge_shm_map2(shm, data)) { setRingBuffer(&data->ringBuffer, false); return true; @@ -207,12 +305,12 @@ struct BridgeNonRtControl : public CarlaRingBufferControl { return false; } - PluginBridgeNonRtClientOpcode readOpcode() noexcept + void writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept { - return static_cast(readInt()); + writeUInt(static_cast(opcode)); } - CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtControl) + CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl) }; // ------------------------------------------------------------------- @@ -221,30 +319,30 @@ class CarlaEngineBridge : public CarlaEngine, public CarlaThread { public: - CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName) + CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) : CarlaEngine(), CarlaThread("CarlaEngineBridge"), fShmAudioPool(), - fShmCVPool(), - fShmRtControl(), - fShmNonRtControl(), + fShmRtClientControl(), + fShmNonRtClientControl(), + fShmNonRtServerControl(), fIsRunning(false), fIsOffline(false), leakDetector_CarlaEngineBridge() { - carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtBaseName, nonRtBaseName); + carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); fShmAudioPool.filename = "/carla-bridge_shm_ap_"; fShmAudioPool.filename += audioPoolBaseName; - //fShmCVPool.filename = "/carla-bridge_shm_cvp_"; - //fShmCVPool.filename += cvPoolBaseName; + fShmRtClientControl.filename = "/carla-bridge_shm_rtC_"; + fShmRtClientControl.filename += rtClientBaseName; - fShmRtControl.filename = "/carla-bridge_shm_rt_"; - fShmRtControl.filename += rtBaseName; + fShmNonRtClientControl.filename = "/carla-bridge_shm_nonrtC_"; + fShmNonRtClientControl.filename += nonRtClientBaseName; - fShmNonRtControl.filename = "/carla-bridge_shm_nonrt_"; - fShmNonRtControl.filename += nonRtBaseName; + fShmNonRtServerControl.filename = "/carla-bridge_shm_nonrtS_"; + fShmNonRtServerControl.filename += nonRtServerBaseName; } ~CarlaEngineBridge() noexcept override @@ -271,28 +369,28 @@ public: return false; } - if (! fShmRtControl.attach()) + if (! fShmRtClientControl.attach()) { clear(); carla_stdout("Failed to attach to rt control shared memory"); return false; } - if (! fShmRtControl.mapData()) + if (! fShmRtClientControl.mapData()) { clear(); carla_stdout("Failed to map rt control shared memory"); return false; } - if (! fShmNonRtControl.attach()) + if (! fShmNonRtClientControl.attach()) { clear(); carla_stdout("Failed to attach to non-rt control shared memory"); return false; } - if (! fShmNonRtControl.mapData()) + if (! fShmNonRtClientControl.mapData()) { clear(); carla_stdout("Failed to map non-rt control shared memory"); @@ -301,22 +399,22 @@ public: PluginBridgeNonRtClientOpcode opcode; - opcode = fShmNonRtControl.readOpcode(); + opcode = fShmNonRtClientControl.readOpcode(); CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientNull, opcode); - const uint32_t shmRtDataSize = fShmNonRtControl.readUInt(); + const uint32_t shmRtDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmRtDataSize == sizeof(BridgeRtClientData), shmRtDataSize, sizeof(BridgeRtClientData)); - const uint32_t shmNonRtDataSize = fShmNonRtControl.readUInt(); + const uint32_t shmNonRtDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmNonRtDataSize == sizeof(BridgeNonRtClientData), shmNonRtDataSize, sizeof(BridgeNonRtClientData)); - opcode = fShmNonRtControl.readOpcode(); + opcode = fShmNonRtClientControl.readOpcode(); CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode); - pData->bufferSize = fShmNonRtControl.readUInt(); + pData->bufferSize = fShmNonRtClientControl.readUInt(); - opcode = fShmNonRtControl.readOpcode(); + opcode = fShmNonRtClientControl.readOpcode(); CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode); - pData->sampleRate = fShmNonRtControl.readDouble(); + pData->sampleRate = fShmNonRtClientControl.readDouble(); carla_stdout("Carla Client Info:"); carla_stdout(" BufferSize: %i", pData->bufferSize); @@ -377,15 +475,15 @@ public: void clear() noexcept { fShmAudioPool.clear(); - fShmRtControl.clear(); - fShmNonRtControl.clear(); + fShmRtClientControl.clear(); + fShmNonRtClientControl.clear(); } void handleNonRtData() { - for (; fShmNonRtControl.isDataAvailableForReading();) + for (; fShmNonRtClientControl.isDataAvailableForReading();) { - const PluginBridgeNonRtClientOpcode opcode(fShmNonRtControl.readOpcode()); + const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode()); CarlaPlugin* const plugin(pData->plugins[0].plugin); #ifdef DEBUG @@ -414,14 +512,14 @@ public: break; case kPluginBridgeNonRtClientSetBufferSize: { - const uint32_t bufferSize(fShmNonRtControl.readUInt()); + const uint32_t bufferSize(fShmNonRtClientControl.readUInt()); pData->bufferSize = bufferSize; bufferSizeChanged(bufferSize); break; } case kPluginBridgeNonRtClientSetSampleRate: { - const double sampleRate(fShmNonRtControl.readDouble()); + const double sampleRate(fShmNonRtClientControl.readDouble()); pData->sampleRate = sampleRate; sampleRateChanged(sampleRate); break; @@ -438,8 +536,8 @@ public: break; case kPluginBridgeNonRtClientSetParameterValue: { - const uint32_t index(fShmNonRtControl.readUInt()); - const float value(fShmNonRtControl.readFloat()); + const uint32_t index(fShmNonRtClientControl.readUInt()); + const float value(fShmNonRtClientControl.readFloat()); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterValue(index, value, false, false, false); @@ -447,8 +545,8 @@ public: } case kPluginBridgeNonRtClientSetParameterMidiChannel: { - const uint32_t index(fShmNonRtControl.readUInt()); - const uint8_t channel(fShmNonRtControl.readByte()); + const uint32_t index(fShmNonRtClientControl.readUInt()); + const uint8_t channel(fShmNonRtClientControl.readByte()); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterMidiChannel(index, channel, false, false); @@ -456,8 +554,8 @@ public: } case kPluginBridgeNonRtClientSetParameterMidiCC: { - const uint32_t index(fShmNonRtControl.readUInt()); - const int16_t cc(fShmNonRtControl.readShort()); + const uint32_t index(fShmNonRtClientControl.readUInt()); + const int16_t cc(fShmNonRtClientControl.readShort()); if (plugin != nullptr && plugin->isEnabled()) plugin->setParameterMidiCC(index, cc, false, false); @@ -465,7 +563,7 @@ public: } case kPluginBridgeNonRtClientSetProgram: { - const int32_t index(fShmNonRtControl.readInt()); + const int32_t index(fShmNonRtClientControl.readInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->setProgram(index, false, false, false); @@ -473,7 +571,7 @@ public: } case kPluginBridgeNonRtClientSetMidiProgram: { - const int32_t index(fShmNonRtControl.readInt()); + const int32_t index(fShmNonRtClientControl.readInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->setMidiProgram(index, false, false, false); @@ -482,22 +580,22 @@ public: case kPluginBridgeNonRtClientSetCustomData: { // type - const uint32_t typeSize(fShmNonRtControl.readUInt()); + const uint32_t typeSize(fShmNonRtClientControl.readUInt()); char typeStr[typeSize+1]; carla_zeroChar(typeStr, typeSize+1); - fShmNonRtControl.readCustomData(typeStr, typeSize); + fShmNonRtClientControl.readCustomData(typeStr, typeSize); // key - const uint32_t keySize(fShmNonRtControl.readUInt()); + const uint32_t keySize(fShmNonRtClientControl.readUInt()); char keyStr[keySize+1]; carla_zeroChar(keyStr, keySize+1); - fShmNonRtControl.readCustomData(keyStr, keySize); + fShmNonRtClientControl.readCustomData(keyStr, keySize); // value - const uint32_t valueSize(fShmNonRtControl.readUInt()); + const uint32_t valueSize(fShmNonRtClientControl.readUInt()); char valueStr[valueSize+1]; carla_zeroChar(valueStr, valueSize+1); - fShmNonRtControl.readCustomData(valueStr, valueSize); + fShmNonRtClientControl.readCustomData(valueStr, valueSize); if (plugin != nullptr && plugin->isEnabled()) plugin->setCustomData(typeStr, keyStr, valueStr, true); @@ -505,12 +603,12 @@ public: } case kPluginBridgeNonRtClientSetChunkDataFile: { - const uint32_t size(fShmNonRtControl.readUInt()); + const uint32_t size(fShmNonRtClientControl.readUInt()); CARLA_SAFE_ASSERT_BREAK(size > 0); char chunkFilePathTry[size+1]; carla_zeroChar(chunkFilePathTry, size+1); - fShmNonRtControl.readCustomData(chunkFilePathTry, size); + fShmNonRtClientControl.readCustomData(chunkFilePathTry, size); CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry[0] != '\0'); if (plugin == nullptr || ! plugin->isEnabled()) break; @@ -536,7 +634,7 @@ public: } case kPluginBridgeNonRtClientSetCtrlChannel: { - const int16_t channel(fShmNonRtControl.readShort()); + const int16_t channel(fShmNonRtClientControl.readShort()); CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS); if (plugin != nullptr && plugin->isEnabled()) @@ -545,8 +643,8 @@ public: } case kPluginBridgeNonRtClientSetOption: { - const uint32_t option(fShmNonRtControl.readUInt()); - const bool yesNo(fShmNonRtControl.readBool()); + const uint32_t option(fShmNonRtClientControl.readUInt()); + const bool yesNo(fShmNonRtClientControl.readBool()); if (plugin != nullptr && plugin->isEnabled()) plugin->setOption(option, yesNo, false); @@ -578,7 +676,7 @@ public: filePath += CARLA_OS_SEP_STR; filePath += ".CarlaChunk_"; - filePath += fShmNonRtControl.filename.buffer() + 24; + filePath += fShmNonRtClientControl.filename.buffer() + 24; if (File(filePath).replaceWithText(dataBase64.buffer())) oscSend_bridge_set_chunk_data_file(filePath.toRawUTF8()); @@ -600,8 +698,8 @@ public: break; case kPluginBridgeNonRtClientUiParameterChange: { - const uint32_t index(fShmNonRtControl.readUInt()); - const float value(fShmNonRtControl.readFloat()); + const uint32_t index(fShmNonRtClientControl.readUInt()); + const float value(fShmNonRtClientControl.readFloat()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiParameterChange(index, value); @@ -609,7 +707,7 @@ public: } case kPluginBridgeNonRtClientUiProgramChange: { - const uint32_t index(fShmNonRtControl.readUInt()); + const uint32_t index(fShmNonRtClientControl.readUInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiProgramChange(index); @@ -617,7 +715,7 @@ public: } case kPluginBridgeNonRtClientUiMidiProgramChange: { - const uint32_t index(fShmNonRtControl.readUInt()); + const uint32_t index(fShmNonRtClientControl.readUInt()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiMidiProgramChange(index); @@ -625,9 +723,9 @@ public: } case kPluginBridgeNonRtClientUiNoteOn: { - const uint8_t chnl(fShmNonRtControl.readByte()); - const uint8_t note(fShmNonRtControl.readByte()); - const uint8_t velo(fShmNonRtControl.readByte()); + const uint8_t chnl(fShmNonRtClientControl.readByte()); + const uint8_t note(fShmNonRtClientControl.readByte()); + const uint8_t velo(fShmNonRtClientControl.readByte()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiNoteOn(chnl, note, velo); @@ -635,8 +733,8 @@ public: } case kPluginBridgeNonRtClientUiNoteOff: { - const uint8_t chnl(fShmNonRtControl.readByte()); - const uint8_t note(fShmNonRtControl.readByte()); + const uint8_t chnl(fShmNonRtClientControl.readByte()); + const uint8_t note(fShmNonRtClientControl.readByte()); if (plugin != nullptr && plugin->isEnabled()) plugin->uiNoteOff(chnl, note); @@ -658,18 +756,18 @@ protected: { for (; ! shouldThreadExit();) { - if (! jackbridge_sem_timedwait(&fShmRtControl.data->sem.server, 5)) + if (! fShmRtClientControl.waitForServer(5)) { - if (errno == ETIMEDOUT) - { - signalThreadShouldExit(); - break; - } + carla_stderr2("Bridge timed-out, final post..."); + fShmRtClientControl.postClient(); + carla_stderr2("Bridge timed-out, done."); + signalThreadShouldExit(); + break; } - for (; fShmRtControl.isDataAvailableForReading();) + for (; fShmRtClientControl.isDataAvailableForReading();) { - const PluginBridgeRtClientOpcode opcode(fShmRtControl.readOpcode()); + const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode()); CarlaPlugin* const plugin(pData->plugins[0].plugin); #ifdef DEBUG @@ -684,24 +782,24 @@ protected: break; case kPluginBridgeRtClientSetAudioPool: { - const uint64_t poolSize(fShmRtControl.readULong()); + const uint64_t poolSize(fShmRtClientControl.readULong()); CARLA_SAFE_ASSERT_BREAK(poolSize > 0); fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast(poolSize)); break; } case kPluginBridgeRtClientSetCVPool: { - const uint64_t poolSize(fShmRtControl.readULong()); + const uint64_t poolSize(fShmRtClientControl.readULong()); CARLA_SAFE_ASSERT_BREAK(poolSize > 0); //fShmCVPool.data = (float*)jackbridge_shm_map(fShmCVPool.shm, static_cast(poolSize)); break; } case kPluginBridgeRtClientControlEventParameter: { - const uint32_t time(fShmRtControl.readUInt()); - const uint8_t channel(fShmRtControl.readByte()); - const uint16_t param(fShmRtControl.readUShort()); - const float value(fShmRtControl.readFloat()); + const uint32_t time(fShmRtClientControl.readUInt()); + const uint8_t channel(fShmRtClientControl.readByte()); + const uint16_t param(fShmRtClientControl.readUShort()); + const float value(fShmRtClientControl.readFloat()); if (EngineEvent* const event = getNextFreeInputEvent()) { @@ -716,9 +814,9 @@ protected: } case kPluginBridgeRtClientControlEventMidiBank: { - const uint32_t time(fShmRtControl.readUInt()); - const uint8_t channel(fShmRtControl.readByte()); - const uint16_t index(fShmRtControl.readUShort()); + const uint32_t time(fShmRtClientControl.readUInt()); + const uint8_t channel(fShmRtClientControl.readByte()); + const uint16_t index(fShmRtClientControl.readUShort()); if (EngineEvent* const event = getNextFreeInputEvent()) { @@ -733,9 +831,9 @@ protected: } case kPluginBridgeRtClientControlEventMidiProgram: { - const uint32_t time(fShmRtControl.readUInt()); - const uint8_t channel(fShmRtControl.readByte()); - const uint16_t index(fShmRtControl.readUShort()); + const uint32_t time(fShmRtClientControl.readUInt()); + const uint8_t channel(fShmRtClientControl.readByte()); + const uint16_t index(fShmRtClientControl.readUShort()); if (EngineEvent* const event = getNextFreeInputEvent()) { @@ -750,8 +848,8 @@ protected: } case kPluginBridgeRtClientControlEventAllSoundOff: { - const uint32_t time(fShmRtControl.readUInt()); - const uint8_t channel(fShmRtControl.readByte()); + const uint32_t time(fShmRtClientControl.readUInt()); + const uint8_t channel(fShmRtClientControl.readByte()); if (EngineEvent* const event = getNextFreeInputEvent()) { @@ -765,8 +863,8 @@ protected: } case kPluginBridgeRtClientControlEventAllNotesOff: { - const uint32_t time(fShmRtControl.readUInt()); - const uint8_t channel(fShmRtControl.readByte()); + const uint32_t time(fShmRtClientControl.readUInt()); + const uint8_t channel(fShmRtClientControl.readByte()); if (EngineEvent* const event = getNextFreeInputEvent()) { @@ -780,15 +878,15 @@ protected: } case kPluginBridgeRtClientMidiEvent: { - const uint32_t time(fShmRtControl.readUInt()); - const uint8_t port(fShmRtControl.readByte()); - const uint8_t size(fShmRtControl.readByte()); + const uint32_t time(fShmRtClientControl.readUInt()); + const uint8_t port(fShmRtClientControl.readByte()); + const uint8_t size(fShmRtClientControl.readByte()); CARLA_SAFE_ASSERT_BREAK(size > 0); uint8_t data[size]; for (uint8_t i=0; iisEnabled() && plugin->tryLock(false)) { - const BridgeTimeInfo& bridgeTimeInfo(fShmRtControl.data->timeInfo); + const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); const uint32_t audioInCount(plugin->getAudioInCount()); const uint32_t audioOutCount(plugin->getAudioOutCount()); @@ -888,8 +986,8 @@ protected: } } - if (! jackbridge_sem_post(&fShmRtControl.data->sem.client)) - carla_stderr2("Could not post to rt semaphore"); + if (! fShmRtClientControl.postClient()) + carla_stderr2("Could not post to client rt semaphore"); } fIsRunning = false; @@ -912,10 +1010,10 @@ protected: // ------------------------------------------------------------------- private: - BridgeAudioPool fShmAudioPool; - BridgeAudioPool fShmCVPool; - BridgeRtControl fShmRtControl; - BridgeNonRtControl fShmNonRtControl; + BridgeAudioPool fShmAudioPool; + BridgeRtClientControl fShmRtClientControl; + BridgeNonRtClientControl fShmNonRtClientControl; + BridgeNonRtServerControl fShmNonRtServerControl; bool fIsRunning; bool fIsOffline; @@ -925,9 +1023,9 @@ private: // ----------------------------------------------------------------------- -CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName) +CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) { - return new CarlaEngineBridge(audioPoolBaseName, rtBaseName, nonRtBaseName); + return new CarlaEngineBridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); } // ----------------------------------------------------------------------- diff --git a/source/backend/engine/CarlaEngineOsc.cpp b/source/backend/engine/CarlaEngineOsc.cpp index bf419cc23..cc50d3ef7 100644 --- a/source/backend/engine/CarlaEngineOsc.cpp +++ b/source/backend/engine/CarlaEngineOsc.cpp @@ -18,11 +18,6 @@ #include "CarlaEngine.hpp" #include "CarlaEngineOsc.hpp" #include "CarlaPlugin.hpp" - -#ifndef BUILD_BRIDGE -# include "CarlaBridgeUtils.hpp" -#endif - #include "CarlaMIDI.h" #include diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index 8aab9e616..bffd4316f 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -32,29 +32,6 @@ #include #include -#define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ - /* check argument count */ \ - if (argc != argcToCompare) \ - { \ - carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \ - return 1; \ - } \ - if (argc > 0) \ - { \ - /* check for nullness */ \ - if (! (types && typesToCompare)) \ - { \ - carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \ - return 1; \ - } \ - /* check argument types */ \ - if (std::strcmp(types, typesToCompare) != 0) \ - { \ - carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \ - return 1; \ - } \ - } - // ------------------------------------------------------------------------------------------------------------------- using juce::File; @@ -63,56 +40,23 @@ using juce::StringArray; CARLA_BACKEND_START_NAMESPACE -#if 0 -// ------------------------------------------------------------------------------------------------------------------- -// call carla_shm_create with for a XXXXXX temp filename - -static shm_t shm_mkstemp(char* const fileBase) -{ - CARLA_SAFE_ASSERT_RETURN(fileBase != nullptr, gNullCarlaShm); - - const size_t fileBaseLen(std::strlen(fileBase)); - - CARLA_SAFE_ASSERT_RETURN(fileBaseLen > 6, gNullCarlaShm); - CARLA_SAFE_ASSERT_RETURN(std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") == 0, gNullCarlaShm); - - static const char charSet[] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - static const int charSetLen = static_cast(std::strlen(charSet) - 1); // -1 to avoid trailing '\0' - - // try until getting a valid shm or an error occurs - for (;;) - { - for (size_t c = fileBaseLen - 6; c < fileBaseLen; ++c) - fileBase[c] = charSet[std::rand() % charSetLen]; - - const shm_t shm = carla_shm_create(fileBase); - - if (carla_is_shm_valid(shm)) - return shm; - if (errno != EEXIST) - return gNullCarlaShm; - } -} - // ------------------------------------------------------------------------------------------------------------------- struct BridgeAudioPool { CarlaString filename; + std::size_t size; float* data; - size_t size; shm_t shm; BridgeAudioPool() noexcept : filename(), - data(nullptr), - size(0) + size(0), + data(nullptr) #ifdef CARLA_PROPER_CPP11_SUPPORT , shm(shm_t_INIT) {} #else { - carla_shm_init(shm); + shm = shm_t_INIT; } #endif @@ -129,7 +73,10 @@ struct BridgeAudioPool { filename.clear(); if (! carla_is_shm_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); return; + } if (data != nullptr) { @@ -139,14 +86,17 @@ struct BridgeAudioPool { size = 0; carla_shm_close(shm); + carla_shm_init(shm); } - void resize(const uint32_t bufferSize, const uint32_t portCount) noexcept + void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept { + CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm),); + if (data != nullptr) carla_shm_unmap(shm, data); - size = portCount*bufferSize*sizeof(float); + size = (audioPortCount+cvPortCount)*bufferSize*sizeof(float); if (size == 0) size = sizeof(float); @@ -159,23 +109,23 @@ struct BridgeAudioPool { // ------------------------------------------------------------------------------------------------------------------- -struct BridgeRtControl : public CarlaRingBuffer { +struct BridgeRtClientControl : public CarlaRingBufferControl { CarlaString filename; - BridgeRtData* data; + BridgeRtClientData* data; shm_t shm; - BridgeRtControl() + BridgeRtClientControl() : filename(), data(nullptr) #ifdef CARLA_PROPER_CPP11_SUPPORT , shm(shm_t_INIT) {} #else { - carla_shm_init(shm); + shm = shm_t_INIT; } #endif - ~BridgeRtControl() noexcept override + ~BridgeRtClientControl() noexcept override { // should be cleared by now CARLA_SAFE_ASSERT(data == nullptr); @@ -188,7 +138,10 @@ struct BridgeRtControl : public CarlaRingBuffer { filename.clear(); if (! carla_is_shm_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); return; + } if (data != nullptr) { @@ -197,17 +150,18 @@ struct BridgeRtControl : public CarlaRingBuffer { } carla_shm_close(shm); + carla_shm_init(shm); } bool mapData() noexcept { CARLA_SAFE_ASSERT(data == nullptr); - if (carla_shm_map(shm, data)) + if (carla_shm_map(shm, data)) { carla_zeroStruct(data->sem); carla_zeroStruct(data->timeInfo); - carla_zeroBytes(data->midiOut, kBridgeRtDataMidiOutSize); + carla_zeroBytes(data->midiOut, kBridgeRtClientDataMidiOutSize); setRingBuffer(&data->ringBuffer, true); return true; } @@ -225,7 +179,7 @@ struct BridgeRtControl : public CarlaRingBuffer { setRingBuffer(nullptr, false); } - bool waitForServer(const uint secs) noexcept + bool waitForClient(const uint secs) noexcept { CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); @@ -234,23 +188,23 @@ struct BridgeRtControl : public CarlaRingBuffer { return jackbridge_sem_timedwait(&data->sem.client, secs); } - void writeOpcode(const PluginBridgeRtOpcode opcode) noexcept + void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept { - writeInt(static_cast(opcode)); + writeUInt(static_cast(opcode)); } - CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtControl) + CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl) }; // ------------------------------------------------------------------------------------------------------------------- -struct BridgeNonRtControl : public CarlaRingBuffer { +struct BridgeNonRtClientControl : public CarlaRingBufferControl { CarlaMutex mutex; CarlaString filename; - BridgeNonRtData* data; + BridgeNonRtClientData* data; shm_t shm; - BridgeNonRtControl() noexcept + BridgeNonRtClientControl() noexcept : mutex(), filename(), data(nullptr) @@ -258,11 +212,88 @@ struct BridgeNonRtControl : public CarlaRingBuffer { , shm(shm_t_INIT) {} #else { + shm = shm_t_INIT; + } +#endif + + ~BridgeNonRtClientControl() noexcept override + { + // should be cleared by now + CARLA_SAFE_ASSERT(data == nullptr); + + clear(); + } + + void clear() noexcept + { + filename.clear(); + + if (! carla_is_shm_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); + return; + } + + if (data != nullptr) + { + carla_shm_unmap(shm, data); + data = nullptr; + } + + carla_shm_close(shm); carla_shm_init(shm); } + + bool mapData() noexcept + { + CARLA_SAFE_ASSERT(data == nullptr); + + if (carla_shm_map(shm, data)) + { + setRingBuffer(&data->ringBuffer, true); + return true; + } + + return false; + } + + void unmapData() noexcept + { + CARLA_SAFE_ASSERT_RETURN(data != nullptr,); + + carla_shm_unmap(shm, data); + data = nullptr; + + setRingBuffer(nullptr, false); + } + + void writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept + { + writeUInt(static_cast(opcode)); + } + + CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl) +}; + +// ------------------------------------------------------------------------------------------------------------------- + +struct BridgeNonRtServerControl : public CarlaRingBufferControl { + CarlaString filename; + BridgeNonRtServerData* data; + shm_t shm; + + BridgeNonRtServerControl() noexcept + : filename(), + data(nullptr) +#ifdef CARLA_PROPER_CPP11_SUPPORT + , shm(shm_t_INIT) {} +#else + { + shm = shm_t_INIT; + } #endif - ~BridgeNonRtControl() noexcept override + ~BridgeNonRtServerControl() noexcept override { // should be cleared by now CARLA_SAFE_ASSERT(data == nullptr); @@ -275,7 +306,10 @@ struct BridgeNonRtControl : public CarlaRingBuffer { filename.clear(); if (! carla_is_shm_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); return; + } if (data != nullptr) { @@ -284,13 +318,14 @@ struct BridgeNonRtControl : public CarlaRingBuffer { } carla_shm_close(shm); + carla_shm_init(shm); } bool mapData() noexcept { CARLA_SAFE_ASSERT(data == nullptr); - if (carla_shm_map(shm, data)) + if (carla_shm_map(shm, data)) { setRingBuffer(&data->ringBuffer, true); return true; @@ -309,12 +344,12 @@ struct BridgeNonRtControl : public CarlaRingBuffer { setRingBuffer(nullptr, false); } - void writeOpcode(const PluginBridgeNonRtOpcode opcode) noexcept + PluginBridgeNonRtClientOpcode readOpcode() noexcept { - writeInt(static_cast(opcode)); + return static_cast(readUInt()); } - CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtControl) + CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl) }; // ------------------------------------------------------------------------------------------------------------------- @@ -349,9 +384,9 @@ public: fLastPongCounter(-1), fBridgeBinary(), fShmAudioPool(), - fShmCVPool(), - fShmRtControl(), - fShmNonRtControl(), + fShmRtClientControl(), + fShmNonRtClientControl(), + fShmNonRtServerControl(), fInfo(), fParams(nullptr), leakDetector_BridgePlugin() @@ -361,6 +396,7 @@ public: pData->hints |= PLUGIN_IS_BRIDGE; } +#if 0 ~BridgePlugin() override { carla_debug("BridgePlugin::~BridgePlugin()"); @@ -410,6 +446,7 @@ public: fInfo.chunk.clear(); } +#endif // ------------------------------------------------------------------- // Information (base) @@ -509,6 +546,7 @@ public: std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX); } +#if 0 // ------------------------------------------------------------------- // Set data (state) @@ -750,6 +788,7 @@ public: CarlaPlugin::idle(); } +#endif // ------------------------------------------------------------------- // Plugin state @@ -759,6 +798,7 @@ public: CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); carla_debug("BridgePlugin::reload() - start"); +#if 0 const EngineProcessMode processMode(pData->engine->getProccessMode()); // Safely disable plugin for reload @@ -881,6 +921,7 @@ public: bufferSizeChanged(pData->engine->getBufferSize()); reloadPrograms(true); +#endif carla_debug("BridgePlugin::reload() - end"); } @@ -891,16 +932,16 @@ public: void activate() noexcept override { { - const CarlaMutexLocker _cml(fShmNonRtControl.mutex); + const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); - fShmNonRtControl.writeOpcode(kPluginBridgeNonRtActivate); - fShmNonRtControl.commitWrite(); + fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate); + fShmNonRtClientControl.commitWrite(); } bool timedOut = true; try { - timedOut = waitForServer(1); + timedOut = waitForClient(1); } catch(...) {} if (! timedOut) @@ -910,16 +951,16 @@ public: void deactivate() noexcept override { { - const CarlaMutexLocker _cml(fShmNonRtControl.mutex); + const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); - fShmNonRtControl.writeOpcode(kPluginBridgeNonRtDeactivate); - fShmNonRtControl.commitWrite(); + fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate); + fShmNonRtClientControl.commitWrite(); } bool timedOut = true; try { - timedOut = waitForServer(1); + timedOut = waitForClient(1); } catch(...) {} if (! timedOut) @@ -951,6 +992,8 @@ public: pData->needsReset = false; } + (void)audioIn; (void)cvIn; +#if 0 // -------------------------------------------------------------------------------------------------------- // Event Input @@ -1168,8 +1211,10 @@ public: } // End of Event Input processSingle(audioIn, audioOut, cvIn, cvOut, frames); +#endif } +#if 0 bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) { CARLA_SAFE_ASSERT_RETURN(frames > 0, false); @@ -1977,7 +2022,7 @@ public: { char tmpFileBase[64]; - std::sprintf(tmpFileBase, "/carla-bridge_shm_rt_XXXXXX"); + std::sprintf(tmpFileBase, "/carla-bridge_shm_rtC_XXXXXX"); fShmRtControl.shm = shm_mkstemp(tmpFileBase); @@ -2031,7 +2076,7 @@ public: { char tmpFileBase[64]; - std::sprintf(tmpFileBase, "/carla-bridge_shm_nonrt_XXXXXX"); + std::sprintf(tmpFileBase, "/carla-bridge_shm_nonrtC_XXXXXX"); fShmNonRtControl.shm = shm_mkstemp(tmpFileBase); @@ -2134,6 +2179,7 @@ public: return true; } +#endif private: const BinaryType fBinaryType; @@ -2149,10 +2195,10 @@ private: CarlaString fBridgeBinary; - BridgeAudioPool fShmAudioPool; - BridgeAudioPool fShmCVPool; - BridgeRtControl fShmRtControl; - BridgeNonRtControl fShmNonRtControl; + BridgeAudioPool fShmAudioPool; + BridgeRtClientControl fShmRtClientControl; + BridgeNonRtClientControl fShmNonRtClientControl; + BridgeNonRtServerControl fShmNonRtServerControl; struct Info { uint32_t aIns, aOuts; @@ -2188,27 +2234,23 @@ private: void resizeAudioAndCVPool(const uint32_t bufferSize) { - fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts); - fShmCVPool.resize(bufferSize, fInfo.cvIns+fInfo.cvOuts); + fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts); - fShmRtControl.writeOpcode(kPluginBridgeRtSetAudioPool); - fShmRtControl.writeLong(static_cast(fShmAudioPool.size)); + fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); + fShmRtClientControl.writeULong(static_cast(fShmAudioPool.size)); - fShmRtControl.writeOpcode(kPluginBridgeRtSetCVPool); - fShmRtControl.writeLong(static_cast(fShmCVPool.size)); + fShmRtClientControl.commitWrite(); - fShmRtControl.commitWrite(); - - waitForServer(); + waitForClient(); } - bool waitForServer(const uint secs = 5) + bool waitForClient(const uint secs = 5) { CARLA_SAFE_ASSERT_RETURN(! fTimedOut, false); - if (! fShmRtControl.waitForServer(secs)) + if (! fShmRtClientControl.waitForClient(secs)) { - carla_stderr("waitForServer() timeout here"); + carla_stderr("waitForClient() timeout here"); fTimedOut = true; return false; } @@ -2218,7 +2260,6 @@ private: CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin) }; -#endif CARLA_BACKEND_END_NAMESPACE @@ -2233,7 +2274,6 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary); #ifndef BUILD_BRIDGE -# if 0 if (bridgeBinary == nullptr || bridgeBinary[0] == '\0') { init.engine->setLastError("Bridge not possible, bridge-binary not found"); @@ -2242,6 +2282,7 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P BridgePlugin* const plugin(new BridgePlugin(init.engine, init.id, btype, ptype)); +# if 0 if (! plugin->init(init.filename, init.name, init.label, bridgeBinary)) { init.engine->registerEnginePlugin(init.id, nullptr); @@ -2252,6 +2293,9 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P plugin->reload(); bool canRun = true; +# else + bool canRun = false; +# endif if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { @@ -2279,12 +2323,6 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P } return plugin; -# else - init.engine->setLastError("Bridged plugins not working due to pending code rewrite."); - return nullptr; - // unused - (void)bridgeBinary; (void)btype; (void)ptype; -# endif #else init.engine->setLastError("Plugin bridge support not available"); return nullptr; diff --git a/source/bridges-plugin/CarlaBridgePlugin.cpp b/source/bridges-plugin/CarlaBridgePlugin.cpp index 22be53500..4d49dabe0 100644 --- a/source/bridges-plugin/CarlaBridgePlugin.cpp +++ b/source/bridges-plugin/CarlaBridgePlugin.cpp @@ -169,7 +169,8 @@ static JUCEApplicationBase* juce_CreateApplication() { return new CarlaJuceApp() class CarlaBridgePlugin { public: - CarlaBridgePlugin(const bool useBridge, const char* const clientName, const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName) + CarlaBridgePlugin(const bool useBridge, const char* const clientName, const char* const audioPoolBaseName, + const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) : fEngine(nullptr), fProjFilename(), fOscControlData(), @@ -178,12 +179,12 @@ public: leakDetector_CarlaBridgePlugin() { CARLA_ASSERT(clientName != nullptr && clientName[0] != '\0'); - carla_debug("CarlaBridgePlugin::CarlaBridgePlugin(%s, \"%s\", %s, %s, %s)", bool2str(useBridge), clientName, audioPoolBaseName, rtBaseName, nonRtBaseName); + carla_debug("CarlaBridgePlugin::CarlaBridgePlugin(%s, \"%s\", %s, %s, %s, %s)", bool2str(useBridge), clientName, audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); carla_set_engine_callback(callback, this); if (useBridge) - carla_engine_init_bridge(audioPoolBaseName, rtBaseName, nonRtBaseName, clientName); + carla_engine_init_bridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName); else carla_engine_init("JACK", clientName); @@ -420,25 +421,29 @@ int main(int argc, char* argv[]) // --------------------------------------------------------------------- // Setup bridge ids - char bridgeBaseAudioName[6+1]; - char bridgeBaseControlName[6+1]; - char bridgeBaseTimeName[6+1]; + char audioPoolBaseName[6+1]; + char rtClientBaseName[6+1]; + char nonRtClientBaseName[6+1]; + char nonRtServerBaseName[6+1]; if (useBridge) { - CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*3, 1); - std::strncpy(bridgeBaseAudioName, shmIds, 6); - std::strncpy(bridgeBaseControlName, shmIds+6, 6); - std::strncpy(bridgeBaseTimeName, shmIds+12, 6); - bridgeBaseAudioName[6] = '\0'; - bridgeBaseControlName[6] = '\0'; - bridgeBaseTimeName[6] = '\0'; + CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*4, 1); + std::strncpy(audioPoolBaseName, shmIds+6*0, 6); + std::strncpy(rtClientBaseName, shmIds+6*1, 6); + std::strncpy(nonRtClientBaseName, shmIds+6*2, 6); + std::strncpy(nonRtServerBaseName, shmIds+6*3, 6); + audioPoolBaseName[6] = '\0'; + rtClientBaseName[6] = '\0'; + nonRtClientBaseName[6] = '\0'; + nonRtServerBaseName[6] = '\0'; } else { - bridgeBaseAudioName[0] = '\0'; - bridgeBaseControlName[0] = '\0'; - bridgeBaseTimeName[0] = '\0'; + audioPoolBaseName[0] = '\0'; + rtClientBaseName[0] = '\0'; + nonRtClientBaseName[0] = '\0'; + nonRtServerBaseName[0] = '\0'; } // --------------------------------------------------------------------- @@ -466,7 +471,7 @@ int main(int argc, char* argv[]) // --------------------------------------------------------------------- // Init plugin bridge - CarlaBridgePlugin bridge(useBridge, clientName, bridgeBaseAudioName, bridgeBaseControlName, bridgeBaseTimeName); + CarlaBridgePlugin bridge(useBridge, clientName, audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); if (! bridge.isOk()) { diff --git a/source/utils/CarlaBridgeUtils.hpp b/source/utils/CarlaBridgeUtils.hpp index 5c2c19b93..53f702c9e 100644 --- a/source/utils/CarlaBridgeUtils.hpp +++ b/source/utils/CarlaBridgeUtils.hpp @@ -125,14 +125,14 @@ struct BridgeTimeInfo { // ----------------------------------------------------------------------- -static const std::size_t kBridgeRtDataMidiOutSize = 512*4; +static const std::size_t kBridgeRtClientDataMidiOutSize = 512*4; // Server => Client RT struct BridgeRtClientData { BridgeSemaphore sem; BridgeTimeInfo timeInfo; SmallStackBuffer ringBuffer; - uint8_t midiOut[kBridgeRtDataMidiOutSize]; + uint8_t midiOut[kBridgeRtClientDataMidiOutSize]; }; // Server => Client Non-RT diff --git a/source/utils/CarlaShmUtils.hpp b/source/utils/CarlaShmUtils.hpp index bf2390a40..8a99ac315 100644 --- a/source/utils/CarlaShmUtils.hpp +++ b/source/utils/CarlaShmUtils.hpp @@ -22,12 +22,13 @@ #ifdef CARLA_OS_WIN struct shm_t { HANDLE shm; HANDLE map; }; -# define shm_t_INIT {nullptr, nullptr} +# define shm_t_INIT { nullptr, nullptr } #else +# include # include # include struct shm_t { int fd; const char* filename; std::size_t size; }; -# define shm_t_INIT {-1, nullptr} +# define shm_t_INIT { -1, nullptr, 0 } #endif // ----------------------------------------------------------------------- @@ -36,11 +37,7 @@ struct shm_t { int fd; const char* filename; std::size_t size; }; /* * Null object returned when a shared memory operation fails. */ -#ifdef CARLA_OS_WIN -static const shm_t gNullCarlaShm = { nullptr, nullptr }; -#else -static const shm_t gNullCarlaShm = { -1, nullptr, 0 }; -#endif +static const shm_t gNullCarlaShm = shm_t_INIT; /* * Check if a shared memory object is valid. @@ -61,14 +58,7 @@ bool carla_is_shm_valid(const shm_t& shm) noexcept static inline void carla_shm_init(shm_t& shm) noexcept { -#ifdef CARLA_OS_WIN - shm.shm = nullptr; - shm.map = nullptr; -#else - shm.fd = -1; - shm.filename = nullptr; - shm.size = 0; -#endif + shm = gNullCarlaShm; } /* @@ -246,6 +236,57 @@ void carla_shm_unmap(shm_t& shm, void* const ptr) noexcept } CARLA_SAFE_EXCEPTION("carla_shm_unmap"); } +// ----------------------------------------------------------------------- +// advanced calls + +/* + * Create and open a new shared memory object for a XXXXXX temp filename. + * Will keep trying until a free random filename is obtained. + */ +static inline +shm_t carla_shm_create_temp(char* const fileBase) +{ + // check if the fileBase name is valid + CARLA_SAFE_ASSERT_RETURN(fileBase != nullptr, gNullCarlaShm); + + const std::size_t fileBaseLen(std::strlen(fileBase)); + + CARLA_SAFE_ASSERT_RETURN(fileBaseLen > 6, gNullCarlaShm); + CARLA_SAFE_ASSERT_RETURN(std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") == 0, gNullCarlaShm); + + // character set to use randomly + static const char charSet[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + static const int charSetLen = static_cast(std::strlen(charSet) - 1); // -1 to avoid trailing '\0' + + // try until getting a valid shm is obtained or an error occurs + for (;;) + { + // fill the XXXXXX characters randomly + for (std::size_t c = fileBaseLen - 6; c < fileBaseLen; ++c) + fileBase[c] = charSet[std::rand() % charSetLen]; + + // (try to) create new shm for this filename + const shm_t shm = carla_shm_create(fileBase); + + // all ok! + if (carla_is_shm_valid(shm)) + return shm; + + // file already exists, keep trying +#ifdef CARLA_OS_WIN + // TODO +#else + if (errno == EEXIST) + continue; +#endif + + // some unknown error occurred, return null + return gNullCarlaShm; + } +} + // ----------------------------------------------------------------------- // shared memory, templated calls