| @@ -251,12 +251,6 @@ CARLA_EXPORT const char* carla_get_library_folder(); | |||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| // TESTING | // TESTING | ||||
| CARLA_EXPORT void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2); | |||||
| CARLA_EXPORT void carla_x11_move_window(uintptr_t winId, int x, int y); | |||||
| CARLA_EXPORT int* carla_x11_get_window_pos(uintptr_t winId); | |||||
| CARLA_EXPORT int carla_cocoa_get_window(void* nsViewPtr); | CARLA_EXPORT int carla_cocoa_get_window(void* nsViewPtr); | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -54,8 +54,7 @@ class CarlaEngineNativeUI : public CarlaExternalUI | |||||
| { | { | ||||
| public: | public: | ||||
| CarlaEngineNativeUI(CarlaEngine* const engine) | CarlaEngineNativeUI(CarlaEngine* const engine) | ||||
| : fEngine(engine), | |||||
| fRemoteWinId(0) | |||||
| : fEngine(engine) | |||||
| { | { | ||||
| carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine); | carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine); | ||||
| } | } | ||||
| @@ -65,16 +64,6 @@ public: | |||||
| carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()"); | carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()"); | ||||
| } | } | ||||
| bool isReady() const noexcept | |||||
| { | |||||
| return fRemoteWinId != 0; | |||||
| } | |||||
| intptr_t getRemoteWinId() const noexcept | |||||
| { | |||||
| return fRemoteWinId; | |||||
| } | |||||
| protected: | protected: | ||||
| bool msgReceived(const char* const msg) noexcept override | bool msgReceived(const char* const msg) noexcept override | ||||
| { | { | ||||
| @@ -550,14 +539,6 @@ protected: | |||||
| if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | ||||
| plugin->showCustomUI(yesNo); | plugin->showCustomUI(yesNo); | ||||
| } | } | ||||
| else if (std::strcmp(msg, "ready") == 0) | |||||
| { | |||||
| uint64_t winId; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(winId), true); | |||||
| fRemoteWinId = static_cast<intptr_t>(winId); | |||||
| } | |||||
| else | else | ||||
| { | { | ||||
| carla_stderr("CarlaEngineNativeUI::msgReceived : %s", msg); | carla_stderr("CarlaEngineNativeUI::msgReceived : %s", msg); | ||||
| @@ -577,7 +558,6 @@ protected: | |||||
| private: | private: | ||||
| CarlaEngine* const fEngine; | CarlaEngine* const fEngine; | ||||
| intptr_t fRemoteWinId; | |||||
| void _updateParamValues(CarlaPlugin* const plugin, const uint32_t pluginId) const noexcept | void _updateParamValues(CarlaPlugin* const plugin, const uint32_t pluginId) const noexcept | ||||
| { | { | ||||
| @@ -603,8 +583,7 @@ public: | |||||
| fIsActive(false), | fIsActive(false), | ||||
| fIsRunning(false), | fIsRunning(false), | ||||
| fUiServer(this), | fUiServer(this), | ||||
| fOptionsForced(false), | |||||
| fWaitForReadyMsg(false) | |||||
| fOptionsForced(false) | |||||
| { | { | ||||
| carla_debug("CarlaEngineNative::CarlaEngineNative()"); | carla_debug("CarlaEngineNative::CarlaEngineNative()"); | ||||
| @@ -1674,19 +1653,6 @@ protected: | |||||
| if (kIsPatchbay) | if (kIsPatchbay) | ||||
| patchbayRefresh(false); | patchbayRefresh(false); | ||||
| if (fWaitForReadyMsg) | |||||
| { | |||||
| carla_stdout("Using Carla plugin embedded, waiting for it to be ready..."); | |||||
| for (; fUiServer.isPipeRunning() && ! fUiServer.isReady();) | |||||
| { | |||||
| carla_msleep(25); | |||||
| fUiServer.idlePipe(); | |||||
| } | |||||
| carla_stdout("Done!"); | |||||
| } | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1970,11 +1936,6 @@ public: | |||||
| switch(opcode) | switch(opcode) | ||||
| { | { | ||||
| case NATIVE_PLUGIN_OPCODE_NULL: | case NATIVE_PLUGIN_OPCODE_NULL: | ||||
| if (static_cast<uint32_t>(index) == 0xDEADF00D && static_cast<uintptr_t>(value) == 0xC0C0B00B) | |||||
| { | |||||
| handlePtr->fWaitForReadyMsg = true; | |||||
| return handlePtr->fUiServer.getRemoteWinId(); | |||||
| } | |||||
| return 0; | return 0; | ||||
| case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED: | case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED: | ||||
| CARLA_SAFE_ASSERT_RETURN(value > 0, 0); | CARLA_SAFE_ASSERT_RETURN(value > 0, 0); | ||||
| @@ -2028,7 +1989,6 @@ private: | |||||
| CarlaEngineNativeUI fUiServer; | CarlaEngineNativeUI fUiServer; | ||||
| bool fOptionsForced; | bool fOptionsForced; | ||||
| bool fWaitForReadyMsg; | |||||
| CarlaPlugin* _getFirstPlugin() const noexcept | CarlaPlugin* _getFirstPlugin() const noexcept | ||||
| { | { | ||||
| @@ -23,82 +23,10 @@ | |||||
| # import <Cocoa/Cocoa.h> | # import <Cocoa/Cocoa.h> | ||||
| #endif | #endif | ||||
| #ifdef HAVE_X11 | |||||
| # include <X11/Xlib.h> | |||||
| #endif | |||||
| namespace CB = CarlaBackend; | namespace CB = CarlaBackend; | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(winId1 != 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(winId2 != 0,); | |||||
| #ifdef HAVE_X11 | |||||
| if (::Display* const disp = XOpenDisplay(nullptr)) | |||||
| { | |||||
| XReparentWindow(disp, winId1, winId2, 0, 0); | |||||
| XMapWindow(disp, winId1); | |||||
| XCloseDisplay(disp); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| void carla_x11_move_window(uintptr_t winId, int x, int y) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(winId != 0,); | |||||
| #ifdef HAVE_X11 | |||||
| if (::Display* const disp = XOpenDisplay(nullptr)) | |||||
| { | |||||
| XMoveWindow(disp, winId, x, y); | |||||
| XCloseDisplay(disp); | |||||
| } | |||||
| #else | |||||
| // unused | |||||
| return; (void)x; (void)y; | |||||
| #endif | |||||
| } | |||||
| int* carla_x11_get_window_pos(uintptr_t winId) | |||||
| { | |||||
| static int pos[4]; | |||||
| if (winId == 0) | |||||
| { | |||||
| pos[0] = 0; | |||||
| pos[1] = 0; | |||||
| pos[2] = 0; | |||||
| pos[3] = 0; | |||||
| } | |||||
| #ifdef HAVE_X11 | |||||
| else if (::Display* const disp = XOpenDisplay(nullptr)) | |||||
| { | |||||
| int x, y; | |||||
| Window child; | |||||
| XWindowAttributes xwa; | |||||
| XTranslateCoordinates(disp, winId, XRootWindow(disp, 0), 0, 0, &x, &y, &child); | |||||
| XGetWindowAttributes(disp, winId, &xwa); | |||||
| XCloseDisplay(disp); | |||||
| pos[0] = x - xwa.x; | |||||
| pos[1] = y - xwa.y; | |||||
| pos[2] = xwa.x; | |||||
| pos[3] = xwa.y; | |||||
| } | |||||
| #endif | |||||
| else | |||||
| { | |||||
| pos[0] = 0; | |||||
| pos[1] = 0; | |||||
| pos[2] = 0; | |||||
| pos[3] = 0; | |||||
| } | |||||
| return pos; | |||||
| } | |||||
| int carla_cocoa_get_window(void* nsViewPtr) | int carla_cocoa_get_window(void* nsViewPtr) | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(nsViewPtr != nullptr, 0); | CARLA_SAFE_ASSERT_RETURN(nsViewPtr != nullptr, 0); | ||||
| @@ -221,15 +221,6 @@ class CarlaUtils(object): | |||||
| self.lib.carla_pipe_client_destroy.argtypes = [CarlaPipeClientHandle] | self.lib.carla_pipe_client_destroy.argtypes = [CarlaPipeClientHandle] | ||||
| self.lib.carla_pipe_client_destroy.restype = None | self.lib.carla_pipe_client_destroy.restype = None | ||||
| self.lib.carla_x11_reparent_window.argtypes = [c_uintptr, c_uintptr] | |||||
| self.lib.carla_x11_reparent_window.restype = None | |||||
| self.lib.carla_x11_move_window.argtypes = [c_uintptr, c_int, c_int] | |||||
| self.lib.carla_x11_move_window.restype = None | |||||
| self.lib.carla_x11_get_window_pos.argtypes = [c_uintptr] | |||||
| self.lib.carla_x11_get_window_pos.restype = POINTER(c_int) | |||||
| self.lib.carla_cocoa_get_window.argtypes = [c_uintptr] | self.lib.carla_cocoa_get_window.argtypes = [c_uintptr] | ||||
| self.lib.carla_cocoa_get_window.restype = c_int | self.lib.carla_cocoa_get_window.restype = c_int | ||||
| @@ -339,16 +330,6 @@ class CarlaUtils(object): | |||||
| def pipe_client_destroy(self, handle): | def pipe_client_destroy(self, handle): | ||||
| self.lib.carla_pipe_client_destroy(handle) | self.lib.carla_pipe_client_destroy(handle) | ||||
| def x11_reparent_window(self, winId1, winId2): | |||||
| self.lib.carla_x11_reparent_window(winId1, winId2) | |||||
| def x11_move_window(self, winId, x, y): | |||||
| self.lib.carla_x11_move_window(winId, x, y) | |||||
| def x11_get_window_pos(self, winId): | |||||
| data = self.lib.carla_x11_get_window_pos(winId) | |||||
| return tuple(int(data[i]) for i in range(4)) | |||||
| def cocoa_get_window(self, winId): | def cocoa_get_window(self, winId): | ||||
| return self.lib.carla_cocoa_get_window(winId) | return self.lib.carla_cocoa_get_window(winId) | ||||
| @@ -405,200 +405,6 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| else: | else: | ||||
| print("unknown message: \"" + msg + "\"") | print("unknown message: \"" + msg + "\"") | ||||
| # ------------------------------------------------------------------------------------------------------------ | |||||
| # Embed Widget | |||||
| if config_UseQt5 and LINUX: | |||||
| from PyQt5.QtGui import QMouseEvent | |||||
| class QEmbedWidget(QWidget): | |||||
| def __init__(self, winId): | |||||
| QWidget.__init__(self) | |||||
| self.setAttribute(Qt.WA_LayoutUsesWidgetRect) | |||||
| self.move(0, 0) | |||||
| self.fPos = (0, 0) | |||||
| self.fWinId = 0 | |||||
| def getWidget(self): | |||||
| return self | |||||
| def finalSetup(self, gui, winId): | |||||
| self.fWinId = int(self.winId()) | |||||
| gui.ui.centralwidget.installEventFilter(self) | |||||
| gui.ui.menubar.installEventFilter(self) | |||||
| gCarla.utils.x11_reparent_window(self.fWinId, winId) | |||||
| self.show() | |||||
| def fixPosition(self): | |||||
| pos = gCarla.utils.x11_get_window_pos(self.fWinId) | |||||
| if self.fPos == pos: | |||||
| return | |||||
| self.fPos = pos | |||||
| self.move(pos[0], pos[1]) | |||||
| gCarla.utils.x11_move_window(self.fWinId, pos[2], pos[3]) | |||||
| def eventFilter(self, obj, ev): | |||||
| if isinstance(ev, QMouseEvent): | |||||
| self.fixPosition() | |||||
| return False | |||||
| def enterEvent(self, ev): | |||||
| self.fixPosition() | |||||
| QWidget.enterEvent(self, ev) | |||||
| elif config_UseQt5 and not LINUX: | |||||
| from PyQt5.QtGui import QWindow | |||||
| class QEmbedWidget(object): | |||||
| def __init__(self, winId): | |||||
| self.fWindow = QWindow.fromWinId(winId) | |||||
| self.fWidget = QWidget.createWindowContainer(self.fWindow) | |||||
| self.fWidget.setAttribute(Qt.WA_LayoutUsesWidgetRect) | |||||
| # TODO: show/hide/close events | |||||
| def getWidget(self): | |||||
| return self.fWidget | |||||
| def finalSetup(self, gui, winId): | |||||
| self.fWidget.show() | |||||
| elif not config_UseQt5 and LINUX: | |||||
| from PyQt4.QtGui import QX11EmbedWidget | |||||
| class QEmbedWidget(QX11EmbedWidget): | |||||
| def __init__(self, winId): | |||||
| QX11EmbedWidget.__init__(self) | |||||
| def getWidget(self): | |||||
| return self | |||||
| def finalSetup(self, gui, winId): | |||||
| self.embedInto(winId) | |||||
| self.show() | |||||
| else: | |||||
| class QEmbedWidget(object): | |||||
| def __init__(self, winId): | |||||
| print("Cannot use embed UI with this configuration") | |||||
| raise Exception | |||||
| # ------------------------------------------------------------------------------------------------------------ | |||||
| # Embed plugin UI | |||||
| class CarlaEmbedW(QEmbedWidget): | |||||
| def __init__(self, host, winId, isPatchbay): | |||||
| QEmbedWidget.__init__(self, winId) | |||||
| self.host = host | |||||
| self.fWinId = winId | |||||
| self.fWidget = self.getWidget() | |||||
| self.fWidget.setFixedSize(740, 512) | |||||
| self.fLayout = QVBoxLayout(self.fWidget) | |||||
| self.fLayout.setContentsMargins(0, 0, 0, 0) | |||||
| self.fLayout.setSpacing(0) | |||||
| self.fWidget.setLayout(self.fLayout) | |||||
| self.gui = CarlaMiniW(host, isPatchbay, self.fWidget) | |||||
| self.gui.hide() | |||||
| self.gui.ui.act_file_quit.setEnabled(False) | |||||
| self.gui.ui.act_file_quit.setVisible(False) | |||||
| self.fShortcutActions = [] | |||||
| self.addShortcutActions(self.gui.ui.menu_File.actions()) | |||||
| self.addShortcutActions(self.gui.ui.menu_Plugin.actions()) | |||||
| self.addShortcutActions(self.gui.ui.menu_PluginMacros.actions()) | |||||
| self.addShortcutActions(self.gui.ui.menu_Settings.actions()) | |||||
| self.addShortcutActions(self.gui.ui.menu_Help.actions()) | |||||
| if self.host.processMode == ENGINE_PROCESS_MODE_PATCHBAY: | |||||
| self.addShortcutActions(self.gui.ui.menu_Canvas.actions()) | |||||
| self.addShortcutActions(self.gui.ui.menu_Canvas_Zoom.actions()) | |||||
| self.addWidget(self.gui.ui.menubar) | |||||
| self.addLine() | |||||
| self.addWidget(self.gui.ui.toolBar) | |||||
| if self.host.processMode == ENGINE_PROCESS_MODE_PATCHBAY: | |||||
| self.addLine() | |||||
| self.addWidget(self.gui.centralWidget()) | |||||
| self.finalSetup(self.gui, winId) | |||||
| self.gui.send(["ready", int(self.fWidget.winId())]) | |||||
| def addShortcutActions(self, actions): | |||||
| for action in actions: | |||||
| if not action.shortcut().isEmpty(): | |||||
| self.fShortcutActions.append(action) | |||||
| def addWidget(self, widget): | |||||
| widget.setParent(self.fWidget) | |||||
| self.fLayout.addWidget(widget) | |||||
| def addLine(self): | |||||
| line = QFrame(self.fWidget) | |||||
| line.setFrameShadow(QFrame.Sunken) | |||||
| line.setFrameShape(QFrame.HLine) | |||||
| line.setLineWidth(0) | |||||
| line.setMidLineWidth(1) | |||||
| self.fLayout.addWidget(line) | |||||
| def keyPressEvent(self, event): | |||||
| modifiers = event.modifiers() | |||||
| modifiersStr = "" | |||||
| if modifiers & Qt.ShiftModifier: | |||||
| modifiersStr += "Shift+" | |||||
| if modifiers & Qt.ControlModifier: | |||||
| modifiersStr += "Ctrl+" | |||||
| if modifiers & Qt.AltModifier: | |||||
| modifiersStr += "Alt+" | |||||
| if modifiers & Qt.MetaModifier: | |||||
| modifiersStr += "Meta+" | |||||
| keyStr = QKeySequence(event.key()).toString() | |||||
| keySeq = QKeySequence(modifiersStr + keyStr) | |||||
| for action in self.fShortcutActions: | |||||
| if not action.isEnabled(): | |||||
| continue | |||||
| if keySeq.matches(action.shortcut()) != QKeySequence.ExactMatch: | |||||
| continue | |||||
| event.accept() | |||||
| action.trigger() | |||||
| return | |||||
| QEmbedWidget.keyPressEvent(self, event) | |||||
| def showEvent(self, event): | |||||
| QEmbedWidget.showEvent(self, event) | |||||
| # set our gui as parent for all plugins UIs | |||||
| if self.host.manageUIs: | |||||
| winIdStr = "%x" % self.fWinId | |||||
| self.host.set_engine_option(ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr) | |||||
| def hideEvent(self, event): | |||||
| # disable parent | |||||
| self.host.set_engine_option(ENGINE_OPTION_FRONTEND_WIN_ID, 0, "0") | |||||
| QEmbedWidget.hideEvent(self, event) | |||||
| def closeEvent(self, event): | |||||
| self.gui.close() | |||||
| self.gui.closeExternalUI() | |||||
| QEmbedWidget.closeEvent(self, event) | |||||
| # there might be other qt windows open which will block carla-plugin from quitting | |||||
| app.quit() | |||||
| def setLoadRDFsNeeded(self): | |||||
| self.gui.setLoadRDFsNeeded() | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Main | # Main | ||||
| @@ -627,17 +433,7 @@ if __name__ == '__main__': | |||||
| # ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
| # Create GUI | # Create GUI | ||||
| try: | |||||
| winId = int(os.getenv("CARLA_PLUGIN_EMBED_WINID")) | |||||
| except: | |||||
| winId = 0 | |||||
| gCarla.utils.setenv("CARLA_PLUGIN_EMBED_WINID", "0") | |||||
| if LINUX and winId != 0: | |||||
| gui = CarlaEmbedW(host, winId, isPatchbay) | |||||
| else: | |||||
| gui = CarlaMiniW(host, isPatchbay) | |||||
| gui = CarlaMiniW(host, isPatchbay) | |||||
| # ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
| # App-Loop | # App-Loop | ||||
| @@ -259,50 +259,8 @@ public: | |||||
| case effEditOpen: | case effEditOpen: | ||||
| if (fDescriptor->ui_show != nullptr) | if (fDescriptor->ui_show != nullptr) | ||||
| { | { | ||||
| #if 0 | |||||
| char strBuf[0xff+1]; | |||||
| strBuf[0xff] = '\0'; | |||||
| std::snprintf(strBuf, 0xff, P_INTPTR, (intptr_t)ptr); | |||||
| // set CARLA_PLUGIN_EMBED_WINID for external process | |||||
| carla_setenv("CARLA_PLUGIN_EMBED_WINID", strBuf); | |||||
| // check if vst host is an old version of tracktion | |||||
| bool oldTracktionWorkaround = false; | |||||
| // tracktion doesn't export its version properly, use env var instead | |||||
| if (std::getenv("CARLA_TRACKTION_WORKAROUND") != nullptr) | |||||
| { | |||||
| carla_zeroChars(strBuf, 0xff+1); | |||||
| hostCallback(audioMasterGetProductString, 0, 0, strBuf, 0.0f); | |||||
| oldTracktionWorkaround = (std::strcmp(strBuf, "Tracktion") == 0); | |||||
| // if vst host is old tracktion, delay UI appearance for a bit (part 1) | |||||
| if (oldTracktionWorkaround) | |||||
| fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_NULL, (int32_t)0xDEADF00D, 0xC0C0B00B, nullptr, 0.0f); | |||||
| } | |||||
| // show UI now | |||||
| fDescriptor->ui_show(fHandle, true); | |||||
| // reset CARLA_PLUGIN_EMBED_WINID just in case | |||||
| carla_setenv("CARLA_PLUGIN_EMBED_WINID", "0"); | |||||
| // if vst host is old tracktion, delay UI appearance for a bit (part 2) | |||||
| if (oldTracktionWorkaround) | |||||
| { | |||||
| carla_stdout("Old Tracktion detected, delaying UI appearance so it works properly..."); | |||||
| for (int x=10; --x>=0;) | |||||
| { | |||||
| hostCallback(audioMasterIdle); | |||||
| carla_msleep(25); | |||||
| } | |||||
| } | |||||
| #else | |||||
| destoryUILauncher(fUiLauncher); | destoryUILauncher(fUiLauncher); | ||||
| fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | ||||
| #endif | |||||
| ret = 1; | ret = 1; | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -310,12 +268,8 @@ public: | |||||
| case effEditClose: | case effEditClose: | ||||
| if (fDescriptor->ui_show != nullptr) | if (fDescriptor->ui_show != nullptr) | ||||
| { | { | ||||
| #if 0 | |||||
| fDescriptor->ui_show(fHandle, false); | |||||
| #else | |||||
| destoryUILauncher(fUiLauncher); | destoryUILauncher(fUiLauncher); | ||||
| fUiLauncher = nullptr; | fUiLauncher = nullptr; | ||||
| #endif | |||||
| ret = 1; | ret = 1; | ||||
| } | } | ||||
| break; | break; | ||||