From 798ab5c13317e994bcfa8bf20157b5bfa9856fbe Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 22 Sep 2018 20:46:18 +0200 Subject: [PATCH 01/17] Fix internal plugins receiving wrong frame pos on split buffers --- source/backend/plugin/CarlaPluginNative.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/backend/plugin/CarlaPluginNative.cpp b/source/backend/plugin/CarlaPluginNative.cpp index 9d187dd82..0e9b99a5b 100644 --- a/source/backend/plugin/CarlaPluginNative.cpp +++ b/source/backend/plugin/CarlaPluginNative.cpp @@ -2064,7 +2064,9 @@ public: } fIsProcessing = false; - fTimeInfo.frame += frames; + + if (fTimeInfo.playing) + fTimeInfo.frame += frames; #ifndef BUILD_BRIDGE // -------------------------------------------------------------------------------------------------------- From b770f61b93be66b3f2904e5c85ffbae9869cbf8c Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 22 Sep 2018 20:47:04 +0200 Subject: [PATCH 02/17] Fix internal plugins not handling internal controls on native bridge --- source/backend/plugin/CarlaPluginNative.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/backend/plugin/CarlaPluginNative.cpp b/source/backend/plugin/CarlaPluginNative.cpp index 0e9b99a5b..04977acd4 100644 --- a/source/backend/plugin/CarlaPluginNative.cpp +++ b/source/backend/plugin/CarlaPluginNative.cpp @@ -2068,7 +2068,7 @@ public: if (fTimeInfo.playing) fTimeInfo.frame += frames; -#ifndef BUILD_BRIDGE +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) From ef07babaadd3929ff28a4ef66c03d645cee840a8 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 22 Sep 2018 21:18:12 +0200 Subject: [PATCH 03/17] Fix dynamic buffer size against plugin bridges Closes #752 --- source/backend/plugin/CarlaPluginBridge.cpp | 8 ++++++-- source/backend/plugin/CarlaPluginJack.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index 1342d991a..687c92f3b 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -380,6 +380,7 @@ public: fSaved(true), fTimedOut(false), fTimedError(false), + fBufferSize(engine->getBufferSize()), fProcWaitTime(0), fLastPongTime(-1), fBridgeBinary(), @@ -1432,6 +1433,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(! fTimedError, false); CARLA_SAFE_ASSERT_RETURN(frames > 0, false); + CARLA_SAFE_ASSERT_RETURN(frames <= fBufferSize, false); if (pData->audioIn.count > 0) { @@ -1473,7 +1475,7 @@ public: // Reset audio buffers for (uint32_t i=0; i < fInfo.aIns; ++i) - carla_copyFloats(fShmAudioPool.data + (i * frames), audioIn[i], frames); + carla_copyFloats(fShmAudioPool.data + (i * fBufferSize), audioIn[i], frames); // -------------------------------------------------------------------------------------------------------- // TimeInfo @@ -1518,7 +1520,7 @@ public: } for (uint32_t i=0; i < fInfo.aOuts; ++i) - carla_copyFloats(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), frames); + carla_copyFloats(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * fBufferSize), frames); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- @@ -1634,6 +1636,7 @@ public: void bufferSizeChanged(const uint32_t newBufferSize) override { + fBufferSize = newBufferSize; resizeAudioPool(newBufferSize); { @@ -2422,6 +2425,7 @@ private: bool fSaved; bool fTimedOut; bool fTimedError; + uint fBufferSize; uint fProcWaitTime; int64_t fLastPongTime; diff --git a/source/backend/plugin/CarlaPluginJack.cpp b/source/backend/plugin/CarlaPluginJack.cpp index 777f26047..0687e2ecc 100644 --- a/source/backend/plugin/CarlaPluginJack.cpp +++ b/source/backend/plugin/CarlaPluginJack.cpp @@ -203,6 +203,7 @@ public: fTimedOut(false), fTimedError(false), fProcCanceled(false), + fBufferSize(engine->getBufferSize()), fProcWaitTime(0), fLastPingTime(-1), fBridgeThread(engine, this), @@ -904,6 +905,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(! fTimedError, false); CARLA_SAFE_ASSERT_RETURN(frames > 0, false); + CARLA_SAFE_ASSERT_RETURN(frames <= fBufferSize, false); if (pData->audioIn.count > 0) { @@ -935,7 +937,7 @@ public: // Reset audio buffers for (uint32_t i=0; i < fInfo.aIns; ++i) - carla_copyFloats(fShmAudioPool.data + (i * frames), audioIn[i], frames); + carla_copyFloats(fShmAudioPool.data + (i * fBufferSize), audioIn[i], frames); // -------------------------------------------------------------------------------------------------------- // TimeInfo @@ -986,7 +988,7 @@ public: } for (uint32_t i=0; i < fInfo.aOuts; ++i) - carla_copyFloats(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), frames); + carla_copyFloats(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * fBufferSize), frames); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // -------------------------------------------------------------------------------------------------------- @@ -1064,6 +1066,7 @@ public: void bufferSizeChanged(const uint32_t newBufferSize) override { + fBufferSize = newBufferSize; resizeAudioPool(newBufferSize); { @@ -1360,6 +1363,7 @@ private: bool fTimedOut; bool fTimedError; bool fProcCanceled; + uint fBufferSize; uint fProcWaitTime; int64_t fLastPingTime; From e8b106fec7dc049e259958e51688fc058b2ad080 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 22 Sep 2018 21:29:07 +0200 Subject: [PATCH 04/17] Remove macOS related note in settings, if not running macOS --- source/frontend/carla_settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/frontend/carla_settings.py b/source/frontend/carla_settings.py index 55b264d30..53c543030 100755 --- a/source/frontend/carla_settings.py +++ b/source/frontend/carla_settings.py @@ -298,6 +298,9 @@ class CarlaSettingsW(QDialog): self.ui.ch_exp_prevent_bad_behaviour.setVisible(False) self.ui.lw_page.hideRow(self.TAB_INDEX_WINE) + if not MACOS: + self.ui.label_engine_ui_bridges_mac_note.setVisible(False) + # FIXME, not implemented yet self.ui.ch_engine_uis_always_on_top.hide() From ba0c12697ce447cd1638b3c1634e71b260bf3214 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 22 Sep 2018 21:55:59 +0200 Subject: [PATCH 05/17] Fix for LV2 plugins with UI feedback ports in bridge mode --- source/backend/plugin/CarlaPlugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 4fb4b046e..f24fa8911 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -1587,7 +1587,8 @@ void CarlaPlugin::setCtrlChannel(const int8_t channel, const bool sendOsc, const void CarlaPlugin::setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept { if (pData->engineBridged) { - CARLA_SAFE_ASSERT_RETURN(!sendGui,); + // NOTE: some LV2 plugins feedback messages to UI on purpose + CARLA_SAFE_ASSERT_RETURN(getType() == PLUGIN_LV2 || !sendGui,); } else if (pData->enginePlugin) { // nothing here } else { From 89416523d1fab64208f669be939ffe5bdb1076dc Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 22 Sep 2018 22:54:20 +0200 Subject: [PATCH 06/17] libjack: fix for clients registering too early --- source/libjack/libjack.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/source/libjack/libjack.cpp b/source/libjack/libjack.cpp index 714a87ee3..9816c4a5f 100644 --- a/source/libjack/libjack.cpp +++ b/source/libjack/libjack.cpp @@ -120,6 +120,7 @@ public: fMidiInBuffers(nullptr), fMidiOutBuffers(nullptr), fIsOffline(false), + fIsReady(false), fLastPingTime(-1), fSessionManager(0), fSetupHints(0), @@ -194,6 +195,9 @@ public: JackClientState* createClient(const char* const name) { + while (fNonRealtimeThread.isThreadRunning() && ! fIsReady) + carla_sleep(1); + return new JackClientState(fServer, name); } @@ -285,6 +289,7 @@ private: char fBaseNameNonRtServerControl[6+1]; bool fIsOffline; + volatile bool fIsReady; int64_t fLastPingTime; int fSessionManager; @@ -390,17 +395,20 @@ bool CarlaJackAppClient::initSharedMemmory() fAudioTmpBuf = new float[fServer.bufferSize]; carla_zeroFloats(fAudioTmpBuf, fServer.bufferSize); - // tell backend we're live - const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); - fLastPingTime = getCurrentTimeMilliseconds(); CARLA_SAFE_ASSERT(fLastPingTime > 0); - // ready! - fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady); - fShmNonRtServerControl.commitWrite(); - fShmNonRtServerControl.waitIfDataIsReachingLimit(); + { + // tell backend we're live + const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); + + // ready! + fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady); + fShmNonRtServerControl.commitWrite(); + fShmNonRtServerControl.waitIfDataIsReachingLimit(); + } + fIsReady = true; return true; } From a71a87cdc5444dc8615cd53d43968eee68cb9760 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 00:23:07 +0200 Subject: [PATCH 07/17] Interposer: intercept MapRaised and MapSubwindows --- source/interposer/interposer-jack-x11.cpp | 123 ++++++++++++++++++---- source/interposer/interposer-x11.cpp | 114 ++++++++++---------- 2 files changed, 161 insertions(+), 76 deletions(-) diff --git a/source/interposer/interposer-jack-x11.cpp b/source/interposer/interposer-jack-x11.cpp index 06e7c5049..e9932b985 100644 --- a/source/interposer/interposer-jack-x11.cpp +++ b/source/interposer/interposer-jack-x11.cpp @@ -1,6 +1,6 @@ /* * Carla Interposer for JACK Applications X11 control - * Copyright (C) 2014-2017 Filipe Coelho + * Copyright (C) 2014-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -24,7 +24,7 @@ struct ScopedLibOpen { void* handle; long long winId; - ScopedLibOpen() + ScopedLibOpen() noexcept : handle(dlopen("libjack.so.0", RTLD_NOW|RTLD_LOCAL)), winId(-1) { @@ -38,7 +38,7 @@ struct ScopedLibOpen { } } - ~ScopedLibOpen() + ~ScopedLibOpen() noexcept { if (handle != nullptr) { @@ -46,16 +46,21 @@ struct ScopedLibOpen { handle = nullptr; } } + + static const ScopedLibOpen& getInstance() noexcept + { + static const ScopedLibOpen slo; + return slo; + } }; -// --------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // Function typedefs -typedef int (*XMapWindowFunc)(Display*, Window); -typedef int (*XUnmapWindowFunc)(Display*, Window); +typedef int (*XWindowFunc)(Display*, Window); typedef int (*CarlaInterposedCallback)(int, void*); -// --------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // Current state static Display* gCurrentlyMappedDisplay = nullptr; @@ -63,15 +68,32 @@ static Window gCurrentlyMappedWindow = 0; static CarlaInterposedCallback gInterposedCallback = nullptr; static int gInterposedSessionManager = 0; static int gInterposedHints = 0; +static int gCurrentWindowType = 0; static bool gCurrentWindowMapped = false; static bool gCurrentWindowVisible = false; -// --------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // Calling the real functions static int real_XMapWindow(Display* display, Window window) { - static const XMapWindowFunc func = (XMapWindowFunc)::dlsym(RTLD_NEXT, "XMapWindow"); + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XMapWindow"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); + + return func(display, window); +} + +static int real_XMapRaised(Display* display, Window window) +{ + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XMapRaised"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); + + return func(display, window); +} + +static int real_XMapSubwindows(Display* display, Window window) +{ + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XMapSubwindows"); CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); return func(display, window); @@ -79,19 +101,18 @@ static int real_XMapWindow(Display* display, Window window) static int real_XUnmapWindow(Display* display, Window window) { - static const XUnmapWindowFunc func = (XUnmapWindowFunc)::dlsym(RTLD_NEXT, "XUnmapWindow"); + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XUnmapWindow"); CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); return func(display, window); } -// --------------------------------------------------------------------------------------------------------------------- -// Our custom functions +// -------------------------------------------------------------------------------------------------------------------- +// Custom carla window handling -CARLA_EXPORT -int XMapWindow(Display* display, Window window) +static int carlaWindowMap(Display* const display, const Window window, const int fallbackFnType) { - static const ScopedLibOpen slo; + const ScopedLibOpen& slo(ScopedLibOpen::getInstance()); for (;;) { @@ -103,11 +124,14 @@ int XMapWindow(Display* display, Window window) unsigned char* atomPtrs; unsigned long numItems, ignored; - const Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", True); + const Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); if (XGetWindowProperty(display, window, wmWindowType, 0, ~0L, False, AnyPropertyType, &atom, &atomFormat, &numItems, &ignored, &atomPtrs) != Success) + { + carla_debug("carlaWindowMap(%p, %lu, %i) - XGetWindowProperty failed", display, window, fallbackFnType); break; + } const Atom* const atomValues = (const Atom*)atomPtrs; bool isMainWindow = (numItems == 0); @@ -131,7 +155,7 @@ int XMapWindow(Display* display, Window window) std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_UTILITY" ) == 0) { isMainWindow = false; - break; + continue; } if (std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_NORMAL") == 0) @@ -185,6 +209,7 @@ int XMapWindow(Display* display, Window window) gCurrentlyMappedDisplay = display; gCurrentlyMappedWindow = window; gCurrentWindowMapped = true; + gCurrentWindowType = fallbackFnType; if (slo.winId > 0) XSetTransientForHint(display, window, static_cast(slo.winId)); @@ -200,16 +225,55 @@ int XMapWindow(Display* display, Window window) return 0; } - return real_XMapWindow(display, window); + carla_debug("carlaWindowMap(%p, %lu, %i) - not captured", display, window, fallbackFnType); + + switch (fallbackFnType) + { + case 1: + return real_XMapWindow(display, window); + case 2: + return real_XMapRaised(display, window); + case 3: + return real_XMapSubwindows(display, window); + default: + return 0; + } +} + +// -------------------------------------------------------------------------------------------------------------------- +// Our custom X11 functions + +CARLA_EXPORT +int XMapWindow(Display* display, Window window) +{ + carla_debug("XMapWindow(%p, %lu)", display, window); + return carlaWindowMap(display, window, 1); +} + +CARLA_EXPORT +int XMapRaised(Display* display, Window window) +{ + carla_debug("XMapRaised(%p, %lu)", display, window); + return carlaWindowMap(display, window, 2); +} + +CARLA_EXPORT +int XMapSubwindows(Display* display, Window window) +{ + carla_debug("XMapSubwindows(%p, %lu)", display, window); + return carlaWindowMap(display, window, 3); } CARLA_EXPORT int XUnmapWindow(Display* display, Window window) { + carla_debug("XUnmapWindow(%p, %lu)", display, window); + if (gCurrentlyMappedWindow == window) { gCurrentlyMappedDisplay = nullptr; gCurrentlyMappedWindow = 0; + gCurrentWindowType = 0; gCurrentWindowMapped = false; gCurrentWindowVisible = false; @@ -220,7 +284,8 @@ int XUnmapWindow(Display* display, Window window) return real_XUnmapWindow(display, window); } -// --------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- +// Full control helper CARLA_EXPORT int jack_carla_interposed_action(int action, int value, void* ptr) @@ -249,7 +314,18 @@ int jack_carla_interposed_action(int action, int value, void* ptr) return 0; gCurrentWindowMapped = true; - return real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + + switch (gCurrentWindowType) + { + case 1: + return real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + case 2: + return real_XMapRaised(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + case 3: + return real_XMapSubwindows(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + default: + return 0; + } } // hide gui else @@ -264,8 +340,9 @@ int jack_carla_interposed_action(int action, int value, void* ptr) break; case 4: // close everything - gCurrentWindowMapped = false; - gCurrentWindowVisible = false; + gCurrentWindowType = 0; + gCurrentWindowMapped = false; + gCurrentWindowVisible = false; gCurrentlyMappedDisplay = nullptr; gCurrentlyMappedWindow = 0; return 0; @@ -274,4 +351,4 @@ int jack_carla_interposed_action(int action, int value, void* ptr) return -1; } -// --------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- diff --git a/source/interposer/interposer-x11.cpp b/source/interposer/interposer-x11.cpp index ce3657fdb..327ec75e8 100644 --- a/source/interposer/interposer-x11.cpp +++ b/source/interposer/interposer-x11.cpp @@ -1,6 +1,6 @@ /* * Carla Interposer for X11 Window Mapping - * Copyright (C) 2014-2017 Filipe Coelho + * Copyright (C) 2014-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -20,77 +20,53 @@ #include #include -// ----------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // Function typedefs -typedef int (*XMapWindowFunc)(Display*, Window); -typedef int (*XUnmapWindowFunc)(Display*, Window); +typedef int (*XWindowFunc)(Display*, Window); -// ----------------------------------------------------------------------- -// Current mapped window - -static Window sCurrentlyMappedWindow = 0; - -// ----------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // Calling the real functions static int real_XMapWindow(Display* display, Window window) { - static const XMapWindowFunc func = (XMapWindowFunc)::dlsym(RTLD_NEXT, "XMapWindow"); + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XMapWindow"); CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); return func(display, window); } -static int real_XUnmapWindow(Display* display, Window window) +static int real_XMapRaised(Display* display, Window window) { - static const XUnmapWindowFunc func = (XUnmapWindowFunc)::dlsym(RTLD_NEXT, "XUnmapWindow"); + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XMapRaised"); CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); return func(display, window); } -// ----------------------------------------------------------------------- -// Our custom functions - -CARLA_EXPORT -int XMapWindow(Display* display, Window window) +static int real_XMapSubwindows(Display* display, Window window) { - for (;;) - { -#if 0 - if (sCurrentlyMappedWindow != 0) - break; + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XMapSubwindows"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); - Atom atom; - int atomFormat; - unsigned char* atomPtrs; - unsigned long numItems, ignored; + return func(display, window); +} - const Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", True); +static int real_XUnmapWindow(Display* display, Window window) +{ + static const XWindowFunc func = (XWindowFunc)::dlsym(RTLD_NEXT, "XUnmapWindow"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); - if (XGetWindowProperty(display, window, wmWindowType, 0, ~0L, False, AnyPropertyType, - &atom, &atomFormat, &numItems, &ignored, &atomPtrs) == Success) - { - const Atom* const atomValues = (const Atom*)atomPtrs; - - for (ulong i=0; i Date: Sun, 23 Sep 2018 00:30:33 +0200 Subject: [PATCH 08/17] Use basename on jack apps when initial name is empty --- source/frontend/carla_database.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/frontend/carla_database.py b/source/frontend/carla_database.py index ab7bbac21..fc7ae6a47 100755 --- a/source/frontend/carla_database.py +++ b/source/frontend/carla_database.py @@ -1757,8 +1757,9 @@ class JackApplicationW(QDialog): command = self.ui.le_command.text() smgr = self.SESSION_MGR_NONE flags = 0x0 + if not name: - name = command.split(" ",1)[0] + name = os.path.basename(command.split(" ",1)[0]) # TODO finalize flag definitions #uiSessionMgrIndex = self.ui.cb_session_mgr.currentIndex() From 8c71b6f4d7412894f5b1a977a86b916baac60b62 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 00:48:52 +0200 Subject: [PATCH 09/17] Don't try to find binary type of certain plugins when loading project --- source/backend/engine/CarlaEngine.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index de4ec2394..97a69a7ad 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -2233,7 +2233,22 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc) break; } - if (addPlugin(getBinaryTypeFromFile(stateSave.binary), ptype, stateSave.binary, + BinaryType btype; + + switch (ptype) + { + case PLUGIN_LADSPA: + case PLUGIN_DSSI: + case PLUGIN_LV2: + case PLUGIN_VST2: + btype = getBinaryTypeFromFile(stateSave.binary); + break; + default: + btype = BINARY_NATIVE; + break; + } + + if (addPlugin(btype, ptype, stateSave.binary, stateSave.name, stateSave.label, stateSave.uniqueId, extraStuff, stateSave.options)) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH From c1c97090a39febfdb86709284768c00a0bf34467 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 03:59:03 +0200 Subject: [PATCH 10/17] libjack: fixup for showing previous windows, just in case --- source/interposer/interposer-jack-x11.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/interposer/interposer-jack-x11.cpp b/source/interposer/interposer-jack-x11.cpp index e9932b985..0b64b1b85 100644 --- a/source/interposer/interposer-jack-x11.cpp +++ b/source/interposer/interposer-jack-x11.cpp @@ -203,7 +203,15 @@ static int carlaWindowMap(Display* const display, const Window window, const int break; carla_stdout("NOTICE: XMapWindow now showing previous window"); - real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + switch (fallbackFnType) + { + case 1: + real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + case 2: + real_XMapRaised(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + case 3: + real_XMapSubwindows(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); + } } gCurrentlyMappedDisplay = display; From 2315e0ba70674eeb78c1f1280c0a88c5361ff1d1 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 04:00:40 +0200 Subject: [PATCH 11/17] Fix for last commit --- source/interposer/interposer-jack-x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/interposer/interposer-jack-x11.cpp b/source/interposer/interposer-jack-x11.cpp index 0b64b1b85..00db5f1de 100644 --- a/source/interposer/interposer-jack-x11.cpp +++ b/source/interposer/interposer-jack-x11.cpp @@ -203,7 +203,7 @@ static int carlaWindowMap(Display* const display, const Window window, const int break; carla_stdout("NOTICE: XMapWindow now showing previous window"); - switch (fallbackFnType) + switch (gCurrentWindowType) { case 1: real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); From a34fd64f432119529671c9f5a7ffe255db2c1441 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 02:29:51 +0200 Subject: [PATCH 12/17] Always expand user home path when loading project from CLI --- source/frontend/carla_shared.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/frontend/carla_shared.py b/source/frontend/carla_shared.py index 337254b0c..d99096072 100644 --- a/source/frontend/carla_shared.py +++ b/source/frontend/carla_shared.py @@ -616,6 +616,7 @@ def getInitialProjectFile(app, skipExistCheck = False): continue if arg in ("-n", "--n", "-no-gui", "--no-gui", "-nogui", "--nogui"): continue + arg = os.path.expanduser(arg) if skipExistCheck or os.path.exists(arg): return arg From d9979d0c56a29d7801a0e22a332f0292e107c94d Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 02:30:10 +0200 Subject: [PATCH 13/17] libjack: Implement basic session management via SIGUSR1 signal --- resources/ui/carla_add_jack.ui | 15 ++++++--------- source/backend/plugin/CarlaPluginJack.cpp | 10 ++++++++++ source/frontend/carla_database.py | 14 ++++++++------ source/libjack/libjack.cpp | 14 ++++++++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/resources/ui/carla_add_jack.ui b/resources/ui/carla_add_jack.ui index 99669ca7b..921f7af38 100644 --- a/resources/ui/carla_add_jack.ui +++ b/resources/ui/carla_add_jack.ui @@ -6,7 +6,7 @@ 0 0 - 468 + 471 369 @@ -111,9 +111,6 @@ - - false - Session Manager: @@ -124,22 +121,22 @@ - - false + + 1 - None / Manual + None - LADISH (SIGUSR1) + Auto - Non Session Manager (OSC) + LADISH (SIGUSR1) diff --git a/source/backend/plugin/CarlaPluginJack.cpp b/source/backend/plugin/CarlaPluginJack.cpp index 0687e2ecc..f5465bed9 100644 --- a/source/backend/plugin/CarlaPluginJack.cpp +++ b/source/backend/plugin/CarlaPluginJack.cpp @@ -325,6 +325,16 @@ public: // ------------------------------------------------------------------- // Set data (state) + void prepareForSave() noexcept override + { + { + const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); + + fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPrepareForSave); + fShmNonRtClientControl.commitWrite(); + } + } + // ------------------------------------------------------------------- // Set data (internal stuff) diff --git a/source/frontend/carla_database.py b/source/frontend/carla_database.py index fc7ae6a47..a10291918 100755 --- a/source/frontend/carla_database.py +++ b/source/frontend/carla_database.py @@ -1718,9 +1718,9 @@ class PluginDatabaseW(QDialog): class JackApplicationW(QDialog): SESSION_MGR_NONE = 0 - SESSION_MGR_JACK = 1 - SESSION_MGR_LADISH = 2 - SESSION_MGR_LASH = 3 + SESSION_MGR_AUTO = 1 + SESSION_MGR_JACK = 2 + SESSION_MGR_LADISH = 3 SESSION_MGR_NSM = 4 FLAG_CONTROL_WINDOW = 0x01 @@ -1762,9 +1762,11 @@ class JackApplicationW(QDialog): name = os.path.basename(command.split(" ",1)[0]) # TODO finalize flag definitions - #uiSessionMgrIndex = self.ui.cb_session_mgr.currentIndex() - #if uiSessionMgrIndex == 1: - #smgr = self.SESSION_MGR_LADISH + uiSessionMgrIndex = self.ui.cb_session_mgr.currentIndex() + if uiSessionMgrIndex == 1: + smgr = self.SESSION_MGR_AUTO + elif uiSessionMgrIndex == 2: + smgr = self.SESSION_MGR_LADISH #elif uiSessionMgrIndex == 2: #smgr = self.SESSION_MGR_NSM diff --git a/source/libjack/libjack.cpp b/source/libjack/libjack.cpp index 9816c4a5f..272b3fcf9 100644 --- a/source/libjack/libjack.cpp +++ b/source/libjack/libjack.cpp @@ -940,6 +940,20 @@ bool CarlaJackAppClient::handleNonRtData() case kPluginBridgeNonRtClientPrepareForSave: { + if (fSessionManager == 1) // auto + { + struct sigaction sig; + carla_zeroStruct(sig); + + sigaction(SIGUSR1, nullptr, &sig); + + if (sig.sa_handler != nullptr) + fSessionManager = 3; + } + + if (fSessionManager == 3) + ::kill(::getpid(), SIGUSR1); + const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved); From 68c24a13aa396f4968d6f36c7eac32ef2d54ead0 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 03:38:03 +0200 Subject: [PATCH 14/17] libjack: catch window close when possible, and hide it instead --- source/backend/plugin/CarlaPluginJack.cpp | 4 --- source/interposer/interposer-jack-x11.cpp | 42 +++++++++++++++++++++++ source/libjack/libjack.cpp | 5 ++- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/source/backend/plugin/CarlaPluginJack.cpp b/source/backend/plugin/CarlaPluginJack.cpp index f5465bed9..b6f7c0310 100644 --- a/source/backend/plugin/CarlaPluginJack.cpp +++ b/source/backend/plugin/CarlaPluginJack.cpp @@ -1182,11 +1182,7 @@ public: break; case kPluginBridgeNonRtServerUiClosed: - carla_stdout("got kPluginBridgeNonRtServerUiClosed, bridge closed cleanly?"); pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); - //fBridgeThread.signalThreadShouldExit(); - //handleProcessStopped(); - //fBridgeThread.stopThread(5000); break; case kPluginBridgeNonRtServerError: { diff --git a/source/interposer/interposer-jack-x11.cpp b/source/interposer/interposer-jack-x11.cpp index 00db5f1de..1b2aa8a2e 100644 --- a/source/interposer/interposer-jack-x11.cpp +++ b/source/interposer/interposer-jack-x11.cpp @@ -58,6 +58,7 @@ struct ScopedLibOpen { // Function typedefs typedef int (*XWindowFunc)(Display*, Window); +typedef int (*XNextEventFunc)(Display*, XEvent*); typedef int (*CarlaInterposedCallback)(int, void*); // -------------------------------------------------------------------------------------------------------------------- @@ -107,6 +108,14 @@ static int real_XUnmapWindow(Display* display, Window window) return func(display, window); } +static int real_XNextEvent(Display* display, XEvent* event) +{ + static const XNextEventFunc func = (XNextEventFunc)::dlsym(RTLD_NEXT, "XNextEvent"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); + + return func(display, event); +} + // -------------------------------------------------------------------------------------------------------------------- // Custom carla window handling @@ -292,6 +301,39 @@ int XUnmapWindow(Display* display, Window window) return real_XUnmapWindow(display, window); } +CARLA_EXPORT +int XNextEvent(Display* display, XEvent* event) +{ + const int ret = real_XNextEvent(display, event); + + if (ret != 0) + return ret; + if (gCurrentlyMappedWindow == 0) + return ret; + if (event->type != ClientMessage) + return ret; + if (event->xclient.window != gCurrentlyMappedWindow) + return ret; + + char* const type = XGetAtomName(display, event->xclient.message_type); + CARLA_SAFE_ASSERT_RETURN(type != nullptr, 0); + + if (std::strcmp(type, "WM_PROTOCOLS") != 0) + return ret; + if (event->xclient.data.l[0] != XInternAtom(display, "WM_DELETE_WINDOW", False)) + return ret; + + gCurrentWindowVisible = false; + gCurrentWindowMapped = false; + + if (gInterposedCallback != nullptr) + gInterposedCallback(1, nullptr); + + event->type = 0; + carla_stdout("XNextEvent close event catched, hiding UI instead"); + return real_XUnmapWindow(display, gCurrentlyMappedWindow); +} + // -------------------------------------------------------------------------------------------------------------------- // Full control helper diff --git a/source/libjack/libjack.cpp b/source/libjack/libjack.cpp index 272b3fcf9..52bd64cbc 100644 --- a/source/libjack/libjack.cpp +++ b/source/libjack/libjack.cpp @@ -242,7 +242,7 @@ public: int handleInterposerCallback(const int cb_action, void* const ptr) { - carla_stdout("handleInterposerCallback(%o, %p)", cb_action, ptr); + carla_debug("handleInterposerCallback(%o, %p)", cb_action, ptr); switch (cb_action) { @@ -255,6 +255,9 @@ public: } return 0; + + // maybe unused + (void)ptr; } // ------------------------------------------------------------------- From 574839045dc864ab7db25f076cb5651bbc59029f Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 03:41:38 +0200 Subject: [PATCH 15/17] Fix a compiler warning --- source/interposer/interposer-jack-x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/interposer/interposer-jack-x11.cpp b/source/interposer/interposer-jack-x11.cpp index 1b2aa8a2e..0318fc60a 100644 --- a/source/interposer/interposer-jack-x11.cpp +++ b/source/interposer/interposer-jack-x11.cpp @@ -320,7 +320,7 @@ int XNextEvent(Display* display, XEvent* event) if (std::strcmp(type, "WM_PROTOCOLS") != 0) return ret; - if (event->xclient.data.l[0] != XInternAtom(display, "WM_DELETE_WINDOW", False)) + if ((Atom)event->xclient.data.l[0] != XInternAtom(display, "WM_DELETE_WINDOW", False)) return ret; gCurrentWindowVisible = false; From c0ee03621bc88c9b9bd574d9396cd2200dd9fa6f Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 23 Sep 2018 11:40:02 +0200 Subject: [PATCH 16/17] PluginEdit: always show keyboard if midi-ins > 0 --- source/frontend/carla_widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/frontend/carla_widgets.py b/source/frontend/carla_widgets.py index b2317cb5e..dba5c1357 100755 --- a/source/frontend/carla_widgets.py +++ b/source/frontend/carla_widgets.py @@ -770,7 +770,7 @@ class PluginEdit(QDialog): self.ui.sw_programs.setCurrentIndex(0 if self.fPluginInfo['type'] in (PLUGIN_VST2, PLUGIN_SFZ) else 1) # Show/hide keyboard - showKeyboard = (self.fPluginInfo['category'] == PLUGIN_CATEGORY_SYNTH or midiCountInfo['ins'] > 0 < midiCountInfo['outs']) + showKeyboard = (self.fPluginInfo['category'] == PLUGIN_CATEGORY_SYNTH or midiCountInfo['ins'] > 0) self.ui.scrollArea.setEnabled(showKeyboard) self.ui.scrollArea.setVisible(showKeyboard) From 92bc6d740cc12d310b4819d2411b3c3ca381c431 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 29 Sep 2018 21:04:12 +0200 Subject: [PATCH 17/17] Fix build with external plugins but no OpenGL --- source/modules/distrho/src/DistrhoPluginCarla.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/modules/distrho/src/DistrhoPluginCarla.cpp b/source/modules/distrho/src/DistrhoPluginCarla.cpp index a0d5bb769..0bbb3a504 100644 --- a/source/modules/distrho/src/DistrhoPluginCarla.cpp +++ b/source/modules/distrho/src/DistrhoPluginCarla.cpp @@ -26,13 +26,14 @@ START_NAMESPACE_DISTRHO +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static const writeMidiFunc writeMidiCallback = nullptr; +#endif + #if DISTRHO_PLUGIN_HAS_UI // ----------------------------------------------------------------------- // Carla UI -#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT -static const writeMidiFunc writeMidiCallback = nullptr; -#endif #if ! DISTRHO_PLUGIN_WANT_STATE static const setStateFunc setStateCallback = nullptr; #endif