Browse Source

Pass time-info to plugin bridges

tags/1.9.4
falkTX 11 years ago
parent
commit
de7105b117
7 changed files with 267 additions and 23 deletions
  1. +1
    -1
      source/backend/CarlaEngine.hpp
  2. +2
    -1
      source/backend/CarlaHost.h
  3. +109
    -7
      source/backend/engine/CarlaEngineBridge.cpp
  4. +124
    -3
      source/backend/plugin/BridgePlugin.cpp
  5. +4
    -3
      source/backend/standalone/CarlaStandalone.cpp
  6. +11
    -7
      source/bridges/CarlaBridgePlugin.cpp
  7. +16
    -1
      source/utils/CarlaBridgeUtils.hpp

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

@@ -1116,7 +1116,7 @@ private:
#ifdef BUILD_BRIDGE
public:
// Bridge
static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName);
static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName);

// -------------------------------------------------------------------
// Bridge/Controller OSC stuff


+ 2
- 1
source/backend/CarlaHost.h View File

@@ -497,9 +497,10 @@ CARLA_EXPORT bool carla_engine_init(const char* driverName, const char* clientNa
* Initialize the engine in bridged mode.
* @param audioBaseName Shared memory key for audio pool
* @param controlBaseName Shared memory key for control messages
* @param timeBaseName Shared memory key for time info
* @param clientName Engine master client name
*/
CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char controlBaseName[6+1], const char* clientName);
CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char controlBaseName[6+1], const char timeBaseName[6+1], const char* clientName);
#endif

/*!


+ 109
- 7
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -82,6 +82,8 @@ struct BridgeAudioPool {
if (jackbridge_shm_is_valid(shm))
jackbridge_shm_close(shm);
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
};

struct BridgeControl : public RingBufferControl<StackRingBuffer> {
@@ -139,6 +141,55 @@ struct BridgeControl : public RingBufferControl<StackRingBuffer> {
{
return static_cast<PluginBridgeOpcode>(readInt());
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeControl)
};

struct BridgeTime {
CarlaString filename;
BridgeTimeInfo* info;
char shm[32];

BridgeTime()
: info(nullptr)
{
carla_zeroChar(shm, 32);
jackbridge_shm_init(shm);
}

~BridgeTime()
{
// should be cleared by now
CARLA_ASSERT(info == nullptr);

clear();
}

bool attach()
{
jackbridge_shm_attach(shm, filename);

return jackbridge_shm_is_valid(shm);
}

void clear()
{
filename.clear();

info = nullptr;

if (jackbridge_shm_is_valid(shm))
jackbridge_shm_close(shm);
}

bool mapData()
{
CARLA_ASSERT(info == nullptr);

return jackbridge_shm_map2<BridgeTimeInfo>(shm, info);
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeTime)
};

// -------------------------------------------------------------------
@@ -147,7 +198,7 @@ class CarlaEngineBridge : public CarlaEngine,
public CarlaThread
{
public:
CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName)
CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName)
: CarlaEngine(),
CarlaThread("CarlaEngineBridge"),
fIsRunning(false)
@@ -157,8 +208,11 @@ public:
fShmAudioPool.filename = "/carla-bridge_shm_";
fShmAudioPool.filename += audioBaseName;

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

fShmTime.filename = "/carla-bridge_sht_";
fShmTime.filename += timeBaseName;
}

~CarlaEngineBridge() override
@@ -194,7 +248,7 @@ public:

if (! fShmControl.mapData())
{
carla_stdout("Failed to mmap shared memory file");
carla_stdout("Failed to map shared memory file #2");
// clear
fShmControl.clear();
fShmAudioPool.clear();
@@ -202,6 +256,28 @@ public:
}
}

// SHM Transport
{
if (! fShmTime.attach())
{
carla_stdout("Failed to open or create shared memory file #3");
// clear
fShmControl.clear();
fShmAudioPool.clear();
return false;
}

if (! fShmTime.mapData())
{
carla_stdout("Failed to map shared memory file #3");
// clear
fShmTime.clear();
fShmControl.clear();
fShmAudioPool.clear();
return false;
}
}

// Read values from memory
PluginBridgeOpcode opcode;

@@ -233,6 +309,7 @@ public:

CarlaThread::stop(6000);

fShmTime.clear();
fShmControl.clear();
fShmAudioPool.clear();

@@ -297,7 +374,7 @@ public:
case kPluginBridgeOpcodeSetAudioPool: {
const int64_t poolSize(fShmControl.readLong());
CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, size_t(poolSize));
fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
break;
}

@@ -388,6 +465,9 @@ public:
CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
CarlaPlugin* const plugin(getPluginUnchecked(0));

BridgeTimeInfo* const bridgeInfo(fShmTime.info);
CARLA_SAFE_ASSERT_BREAK(bridgeInfo != nullptr);

if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(true)) // FIXME - always lock?
{
const uint32_t inCount(plugin->getAudioInCount());
@@ -401,6 +481,27 @@ public:
for (uint32_t i=0; i < outCount; ++i)
outBuffer[i] = fShmAudioPool.data + (i+inCount)*pData->bufferSize;

EngineTimeInfo& timeInfo(pData->timeInfo);

timeInfo.playing = bridgeInfo->playing;
timeInfo.frame = bridgeInfo->frame;
timeInfo.usecs = bridgeInfo->usecs;
timeInfo.valid = bridgeInfo->valid;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
{
timeInfo.bbt.bar = bridgeInfo->bar;
timeInfo.bbt.beat = bridgeInfo->beat;
timeInfo.bbt.tick = bridgeInfo->tick;

timeInfo.bbt.beatsPerBar = bridgeInfo->beatsPerBar;
timeInfo.bbt.beatType = bridgeInfo->beatType;

timeInfo.bbt.ticksPerBeat = bridgeInfo->ticksPerBeat;
timeInfo.bbt.beatsPerMinute = bridgeInfo->beatsPerMinute;
timeInfo.bbt.barStartTick = bridgeInfo->barStartTick;
}

plugin->initBuffers();
plugin->process(inBuffer, outBuffer, pData->bufferSize);
plugin->unlock();
@@ -431,6 +532,7 @@ public:
private:
BridgeAudioPool fShmAudioPool;
BridgeControl fShmControl;
BridgeTime fShmTime;

volatile bool fIsRunning;

@@ -439,9 +541,9 @@ private:

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

CarlaEngine* CarlaEngine::newBridge(const char* const audioBaseName, const char* const controlBaseName)
CarlaEngine* CarlaEngine::newBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName)
{
return new CarlaEngineBridge(audioBaseName, controlBaseName);
return new CarlaEngineBridge(audioBaseName, controlBaseName, timeBaseName);
}

CARLA_BACKEND_END_NAMESPACE


+ 124
- 3
source/backend/plugin/BridgePlugin.cpp View File

@@ -142,6 +142,8 @@ struct BridgeAudioPool {

data = (float*)carla_shm_map(shm, size);
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
};

struct BridgeControl : public RingBufferControl<StackRingBuffer> {
@@ -220,8 +222,68 @@ struct BridgeControl : public RingBufferControl<StackRingBuffer> {
{
writeInt(static_cast<int32_t>(opcode));
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeControl)
};

struct BridgeTime {
CarlaString filename;
BridgeTimeInfo* info;
shm_t shm;

BridgeTime()
: info(nullptr)
{
carla_shm_init(shm);
}

~BridgeTime()
{
// should be cleared by now
CARLA_ASSERT(info == nullptr);

clear();
}

void clear()
{
filename.clear();

if (! carla_is_shm_valid(shm))
return;

if (info != nullptr)
{
carla_shm_unmap(shm, info, sizeof(BridgeTimeInfo));
info = nullptr;
}

carla_shm_close(shm);
}

bool mapData()
{
CARLA_ASSERT(info == nullptr);

return carla_shm_map<BridgeTimeInfo>(shm, info);
}

void unmapData()
{
CARLA_ASSERT(info != nullptr);

if (info == nullptr)
return;

carla_shm_unmap(shm, info, sizeof(BridgeTimeInfo));
info = nullptr;
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeTime)
};

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

struct BridgeParamInfo {
float value;
QString name;
@@ -299,6 +361,7 @@ public:

fShmAudioPool.clear();
fShmControl.clear();
fShmTime.clear();

clearBuffers();

@@ -1084,6 +1147,31 @@ public:
for (uint32_t i=0; i < fInfo.aIns; ++i)
FLOAT_COPY(fShmAudioPool.data + (i * frames), inBuffer[i], frames);

// --------------------------------------------------------------------------------------------------------
// TimeInfo

const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
BridgeTimeInfo* const bridgeInfo(fShmTime.info);

bridgeInfo->playing = timeInfo.playing;
bridgeInfo->frame = timeInfo.frame;
bridgeInfo->usecs = timeInfo.usecs;
bridgeInfo->valid = timeInfo.valid;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
{
bridgeInfo->bar = timeInfo.bbt.bar;
bridgeInfo->beat = timeInfo.bbt.beat;
bridgeInfo->tick = timeInfo.bbt.tick;

bridgeInfo->beatsPerBar = timeInfo.bbt.beatsPerBar;
bridgeInfo->beatType = timeInfo.bbt.beatType;

bridgeInfo->ticksPerBeat = timeInfo.bbt.ticksPerBeat;
bridgeInfo->beatsPerMinute = timeInfo.bbt.beatsPerMinute;
bridgeInfo->barStartTick = timeInfo.bbt.barStartTick;
}

// --------------------------------------------------------------------------------------------------------
// Run plugin

@@ -1696,12 +1784,13 @@ public:
if (bridgeBinary != nullptr)
fBridgeBinary = bridgeBinary;

std::srand(static_cast<uint>(std::time(nullptr)));

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

std::srand(static_cast<uint>(std::time(nullptr)));
std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");

fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
@@ -1736,7 +1825,7 @@ public:

if (! fShmControl.mapData())
{
carla_stdout("Failed to mmap shared memory file");
carla_stdout("Failed to map shared memory file #2");
// clear
carla_shm_close(fShmControl.shm);
carla_shm_close(fShmAudioPool.shm);
@@ -1769,6 +1858,36 @@ public:
fNeedsSemDestroy = true;
}

// ---------------------------------------------------------------
// SHM TimeInfo
{
char tmpFileBase[60];

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

fShmTime.shm = shm_mkstemp(tmpFileBase);

if (! carla_is_shm_valid(fShmTime.shm))
{
carla_stdout("Failed to open or create shared memory file #3");
return false;
}

fShmTime.filename = tmpFileBase;

if (! fShmTime.mapData())
{
carla_stdout("Failed to map shared memory file #3");
// clear
jackbridge_sem_destroy(&fShmControl.data->runServer);
fShmControl.unmapData();
carla_shm_close(fShmTime.shm);
carla_shm_close(fShmControl.shm);
carla_shm_close(fShmAudioPool.shm);
return false;
}
}

// initial values
fShmControl.writeOpcode(kPluginBridgeOpcodeNull);
fShmControl.writeInt(static_cast<int32_t>(sizeof(BridgeShmControl)));
@@ -1787,9 +1906,10 @@ public:

// init OSC
{
char shmIdStr[12+1] = { 0 };
char shmIdStr[16+1] = { 0 };
std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6);
std::strncat(shmIdStr, &fShmTime.filename[fShmTime.filename.length()-6], 6);

pData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
pData->osc.thread.start();
@@ -1858,6 +1978,7 @@ private:

BridgeAudioPool fShmAudioPool;
BridgeControl fShmControl;
BridgeTime fShmTime;

struct Info {
uint32_t aIns, aOuts;


+ 4
- 3
source/backend/standalone/CarlaStandalone.cpp View File

@@ -527,12 +527,13 @@ 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 controlBaseName[6+1], const char* clientName)
bool carla_engine_init_bridge(const char audioBaseName[6+1], const char controlBaseName[6+1], const char timeBaseName[6+1], const char* clientName)
{
CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(controlBaseName != nullptr && controlBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(timeBaseName != nullptr && timeBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\")", audioBaseName, controlBaseName, clientName);
carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioBaseName, controlBaseName, timeBaseName, clientName);

if (gStandalone.engine != nullptr)
{
@@ -541,7 +542,7 @@ bool carla_engine_init_bridge(const char audioBaseName[6+1], const char controlB
return false;
}

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

if (gStandalone.engine == nullptr)
{


+ 11
- 7
source/bridges/CarlaBridgePlugin.cpp View File

@@ -157,18 +157,18 @@ CARLA_BRIDGE_START_NAMESPACE
class CarlaPluginClient : public CarlaBridgeClient
{
public:
CarlaPluginClient(const bool useBridge, const char* const clientName, const char* audioBaseName, const char* controlBaseName)
CarlaPluginClient(const bool useBridge, const char* const clientName, const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName)
: CarlaBridgeClient(nullptr),
fPlugin(nullptr),
fEngine(nullptr)
{
CARLA_ASSERT(clientName != nullptr && clientName[0] != '\0');
carla_debug("CarlaPluginClient::CarlaPluginClient(%s, \"%s\", %s, %s)", bool2str(useBridge), clientName, audioBaseName, controlBaseName);
carla_debug("CarlaPluginClient::CarlaPluginClient(%s, \"%s\", %s, %s, %s)", bool2str(useBridge), clientName, audioBaseName, controlBaseName, timeBaseName);

carla_set_engine_callback(callback, this);

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

@@ -585,19 +585,23 @@ int main(int argc, char* argv[])

char bridgeBaseAudioName[6+1];
char bridgeBaseControlName[6+1];
char bridgeBaseTimeName[6+1];

if (useBridge)
{
CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*2, 1);
std::strncpy(bridgeBaseAudioName, shmIds, 6);
std::strncpy(bridgeBaseControlName, shmIds+6, 6);
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';
}
else
{
bridgeBaseAudioName[0] = '\0';
bridgeBaseControlName[0] = '\0';
bridgeBaseTimeName[0] = '\0';
}

// ---------------------------------------------------------------------
@@ -636,7 +640,7 @@ int main(int argc, char* argv[])
// ---------------------------------------------------------------------
// Init plugin client

CarlaPluginClient client(useBridge, clientName, bridgeBaseAudioName, bridgeBaseControlName);
CarlaPluginClient client(useBridge, clientName, bridgeBaseAudioName, bridgeBaseControlName, bridgeBaseTimeName);

if (! client.isOk())
{


+ 16
- 1
source/utils/CarlaBridgeUtils.hpp View File

@@ -18,7 +18,8 @@
#ifndef CARLA_BRIDGE_UTILS_HPP_INCLUDED
#define CARLA_BRIDGE_UTILS_HPP_INCLUDED

#include "CarlaBackend.h"
//#include "CarlaBackend.h"
#include "CarlaEngine.hpp"
#include "CarlaRingBuffer.hpp"

// -----------------------------------------------------------------------
@@ -74,6 +75,20 @@ const char* const CARLA_BRIDGE_MSG_SET_CUSTOM = "CarlaBridgeSetCustom"; //!< Hos

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

PRE_PACKED_STRUCTURE
struct BridgeTimeInfo {
bool playing;
uint64_t frame;
uint64_t usecs;
uint valid;
// bbt
int32_t bar, beat, tick;
float beatsPerBar, beatType;
double barStartTick, ticksPerBeat, beatsPerMinute;
} POST_PACKED_STRUCTURE;

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

PRE_PACKED_STRUCTURE
struct BridgeShmControl {
union {


Loading…
Cancel
Save