@@ -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<SmallStackBuffer> { | |||
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" | |||
// ----------------------------------------------------------------------- |
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Plugin Bridge | |||
* Copyright (C) 2011-2016 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* 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<SmallStackBuffer> { | |||
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<uint64_t>(fShmAudioPool.size)); | |||
fShmRtClientControl.writeULong(static_cast<uint64_t>(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" |
@@ -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 \ | |||
@@ -0,0 +1,163 @@ | |||
/* | |||
* Carla Bridge definitions | |||
* Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* 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 |
@@ -0,0 +1,138 @@ | |||
/* | |||
* Carla Bridge utils | |||
* Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* 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); | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- |
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Bridge utils | |||
* Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* 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 |