| @@ -0,0 +1,82 @@ | |||||
| /* | |||||
| * Carla Bridge API | |||||
| * Copyright (C) 2013 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 GPL.txt file | |||||
| */ | |||||
| #ifndef __CARLA_BRIDGE_HPP__ | |||||
| #define __CARLA_BRIDGE_HPP__ | |||||
| #include <semaphore.h> | |||||
| #define BRIDGE_SHM_RING_BUFFER_SIZE 2048 | |||||
| #ifndef BUILD_BRIDGE | |||||
| /*! | |||||
| * TODO. | |||||
| */ | |||||
| enum PluginBridgeInfoType { | |||||
| kPluginBridgeAudioCount, | |||||
| kPluginBridgeMidiCount, | |||||
| kPluginBridgeParameterCount, | |||||
| kPluginBridgeProgramCount, | |||||
| kPluginBridgeMidiProgramCount, | |||||
| kPluginBridgePluginInfo, | |||||
| kPluginBridgeParameterInfo, | |||||
| kPluginBridgeParameterData, | |||||
| kPluginBridgeParameterRanges, | |||||
| kPluginBridgeProgramInfo, | |||||
| kPluginBridgeMidiProgramInfo, | |||||
| kPluginBridgeConfigure, | |||||
| kPluginBridgeSetParameterValue, | |||||
| kPluginBridgeSetDefaultValue, | |||||
| kPluginBridgeSetProgram, | |||||
| kPluginBridgeSetMidiProgram, | |||||
| kPluginBridgeSetCustomData, | |||||
| kPluginBridgeSetChunkData, | |||||
| kPluginBridgeUpdateNow, | |||||
| kPluginBridgeError | |||||
| }; | |||||
| #endif | |||||
| /*! | |||||
| * TODO. | |||||
| */ | |||||
| struct BridgeRingBuffer { | |||||
| int head; | |||||
| int tail; | |||||
| int written; | |||||
| bool invalidateCommit; | |||||
| char buf[BRIDGE_SHM_RING_BUFFER_SIZE]; | |||||
| }; | |||||
| /*! | |||||
| * TODO. | |||||
| */ | |||||
| struct BridgeShmControl { | |||||
| // 32 and 64-bit binaries align semaphores differently. | |||||
| // Let's make sure there's plenty of room for either one. | |||||
| union { | |||||
| sem_t runServer; | |||||
| char _alignServer[32]; | |||||
| }; | |||||
| union { | |||||
| sem_t runClient; | |||||
| char _alignClient[32]; | |||||
| }; | |||||
| BridgeRingBuffer ringBuffer; | |||||
| }; | |||||
| #endif // __CARLA_BRIDGE_HPP__ | |||||
| @@ -58,7 +58,12 @@ enum EngineType { | |||||
| /*! | /*! | ||||
| * Plugin engine type, used to export the engine as a plugin. | * Plugin engine type, used to export the engine as a plugin. | ||||
| */ | */ | ||||
| kEngineTypePlugin = 3 | |||||
| kEngineTypePlugin = 3, | |||||
| /*! | |||||
| * TODO. | |||||
| */ | |||||
| kEngineTypeBridge = 4 | |||||
| }; | }; | ||||
| /*! | /*! | ||||
| @@ -1008,6 +1013,9 @@ protected: | |||||
| #endif | #endif | ||||
| private: | private: | ||||
| #ifdef BUILD_BRIDGE | |||||
| static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName); | |||||
| #endif | |||||
| #ifdef WANT_JACK | #ifdef WANT_JACK | ||||
| static CarlaEngine* newJack(); | static CarlaEngine* newJack(); | ||||
| #endif | #endif | ||||
| @@ -34,34 +34,6 @@ CARLA_BACKEND_START_NAMESPACE | |||||
| } // Fix editor indentation | } // Fix editor indentation | ||||
| #endif | #endif | ||||
| #if 1//ndef BUILD_BRIDGE | |||||
| /*! | |||||
| * TODO. | |||||
| */ | |||||
| enum PluginBridgeInfoType { | |||||
| kPluginBridgeAudioCount, | |||||
| kPluginBridgeMidiCount, | |||||
| kPluginBridgeParameterCount, | |||||
| kPluginBridgeProgramCount, | |||||
| kPluginBridgeMidiProgramCount, | |||||
| kPluginBridgePluginInfo, | |||||
| kPluginBridgeParameterInfo, | |||||
| kPluginBridgeParameterData, | |||||
| kPluginBridgeParameterRanges, | |||||
| kPluginBridgeProgramInfo, | |||||
| kPluginBridgeMidiProgramInfo, | |||||
| kPluginBridgeConfigure, | |||||
| kPluginBridgeSetParameterValue, | |||||
| kPluginBridgeSetDefaultValue, | |||||
| kPluginBridgeSetProgram, | |||||
| kPluginBridgeSetMidiProgram, | |||||
| kPluginBridgeSetCustomData, | |||||
| kPluginBridgeSetChunkData, | |||||
| kPluginBridgeUpdateNow, | |||||
| kPluginBridgeError | |||||
| }; | |||||
| #endif | |||||
| /*! | /*! | ||||
| * TODO. | * TODO. | ||||
| */ | */ | ||||
| @@ -35,6 +35,13 @@ CARLA_BACKEND_START_NAMESPACE | |||||
| return CarlaEngineProtectedData::getHostWindow(engine); | return CarlaEngineProtectedData::getHostWindow(engine); | ||||
| } | } | ||||
| #ifndef BUILD_BRIDGE | |||||
| void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin) | |||||
| { | |||||
| CarlaEngineProtectedData::registerEnginePlugin(engine, id, plugin); | |||||
| } | |||||
| #endif | |||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| // Carla Engine port (Abstract) | // Carla Engine port (Abstract) | ||||
| @@ -61,6 +61,7 @@ SOURCES = \ | |||||
| CarlaEngine.cpp \ | CarlaEngine.cpp \ | ||||
| CarlaEngineOsc.cpp \ | CarlaEngineOsc.cpp \ | ||||
| CarlaEngineThread.cpp \ | CarlaEngineThread.cpp \ | ||||
| CarlaEngineBridge.cpp \ | |||||
| CarlaEngineJack.cpp \ | CarlaEngineJack.cpp \ | ||||
| CarlaEnginePlugin.cpp \ | CarlaEnginePlugin.cpp \ | ||||
| CarlaEngineRtAudio.cpp | CarlaEngineRtAudio.cpp | ||||
| @@ -72,6 +73,7 @@ HEADERS = \ | |||||
| HEADERS += \ | HEADERS += \ | ||||
| ../CarlaBackend.hpp \ | ../CarlaBackend.hpp \ | ||||
| ../CarlaBridge.hpp \ | |||||
| ../CarlaEngine.hpp \ | ../CarlaEngine.hpp \ | ||||
| ../CarlaPlugin.hpp | ../CarlaPlugin.hpp | ||||
| @@ -0,0 +1,183 @@ | |||||
| /* | |||||
| * Carla Plugin Engine | |||||
| * Copyright (C) 2012-2013 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 GPL.txt file | |||||
| */ | |||||
| #ifdef BUILD_BRIDGE | |||||
| #include "CarlaEngineInternal.hpp" | |||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "CarlaMIDI.h" | |||||
| #include "CarlaBridge.hpp" | |||||
| #include "CarlaShmUtils.hpp" | |||||
| CARLA_BACKEND_START_NAMESPACE | |||||
| #if 0 | |||||
| } // Fix editor indentation | |||||
| #endif | |||||
| // ----------------------------------------- | |||||
| class CarlaEngineBridge : public CarlaEngine | |||||
| { | |||||
| public: | |||||
| CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName) | |||||
| : CarlaEngine() | |||||
| { | |||||
| carla_debug("CarlaEngineBridge::CarlaEngineBridge()"); | |||||
| fShmAudioPool.filename = "/carla-bridge_shm_" + audioBaseName; | |||||
| fShmControl.filename = "/carla-bridge_shc_" + controlBaseName; | |||||
| } | |||||
| ~CarlaEngineBridge() | |||||
| { | |||||
| carla_debug("CarlaEngineBridge::~CarlaEngineBridge()"); | |||||
| } | |||||
| // ------------------------------------- | |||||
| // CarlaEngine virtual calls | |||||
| bool init(const char* const clientName) | |||||
| { | |||||
| carla_debug("CarlaEngineBridge::init(\"%s\")", clientName); | |||||
| char tmpFileBase[60]; | |||||
| // SHM Audio Pool | |||||
| { | |||||
| fShmAudioPool.shm = carla_shm_attach((const char*)fShmAudioPool.filename); | |||||
| if (! carla_is_shm_valid(fShmAudioPool.shm)) | |||||
| { | |||||
| _cleanup(); | |||||
| carla_stdout("Failed to open or create shared memory file #1"); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| // SHM Control | |||||
| { | |||||
| fShmControl.shm = carla_shm_attach((const char*)fShmControl.filename); | |||||
| if (! carla_is_shm_valid(fShmControl.shm)) | |||||
| { | |||||
| _cleanup(); | |||||
| carla_stdout("Failed to open or create shared memory file #2"); | |||||
| return false; | |||||
| } | |||||
| if (! carla_shm_map<ShmControl>(fShmControl.shm, fShmControl.data)) | |||||
| { | |||||
| _cleanup(); | |||||
| carla_stdout("Failed to mmap shared memory file"); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| CarlaEngine::init(fName); | |||||
| return true; | |||||
| } | |||||
| bool close() | |||||
| { | |||||
| carla_debug("CarlaEnginePlugin::close()"); | |||||
| CarlaEngine::close(); | |||||
| _cleanup(); | |||||
| return true; | |||||
| } | |||||
| bool isRunning() const | |||||
| { | |||||
| return true; | |||||
| } | |||||
| bool isOffline() const | |||||
| { | |||||
| return false; | |||||
| } | |||||
| EngineType type() const | |||||
| { | |||||
| return kEngineTypeBridge; | |||||
| } | |||||
| private: | |||||
| struct BridgeAudioPool { | |||||
| CarlaString filename; | |||||
| float* data; | |||||
| size_t size; | |||||
| shm_t shm; | |||||
| BridgeAudioPool() | |||||
| : data(nullptr), | |||||
| size(0) | |||||
| { | |||||
| carla_shm_init(shm); | |||||
| } | |||||
| } fShmAudioPool; | |||||
| struct BridgeControl { | |||||
| CarlaString filename; | |||||
| ShmControl* data; | |||||
| shm_t shm; | |||||
| BridgeControl() | |||||
| : data(nullptr) | |||||
| { | |||||
| carla_shm_init(shm); | |||||
| } | |||||
| } fShmControl; | |||||
| void _cleanup() | |||||
| { | |||||
| if (fShmAudioPool.filename.isNotEmpty()) | |||||
| fShmAudioPool.filename.clear(); | |||||
| if (fShmControl.filename.isNotEmpty()) | |||||
| fShmControl.filename.clear(); | |||||
| // delete data | |||||
| fShmAudioPool.data = nullptr; | |||||
| fShmAudioPool.size = 0; | |||||
| // and again | |||||
| fShmControl.data = nullptr; | |||||
| if (carla_is_shm_valid(fShmAudioPool.shm)) | |||||
| carla_shm_close(fShmAudioPool.shm); | |||||
| if (carla_is_shm_valid(fShmControl.shm)) | |||||
| carla_shm_close(fShmControl.shm); | |||||
| } | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge) | |||||
| }; | |||||
| // ----------------------------------------- | |||||
| CarlaEngine* CarlaEngine::newBridge(const char* const audioBaseName, const char* const controlBaseName) | |||||
| { | |||||
| return new CarlaEngineBridge(audioBaseName, controlBaseName); | |||||
| } | |||||
| CARLA_BACKEND_END_NAMESPACE | |||||
| #endif // BUILD_BRIDGE | |||||
| @@ -47,6 +47,8 @@ const char* EngineType2Str(const EngineType type) | |||||
| return "kEngineTypeRtAudio"; | return "kEngineTypeRtAudio"; | ||||
| case kEngineTypePlugin: | case kEngineTypePlugin: | ||||
| return "kEngineTypePlugin"; | return "kEngineTypePlugin"; | ||||
| case kEngineTypeBridge: | |||||
| return "kEngineTypeBridge"; | |||||
| } | } | ||||
| carla_stderr("CarlaBackend::EngineType2Str(%i) - invalid type", type); | carla_stderr("CarlaBackend::EngineType2Str(%i) - invalid type", type); | ||||
| @@ -204,6 +206,16 @@ struct CarlaEngineProtectedData { | |||||
| (void)engine; | (void)engine; | ||||
| #endif | #endif | ||||
| } | } | ||||
| #ifndef BUILD_BRIDGE | |||||
| static void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin) | |||||
| { | |||||
| CARLA_ASSERT(id < engine->kData->curPluginCount); | |||||
| if (id < engine->kData->curPluginCount) | |||||
| engine->kData->plugins[id].plugin = plugin; | |||||
| } | |||||
| #endif | |||||
| }; | }; | ||||
| CARLA_BACKEND_END_NAMESPACE | CARLA_BACKEND_END_NAMESPACE | ||||
| @@ -21,6 +21,10 @@ | |||||
| #include "CarlaPlugin.hpp" | #include "CarlaPlugin.hpp" | ||||
| #include "CarlaMIDI.h" | #include "CarlaMIDI.h" | ||||
| #ifndef BUILD_BRIDGE | |||||
| # include "CarlaBridge.hpp" | |||||
| #endif | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| @@ -42,6 +42,7 @@ endif | |||||
| OBJS = \ | OBJS = \ | ||||
| CarlaEngine.cpp.o \ | CarlaEngine.cpp.o \ | ||||
| CarlaEngineBridge.cpp.o \ | |||||
| CarlaEngineJack.cpp.o \ | CarlaEngineJack.cpp.o \ | ||||
| CarlaEnginePlugin.cpp.o \ | CarlaEnginePlugin.cpp.o \ | ||||
| CarlaEngineRtAudio.cpp.o \ | CarlaEngineRtAudio.cpp.o \ | ||||
| @@ -17,8 +17,13 @@ | |||||
| #include "CarlaPluginInternal.hpp" | #include "CarlaPluginInternal.hpp" | ||||
| #if 1//ndef BUILD_BRIDGE | |||||
| #ifndef BUILD_BRIDGE | |||||
| #include "CarlaBridge.hpp" | |||||
| #include "CarlaShmUtils.hpp" | |||||
| #include <cerrno> | |||||
| #include <ctime> | |||||
| #include <QtCore/QDir> | #include <QtCore/QDir> | ||||
| #include <QtCore/QFile> | #include <QtCore/QFile> | ||||
| #include <QtCore/QStringList> | #include <QtCore/QStringList> | ||||
| @@ -49,6 +54,55 @@ | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| // Engine Helpers | |||||
| extern void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin); | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| shm_t shm_mkstemp(char* const fileBase) | |||||
| { | |||||
| static const char charSet[] = "abcdefghijklmnopqrstuvwxyz" | |||||
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |||||
| "0123456789"; | |||||
| const int size = (fileBase != nullptr) ? std::strlen(fileBase) : 0; | |||||
| shm_t shm; | |||||
| carla_shm_init(shm); | |||||
| if (size < 6) | |||||
| { | |||||
| errno = EINVAL; | |||||
| return shm; | |||||
| } | |||||
| if (std::strcmp(fileBase + size - 6, "XXXXXX") != 0) | |||||
| { | |||||
| errno = EINVAL; | |||||
| return shm; | |||||
| } | |||||
| std::srand(std::time(NULL)); | |||||
| while (true) | |||||
| { | |||||
| for (int c = size - 6; c < size; c++) | |||||
| { | |||||
| // Note the -1 to avoid the trailing '\0' in charSet. | |||||
| fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)]; | |||||
| } | |||||
| shm_t shm = carla_shm_create(fileBase); | |||||
| if (carla_is_shm_valid(shm) || errno != EEXIST) | |||||
| return shm; | |||||
| } | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| struct BridgeParamInfo { | struct BridgeParamInfo { | ||||
| float value; | float value; | ||||
| CarlaString name; | CarlaString name; | ||||
| @@ -75,7 +129,6 @@ public: | |||||
| kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE); | kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE); | ||||
| } | } | ||||
| #if 0 | |||||
| ~BridgePlugin() | ~BridgePlugin() | ||||
| { | { | ||||
| carla_debug("BridgePlugin::~BridgePlugin()"); | carla_debug("BridgePlugin::~BridgePlugin()"); | ||||
| @@ -83,6 +136,7 @@ public: | |||||
| kData->singleMutex.lock(); | kData->singleMutex.lock(); | ||||
| kData->masterMutex.lock(); | kData->masterMutex.lock(); | ||||
| #if 0 | |||||
| if (osc.data.target) | if (osc.data.target) | ||||
| { | { | ||||
| osc_send_hide(&osc.data); | osc_send_hide(&osc.data); | ||||
| @@ -103,8 +157,8 @@ public: | |||||
| } | } | ||||
| info.chunk.clear(); | info.chunk.clear(); | ||||
| } | |||||
| #endif | #endif | ||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Information (base) | // Information (base) | ||||
| @@ -909,11 +963,16 @@ public: | |||||
| carla_debug("BridgePlugin::delete_buffers() - end"); | carla_debug("BridgePlugin::delete_buffers() - end"); | ||||
| } | } | ||||
| #endif | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary) | bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary) | ||||
| { | { | ||||
| CARLA_ASSERT(kData->engine != nullptr); | |||||
| CARLA_ASSERT(kData->client == nullptr); | |||||
| CARLA_ASSERT(filename != nullptr); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // first checks | // first checks | ||||
| @@ -934,46 +993,109 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| m_filename = strdup(filename); | |||||
| // --------------------------------------------------------------- | |||||
| // set info | |||||
| if (name != nullptr) | |||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fFilename = filename; | |||||
| // --------------------------------------------------------------- | |||||
| // SHM Audio Pool | |||||
| { | |||||
| char tmpFileBase[60]; | |||||
| if (name) | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX"); | |||||
| fShmAudioPool.shm = shm_mkstemp(tmpFileBase); | |||||
| if (! carla_is_shm_valid(fShmAudioPool.shm)) | |||||
| { | |||||
| //_cleanup(); | |||||
| carla_stdout("Failed to open or create shared memory file #1"); | |||||
| return false; | |||||
| } | |||||
| fShmAudioPool.filename = tmpFileBase; | |||||
| } | |||||
| // --------------------------------------------------------------- | |||||
| // SHM Control | |||||
| { | |||||
| char tmpFileBase[60]; | |||||
| std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX"); | |||||
| fShmControl.shm = shm_mkstemp(tmpFileBase); | |||||
| if (! carla_is_shm_valid(fShmControl.shm)) | |||||
| { | |||||
| //_cleanup(); | |||||
| carla_stdout("Failed to open or create shared memory file #2"); | |||||
| return false; | |||||
| } | |||||
| fShmControl.filename = tmpFileBase; | |||||
| if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data)) | |||||
| { | |||||
| //_cleanup(); | |||||
| carla_stdout("Failed to mmap shared memory file"); | |||||
| return false; | |||||
| } | |||||
| std::memset(fShmControl.data, 0, sizeof(BridgeShmControl)); | |||||
| if (sem_init(&fShmControl.data->runServer, 1, 0) != 0) | |||||
| { | |||||
| //_cleanup(); | |||||
| carla_stdout("Failed to initialize shared memory semaphore #1"); | |||||
| return false; | |||||
| } | |||||
| if (sem_init(&fShmControl.data->runClient, 1, 0) != 0) | |||||
| { | |||||
| //_cleanup(); | |||||
| carla_stdout("Failed to initialize shared memory semaphore #2"); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| // register plugin now so we can receive OSC (and wait for it) | // register plugin now so we can receive OSC (and wait for it) | ||||
| x_engine->__bridgePluginRegister(m_id, this); | |||||
| registerEnginePlugin(kData->engine, fId, this); | |||||
| osc.thread->setOscData(bridgeBinary, label, getPluginTypeString(m_type)); | |||||
| osc.thread->start(); | |||||
| kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType)); | |||||
| kData->osc.thread.start(); | |||||
| for (int i=0; i < 200; i++) | for (int i=0; i < 200; i++) | ||||
| { | { | ||||
| if (m_initiated || osc.thread->isFinished()) | |||||
| if (fInitiated || ! kData->osc.thread.isRunning()) | |||||
| break; | break; | ||||
| carla_msleep(50); | carla_msleep(50); | ||||
| } | } | ||||
| if (! m_initiated) | |||||
| if (! fInitiated) | |||||
| { | { | ||||
| // unregister so it gets handled properly | // unregister so it gets handled properly | ||||
| x_engine->__bridgePluginRegister(m_id, nullptr); | |||||
| registerEnginePlugin(kData->engine, fId, nullptr); | |||||
| osc.thread->terminate(); | |||||
| x_engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)"); | |||||
| kData->osc.thread.terminate(); | |||||
| kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)"); | |||||
| return false; | return false; | ||||
| } | } | ||||
| else if (m_initError) | |||||
| else if (fInitError) | |||||
| { | { | ||||
| // unregister so it gets handled properly | // unregister so it gets handled properly | ||||
| x_engine->__bridgePluginRegister(m_id, nullptr); | |||||
| registerEnginePlugin(kData->engine, fId, nullptr); | |||||
| osc.thread->quit(); | |||||
| kData->osc.thread.stop(); | |||||
| // last error was set before | // last error was set before | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| #endif | |||||
| private: | private: | ||||
| const BinaryType fBinaryType; | const BinaryType fBinaryType; | ||||
| @@ -983,6 +1105,33 @@ private: | |||||
| bool fInitError; | bool fInitError; | ||||
| bool fSaved; | bool fSaved; | ||||
| struct BridgeAudioPool { | |||||
| CarlaString filename; | |||||
| float* data; | |||||
| size_t size; | |||||
| shm_t shm; | |||||
| BridgeAudioPool() | |||||
| : data(nullptr), | |||||
| size(0) | |||||
| { | |||||
| carla_shm_init(shm); | |||||
| } | |||||
| } fShmAudioPool; | |||||
| struct BridgeControl { | |||||
| CarlaString filename; | |||||
| BridgeShmControl* data; | |||||
| shm_t shm; | |||||
| BridgeControl() | |||||
| : data(nullptr) | |||||
| { | |||||
| carla_shm_init(shm); | |||||
| } | |||||
| } fShmControl; | |||||
| struct Info { | struct Info { | ||||
| uint32_t aIns, aOuts; | uint32_t aIns, aOuts; | ||||
| uint32_t mIns, mOuts; | uint32_t mIns, mOuts; | ||||
| @@ -35,7 +35,7 @@ typedef int shm_t; | |||||
| // shared memory calls | // shared memory calls | ||||
| static inline | static inline | ||||
| bool carla_is_shm_valid(shm_t shm) | |||||
| bool carla_is_shm_valid(const shm_t& shm) | |||||
| { | { | ||||
| #ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
| return (shm.shm != nullptr && shm.shm != INVALID_HANDLE_VALUE); | return (shm.shm != nullptr && shm.shm != INVALID_HANDLE_VALUE); | ||||
| @@ -105,7 +105,7 @@ void carla_shm_close(shm_t& shm) | |||||
| } | } | ||||
| static inline | static inline | ||||
| void* carla_shm_map(shm_t shm, const size_t size) | |||||
| void* carla_shm_map(shm_t& shm, const size_t size) | |||||
| { | { | ||||
| CARLA_ASSERT(carla_is_shm_valid(shm)); | CARLA_ASSERT(carla_is_shm_valid(shm)); | ||||
| CARLA_ASSERT(size > 0); | CARLA_ASSERT(size > 0); | ||||
| @@ -129,12 +129,13 @@ void* carla_shm_map(shm_t shm, const size_t size) | |||||
| return ptr; | return ptr; | ||||
| #else | #else | ||||
| ftruncate(shm, size); | |||||
| return mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0); | return mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0); | ||||
| #endif | #endif | ||||
| } | } | ||||
| static inline | static inline | ||||
| void carla_shm_unmap(const shm_t shm, void* const ptr, const size_t size) | |||||
| void carla_shm_unmap(const shm_t& shm, void* const ptr, const size_t size) | |||||
| { | { | ||||
| CARLA_ASSERT(carla_is_shm_valid(shm)); | CARLA_ASSERT(carla_is_shm_valid(shm)); | ||||
| CARLA_ASSERT(ptr != nullptr); | CARLA_ASSERT(ptr != nullptr); | ||||
| @@ -177,14 +178,15 @@ void carla_shm_unmap(const shm_t shm, void* const ptr, const size_t size) | |||||
| template<typename T> | template<typename T> | ||||
| static inline | static inline | ||||
| void carla_shm_map(shm_t shm, T* value) | |||||
| bool carla_shm_map(shm_t& shm, T* value) | |||||
| { | { | ||||
| value = carla_shm_map(shm, sizeof(value)); | |||||
| value = (T*)carla_shm_map(shm, sizeof(value)); | |||||
| return (value != nullptr); | |||||
| } | } | ||||
| template<typename T> | template<typename T> | ||||
| static inline | static inline | ||||
| void carla_shm_unmap(const shm_t shm, T* value) | |||||
| void carla_shm_unmap(const shm_t& shm, T* value) | |||||
| { | { | ||||
| carla_shm_unmap(shm, value, sizeof(value)); | carla_shm_unmap(shm, value, sizeof(value)); | ||||
| value = nullptr; | value = nullptr; | ||||