From de7105b1177bde5356984900f4088a80450cb259 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 21 Feb 2014 20:47:37 +0000 Subject: [PATCH] Pass time-info to plugin bridges --- source/backend/CarlaEngine.hpp | 2 +- source/backend/CarlaHost.h | 3 +- source/backend/engine/CarlaEngineBridge.cpp | 116 +++++++++++++++- source/backend/plugin/BridgePlugin.cpp | 127 +++++++++++++++++- source/backend/standalone/CarlaStandalone.cpp | 7 +- source/bridges/CarlaBridgePlugin.cpp | 18 ++- source/utils/CarlaBridgeUtils.hpp | 17 ++- 7 files changed, 267 insertions(+), 23 deletions(-) diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index e2311ea81..e1aee61f0 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -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 diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h index eda302c97..ea1caea90 100644 --- a/source/backend/CarlaHost.h +++ b/source/backend/CarlaHost.h @@ -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 /*! diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index ec77ab8a3..eb7582e3c 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -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 { @@ -139,6 +141,55 @@ struct BridgeControl : public RingBufferControl { { return static_cast(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(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(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 diff --git a/source/backend/plugin/BridgePlugin.cpp b/source/backend/plugin/BridgePlugin.cpp index fa9a9cd91..9f555de65 100644 --- a/source/backend/plugin/BridgePlugin.cpp +++ b/source/backend/plugin/BridgePlugin.cpp @@ -142,6 +142,8 @@ struct BridgeAudioPool { data = (float*)carla_shm_map(shm, size); } + + CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) }; struct BridgeControl : public RingBufferControl { @@ -220,8 +222,68 @@ struct BridgeControl : public RingBufferControl { { writeInt(static_cast(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(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(std::time(nullptr))); + // --------------------------------------------------------------- // SHM Audio Pool { char tmpFileBase[60]; - std::srand(static_cast(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(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; diff --git a/source/backend/standalone/CarlaStandalone.cpp b/source/backend/standalone/CarlaStandalone.cpp index 869042776..c738ff0f3 100644 --- a/source/backend/standalone/CarlaStandalone.cpp +++ b/source/backend/standalone/CarlaStandalone.cpp @@ -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) { diff --git a/source/bridges/CarlaBridgePlugin.cpp b/source/bridges/CarlaBridgePlugin.cpp index c1f6d3f4d..8e6e1e4af 100644 --- a/source/bridges/CarlaBridgePlugin.cpp +++ b/source/bridges/CarlaBridgePlugin.cpp @@ -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()) { diff --git a/source/utils/CarlaBridgeUtils.hpp b/source/utils/CarlaBridgeUtils.hpp index e862dc485..2d6cf75b5 100644 --- a/source/utils/CarlaBridgeUtils.hpp +++ b/source/utils/CarlaBridgeUtils.hpp @@ -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 {