From b10cf995debb04ea9eaac409320b229b83447f00 Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Mon, 6 Nov 2017 22:48:22 +0900 Subject: [PATCH 1/8] Fix Qt4 compatibility --- plugins/VstEffect/VstEffect.cpp | 11 +++++++++++ src/gui/SetupDialog.cpp | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index 494613e26df..19d08c805b5 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -128,10 +128,21 @@ void VstEffect::openPlugin( const QString & _plugin ) PLUGIN_NAME::getIconPixmap( "logo", 24, 24 ), 0 ); QMutexLocker ml( &m_pluginMutex ); Q_UNUSED( ml ); +#if QT_VERSION > 0x050000 m_plugin.reset(new VstPlugin( _plugin )); +#else + { + QSharedPointer newPlugin(new VstPlugin( _plugin )); + std::swap(m_plugin, newPlugin); + } +#endif if( m_plugin->failed() ) { +#if QT_VERSION > 0x050000 m_plugin.reset(nullptr); +#else + m_plugin.clear(); +#endif delete tf; collectErrorForUI( VstPlugin::tr( "The VST plugin %1 could not be loaded." ).arg( _plugin ) ); return; diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 0d5f2c454a5..090de1eb80d 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -1077,7 +1077,11 @@ void SetupDialog::accept() QString::number( m_disableAutoQuit ) ); ConfigManager::inst()->setValue( "app", "language", m_lang ); ConfigManager::inst()->setValue( "ui", "vstembedmethod", +#if QT_VERSION >= 0x050000 m_vstEmbedComboBox->currentData().toString() ); +#else + m_vstEmbedComboBox->itemData(m_vstEmbedComboBox->currentIndex()).toString() ); +#endif ConfigManager::inst()->setWorkingDir(QDir::fromNativeSeparators(m_workingDir)); From fd92c14343ff0a1adf81de2e4c7f90b1ec70f27d Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Mon, 6 Nov 2017 23:28:45 +0900 Subject: [PATCH 2/8] Restrict "qt" embed method to Qt5 only --- plugins/vst_base/VstPlugin.cpp | 3 +++ src/gui/SetupDialog.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 8b514770809..4a7bed403ed 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -659,6 +659,7 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) m_pluginSubWindow = new vstSubWin( gui->mainWindow()->workspace() ); auto sw = m_pluginSubWindow.data(); +#if QT_VERSION >= 0x050100 if (m_embedMethod == "qt" ) { QWindow* vw = QWindow::fromWinId(m_pluginWindowID); @@ -668,6 +669,8 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) // Tell remote that it is embedded // Wait for remote reply } +#endif + #ifdef LMMS_BUILD_LINUX else if (m_embedMethod == "xembed" ) { diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 090de1eb80d..550f1d93ed8 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -343,7 +343,10 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : m_vstEmbedComboBox = new QComboBox( embed_tw ); m_vstEmbedComboBox->move( XDelta, YDelta ); m_vstEmbedComboBox->addItem( tr( "No embedding" ), "none" ); +#if QT_VERSION >= 0x050100 m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); +#endif + #ifdef LMMS_BUILD_LINUX if ( QX11Info::isPlatformX11() ) { m_vstEmbedComboBox->addItem( tr( "Embed using XEmbed protocol" ), "xembed" ); From f84dd610b91d95df48f9df2e889ac34c5ad75077 Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Tue, 7 Nov 2017 10:47:24 +0900 Subject: [PATCH 3/8] Add Win32 embedding --- plugins/vst_base/RemoteVstPlugin.cpp | 24 +++++++---------- plugins/vst_base/VstPlugin.cpp | 39 +++++++++++++++++++++++++--- plugins/vst_base/communication.h | 2 -- src/core/ConfigManager.cpp | 4 +++ src/gui/SetupDialog.cpp | 4 +++ 5 files changed, 53 insertions(+), 20 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 3a5eeed006a..175c9f5c764 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -109,6 +109,7 @@ static VstHostLanguages hlang = LanguageEnglish; static bool EMBED = false; static bool EMBED_X11 = false; +static bool EMBED_WIN32 = false; class RemoteVstPlugin; @@ -567,17 +568,6 @@ bool RemoteVstPlugin::processMessage( const message & _m ) init( _m.getString() ); break; -// TODO: Drop Windows hack for Qt 4 -#ifdef LMMS_BUILD_WIN32 - case IdVstPluginWindowInformation: - { - HWND top = FindWindowEx( NULL, NULL, NULL, - _m.getString().c_str() ); - m_window = FindWindowEx( top, NULL, NULL, NULL ); - break; - } -#endif - case IdVstSetTempo: setBPM( _m.getInt() ); break; @@ -2084,21 +2074,27 @@ int main( int _argc, char * * _argv ) if ( embedMethod == "none" ) { cerr << "Starting detached." << endl; - EMBED = EMBED_X11 = false; + EMBED = EMBED_X11 = EMBED_WIN32 = false; + } + else if ( embedMethod == "win32" ) + { + cerr << "Starting using Win32-native embedding." << endl; + EMBED = EMBED_WIN32 = true; EMBED_X11= false; } else if ( embedMethod == "qt" ) { cerr << "Starting using Qt-native embedding." << endl; - EMBED = true; EMBED_X11 = false; + EMBED = true; EMBED_X11 = EMBED_WIN32 = false; } else if ( embedMethod == "xembed" ) { cerr << "Starting using X11Embed protocol." << endl; - EMBED = true; EMBED_X11 = true; + EMBED = EMBED_X11 = true; EMBED_WIN32 = false; } else { cerr << "Unknown embed method " << embedMethod << ". Starting detached instead." << endl; + EMBED = EMBED_X11 = EMBED_WIN32 = false; } } diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 4a7bed403ed..cada57293c3 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -51,6 +51,7 @@ #ifdef LMMS_BUILD_WIN32 # include +# include #endif #include "ConfigManager.h" @@ -668,19 +669,49 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) // TODO: Synchronize show // Tell remote that it is embedded // Wait for remote reply - } + } else +#endif + +#ifdef LMMS_BUILD_WIN32 + if (m_embedMethod == "win32" ) + { + QWidget * helper = new QWidget; + QHBoxLayout * l = new QHBoxLayout( helper ); + QWidget * target = new QWidget( helper ); + l->setSpacing( 0 ); + l->setMargin( 0 ); + l->addWidget( target ); + + // we've to call that for making sure, Qt created the windows + helper->winId(); + HWND targetHandle = (HWND)target->winId(); + HWND pluginHandle = (HWND)(intptr_t)m_pluginWindowID; + + DWORD style = GetWindowLong(pluginHandle, GWL_STYLE); + style = style & ~(WS_POPUP); + style = style | WS_CHILD; + SetWindowLong(pluginHandle, GWL_STYLE, style); + SetParent(pluginHandle, targetHandle); + + DWORD threadId = GetWindowThreadProcessId(pluginHandle, NULL); + DWORD currentThreadId = GetCurrentThreadId(); + AttachThreadInput(currentThreadId, threadId, true); + + container = helper; + RemotePlugin::showUI(); + + } else #endif #ifdef LMMS_BUILD_LINUX - else if (m_embedMethod == "xembed" ) + if (m_embedMethod == "xembed" ) { QX11EmbedContainer * embedContainer = new QX11EmbedContainer( sw ); connect(embedContainer, SIGNAL(clientIsEmbedded()), this, SLOT(handleClientEmbed())); embedContainer->embedClient( m_pluginWindowID ); container = embedContainer; - } + } else #endif - else { qCritical() << "Unknown embed method" << m_embedMethod; delete m_pluginSubWindow; diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index 3e85007e711..bacf43c1edc 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -57,8 +57,6 @@ enum VstRemoteMessageIDs { // vstPlugin -> remoteVstPlugin IdVstLoadPlugin = IdUserBase, - // TODO: Drop IdVstPluginWindowInformation, Windows hack for Qt 4 - IdVstPluginWindowInformation, IdVstClosePlugin, IdVstSetTempo, IdVstSetLanguage, diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 734c39c1f0f..8cbee6acfe4 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -199,6 +199,10 @@ QString ConfigManager::vstEmbedMethod() const } #endif +#ifdef LMMS_BUILD_WIN32 + defaultMethod = "win32"; +#endif + return value( "ui", "vstembedmethod", defaultMethod ); } diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 550f1d93ed8..14355f894e6 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -347,6 +347,10 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); #endif +#ifdef LMMS_BUILD_WIN32 + m_vstEmbedComboBox->addItem( tr( "Embed using native Win32 API" ), "win32" ); +#endif + #ifdef LMMS_BUILD_LINUX if ( QX11Info::isPlatformX11() ) { m_vstEmbedComboBox->addItem( tr( "Embed using XEmbed protocol" ), "xembed" ); From 3432368125f83c31767804b23590e85dfe748cde Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Wed, 8 Nov 2017 23:44:57 +0900 Subject: [PATCH 4/8] Move SC_CLOSE handling code --- plugins/vst_base/RemoteVstPlugin.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 175c9f5c764..f3a7ebc16b7 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -1967,13 +1967,6 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop() while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) { TranslateMessage( &msg ); - - if( msg.message == WM_SYSCOMMAND && msg.wParam == SC_CLOSE ) - { - __plugin->destroyEditor(); - continue; - } - DispatchMessage( &msg ); } @@ -2020,6 +2013,12 @@ LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg, break; } } + else if( uMsg == WM_SYSCOMMAND && wParam == SC_CLOSE ) + { + __plugin->destroyEditor(); + return 0; + } + return DefWindowProc( hwnd, uMsg, wParam, lParam ); } From 0d8c6783cd8b744f7207a74d84449a44241ceb65 Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Sat, 18 Nov 2017 15:16:44 +0900 Subject: [PATCH 5/8] Try to improve embedding method logic --- include/ConfigManager.h | 1 + src/core/ConfigManager.cpp | 31 +++++++++++++++++++++++-------- src/gui/SetupDialog.cpp | 23 ++++++++++++----------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/include/ConfigManager.h b/include/ConfigManager.h index 3e5c0578f0b..74cb29c17fc 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -210,6 +210,7 @@ class EXPORT ConfigManager : public QObject return m_recentlyOpenedProjects; } + static QStringList availabeVstEmbedMethods(); QString vstEmbedMethod() const; // returns true if the working dir (e.g. ~/lmms) exists on disk diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 8cbee6acfe4..4819799605a 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -190,19 +190,34 @@ QString ConfigManager::defaultVersion() const return LMMS_VERSION; } -QString ConfigManager::vstEmbedMethod() const +QStringList ConfigManager::availabeVstEmbedMethods() { - QString defaultMethod = "qt"; -#ifdef LMMS_BUILD_LINUX - if (QX11Info::isPlatformX11()) { - defaultMethod = "xembed"; - } + QStringList methods; + methods.append("none"); +#if QT_VERSION >= 0x050100 + methods.append("qt"); #endif - #ifdef LMMS_BUILD_WIN32 - defaultMethod = "win32"; + methods.append("win32"); +#endif +#ifdef LMMS_BUILD_LINUX +#if QT_VERSION >= 0x050000 + if (static_cast(QApplication::instance())-> + platformName() == "xcb") +#else + if (qgetenv("QT_QPA_PLATFORM").isNull() + || qgetenv("QT_QPA_PLATFORM") == "xcb") #endif + { + methods.append("xembed"); + } +#endif + return methods; +} +QString ConfigManager::vstEmbedMethod() const +{ + QString defaultMethod = *(availabeVstEmbedMethods().end() - 1); return value( "ui", "vstembedmethod", defaultMethod ); } diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 14355f894e6..e248b40a975 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -342,20 +342,21 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : embed_tw->setFixedHeight( 48 ); m_vstEmbedComboBox = new QComboBox( embed_tw ); m_vstEmbedComboBox->move( XDelta, YDelta ); - m_vstEmbedComboBox->addItem( tr( "No embedding" ), "none" ); -#if QT_VERSION >= 0x050100 - m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); -#endif -#ifdef LMMS_BUILD_WIN32 - m_vstEmbedComboBox->addItem( tr( "Embed using native Win32 API" ), "win32" ); -#endif - -#ifdef LMMS_BUILD_LINUX - if ( QX11Info::isPlatformX11() ) { + QStringList embedMethods = ConfigManager::availabeVstEmbedMethods(); + m_vstEmbedComboBox->addItem( tr( "No embedding" ), "none" ); + if( embedMethods.contains("qt") ) + { + m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); + } + if( embedMethods.contains("win32") ) + { + m_vstEmbedComboBox->addItem( tr( "Embed using native Win32 API" ), "win32" ); + } + if( embedMethods.contains("xembed") ) + { m_vstEmbedComboBox->addItem( tr( "Embed using XEmbed protocol" ), "xembed" ); } -#endif m_vstEmbedComboBox->setCurrentIndex( m_vstEmbedComboBox->findData( m_vstEmbedMethod ) ); TabWidget * lang_tw = new TabWidget( tr( "LANGUAGE" ), general ); From 0278f302232bbecbba918cede9a6f7824c0f1ddf Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Mon, 20 Nov 2017 15:57:29 +0900 Subject: [PATCH 6/8] Add a fallback logic for VST embedding methods --- src/core/ConfigManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 4819799605a..e75e2413e33 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -217,8 +217,10 @@ QStringList ConfigManager::availabeVstEmbedMethods() QString ConfigManager::vstEmbedMethod() const { - QString defaultMethod = *(availabeVstEmbedMethods().end() - 1); - return value( "ui", "vstembedmethod", defaultMethod ); + QStringList methods = availabeVstEmbedMethods(); + QString defaultMethod = *(methods.end() - 1); + QString currentMethod = value( "ui", "vstembedmethod", defaultMethod ); + return methods.contains(currentMethod) ? currentMethod : defaultMethod; } bool ConfigManager::hasWorkingDir() const From 8e48c884c06e3606b5e32fc591459fa0c2d752dc Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 24 Nov 2017 12:35:39 +0100 Subject: [PATCH 7/8] VST: Fix Qt4 compilation --- plugins/vst_base/CMakeLists.txt | 2 +- src/core/ConfigManager.cpp | 4 ---- src/gui/SetupDialog.cpp | 4 ---- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index af58ffb1a98..ed956e2181a 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -29,7 +29,7 @@ SET(REMOTE_VST_PLUGIN_FILEPATH "RemoteVstPlugin" CACHE STRING "Relative file pat ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH="${REMOTE_VST_PLUGIN_FILEPATH}") BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h) -IF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX AND WANT_QT5) TARGET_LINK_LIBRARIES(vstbase qx11embedcontainer) ENDIF() diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index e75e2413e33..985d5e08cd7 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -35,10 +35,6 @@ #include "lmmsversion.h" -#ifdef LMMS_BUILD_LINUX -#include -#endif - static inline QString ensureTrailingSlash( const QString & s ) { if( ! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\') ) diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index e248b40a975..f88e1dcf6ce 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -67,10 +67,6 @@ #include "MidiApple.h" #include "MidiDummy.h" -#ifdef LMMS_BUILD_LINUX -#include -#endif - inline void labelWidget( QWidget * _w, const QString & _txt ) { QLabel * title = new QLabel( _txt, _w ); From 8c3c8ce06d5682cf747e5dcda74e648fc5733198 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 24 Nov 2017 12:58:44 +0100 Subject: [PATCH 8/8] Travis: Enable Linux/Qt4 builds --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 773aed79f6e..fa331f58197 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ matrix: - env: TARGET_OS=win64 - os: osx osx_image: xcode8.2 + - env: QT5= - env: QT5=True - env: QT5=True TARGET_OS=win32 - env: QT5=True TARGET_OS=win64