| @@ -251,12 +251,6 @@ CARLA_EXPORT const char* carla_get_library_folder(); | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // 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); | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| @@ -54,8 +54,7 @@ class CarlaEngineNativeUI : public CarlaExternalUI | |||
| { | |||
| public: | |||
| CarlaEngineNativeUI(CarlaEngine* const engine) | |||
| : fEngine(engine), | |||
| fRemoteWinId(0) | |||
| : fEngine(engine) | |||
| { | |||
| carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine); | |||
| } | |||
| @@ -65,16 +64,6 @@ public: | |||
| carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()"); | |||
| } | |||
| bool isReady() const noexcept | |||
| { | |||
| return fRemoteWinId != 0; | |||
| } | |||
| intptr_t getRemoteWinId() const noexcept | |||
| { | |||
| return fRemoteWinId; | |||
| } | |||
| protected: | |||
| bool msgReceived(const char* const msg) noexcept override | |||
| { | |||
| @@ -550,14 +539,6 @@ protected: | |||
| if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
| 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 | |||
| { | |||
| carla_stderr("CarlaEngineNativeUI::msgReceived : %s", msg); | |||
| @@ -577,7 +558,6 @@ protected: | |||
| private: | |||
| CarlaEngine* const fEngine; | |||
| intptr_t fRemoteWinId; | |||
| void _updateParamValues(CarlaPlugin* const plugin, const uint32_t pluginId) const noexcept | |||
| { | |||
| @@ -603,8 +583,7 @@ public: | |||
| fIsActive(false), | |||
| fIsRunning(false), | |||
| fUiServer(this), | |||
| fOptionsForced(false), | |||
| fWaitForReadyMsg(false) | |||
| fOptionsForced(false) | |||
| { | |||
| carla_debug("CarlaEngineNative::CarlaEngineNative()"); | |||
| @@ -1674,19 +1653,6 @@ protected: | |||
| if (kIsPatchbay) | |||
| 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 | |||
| { | |||
| @@ -1970,11 +1936,6 @@ public: | |||
| switch(opcode) | |||
| { | |||
| 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; | |||
| case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED: | |||
| CARLA_SAFE_ASSERT_RETURN(value > 0, 0); | |||
| @@ -2028,7 +1989,6 @@ private: | |||
| CarlaEngineNativeUI fUiServer; | |||
| bool fOptionsForced; | |||
| bool fWaitForReadyMsg; | |||
| CarlaPlugin* _getFirstPlugin() const noexcept | |||
| { | |||
| @@ -23,82 +23,10 @@ | |||
| # import <Cocoa/Cocoa.h> | |||
| #endif | |||
| #ifdef HAVE_X11 | |||
| # include <X11/Xlib.h> | |||
| #endif | |||
| 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) | |||
| { | |||
| 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.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.restype = c_int | |||
| @@ -339,16 +330,6 @@ class CarlaUtils(object): | |||
| def pipe_client_destroy(self, 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): | |||
| return self.lib.carla_cocoa_get_window(winId) | |||
| @@ -405,200 +405,6 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| else: | |||
| 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 | |||
| @@ -627,17 +433,7 @@ if __name__ == '__main__': | |||
| # ------------------------------------------------------------- | |||
| # 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 | |||
| @@ -259,50 +259,8 @@ public: | |||
| case effEditOpen: | |||
| 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); | |||
| fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | |||
| #endif | |||
| ret = 1; | |||
| } | |||
| break; | |||
| @@ -310,12 +268,8 @@ public: | |||
| case effEditClose: | |||
| if (fDescriptor->ui_show != nullptr) | |||
| { | |||
| #if 0 | |||
| fDescriptor->ui_show(fHandle, false); | |||
| #else | |||
| destoryUILauncher(fUiLauncher); | |||
| fUiLauncher = nullptr; | |||
| #endif | |||
| ret = 1; | |||
| } | |||
| break; | |||