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