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); | ||||