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