| @@ -24,7 +24,6 @@ | |||
| #include "CarlaBackendUtils.hpp" | |||
| #include "CarlaBridgeUtils.hpp" | |||
| #include "CarlaShmUtils.hpp" | |||
| #include "CarlaMIDI.h" | |||
| #include "jackbridge/JackBridge.hpp" | |||
| @@ -40,15 +39,23 @@ CARLA_BACKEND_START_NAMESPACE | |||
| // ------------------------------------------------------------------- | |||
| template<typename T> | |||
| bool jackbridge_shm_map2(char* shm, T*& value) | |||
| { | |||
| value = (T*)jackbridge_shm_map(shm, sizeof(T)); | |||
| return (value != nullptr); | |||
| } | |||
| struct BridgeAudioPool { | |||
| CarlaString filename; | |||
| float* data; | |||
| shm_t shm; | |||
| char shm[32]; | |||
| BridgeAudioPool() | |||
| : data(nullptr) | |||
| { | |||
| carla_shm_init(shm); | |||
| carla_zeroChar(shm, 32); | |||
| jackbridge_shm_init(shm); | |||
| } | |||
| ~BridgeAudioPool() | |||
| @@ -61,14 +68,9 @@ struct BridgeAudioPool { | |||
| bool attach() | |||
| { | |||
| #ifdef CARLA_OS_WIN | |||
| // TESTING! | |||
| shm = carla_shm_attach_linux((const char*)filename); | |||
| #else | |||
| shm = carla_shm_attach((const char*)filename); | |||
| #endif | |||
| jackbridge_shm_attach(shm, filename.getBuffer()); | |||
| return carla_is_shm_valid(shm); | |||
| return jackbridge_shm_is_valid(shm); | |||
| } | |||
| void clear() | |||
| @@ -77,21 +79,22 @@ struct BridgeAudioPool { | |||
| data = nullptr; | |||
| if (carla_is_shm_valid(shm)) | |||
| carla_shm_close(shm); | |||
| if (jackbridge_shm_is_valid(shm)) | |||
| jackbridge_shm_close(shm); | |||
| } | |||
| }; | |||
| struct BridgeControl : public RingBufferControl<StackPackedRingBuffer> { | |||
| struct BridgeControl : public RingBufferControl<StackRingBuffer> { | |||
| CarlaString filename; | |||
| BridgeShmControl* data; | |||
| shm_t shm; | |||
| char shm[32]; | |||
| BridgeControl() | |||
| : RingBufferControl(nullptr), | |||
| data(nullptr) | |||
| { | |||
| carla_shm_init(shm); | |||
| carla_zeroChar(shm, 32); | |||
| jackbridge_shm_init(shm); | |||
| } | |||
| ~BridgeControl() | |||
| @@ -104,14 +107,9 @@ struct BridgeControl : public RingBufferControl<StackPackedRingBuffer> { | |||
| bool attach() | |||
| { | |||
| #ifdef CARLA_OS_WIN | |||
| // TESTING! | |||
| shm = carla_shm_attach_linux((const char*)filename); | |||
| #else | |||
| shm = carla_shm_attach((const char*)filename); | |||
| #endif | |||
| jackbridge_shm_attach(shm, filename.getBuffer()); | |||
| return carla_is_shm_valid(shm); | |||
| return jackbridge_shm_is_valid(shm); | |||
| } | |||
| void clear() | |||
| @@ -120,15 +118,15 @@ struct BridgeControl : public RingBufferControl<StackPackedRingBuffer> { | |||
| data = nullptr; | |||
| if (carla_is_shm_valid(shm)) | |||
| carla_shm_close(shm); | |||
| if (jackbridge_shm_is_valid(shm)) | |||
| jackbridge_shm_close(shm); | |||
| } | |||
| bool mapData() | |||
| { | |||
| CARLA_ASSERT(data == nullptr); | |||
| if (carla_shm_map<BridgeShmControl>(shm, data)) | |||
| if (jackbridge_shm_map2<BridgeShmControl>(shm, data)) | |||
| { | |||
| setRingBuffer(&data->ringBuffer, false); | |||
| return true; | |||
| @@ -208,12 +206,18 @@ public: | |||
| PluginBridgeOpcode opcode; | |||
| opcode = fShmControl.readOpcode(); | |||
| CARLA_ASSERT_INT(opcode == kPluginBridgeOpcodeSetBufferSize, opcode); | |||
| CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeNull, opcode); | |||
| const uint32_t structSize = fShmControl.readUInt(); | |||
| CARLA_SAFE_ASSERT_INT2(structSize == sizeof(BridgeShmControl), structSize, sizeof(BridgeShmControl)); | |||
| carla_stderr("Struct Size: %i", structSize); | |||
| opcode = fShmControl.readOpcode(); | |||
| CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeSetBufferSize, opcode); | |||
| pData->bufferSize = fShmControl.readUInt(); | |||
| carla_stderr("BufferSize: %i", pData->bufferSize); | |||
| opcode = fShmControl.readOpcode(); | |||
| CARLA_ASSERT_INT(opcode == kPluginBridgeOpcodeSetSampleRate, opcode); | |||
| CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeSetSampleRate, opcode); | |||
| pData->sampleRate = fShmControl.readFloat(); | |||
| carla_stderr("SampleRate: %f", pData->sampleRate); | |||
| @@ -294,7 +298,7 @@ public: | |||
| case kPluginBridgeOpcodeSetAudioPool: { | |||
| const int64_t poolSize(fShmControl.readLong()); | |||
| CARLA_SAFE_ASSERT_BREAK(poolSize > 0); | |||
| fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, size_t(poolSize)); | |||
| fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, size_t(poolSize)); | |||
| break; | |||
| } | |||
| @@ -142,7 +142,7 @@ struct BridgeAudioPool { | |||
| } | |||
| }; | |||
| struct BridgeControl : public RingBufferControl<StackPackedRingBuffer> { | |||
| struct BridgeControl : public RingBufferControl<StackRingBuffer> { | |||
| CarlaString filename; | |||
| BridgeShmControl* data; | |||
| shm_t shm; | |||
| @@ -718,12 +718,7 @@ public: | |||
| } catch(...) {} | |||
| if (! timedOut) | |||
| { | |||
| carla_stdout("woohoo! activate was successful!"); | |||
| fTimedOut = false; | |||
| } | |||
| else | |||
| carla_stdout("beh! activate failed!"); | |||
| } | |||
| void deactivate() noexcept override | |||
| @@ -740,9 +735,8 @@ public: | |||
| timedOut = waitForServer(); | |||
| } catch(...) {} | |||
| (void)timedOut; | |||
| //if (! timedOut) | |||
| // fTimedOut = false; | |||
| if (! timedOut) | |||
| fTimedOut = false; | |||
| } | |||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override | |||
| @@ -1743,6 +1737,9 @@ public: | |||
| } | |||
| // initial values | |||
| fShmControl.writeOpcode(kPluginBridgeOpcodeNull); | |||
| fShmControl.writeInt(static_cast<int32_t>(sizeof(BridgeShmControl))); | |||
| fShmControl.writeOpcode(kPluginBridgeOpcodeSetBufferSize); | |||
| fShmControl.writeInt(static_cast<int32_t>(pData->engine->getBufferSize())); | |||
| @@ -30,6 +30,10 @@ | |||
| #include <QtCore/QByteArray> | |||
| #ifdef BUILD_BRIDGE | |||
| # undef HAVE_JUCE | |||
| #endif | |||
| #ifdef HAVE_JUCE | |||
| # include "juce_gui_basics.h" | |||
| using juce::initialiseJuce_GUI; | |||
| @@ -123,21 +123,23 @@ void CarlaBridgeClient::oscInit(const char* const url) | |||
| fOsc.init(url); | |||
| } | |||
| void CarlaBridgeClient::oscClose() | |||
| bool CarlaBridgeClient::oscIdle() const | |||
| { | |||
| carla_debug("CarlaBridgeClient::oscClose()"); | |||
| fOsc.idle(); | |||
| fOsc.close(); | |||
| #ifdef BUILD_BRIDGE_UI | |||
| return ! fUI.quit; | |||
| #else | |||
| return true; | |||
| #endif | |||
| } | |||
| #ifdef BUILD_BRIDGE_UI | |||
| bool CarlaBridgeClient::oscIdle() const | |||
| void CarlaBridgeClient::oscClose() | |||
| { | |||
| fOsc.idle(); | |||
| carla_debug("CarlaBridgeClient::oscClose()"); | |||
| return ! fUI.quit; | |||
| fOsc.close(); | |||
| } | |||
| #endif | |||
| bool CarlaBridgeClient::isOscControlRegistered() const noexcept | |||
| { | |||
| @@ -74,11 +74,8 @@ public: | |||
| // osc stuff | |||
| void oscInit(const char* const url); | |||
| void oscClose(); | |||
| #ifdef BUILD_BRIDGE_UI | |||
| bool oscIdle() const; | |||
| #endif | |||
| void oscClose(); | |||
| bool isOscControlRegistered() const noexcept; | |||
| void sendOscUpdate() const; | |||
| @@ -62,11 +62,7 @@ void CarlaBridgeOsc::init(const char* const url) | |||
| fName += CarlaString(std::rand() % 99999); | |||
| #endif | |||
| #ifdef BUILD_BRIDGE_UI | |||
| fServer = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler); | |||
| #else | |||
| fServer = lo_server_thread_new_with_proto(nullptr, LO_UDP, osc_error_handler); | |||
| #endif | |||
| CARLA_SAFE_ASSERT_RETURN(fServer != nullptr,) | |||
| @@ -80,28 +76,26 @@ void CarlaBridgeOsc::init(const char* const url) | |||
| std::free(port); | |||
| } | |||
| #ifdef BUILD_BRIDGE_UI | |||
| if (char* const tmpServerPath = lo_server_get_url(fServer)) | |||
| #else | |||
| if (char* const tmpServerPath = lo_server_thread_get_url(fServer)) | |||
| #endif | |||
| { | |||
| fServerPath = tmpServerPath; | |||
| fServerPath += fName; | |||
| std::free(tmpServerPath); | |||
| } | |||
| #ifdef BUILD_BRIDGE_UI | |||
| lo_server_add_method(fServer, nullptr, nullptr, osc_message_handler, this); | |||
| #else | |||
| lo_server_thread_add_method(fServer, nullptr, nullptr, osc_message_handler, this); | |||
| lo_server_thread_start(fServer); | |||
| #endif | |||
| CARLA_ASSERT(fName.isNotEmpty()); | |||
| CARLA_ASSERT(fServerPath.isNotEmpty()); | |||
| } | |||
| void CarlaBridgeOsc::idle() const | |||
| { | |||
| if (fServer == nullptr) | |||
| return; | |||
| for (; lo_server_recv_noblock(fServer, 0) != 0;) {} | |||
| } | |||
| void CarlaBridgeOsc::close() | |||
| { | |||
| CARLA_ASSERT(fControlData.source == nullptr); // must never be used | |||
| @@ -114,14 +108,8 @@ void CarlaBridgeOsc::close() | |||
| if (fServer != nullptr) | |||
| { | |||
| #ifdef BUILD_BRIDGE_UI | |||
| lo_server_del_method(fServer, nullptr, nullptr); | |||
| lo_server_free(fServer); | |||
| #else | |||
| lo_server_thread_del_method(fServer, nullptr, nullptr); | |||
| lo_server_thread_del_method(fServer, nullptr, nullptr); | |||
| lo_server_thread_free(fServer); | |||
| #endif | |||
| fServer = nullptr; | |||
| } | |||
| @@ -133,16 +121,6 @@ void CarlaBridgeOsc::close() | |||
| CARLA_ASSERT(fServer == nullptr); | |||
| } | |||
| #ifdef BUILD_BRIDGE_UI | |||
| void CarlaBridgeOsc::idle() const | |||
| { | |||
| if (fServer == nullptr) | |||
| return; | |||
| for (; lo_server_recv_noblock(fServer, 0) != 0;) {} | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| int CarlaBridgeOsc::handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg) | |||
| @@ -60,11 +60,8 @@ public: | |||
| ~CarlaBridgeOsc(); | |||
| void init(const char* const url); | |||
| void close(); | |||
| #ifdef BUILD_BRIDGE_UI | |||
| void idle() const; | |||
| #endif | |||
| void close(); | |||
| // ------------------------------------------------------------------- | |||
| @@ -91,11 +88,7 @@ private: | |||
| CarlaOscData fControlData; | |||
| CarlaString fName; | |||
| CarlaString fServerPath; | |||
| #ifdef BUILD_BRIDGE_UI | |||
| lo_server fServer; | |||
| #else | |||
| lo_server_thread fServer; | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| @@ -25,12 +25,22 @@ | |||
| #include "CarlaBridgeUtils.hpp" | |||
| #include "CarlaMIDI.h" | |||
| //#include "juce_core.h" | |||
| #ifdef CARLA_OS_UNIX | |||
| # include <signal.h> | |||
| #endif | |||
| // #ifdef BUILD_BRIDGE | |||
| // # undef HAVE_JUCE | |||
| // #endif | |||
| #ifdef HAVE_JUCE | |||
| # include "juce_gui_basics.h" | |||
| using juce::JUCEApplication; | |||
| using juce::JUCEApplicationBase; | |||
| using juce::String; | |||
| using juce::Timer; | |||
| #endif | |||
| //using juce::File; | |||
| // ------------------------------------------------------------------------- | |||
| @@ -91,6 +101,57 @@ static void initSignalHandler() | |||
| // ------------------------------------------------------------------------- | |||
| #ifdef HAVE_JUCE | |||
| static CarlaBridge::CarlaBridgeClient* gBridgeClient = nullptr; | |||
| class CarlaJuceApp : public JUCEApplication, | |||
| Timer | |||
| { | |||
| public: | |||
| CarlaJuceApp() {} | |||
| ~CarlaJuceApp() {} | |||
| void initialise(const String&) override | |||
| { | |||
| startTimer(30); | |||
| } | |||
| void shutdown() override | |||
| { | |||
| gCloseNow = true; | |||
| stopTimer(); | |||
| } | |||
| const String getApplicationName() override | |||
| { | |||
| return "CarlaPlugin"; | |||
| } | |||
| const String getApplicationVersion() override | |||
| { | |||
| return CARLA_VERSION_STRING; | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| carla_engine_idle(); | |||
| if (gBridgeClient != nullptr) | |||
| gBridgeClient->oscIdle(); | |||
| if (gCloseNow) | |||
| { | |||
| quit(); | |||
| gCloseNow = false; | |||
| } | |||
| } | |||
| }; | |||
| static JUCEApplicationBase* juce_CreateApplication() { return new CarlaJuceApp(); } | |||
| #endif | |||
| // ------------------------------------------------------------------------- | |||
| CARLA_BRIDGE_START_NAMESPACE | |||
| #if 0 | |||
| @@ -135,6 +196,10 @@ public: | |||
| { | |||
| carla_debug("CarlaPluginClient::~CarlaPluginClient()"); | |||
| #ifdef HAVE_JUCE | |||
| gBridgeClient = nullptr; | |||
| #endif | |||
| carla_engine_close(); | |||
| } | |||
| @@ -167,13 +232,14 @@ public: | |||
| } | |||
| } | |||
| #ifndef HAVE_JUCE | |||
| void idle() | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| carla_engine_idle(); | |||
| //CarlaBridgeClient::oscIdle(); | |||
| CarlaBridgeClient::oscIdle(); | |||
| if (gSaveNow) | |||
| { | |||
| @@ -192,14 +258,22 @@ public: | |||
| // close something? | |||
| } | |||
| } | |||
| #endif | |||
| void exec() | |||
| void exec(int argc, char* argv[]) | |||
| { | |||
| #ifdef HAVE_JUCE | |||
| gBridgeClient = this; | |||
| JUCEApplicationBase::createInstance = &juce_CreateApplication; | |||
| JUCEApplicationBase::main(JUCE_MAIN_FUNCTION_ARGS); | |||
| #else | |||
| for (; ! gCloseNow;) | |||
| { | |||
| idle(); | |||
| carla_msleep(30); | |||
| carla_msleep(24); | |||
| } | |||
| #endif | |||
| return; (void)argc; (void)argv; | |||
| } | |||
| // --------------------------------------------------------------------- | |||
| @@ -367,6 +441,10 @@ int CarlaBridgeOsc::handleMsgShow() | |||
| { | |||
| carla_debug("CarlaBridgeOsc::handleMsgShow()"); | |||
| #ifdef HAVE_JUCE | |||
| const juce::MessageManagerLock mmLock; | |||
| #endif | |||
| if (carla_get_plugin_info(0)->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI) | |||
| carla_show_custom_ui(0, true); | |||
| @@ -377,6 +455,10 @@ int CarlaBridgeOsc::handleMsgHide() | |||
| { | |||
| carla_debug("CarlaBridgeOsc::handleMsgHide()"); | |||
| #ifdef HAVE_JUCE | |||
| const juce::MessageManagerLock mmLock; | |||
| #endif | |||
| if (carla_get_plugin_info(0)->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI) | |||
| carla_show_custom_ui(0, false); | |||
| @@ -607,7 +689,7 @@ int main(int argc, char* argv[]) | |||
| client.ready(!useOsc); | |||
| gIsInitiated = true; | |||
| client.exec(); | |||
| client.exec(argc, argv); | |||
| carla_set_engine_about_to_close(); | |||
| carla_remove_plugin(0); | |||
| @@ -378,4 +378,10 @@ CARLA_EXPORT bool jackbridge_sem_destroy(void* sem) noexcept; | |||
| CARLA_EXPORT bool jackbridge_sem_post(void* sem) noexcept; | |||
| CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs); | |||
| CARLA_EXPORT bool jackbridge_shm_is_valid(char* shm); | |||
| CARLA_EXPORT void jackbridge_shm_init(char* shm); | |||
| CARLA_EXPORT void jackbridge_shm_attach(char* shm, const char* name); | |||
| CARLA_EXPORT void jackbridge_shm_close(char* shm); | |||
| CARLA_EXPORT void* jackbridge_shm_map(char* shm, size_t size); | |||
| #endif // JACKBRIDGE_HPP_INCLUDED | |||
| @@ -17,10 +17,7 @@ | |||
| #include "CarlaDefines.h" | |||
| #include "JackBridge.hpp" | |||
| #ifdef CARLA_OS_MAC | |||
| # include <unistd.h> | |||
| #endif | |||
| #include "CarlaShmUtils.hpp" | |||
| #ifndef JACKBRIDGE_HPP_INCLUDED | |||
| // don't include the whole JACK API in this file | |||
| @@ -28,6 +25,12 @@ CARLA_EXPORT bool jackbridge_sem_init(void* sem) noexcept; | |||
| CARLA_EXPORT bool jackbridge_sem_destroy(void* sem) noexcept; | |||
| CARLA_EXPORT bool jackbridge_sem_post(void* sem) noexcept; | |||
| CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs); | |||
| CARLA_EXPORT bool jackbridge_shm_is_valid(char* shm); | |||
| CARLA_EXPORT void jackbridge_shm_init(char* shm); | |||
| CARLA_EXPORT void jackbridge_shm_attach(char* shm, const char* name); | |||
| CARLA_EXPORT void jackbridge_shm_close(char* shm); | |||
| CARLA_EXPORT void* jackbridge_shm_map(char* shm, size_t size); | |||
| #endif | |||
| // ----------------------------------------------------------------------------- | |||
| @@ -52,6 +55,28 @@ bool jackbridge_sem_timedwait(void*, int) | |||
| { | |||
| return false; | |||
| } | |||
| bool jackbridge_shm_is_valid(char*) | |||
| { | |||
| return false; | |||
| } | |||
| void jackbridge_shm_init(char*) | |||
| { | |||
| } | |||
| void jackbridge_shm_attach(char*, const char*) | |||
| { | |||
| } | |||
| void jackbridge_shm_close(char*) | |||
| { | |||
| } | |||
| void* jackbridge_shm_map(char*, size_t) | |||
| { | |||
| return nullptr; | |||
| } | |||
| #else //JACKBRIDGE_DUMMY | |||
| #include <ctime> | |||
| #include <sys/time.h> | |||
| @@ -60,17 +85,17 @@ bool jackbridge_sem_timedwait(void*, int) | |||
| bool jackbridge_sem_init(void* sem) noexcept | |||
| { | |||
| return (sem_init((sem_t*)sem, 1, 0) == 0); | |||
| return sem_init((sem_t*)sem, 1, 0) == 0; | |||
| } | |||
| bool jackbridge_sem_destroy(void* sem) noexcept | |||
| { | |||
| return (sem_destroy((sem_t*)sem) == 0); | |||
| return sem_destroy((sem_t*)sem) == 0; | |||
| } | |||
| bool jackbridge_sem_post(void* sem) noexcept | |||
| { | |||
| return (sem_post((sem_t*)sem) == 0); | |||
| return sem_post((sem_t*)sem) == 0; | |||
| } | |||
| bool jackbridge_sem_timedwait(void* sem, int secs) | |||
| @@ -94,6 +119,37 @@ bool jackbridge_sem_timedwait(void* sem, int secs) | |||
| return (sem_timedwait((sem_t*)sem, &timeout) == 0); | |||
| # endif | |||
| } | |||
| #endif // JACKBRIDGE_DUMMY | |||
| bool jackbridge_shm_is_valid(char* shm) | |||
| { | |||
| shm_t* t = (shm_t*)shm; | |||
| return carla_is_shm_valid(*t); | |||
| } | |||
| void jackbridge_shm_init(char* shm) | |||
| { | |||
| shm_t* t = (shm_t*)shm; | |||
| carla_shm_init(*t); | |||
| } | |||
| void jackbridge_shm_attach(char* shm, const char* name) | |||
| { | |||
| shm_t* t = (shm_t*)shm; | |||
| *t = carla_shm_attach(name); | |||
| } | |||
| void jackbridge_shm_close(char* shm) | |||
| { | |||
| shm_t* t = (shm_t*)shm; | |||
| carla_shm_close(*t); | |||
| } | |||
| void* jackbridge_shm_map(char* shm, size_t size) | |||
| { | |||
| shm_t* t = (shm_t*)shm; | |||
| return carla_shm_map(*t, size); | |||
| } | |||
| #endif // ! JACKBRIDGE_DUMMY | |||
| // ----------------------------------------------------------------------------- | |||
| @@ -84,7 +84,7 @@ struct BridgeShmControl { | |||
| void* runClient; | |||
| char _padClient[32]; | |||
| }; | |||
| StackPackedRingBuffer ringBuffer; | |||
| StackRingBuffer ringBuffer; | |||
| } POST_PACKED_STRUCTURE; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -82,22 +82,6 @@ shm_t carla_shm_attach(const char* const name) | |||
| return ret; | |||
| } | |||
| static inline | |||
| shm_t carla_shm_attach_linux(const char* const name) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullCarlaShm); | |||
| char shmName[std::strlen(name)+10]; | |||
| std::strcpy(shmName, "/dev/shm/"); | |||
| std::strcat(shmName, name); | |||
| shm_t ret; | |||
| ret.shm = CreateFileA(shmName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); | |||
| ret.map = nullptr; | |||
| return ret; | |||
| } | |||
| #else | |||
| static inline | |||
| shm_t carla_shm_create(const char* const name) | |||