Leave the middleware window for non-linux OSes Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
| @@ -208,16 +208,19 @@ class HostWindow(QMainWindow): | |||||
| self.ui.menu_Engine.setEnabled(False) | self.ui.menu_Engine.setEnabled(False) | ||||
| self.ui.menu_Engine.setVisible(False) | self.ui.menu_Engine.setVisible(False) | ||||
| self.ui.menu_Engine.menuAction().setVisible(False) | self.ui.menu_Engine.menuAction().setVisible(False) | ||||
| self.ui.tabWidget.removeTab(2) | |||||
| if self.host.isControl: | if self.host.isControl: | ||||
| self.ui.act_file_new.setVisible(False) | self.ui.act_file_new.setVisible(False) | ||||
| self.ui.act_file_open.setVisible(False) | self.ui.act_file_open.setVisible(False) | ||||
| self.ui.act_file_save_as.setVisible(False) | self.ui.act_file_save_as.setVisible(False) | ||||
| self.ui.tabUtils.removeTab(0) | self.ui.tabUtils.removeTab(0) | ||||
| self.ui.tabWidget.removeTab(2) | |||||
| else: | else: | ||||
| self.ui.act_file_save_as.setText(self.tr("Export as...")) | self.ui.act_file_save_as.setText(self.tr("Export as...")) | ||||
| if not withCanvas: | |||||
| self.ui.tabWidget.tabBar().hide() | |||||
| else: | else: | ||||
| self.ui.act_engine_start.setEnabled(True) | self.ui.act_engine_start.setEnabled(True) | ||||
| @@ -2333,7 +2336,7 @@ class HostWindow(QMainWindow): | |||||
| self.ui.pb_dsp_load.setValue(int(load)) | self.ui.pb_dsp_load.setValue(int(load)) | ||||
| def getAndRefreshRuntimeInfo(self): | def getAndRefreshRuntimeInfo(self): | ||||
| if not self.isVisible(): | |||||
| if not self.ui.pb_dsp_load.isVisible(): | |||||
| return | return | ||||
| if not self.host.is_engine_running(): | if not self.host.is_engine_running(): | ||||
| return | return | ||||
| @@ -19,7 +19,7 @@ | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Imports (Global) | # Imports (Global) | ||||
| from PyQt5.QtGui import QKeySequence | |||||
| from PyQt5.QtGui import QKeySequence, QMouseEvent | |||||
| from PyQt5.QtWidgets import QHBoxLayout | from PyQt5.QtWidgets import QHBoxLayout | ||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| @@ -81,12 +81,12 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| def __init__(self, host, isPatchbay, parent=None): | def __init__(self, host, isPatchbay, parent=None): | ||||
| ExternalUI.__init__(self) | ExternalUI.__init__(self) | ||||
| HostWindow.__init__(self, host, isPatchbay, parent) | HostWindow.__init__(self, host, isPatchbay, parent) | ||||
| self.host = host | |||||
| if False: | if False: | ||||
| # kdevelop likes this :) | # kdevelop likes this :) | ||||
| host = PluginHost() | host = PluginHost() | ||||
| self.host = host | |||||
| self.host = host | |||||
| host.setExternalUI(self) | host.setExternalUI(self) | ||||
| @@ -387,6 +387,157 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
| else: | else: | ||||
| print("unknown message: \"" + msg + "\"") | 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 | # Main | ||||
| @@ -415,7 +566,17 @@ if __name__ == '__main__': | |||||
| # ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
| # Create GUI | # 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 | # App-Loop | ||||
| @@ -1,6 +1,6 @@ | |||||
| /* | /* | ||||
| * Carla Native Plugins | * Carla Native Plugins | ||||
| * Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com> | |||||
| * Copyright (C) 2013-2019 Filipe Coelho <falktx@falktx.com> | |||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
| @@ -16,10 +16,13 @@ | |||||
| */ | */ | ||||
| #include "carla-vst.hpp" | #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 <cstring> | |||||
| #ifdef __WINE__ | #ifdef __WINE__ | ||||
| __cdecl static intptr_t cvst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) | __cdecl static intptr_t cvst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) | ||||
| @@ -84,7 +84,9 @@ public: | |||||
| fMidiEventCount(0), | fMidiEventCount(0), | ||||
| fTimeInfo(), | fTimeInfo(), | ||||
| fVstRect(), | fVstRect(), | ||||
| #ifndef CARLA_OS_LINUX | |||||
| fUiLauncher(nullptr), | fUiLauncher(nullptr), | ||||
| #endif | |||||
| fHostType(kHostTypeNull), | fHostType(kHostTypeNull), | ||||
| fMidiOutEvents(), | fMidiOutEvents(), | ||||
| #ifdef USING_JUCE | #ifdef USING_JUCE | ||||
| @@ -133,8 +135,13 @@ public: | |||||
| fVstRect.top = 0; | fVstRect.top = 0; | ||||
| fVstRect.left = 0; | fVstRect.left = 0; | ||||
| #ifdef CARLA_OS_LINUX | |||||
| fVstRect.bottom = 712; | |||||
| fVstRect.right = 1024; | |||||
| #else | |||||
| fVstRect.bottom = ui_launcher_res::carla_uiHeight; | fVstRect.bottom = ui_launcher_res::carla_uiHeight; | ||||
| fVstRect.right = ui_launcher_res::carla_uiWidth; | fVstRect.right = ui_launcher_res::carla_uiWidth; | ||||
| #endif | |||||
| init(); | init(); | ||||
| } | } | ||||
| @@ -288,8 +295,23 @@ public: | |||||
| case effEditOpen: | case effEditOpen: | ||||
| if (fDescriptor->ui_show != nullptr) | 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); | destoryUILauncher(fUiLauncher); | ||||
| fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | ||||
| #endif | |||||
| ret = 1; | ret = 1; | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -297,20 +319,23 @@ public: | |||||
| case effEditClose: | case effEditClose: | ||||
| if (fDescriptor->ui_show != nullptr) | if (fDescriptor->ui_show != nullptr) | ||||
| { | { | ||||
| #ifdef CARLA_OS_LINUX | |||||
| fDescriptor->ui_show(fHandle, false); | |||||
| #else | |||||
| destoryUILauncher(fUiLauncher); | destoryUILauncher(fUiLauncher); | ||||
| fUiLauncher = nullptr; | fUiLauncher = nullptr; | ||||
| #endif | |||||
| ret = 1; | ret = 1; | ||||
| } | } | ||||
| break; | break; | ||||
| case effEditIdle: | case effEditIdle: | ||||
| #ifndef CARLA_OS_LINUX | |||||
| if (fUiLauncher != nullptr) | if (fUiLauncher != nullptr) | ||||
| { | |||||
| idleUILauncher(fUiLauncher); | idleUILauncher(fUiLauncher); | ||||
| if (fDescriptor->ui_idle != nullptr) | |||||
| fDescriptor->ui_idle(fHandle); | |||||
| } | |||||
| #endif | |||||
| if (fDescriptor->ui_idle != nullptr) | |||||
| fDescriptor->ui_idle(fHandle); | |||||
| break; | break; | ||||
| case effGetChunk: | case effGetChunk: | ||||
| @@ -604,8 +629,10 @@ private: | |||||
| NativeTimeInfo fTimeInfo; | NativeTimeInfo fTimeInfo; | ||||
| ERect fVstRect; | ERect fVstRect; | ||||
| #ifndef CARLA_OS_LINUX | |||||
| // UI button | // UI button | ||||
| CarlaUILauncher* fUiLauncher; | CarlaUILauncher* fUiLauncher; | ||||
| #endif | |||||
| // Host data | // Host data | ||||
| enum HostType { | enum HostType { | ||||
| @@ -1,6 +1,6 @@ | |||||
| /* | /* | ||||
| * Carla Native Plugins | * Carla Native Plugins | ||||
| * Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com> | |||||
| * Copyright (C) 2013-2019 Filipe Coelho <falktx@falktx.com> | |||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License as | * 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. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaDefines.h" | |||||
| #include "CarlaNative.h" | #include "CarlaNative.h" | ||||
| #include "vestige/vestige.h" | #include "vestige/vestige.h" | ||||
| #include "ui_launcher_res.hpp" | |||||
| #ifndef CARLA_OS_LINUX | |||||
| # include "ui_launcher_res.hpp" | |||||
| struct CarlaUILauncher; | struct CarlaUILauncher; | ||||
| #endif | |||||
| class NativePlugin; | class NativePlugin; | ||||
| struct VstObject { | struct VstObject { | ||||
| @@ -27,11 +31,13 @@ struct VstObject { | |||||
| NativePlugin* plugin; | NativePlugin* plugin; | ||||
| }; | }; | ||||
| #ifndef CARLA_OS_LINUX | |||||
| CarlaUILauncher* createUILauncher(const intptr_t winId, | CarlaUILauncher* createUILauncher(const intptr_t winId, | ||||
| const NativePluginDescriptor* const d, | const NativePluginDescriptor* const d, | ||||
| const NativePluginHandle h); | const NativePluginHandle h); | ||||
| void idleUILauncher(CarlaUILauncher* const ui); | void idleUILauncher(CarlaUILauncher* const ui); | ||||
| void destoryUILauncher(CarlaUILauncher* const ui); | void destoryUILauncher(CarlaUILauncher* const ui); | ||||
| #endif | |||||
| const AEffect* VSTPluginMainInit(AEffect* const effect); | const AEffect* VSTPluginMainInit(AEffect* const effect); | ||||
| intptr_t VSTAudioMaster(AEffect*, int32_t, int32_t, intptr_t, void*, float); | intptr_t VSTAudioMaster(AEffect*, int32_t, int32_t, intptr_t, void*, float); | ||||