From 28e8f9ed67a3656a8a84fd54e7ee34b94aee861b Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 13 Mar 2019 02:33:23 +0100 Subject: [PATCH] Go back to have real embed carla UI as VST Leave the middleware window for non-linux OSes Signed-off-by: falkTX --- source/frontend/carla_host.py | 7 +- source/native-plugins/resources/carla-plugin | 169 ++++++++++++++++++- source/plugin/carla-vst-export.cpp | 11 +- source/plugin/carla-vst.cpp | 37 +++- source/plugin/carla-vst.hpp | 10 +- 5 files changed, 217 insertions(+), 17 deletions(-) diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py index 72559d2bf..73e3e7af0 100644 --- a/source/frontend/carla_host.py +++ b/source/frontend/carla_host.py @@ -208,16 +208,19 @@ class HostWindow(QMainWindow): self.ui.menu_Engine.setEnabled(False) self.ui.menu_Engine.setVisible(False) self.ui.menu_Engine.menuAction().setVisible(False) + self.ui.tabWidget.removeTab(2) if self.host.isControl: self.ui.act_file_new.setVisible(False) self.ui.act_file_open.setVisible(False) self.ui.act_file_save_as.setVisible(False) self.ui.tabUtils.removeTab(0) - self.ui.tabWidget.removeTab(2) else: self.ui.act_file_save_as.setText(self.tr("Export as...")) + if not withCanvas: + self.ui.tabWidget.tabBar().hide() + else: self.ui.act_engine_start.setEnabled(True) @@ -2333,7 +2336,7 @@ class HostWindow(QMainWindow): self.ui.pb_dsp_load.setValue(int(load)) def getAndRefreshRuntimeInfo(self): - if not self.isVisible(): + if not self.ui.pb_dsp_load.isVisible(): return if not self.host.is_engine_running(): return diff --git a/source/native-plugins/resources/carla-plugin b/source/native-plugins/resources/carla-plugin index 64185ae5d..18d348057 100755 --- a/source/native-plugins/resources/carla-plugin +++ b/source/native-plugins/resources/carla-plugin @@ -19,7 +19,7 @@ # ------------------------------------------------------------------------------------------------------------ # Imports (Global) -from PyQt5.QtGui import QKeySequence +from PyQt5.QtGui import QKeySequence, QMouseEvent from PyQt5.QtWidgets import QHBoxLayout # ------------------------------------------------------------------------------------------------------------ @@ -81,12 +81,12 @@ class CarlaMiniW(ExternalUI, HostWindow): def __init__(self, host, isPatchbay, parent=None): ExternalUI.__init__(self) HostWindow.__init__(self, host, isPatchbay, parent) - self.host = host if False: # kdevelop likes this :) host = PluginHost() - self.host = host + + self.host = host host.setExternalUI(self) @@ -387,6 +387,157 @@ class CarlaMiniW(ExternalUI, HostWindow): else: print("unknown message: \"" + msg + "\"") +# ------------------------------------------------------------------------------------------------------------ +# Embed Widget + +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 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) + +# ------------------------------------------------------------------------------------------------------------ +# Embed plugin UI + +class CarlaEmbedW(QEmbedWidget): + def __init__(self, host, winId, isPatchbay): + QEmbedWidget.__init__(self, winId) + + if False: + host = CarlaHostPlugin() + + self.host = host + self.fWinId = winId + self.setFixedSize(1024, 712) + + self.fLayout = QVBoxLayout(self) + self.fLayout.setContentsMargins(0, 0, 0, 0) + self.fLayout.setSpacing(0) + self.setLayout(self.fLayout) + + self.gui = CarlaMiniW(host, isPatchbay, self) + 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) + + def addShortcutActions(self, actions): + for action in actions: + if not action.shortcut().isEmpty(): + self.fShortcutActions.append(action) + + def addWidget(self, widget): + widget.setParent(self) + self.fLayout.addWidget(widget) + + def addLine(self): + line = QFrame(self) + 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 @@ -415,7 +566,17 @@ if __name__ == '__main__': # ------------------------------------------------------------- # Create GUI - gui = CarlaMiniW(host, isPatchbay) + 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) # ------------------------------------------------------------- # App-Loop diff --git a/source/plugin/carla-vst-export.cpp b/source/plugin/carla-vst-export.cpp index 31e9f8fd4..94752ea90 100644 --- a/source/plugin/carla-vst-export.cpp +++ b/source/plugin/carla-vst-export.cpp @@ -1,6 +1,6 @@ /* * Carla Native Plugins - * Copyright (C) 2013-2018 Filipe Coelho + * Copyright (C) 2013-2019 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 @@ -16,10 +16,13 @@ */ #include "carla-vst.hpp" -#include "ui_launcher.cpp" -#include "ui_launcher_res.cpp" -#include "CarlaDefines.h" +#ifndef CARLA_OS_LINUX +# include "ui_launcher.cpp" +# include "ui_launcher_res.cpp" +#endif + +#include #ifdef __WINE__ __cdecl static intptr_t cvst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) diff --git a/source/plugin/carla-vst.cpp b/source/plugin/carla-vst.cpp index 829a53696..0c21b3ce4 100644 --- a/source/plugin/carla-vst.cpp +++ b/source/plugin/carla-vst.cpp @@ -84,7 +84,9 @@ public: fMidiEventCount(0), fTimeInfo(), fVstRect(), +#ifndef CARLA_OS_LINUX fUiLauncher(nullptr), +#endif fHostType(kHostTypeNull), fMidiOutEvents(), #ifdef USING_JUCE @@ -133,8 +135,13 @@ public: fVstRect.top = 0; fVstRect.left = 0; +#ifdef CARLA_OS_LINUX + fVstRect.bottom = 712; + fVstRect.right = 1024; +#else fVstRect.bottom = ui_launcher_res::carla_uiHeight; fVstRect.right = ui_launcher_res::carla_uiWidth; +#endif init(); } @@ -288,8 +295,23 @@ public: case effEditOpen: if (fDescriptor->ui_show != nullptr) { +#ifdef CARLA_OS_LINUX + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, P_INTPTR, (intptr_t)ptr); + strBuf[0xff] = '\0'; + + // set CARLA_PLUGIN_EMBED_WINID for external process + carla_setenv("CARLA_PLUGIN_EMBED_WINID", strBuf); + + // show UI now + fDescriptor->ui_show(fHandle, true); + + // reset CARLA_PLUGIN_EMBED_WINID just in case + carla_setenv("CARLA_PLUGIN_EMBED_WINID", "0"); +#else destoryUILauncher(fUiLauncher); fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); +#endif ret = 1; } break; @@ -297,20 +319,23 @@ public: case effEditClose: if (fDescriptor->ui_show != nullptr) { +#ifdef CARLA_OS_LINUX + fDescriptor->ui_show(fHandle, false); +#else destoryUILauncher(fUiLauncher); fUiLauncher = nullptr; +#endif ret = 1; } break; case effEditIdle: +#ifndef CARLA_OS_LINUX if (fUiLauncher != nullptr) - { idleUILauncher(fUiLauncher); - - if (fDescriptor->ui_idle != nullptr) - fDescriptor->ui_idle(fHandle); - } +#endif + if (fDescriptor->ui_idle != nullptr) + fDescriptor->ui_idle(fHandle); break; case effGetChunk: @@ -604,8 +629,10 @@ private: NativeTimeInfo fTimeInfo; ERect fVstRect; +#ifndef CARLA_OS_LINUX // UI button CarlaUILauncher* fUiLauncher; +#endif // Host data enum HostType { diff --git a/source/plugin/carla-vst.hpp b/source/plugin/carla-vst.hpp index f3d362ca9..08c6fa35a 100644 --- a/source/plugin/carla-vst.hpp +++ b/source/plugin/carla-vst.hpp @@ -1,6 +1,6 @@ /* * Carla Native Plugins - * Copyright (C) 2013-2018 Filipe Coelho + * Copyright (C) 2013-2019 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 @@ -15,11 +15,15 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ +#include "CarlaDefines.h" #include "CarlaNative.h" #include "vestige/vestige.h" -#include "ui_launcher_res.hpp" +#ifndef CARLA_OS_LINUX +# include "ui_launcher_res.hpp" struct CarlaUILauncher; +#endif + class NativePlugin; struct VstObject { @@ -27,11 +31,13 @@ struct VstObject { NativePlugin* plugin; }; +#ifndef CARLA_OS_LINUX CarlaUILauncher* createUILauncher(const intptr_t winId, const NativePluginDescriptor* const d, const NativePluginHandle h); void idleUILauncher(CarlaUILauncher* const ui); void destoryUILauncher(CarlaUILauncher* const ui); +#endif const AEffect* VSTPluginMainInit(AEffect* const effect); intptr_t VSTAudioMaster(AEffect*, int32_t, int32_t, intptr_t, void*, float);