diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index d82fe4efe..5bd83f85a 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -51,58 +51,6 @@ CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- -struct BridgeAudioPool { - CarlaString filename; - float* data; - char shm[64]; - - BridgeAudioPool() noexcept - : filename(), - data(nullptr) - { - carla_zeroChars(shm, 64); - jackbridge_shm_init(shm); - } - - ~BridgeAudioPool() noexcept - { - // 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; - - 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; @@ -417,15 +365,13 @@ public: fShmRtClientControl(), fShmNonRtClientControl(), fShmNonRtServerControl(), + fBaseNameAudioPool(audioPoolBaseName), fIsOffline(false), fFirstIdle(true), fLastPingTime(-1) { carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); - fShmAudioPool.filename = PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL; - fShmAudioPool.filename += audioPoolBaseName; - fShmRtClientControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT; fShmRtClientControl.filename += rtClientBaseName; @@ -456,7 +402,7 @@ public: return false; } - if (! fShmAudioPool.attach()) + if (! fShmAudioPool.attachClient(fBaseNameAudioPool)) { carla_stderr("Failed to attach to audio pool shared memory"); return false; @@ -1639,6 +1585,8 @@ private: BridgeNonRtClientControl fShmNonRtClientControl; BridgeNonRtServerControl fShmNonRtServerControl; + CarlaString fBaseNameAudioPool; + bool fIsOffline; bool fFirstIdle; int64_t fLastPingTime; @@ -1655,7 +1603,7 @@ CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const c // ----------------------------------------------------------------------- -#ifdef BRIDGE_PLUGIN +#ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaPlugin* CarlaPlugin::newNative(const CarlaPlugin::Initializer&) { return nullptr; } CarlaPlugin* CarlaPlugin::newFileGIG(const CarlaPlugin::Initializer&, const bool) { return nullptr; } CarlaPlugin* CarlaPlugin::newFileSF2(const CarlaPlugin::Initializer&, const bool) { return nullptr; } @@ -1674,4 +1622,6 @@ extern "C" __attribute__ ((visibility("default"))) void carla_register_native_plugin_carla(); void carla_register_native_plugin_carla(){} +#include "CarlaBridgeUtils.cpp" + // ----------------------------------------------------------------------- diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index aa151dc6e..2e61580f9 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -1,6 +1,6 @@ /* * Carla Plugin Bridge - * Copyright (C) 2011-2016 Filipe Coelho + * Copyright (C) 2011-2017 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -15,7 +15,7 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ -#if defined(BUILD_BRIDGE) && defined(BRIDGE_PLUGIN) +#ifdef BUILD_BRIDGE # error This file should be used under bridge mode #endif @@ -51,88 +51,6 @@ static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; // ------------------------------------------------------------------------------------------------------------------- -struct BridgeAudioPool { - CarlaString filename; - std::size_t size; - float* data; - carla_shm_t shm; - - BridgeAudioPool() noexcept - : filename(), - size(0), - data(nullptr) -#ifdef CARLA_PROPER_CPP11_SUPPORT - , shm(carla_shm_t_INIT) {} -#else - { - carla_shm_init(shm); - } -#endif - - ~BridgeAudioPool() noexcept - { - // should be cleared by now - CARLA_SAFE_ASSERT(data == nullptr); - - clear(); - } - - bool initialize() noexcept - { - char tmpFileBase[64]; - - std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "XXXXXX"); - - shm = carla_shm_create_temp(tmpFileBase); - - CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm), false); - - filename = tmpFileBase; - return true; - } - - 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; - } - - size = 0; - carla_shm_close(shm); - carla_shm_init(shm); - } - - 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 = (audioPortCount+cvPortCount)*bufferSize*sizeof(float); - - if (size == 0) - size = sizeof(float); - - data = (float*)carla_shm_map(shm, size); - std::memset(data, 0, size); - } - - CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) -}; - -// ------------------------------------------------------------------------------------------------------------------- - struct BridgeRtClientControl : public CarlaRingBufferControl { BridgeRtClientData* data; CarlaString filename; @@ -2559,7 +2477,7 @@ public: // --------------------------------------------------------------- // init sem/shm - if (! fShmAudioPool.initialize()) + if (! fShmAudioPool.initializeServer()) { carla_stderr("Failed to initialize shared memory audio pool"); return false; @@ -2757,7 +2675,7 @@ private: fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts); fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); - fShmRtClientControl.writeULong(static_cast(fShmAudioPool.size)); + fShmRtClientControl.writeULong(static_cast(fShmAudioPool.dataSize)); fShmRtClientControl.commitWrite(); waitForClient("resize-pool", 5000); @@ -2814,3 +2732,5 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P CARLA_BACKEND_END_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- + +#include "CarlaBridgeUtils.cpp" diff --git a/source/bridges-plugin/Makefile b/source/bridges-plugin/Makefile index 65b453f66..662268af3 100644 --- a/source/bridges-plugin/Makefile +++ b/source/bridges-plugin/Makefile @@ -30,8 +30,8 @@ ifeq ($(CARLA_VESTIGE_HEADER),true) BUILD_CXX_FLAGS += -DVESTIGE_HEADER endif -32BIT_FLAGS += -DBRIDGE_PLUGIN -64BIT_FLAGS += -DBRIDGE_PLUGIN +32BIT_FLAGS += -DBUILD_BRIDGE_ALTERNATIVE_ARCH +64BIT_FLAGS += -DBUILD_BRIDGE_ALTERNATIVE_ARCH # ---------------------------------------------------------------------------------------------------------------------------- @@ -170,7 +170,6 @@ OBJS_native = \ $(OBJDIR)/CarlaEngineBridge.cpp.o \ $(OBJDIR)/CarlaPlugin.cpp.o \ $(OBJDIR)/CarlaPluginInternal.cpp.o \ - $(OBJDIR)/CarlaPluginBridge.cpp.o \ $(OBJDIR)/CarlaPluginNative.cpp.o \ $(OBJDIR)/CarlaPluginLADSPA.cpp.o \ $(OBJDIR)/CarlaPluginDSSI.cpp.o \ diff --git a/source/utils/CarlaBridgeDefines.hpp b/source/utils/CarlaBridgeDefines.hpp new file mode 100644 index 000000000..2e235e36b --- /dev/null +++ b/source/utils/CarlaBridgeDefines.hpp @@ -0,0 +1,163 @@ +/* + * Carla Bridge definitions + * Copyright (C) 2013-2017 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#ifndef CARLA_BRIDGE_DEFINES_HPP_INCLUDED +#define CARLA_BRIDGE_DEFINES_HPP_INCLUDED + +#include "CarlaRingBuffer.hpp" + +// ------------------------------------------------------------------------------------------------------------------- + +// Server sends these to client during RT +enum PluginBridgeRtClientOpcode { + kPluginBridgeRtClientNull = 0, + kPluginBridgeRtClientSetAudioPool, // ulong/ptr + kPluginBridgeRtClientControlEventParameter, // uint/frame, byte/chan, ushort, float + kPluginBridgeRtClientControlEventMidiBank, // uint/frame, byte/chan, ushort + kPluginBridgeRtClientControlEventMidiProgram, // uint/frame, byte/chan, ushort + kPluginBridgeRtClientControlEventAllSoundOff, // uint/frame, byte/chan + kPluginBridgeRtClientControlEventAllNotesOff, // uint/frame, byte/chan + kPluginBridgeRtClientMidiEvent, // uint/frame, byte/port, byte/size, byte[]/data + kPluginBridgeRtClientProcess, + kPluginBridgeRtClientQuit +}; + +// Server sends these to client during non-RT +enum PluginBridgeNonRtClientOpcode { + kPluginBridgeNonRtClientNull = 0, + kPluginBridgeNonRtClientPing, + kPluginBridgeNonRtClientPingOnOff, // bool + kPluginBridgeNonRtClientActivate, + kPluginBridgeNonRtClientDeactivate, + kPluginBridgeNonRtClientSetBufferSize, // uint + kPluginBridgeNonRtClientSetSampleRate, // double + kPluginBridgeNonRtClientSetOffline, + kPluginBridgeNonRtClientSetOnline, + kPluginBridgeNonRtClientSetParameterValue, // uint, float + kPluginBridgeNonRtClientSetParameterMidiChannel, // uint, byte + kPluginBridgeNonRtClientSetParameterMidiCC, // uint, short + kPluginBridgeNonRtClientSetProgram, // int + kPluginBridgeNonRtClientSetMidiProgram, // int + kPluginBridgeNonRtClientSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[] + kPluginBridgeNonRtClientSetChunkDataFile, // uint/size, str[] (filename, base64 content) + kPluginBridgeNonRtClientSetCtrlChannel, // short + kPluginBridgeNonRtClientSetOption, // uint/option, bool + kPluginBridgeNonRtClientPrepareForSave, + kPluginBridgeNonRtClientShowUI, + kPluginBridgeNonRtClientHideUI, + kPluginBridgeNonRtClientUiParameterChange, // uint, float + kPluginBridgeNonRtClientUiProgramChange, // uint + kPluginBridgeNonRtClientUiMidiProgramChange, // uint + kPluginBridgeNonRtClientUiNoteOn, // byte, byte, byte + kPluginBridgeNonRtClientUiNoteOff, // byte, byte + kPluginBridgeNonRtClientQuit +}; + +// Client sends these to server during non-RT +enum PluginBridgeNonRtServerOpcode { + kPluginBridgeNonRtServerNull = 0, + kPluginBridgeNonRtServerPong, + kPluginBridgeNonRtServerPluginInfo1, // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId + kPluginBridgeNonRtServerPluginInfo2, // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright) + kPluginBridgeNonRtServerAudioCount, // uint/ins, uint/outs + kPluginBridgeNonRtServerMidiCount, // uint/ins, uint/outs + kPluginBridgeNonRtServerCvCount, // uint/ins, uint/outs + kPluginBridgeNonRtServerParameterCount, // uint/count + kPluginBridgeNonRtServerProgramCount, // uint/count + kPluginBridgeNonRtServerMidiProgramCount, // uint/count + kPluginBridgeNonRtServerPortName, // byte/type, uint/index, uint/size, str[] (name) + kPluginBridgeNonRtServerParameterData1, // uint/index, int/rindex, uint/type, uint/hints, short/cc + kPluginBridgeNonRtServerParameterData2, // uint/index, uint/size, str[] (name), uint/size, str[] (symbol), uint/size, str[] (unit) + kPluginBridgeNonRtServerParameterRanges, // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge + kPluginBridgeNonRtServerParameterValue, // uint/index, float/value + kPluginBridgeNonRtServerParameterValue2, // uint/index, float/value (used for init/output parameters only, don't resend values) + kPluginBridgeNonRtServerDefaultValue, // uint/index, float/value + kPluginBridgeNonRtServerCurrentProgram, // int/index + kPluginBridgeNonRtServerCurrentMidiProgram, // int/index + kPluginBridgeNonRtServerProgramName, // uint/index, uint/size, str[] (name) + kPluginBridgeNonRtServerMidiProgramData, // uint/index, uint/bank, uint/program, uint/size, str[] (name) + kPluginBridgeNonRtServerSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[] + kPluginBridgeNonRtServerSetChunkDataFile, // uint/size, str[] (filename, base64 content) + kPluginBridgeNonRtServerSetLatency, // uint + kPluginBridgeNonRtServerReady, + kPluginBridgeNonRtServerSaved, + kPluginBridgeNonRtServerUiClosed, + kPluginBridgeNonRtServerError // uint/size, str[] +}; + +// used for kPluginBridgeNonRtServerPortName +enum PluginBridgePortType { + kPluginBridgePortNull = 0, + kPluginBridgePortAudioInput, + kPluginBridgePortAudioOutput, + kPluginBridgePortCvInput, + kPluginBridgePortCvOutput, + kPluginBridgePortMidiInput, + kPluginBridgePortMidiOutput, + kPluginBridgePortTypeCount +}; + +// ------------------------------------------------------------------------------------------------------------------- + +struct BridgeSemaphore { + union { + void* server; + char _padServer[64]; + }; + union { + void* client; + char _padClient[64]; + }; +}; + +// needs to be 64bit aligned +struct BridgeTimeInfo { + uint64_t playing; + uint64_t frame; + uint64_t usecs; + uint32_t valid; + // bbt + int32_t bar, beat, tick; + float beatsPerBar, beatType; + double barStartTick, ticksPerBeat, beatsPerMinute; +}; + +// ------------------------------------------------------------------------------------------------------------------- + +static const std::size_t kBridgeRtClientDataMidiOutSize = 512*4; + +// Server => Client RT +struct BridgeRtClientData { + BridgeSemaphore sem; + BridgeTimeInfo timeInfo; + SmallStackBuffer ringBuffer; + uint8_t midiOut[kBridgeRtClientDataMidiOutSize]; +}; + +// Server => Client Non-RT +struct BridgeNonRtClientData { + BigStackBuffer ringBuffer; +}; + +// Client => Server Non-RT +struct BridgeNonRtServerData { + HugeStackBuffer ringBuffer; +}; + +// ------------------------------------------------------------------------------------------------------------------- + +#endif // CARLA_BRIDGE_DEFINES_HPP_INCLUDED diff --git a/source/utils/CarlaBridgeUtils.cpp b/source/utils/CarlaBridgeUtils.cpp new file mode 100644 index 000000000..b4ec1abdb --- /dev/null +++ b/source/utils/CarlaBridgeUtils.cpp @@ -0,0 +1,138 @@ +/* + * Carla Bridge utils + * Copyright (C) 2013-2017 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaBridgeUtils.hpp" + +#ifndef BUILD_BRIDGE +# include "CarlaShmUtils.hpp" +#endif + +// must be last +#include "jackbridge/JackBridge.hpp" + +#if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS) +# define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "Global\\carla-bridge_shm_ap_" +# define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "Global\\carla-bridge_shm_rtC_" +# define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "Global\\carla-bridge_shm_nonrtC_" +# define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "Global\\carla-bridge_shm_nonrtS_" +#else +# define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "/crlbrdg_shm_ap_" +# define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "/crlbrdg_shm_rtC_" +# define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "/crlbrdg_shm_nonrtC_" +# define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "/crlbrdg_shm_nonrtS_" +#endif + +// ------------------------------------------------------------------------------------------------------------------- + +BridgeAudioPool::BridgeAudioPool() noexcept + : data(nullptr), + dataSize(0), + filename() +{ + carla_zeroChars(shm, 64); + jackbridge_shm_init(shm); +} + +BridgeAudioPool::~BridgeAudioPool() noexcept +{ + // should be cleared by now + CARLA_SAFE_ASSERT(data == nullptr); + + clear(); +} + +bool BridgeAudioPool::initializeServer() noexcept +{ +#ifndef BUILD_BRIDGE + char tmpFileBase[64]; + std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "XXXXXX"); + + const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase); + CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false); + + void* const shmptr = shm; + carla_shm_t& shm1 = *(carla_shm_t*)shmptr; + carla_copyStruct(shm1, shm2); + + filename = tmpFileBase; + return true; +#else + return false; +#endif +} + +bool BridgeAudioPool::attachClient(const char* const basename) noexcept +{ + CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false); + +#ifdef BUILD_BRIDGE + // must be invalid right now + CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); + + filename = PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL; + filename += basename; + + jackbridge_shm_attach(shm, filename); + + return jackbridge_shm_is_valid(shm); +#else + return false; +#endif +} + +void BridgeAudioPool::clear() noexcept +{ + filename.clear(); + + if (! jackbridge_shm_is_valid(shm)) + { + CARLA_SAFE_ASSERT(data == nullptr); + return; + } + + if (data != nullptr) + { +#ifndef BUILD_BRIDGE + jackbridge_shm_unmap(shm, data); +#endif + data = nullptr; + } + + dataSize = 0; + jackbridge_shm_close(shm); + jackbridge_shm_init(shm); +} + +void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept +{ + CARLA_SAFE_ASSERT_RETURN(jackbridge_shm_is_valid(shm),); + + if (data != nullptr) + jackbridge_shm_unmap(shm, data); + + dataSize = (audioPortCount+cvPortCount)*bufferSize*sizeof(float); + + if (dataSize == 0) + dataSize = sizeof(float); + + data = (float*)jackbridge_shm_map(shm, dataSize); + CARLA_SAFE_ASSERT_RETURN(data != nullptr,); + + std::memset(data, 0, dataSize); +} + +// ------------------------------------------------------------------------------------------------------------------- diff --git a/source/utils/CarlaBridgeUtils.hpp b/source/utils/CarlaBridgeUtils.hpp index 211d4b935..af172f704 100644 --- a/source/utils/CarlaBridgeUtils.hpp +++ b/source/utils/CarlaBridgeUtils.hpp @@ -1,6 +1,6 @@ /* * Carla Bridge utils - * Copyright (C) 2013-2014 Filipe Coelho + * Copyright (C) 2013-2017 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,159 +18,20 @@ #ifndef CARLA_BRIDGE_UTILS_HPP_INCLUDED #define CARLA_BRIDGE_UTILS_HPP_INCLUDED -#include "CarlaRingBuffer.hpp" +#include "CarlaBridgeDefines.hpp" +#include "CarlaString.hpp" #if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS) -# define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "Global\\carla-bridge_shm_ap_" # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "Global\\carla-bridge_shm_rtC_" # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "Global\\carla-bridge_shm_nonrtC_" # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "Global\\carla-bridge_shm_nonrtS_" #else -# define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "/crlbrdg_shm_ap_" # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "/crlbrdg_shm_rtC_" # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "/crlbrdg_shm_nonrtC_" # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "/crlbrdg_shm_nonrtS_" #endif -// ----------------------------------------------------------------------- - -// Server sends these to client during RT -enum PluginBridgeRtClientOpcode { - kPluginBridgeRtClientNull = 0, - kPluginBridgeRtClientSetAudioPool, // ulong/ptr - kPluginBridgeRtClientControlEventParameter, // uint/frame, byte/chan, ushort, float - kPluginBridgeRtClientControlEventMidiBank, // uint/frame, byte/chan, ushort - kPluginBridgeRtClientControlEventMidiProgram, // uint/frame, byte/chan, ushort - kPluginBridgeRtClientControlEventAllSoundOff, // uint/frame, byte/chan - kPluginBridgeRtClientControlEventAllNotesOff, // uint/frame, byte/chan - kPluginBridgeRtClientMidiEvent, // uint/frame, byte/port, byte/size, byte[]/data - kPluginBridgeRtClientProcess, - kPluginBridgeRtClientQuit -}; - -// Server sends these to client during non-RT -enum PluginBridgeNonRtClientOpcode { - kPluginBridgeNonRtClientNull = 0, - kPluginBridgeNonRtClientPing, - kPluginBridgeNonRtClientPingOnOff, // bool - kPluginBridgeNonRtClientActivate, - kPluginBridgeNonRtClientDeactivate, - kPluginBridgeNonRtClientSetBufferSize, // uint - kPluginBridgeNonRtClientSetSampleRate, // double - kPluginBridgeNonRtClientSetOffline, - kPluginBridgeNonRtClientSetOnline, - kPluginBridgeNonRtClientSetParameterValue, // uint, float - kPluginBridgeNonRtClientSetParameterMidiChannel, // uint, byte - kPluginBridgeNonRtClientSetParameterMidiCC, // uint, short - kPluginBridgeNonRtClientSetProgram, // int - kPluginBridgeNonRtClientSetMidiProgram, // int - kPluginBridgeNonRtClientSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[] - kPluginBridgeNonRtClientSetChunkDataFile, // uint/size, str[] (filename, base64 content) - kPluginBridgeNonRtClientSetCtrlChannel, // short - kPluginBridgeNonRtClientSetOption, // uint/option, bool - kPluginBridgeNonRtClientPrepareForSave, - kPluginBridgeNonRtClientShowUI, - kPluginBridgeNonRtClientHideUI, - kPluginBridgeNonRtClientUiParameterChange, // uint, float - kPluginBridgeNonRtClientUiProgramChange, // uint - kPluginBridgeNonRtClientUiMidiProgramChange, // uint - kPluginBridgeNonRtClientUiNoteOn, // byte, byte, byte - kPluginBridgeNonRtClientUiNoteOff, // byte, byte - kPluginBridgeNonRtClientQuit -}; - -// Client sends these to server during non-RT -enum PluginBridgeNonRtServerOpcode { - kPluginBridgeNonRtServerNull = 0, - kPluginBridgeNonRtServerPong, - kPluginBridgeNonRtServerPluginInfo1, // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId - kPluginBridgeNonRtServerPluginInfo2, // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright) - kPluginBridgeNonRtServerAudioCount, // uint/ins, uint/outs - kPluginBridgeNonRtServerMidiCount, // uint/ins, uint/outs - kPluginBridgeNonRtServerCvCount, // uint/ins, uint/outs - kPluginBridgeNonRtServerParameterCount, // uint/count - kPluginBridgeNonRtServerProgramCount, // uint/count - kPluginBridgeNonRtServerMidiProgramCount, // uint/count - kPluginBridgeNonRtServerPortName, // byte/type, uint/index, uint/size, str[] (name) - kPluginBridgeNonRtServerParameterData1, // uint/index, int/rindex, uint/type, uint/hints, short/cc - kPluginBridgeNonRtServerParameterData2, // uint/index, uint/size, str[] (name), uint/size, str[] (symbol), uint/size, str[] (unit) - kPluginBridgeNonRtServerParameterRanges, // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge - kPluginBridgeNonRtServerParameterValue, // uint/index, float/value - kPluginBridgeNonRtServerParameterValue2, // uint/index, float/value (used for init/output parameters only, don't resend values) - kPluginBridgeNonRtServerDefaultValue, // uint/index, float/value - kPluginBridgeNonRtServerCurrentProgram, // int/index - kPluginBridgeNonRtServerCurrentMidiProgram, // int/index - kPluginBridgeNonRtServerProgramName, // uint/index, uint/size, str[] (name) - kPluginBridgeNonRtServerMidiProgramData, // uint/index, uint/bank, uint/program, uint/size, str[] (name) - kPluginBridgeNonRtServerSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[] - kPluginBridgeNonRtServerSetChunkDataFile, // uint/size, str[] (filename, base64 content) - kPluginBridgeNonRtServerSetLatency, // uint - kPluginBridgeNonRtServerReady, - kPluginBridgeNonRtServerSaved, - kPluginBridgeNonRtServerUiClosed, - kPluginBridgeNonRtServerError // uint/size, str[] -}; - -// used for kPluginBridgeNonRtServerPortName -enum PluginBridgePortType { - kPluginBridgePortNull = 0, - kPluginBridgePortAudioInput, - kPluginBridgePortAudioOutput, - kPluginBridgePortCvInput, - kPluginBridgePortCvOutput, - kPluginBridgePortMidiInput, - kPluginBridgePortMidiOutput, - kPluginBridgePortTypeCount -}; - -// ----------------------------------------------------------------------- - -struct BridgeSemaphore { - union { - void* server; - char _padServer[64]; - }; - union { - void* client; - char _padClient[64]; - }; -}; - -// needs to be 64bit aligned -struct BridgeTimeInfo { - uint64_t playing; - uint64_t frame; - uint64_t usecs; - uint32_t valid; - // bbt - int32_t bar, beat, tick; - float beatsPerBar, beatType; - double barStartTick, ticksPerBeat, beatsPerMinute; -}; - -// ----------------------------------------------------------------------- - -static const std::size_t kBridgeRtClientDataMidiOutSize = 512*4; - -// Server => Client RT -struct BridgeRtClientData { - BridgeSemaphore sem; - BridgeTimeInfo timeInfo; - SmallStackBuffer ringBuffer; - uint8_t midiOut[kBridgeRtClientDataMidiOutSize]; -}; - -// Server => Client Non-RT -struct BridgeNonRtClientData { - BigStackBuffer ringBuffer; -}; - -// Client => Server Non-RT -struct BridgeNonRtServerData { - HugeStackBuffer ringBuffer; -}; - -// ----------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------------------------- static inline const char* PluginBridgeRtClientOpcode2str(const PluginBridgeRtClientOpcode opcode) noexcept @@ -335,6 +196,26 @@ const char* PluginBridgeNonRtServerOpcode2str(const PluginBridgeNonRtServerOpcod return nullptr; } -// ----------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------------------------- + +struct BridgeAudioPool { + float* data; + std::size_t dataSize; + CarlaString filename; + char shm[64]; + + BridgeAudioPool() noexcept; + ~BridgeAudioPool() noexcept; + + bool initializeServer() noexcept; + bool attachClient(const char* const fname) noexcept; + void clear() noexcept; + + void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept; + + CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) +}; + +// ------------------------------------------------------------------------------------------------------------------- #endif // CARLA_BRIDGE_UTILS_HPP_INCLUDED