Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed VST GUI in subwindow #2856

Closed
wants to merge 8 commits into from
Closed

Embed VST GUI in subwindow #2856

wants to merge 8 commits into from

Conversation

jasp00
Copy link
Member

@jasp00 jasp00 commented Jun 17, 2016

This fixes #2855, but the new window causes glitches. Initially, the window may not be painted properly. When any window is moved, it may shake.

@BaraMGB
Copy link
Contributor

BaraMGB commented Jun 17, 2016

Synth1 works good, I only notice the shaking. Effect plugins (vst) seems not work.

@BaraMGB
Copy link
Contributor

BaraMGB commented Jun 23, 2016

I'm on Ubuntu 14.04 now and have that graphic glitches too (on 16.04 I hadn't these glitches). If I click "show/hide Gui" twice everything works fine. But if I merge #2826 (which only changed QMdiSubindow to our Subwindow) it doesn't work anymore. I hoped this fixes the glitches on the title bar which I notice on Qt4 build.

@tresf
Copy link
Member

tresf commented Jul 5, 2016

but the new window causes glitches. Initially, the window may not be painted properly. When any window is moved, it may shake.

@jasp00 What do you think? Better to have a window than none at all or wait until this issue is sorted out?

@tresf
Copy link
Member

tresf commented Jul 6, 2016

Test results (screenshots provided below):

  • Windows 10 x64: (Qt 5.4.2) Completely usable. Minor visual artifacts. Clicking title bar is the only way to bring plugin to foreground.
  • ⚠️ Ubuntu 14.04 x64 (VM, Qt 5.2.1): Once VST window is displayed, all QMdiSubWindow instances become erratic. SubWindows can't be moved without some strange mouse behavior. This may be a VM-specific bug, but it only affects QT. The visual artifacts (sometimes falling behind other windows) is an annoyance, but the plugin is responsive and usable. @jasp00 @Umcaruje @mikobuntu can you test on a physical machine and confirm?
  • ⛔️ Wine x64 (Ubuntu 14.04 x32, VM, Qt 5.4.2): Unusable. The visual artifacts are so bad that the plugin cannot be used 99% of the time.
  • ⚠️ MacOS 10.11 x64: Out of scope. Can't test per VST plugins on OS X (Apple) #698.

Windows 10 x64 Native:
image

Ubuntu 14.04 x64 VM:
image

Wine x64 (in Ubuntu 14.04 32-bit):
screen shot 2016-07-06 at 1 30 35 am

@jasp00
Copy link
Member Author

jasp00 commented Jul 6, 2016

On Linux, the visual artifacts are annoying.

Better to have a window than none at all or wait until this issue is sorted out?

I do not have a clear answer with the current proposal. Perhaps launching a helper application that embeds the VST GUI, out of MDI, would work around this.

@tresf
Copy link
Member

tresf commented Jul 6, 2016

I do not have a clear answer with the current proposal. Perhaps launching a helper application that embeds the VST GUI, out of MDI, would work around this.

Is there a way to launch it in a separate OS-decorated process?

Also

SubWindows can't be moved without some strange mouse behavior.

@jasp00 do you experience this or do you suspect it to be a VM-specific bug? Only Qt is affected, but once the VST window becomes active, I can't drag around any subwindows properly.

@jasp00
Copy link
Member Author

jasp00 commented Jul 7, 2016

do you experience this or do you suspect it to be a VM-specific bug?

I experience it.

Is there a way to launch it in a separate OS-decorated process?

I was thinking of a helper application that used Qt/LMMS decorations, but using a commented function for RemoteVstPlugin would be another option. It would work like ZynAddSubFX.

@tresf
Copy link
Member

tresf commented Aug 31, 2016

FYI, without this patch, Windows seems to be OK in the latest tests: https://youtu.be/exQwD1Kjsmg

@BaraMGB
Copy link
Contributor

BaraMGB commented Sep 2, 2016

I had some successes on put the Vst into a QDialog:

qt5vst

The most Instruments on my harddisk seems to work fine. But for example "Superwave P8" is not catched by the QDialog. I have to explore more on this.

@jasp00
Copy link
Member Author

jasp00 commented Sep 24, 2016

To solve the Linux Qt5 program, I will use a separate window. To unify the implementation, Windows and Qt4 will use a separate window too.

@Umcaruje
Copy link
Member

I really agree on separate VST windows, since this will allow you to put a, say large VST spectrum analyzer on a seperate screen, if you're running a dual or more monitor setup.

@karmux
Copy link
Contributor

karmux commented Dec 6, 2016

I tested this PR on Kubuntu 16.10 64-bit (Qt 5.6.1). Didn't notice any regression compared to Qt4 when when using various VST plugins. 👍

@tresf
Copy link
Member

tresf commented Dec 7, 2016

@karmux thanks for the testing. If your results are consistent with newer Qt versions, we should merge this PR, epecially considering it only applies to Qt > 5. Any objections?

@jasp00
Copy link
Member Author

jasp00 commented Dec 7, 2016

I have an implementation that uses a separate window to avoid the detected glitches; I am sorry I cannot commit yet. Are you sure the glitches are gone with current Qt 5?

@karmux
Copy link
Contributor

karmux commented Dec 17, 2016

@jasp00 yes. Even in GTG DPC 3 (drum sampler on screenshots above) I couldn't see any artifacts.

@jasp00
Copy link
Member Author

jasp00 commented Dec 26, 2016

The glitches are still there with Qt 5.7.1.

@jasp00
Copy link
Member Author

jasp00 commented Dec 26, 2016

One glitch with Qt 5 when moving a separate window is that mouse events happen in the Qt application, and it may draw over the moving window. So there is no glitch-free method and the real solution would be to fix Qt. I will finish the separate window workaround: it is more complicated, but visually acceptable, and it does not leave a broken state when VST windows are gone.

@jasp00
Copy link
Member Author

jasp00 commented Dec 27, 2016

I see that #2855 is the only bug that prevents the switch to Qt5 on Linux, and that the switch can be done on Windows. This PR could work with Qt4 on Linux, but may I implement Qt5 only? Qt5 implementation works, just needs cleaning and error checking. More important, to unify the behavior as much as possible, since there are no embedding functions with Qt4 on Windows, may I drop Qt4 support for Windows?

@tresf
Copy link
Member

tresf commented Dec 27, 2016

may I drop Qt4 support for Windows?

Sure so as long you're OK helping us revert it all if Qt5 exposes unexpected Windows issues in RC2.

@jasp00
Copy link
Member Author

jasp00 commented Dec 27, 2016

Sure so as long you're OK helping us revert it all

There is the will, but no time. I will keep Qt4, write the implementation guidelines for Qt5, and delay unification until RC2 is tested.

@jasp00 jasp00 force-pushed the qt5-embed branch 2 times, most recently from ddcc57f to e20b648 Compare January 3, 2017 10:37
@karmux
Copy link
Contributor

karmux commented Jan 12, 2017

On the first load of plugin, it's loaded separately from Qt window (there's empty Qt window and borderless VST window). Pressing show/hide GUI button twice loads it correctly. Using same setup as I wrote before.

@jasp00
Copy link
Member Author

jasp00 commented Jan 20, 2017

Using same setup as I wrote before.

@karmux, GTG DPC 3 plug-in on Qt 5.6.1?

@karmux
Copy link
Contributor

karmux commented Jan 21, 2017

@jasp00 When VST is loaded in new project then it loads properly inside Qt's window. But when some project has VSTs saved then it loades like I described in my previous #2856 (comment). This applies to all VSTs.

@@ -62,6 +62,9 @@ class VstEffectControlDialog : public EffectControlDialog
VstPlugin * m_plugin;

QLabel * tbLabel;

private slots:
void togglePluginUI( bool checked );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void togglePluginUI( const bool checked );

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use const only when it is useful:

  • Pointers and references.
  • Read-only methods.
  • Constants.

As I said, only when it is useful, not when it is possible. Excessive use of const makes the code harder to read (this is subjective, but it is simpler). Without const, you can reuse parameters (simplicity) and you do not have to take const back if you need write access later (less typing and less thinking).

const bool and alike are useless in prototypes because values are copied. Do you see const in the dup2 prototype?

It used to be a good idea to add const to avoid if (x = 5) errors, but a good compiler with warnings will warn you. I will not ask you to remove const in a complex function body, but you should not ask others to use const unless there is a clear benefit.




void VstEffectControlDialog::togglePluginUI( bool checked )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void VstEffectControlDialog::togglePluginUI( const bool checked )

@@ -3,7 +3,7 @@ IF(LMMS_SUPPORT_VST)
INCLUDE(BuildPlugin)

IF(LMMS_BUILD_WIN32)
ADD_DEFINITIONS(-DPTW32_STATIC_LIB)
ADD_DEFINITIONS(-DPTW32_STATIC_LIB -std=c++0x)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c++0x
The working draft of the upcoming ISO C ++ 0x standard. This option enables experimental features that are likely to be included in C ++ 0x. The working draft is constantly changing, and any feature that is enabled by this flag may be removed from future versions of GCC if it is not part of the C ++ 0x standard.

Your commit say you wanted to enable C++11, so, it's more like -std=c++11 I guess.

Or the compiler on win32 is old, and what's considered like experimental at the time is now C++11 ?

Copy link
Member

@tresf tresf Jan 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's more like -std=c++11 I guess

Same effectiveness. c++0x is fine for now. We can switch it down the road as more compilers adopt the official standard. BTW, this specific change superseded by 607d3f4; Can be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC supports -std=c++14 ; so I guess -std=c++0x includes C++14 and some features of C++17.

Copy link
Member

@tresf tresf Jan 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess -std=c++0x includes C++14 and some features of C++17.

Perhaps but that should be equally called C++1y, etc.

https://herbsutter.com/2011/08/12/we-have-an-international-standard-c0x-is-unanimously-approved/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess -std=c++0x includes C++14 and some features of C++17.

It does not.

@@ -464,24 +478,103 @@ RemoteVstPlugin::~RemoteVstPlugin()



#ifdef USE_LINUX_EMBEDDER
static void checkExitStatus( int status )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static void checkExitStatus( const int status )

@@ -619,9 +712,34 @@ void RemoteVstPlugin::init( const std::string & _plugin_file )



#ifdef USE_LINUX_EMBEDDER
static void assert_dup2( int oldfd, int newfd )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static void assert_dup2( const int oldfd, const int newfd )


void EmbedderApplication::readCommand()
{
int c = getchar();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const int c = getchar();

const char * title = argv[1];
unsigned int windowId = strtol( argv[2], NULL, 16 );
int width = strtol( argv[3], NULL, 16 );
int height = strtol( argv[4], NULL, 16 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const unsigned int windowId = strtol( argv[2], NULL, 16 );
const int width = strtol( argv[3], NULL, 16 );
const int height = strtol( argv[4], NULL, 16 );


QTimer::singleShot( 0, app, SLOT( applicationReady() ) );

int ret = app->exec();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const int ret = app->exec();

{
public:
void init( const char * title, unsigned int windowId, int width,
int height );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void init( const char * title, const unsigned int windowId, const int width, const int height );

virtual ~EmbedderApplication();

void init( const char * title, unsigned int windowId, int width,
int height );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void init( const char * title, const unsigned int windowId, const int width, const int height );

@jasp00
Copy link
Member Author

jasp00 commented Jan 23, 2017

Unreproducible with Qt 5.7.1 and Wine 1.8.6. If I tamper with the window system, I get that behavior. @karmux, do you see any errors in the console? When you have the empty window, what is the output of ps -A -o args | grep embed-window?

@karmux
Copy link
Contributor

karmux commented Mar 29, 2017

@jasp00 I'd like to test this again with ouput of command you gave but can't compile this anymore.
I made a staging branch from latest master and merged my wine-devel PR and this PR into it.
Wine 2.4.0 and Qt 5.6.1 on Kubuntu 16.10.

Compilation error:

In file included from /usr/include/c++/6/cinttypes:35:0,
                 from /home/karmo/Dev/lmms/plugins/vst_base/RemoteVstPlugin.cpp:70:
/usr/include/c++/6/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
 #error This file requires compiler and library support \
  ^~~~~
/home/karmo/Dev/lmms/plugins/vst_base/RemoteVstPlugin.cpp: In member function ‘void RemoteVstPlugin::initEditor()’:
/home/karmo/Dev/lmms/plugins/vst_base/RemoteVstPlugin.cpp:844:25: error: expected ‘)’ before ‘PRIxPTR’
    sprintf( widStr, "%" PRIxPTR, m_windowID );
                         ^~~~~~~
/home/karmo/Dev/lmms/plugins/vst_base/RemoteVstPlugin.cpp:844:45: warning: spurious trailing ‘%’ in format [-Wformat=]
    sprintf( widStr, "%" PRIxPTR, m_windowID );
                                             ^
/home/karmo/Dev/lmms/plugins/vst_base/RemoteVstPlugin.cpp:844:45: warning: too many arguments for format [-Wformat-extra-args]
winegcc: g++ failed
plugins/vst_base/CMakeFiles/vstbase.dir/build.make:61: recipe for target 'plugins/RemoteVstPlugin' failed
make[2]: *** [plugins/RemoteVstPlugin] Error 2
CMakeFiles/Makefile2:9200: recipe for target 'plugins/vst_base/CMakeFiles/vstbase.dir/all' failed
make[1]: *** [plugins/vst_base/CMakeFiles/vstbase.dir/all] Error 2

wine-devel and qt5-embed merge result:

ADD_CUSTOM_COMMAND(
	SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp"
	COMMAND ${WINE_CXX}
	ARGS "-I\"${CMAKE_BINARY_DIR}\""
		"-I\"${CMAKE_SOURCE_DIR}/include\""
		"-I\"${CMAKE_INSTALL_PREFIX}/include/wine/windows\""
		"-I\"${CMAKE_INSTALL_PREFIX}/include\""
		"-I\"${WINE_INCLUDE_DIR_REPLACED}\""
		"-L\"${WINE_LIBRARY_REPLACED}\""
		"\"${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp\""
		-std=c++11 -ansi -mwindows -lpthread ${EXTRA_FLAGS} -fno-omit-frame-pointer
		${WINE_BUILD_FLAGS}
		-o ../RemoteVstPlugin
	COMMAND sh -c "mv ../RemoteVstPlugin.exe ../RemoteVstPlugin || true"
	TARGET vstbase
	OUTPUTS ../RemoteVstPlugin
)

@karmux
Copy link
Contributor

karmux commented Apr 1, 2017

It compiles now after your new commits but VST instruments and effects are separate from Qt window. Clicking show/hide doesn't fix it anymore.
Wine 2.4.0 and Qt 5.6.1 on Kubuntu 16.10.

screenshot_20170401_162358

@jasp00
Copy link
Member Author

jasp00 commented Apr 1, 2017

@karmux, could you explain the screenshot? In the taskbar on the left, what application does the white window icon represent? The one between the selected VeSTige logo and the LMMS logo.

Could you try running Wine 2.0?

@karmux
Copy link
Contributor

karmux commented Apr 1, 2017

@jasp00, white icon is actual VST instrument window on the left and red/green VST icon is blank Qt window on the right.

@jasp00
Copy link
Member Author

jasp00 commented Apr 1, 2017

Wine 2.0 works. @karmux, according to #2856 (comment) and #3295 (comment), it looks like your Qt 5 environment has trouble embedding native windows. Could you try 1ded76b and post the debug information?

@lukas-w
Copy link
Member

lukas-w commented Apr 1, 2017

@jasp00 That's an issue with certain window managers, as I have stated in #3295 (comment). I've been able to reproduce it with both PRs on Plasma and i3, bot not on Xfce for example.

I already debugged this issue in #3295 with lines similar to those in 1ded76b, which showed the correct window ids with Qt 5.6.1, Plasma desktop, and Wine 2.4. I expect @karmux will get the same results. I could work around it by sleeping (QThread::sleep(1)) before calling createWindowContainer, so there seems to be some sort of synchronization issue, i.e. createWindowContainer is probably being called before the window has been mapped.

@karmux
Copy link
Contributor

karmux commented Apr 1, 2017

// Here I opened SuperRiff Bass

kf5.kio.core: Refilling KProtocolInfoFactory cache in the hope to find ""
Error loading icon pixmap "vestige/track_op_menu_active": File not found
Error loading icon pixmap "vestige/track_op_menu": File not found
Error loading icon pixmap "vestige/project_open": File not found
Error loading icon pixmap "vestige/project_open": File not found
Error loading icon pixmap "vestige/stepper-left-press": File not found
Error loading icon pixmap "vestige/stepper-left": File not found
Error loading icon pixmap "vestige/project_save": File not found
Error loading icon pixmap "vestige/project_save": File not found
Error loading icon pixmap "vestige/stepper-right-press": File not found
Error loading icon pixmap "vestige/stepper-right": File not found
Error loading icon pixmap "vestige/stepper-down": File not found
Error loading icon pixmap "state_stop": File not found
kf5.kio.core: Refilling KProtocolInfoFactory cache in the hope to find ""
unique ID: 1999
RemotePlugin::DebugMessage: inputs: 0  output: 2
RemotePlugin::DebugMessage: creating editor
m_windowID 9200001
RemotePlugin::DebugMessage: editor successfully created
m_pluginWindowID 9200001
window 0x5571be8db120
RemotePlugin::DebugMessage: failed getting shared memory

// Here I opened massTURBOTar

kf5.kio.core: Refilling KProtocolInfoFactory cache in the hope to find ""
QProcess: Destroyed while process ("/home/karmo/Dev/lmms/build/plugins/RemoteVstPlugin") is still running.
unique ID: mtub
RemotePlugin::DebugMessage: inputs: 0  output: 2
RemotePlugin::DebugMessage: creating editor
m_windowID 9000001
RemotePlugin::DebugMessage: editor successfully created
m_pluginWindowID 9000001
window 0x5571bdb5c940
RemotePlugin::DebugMessage: failed getting shared memory

// Here I opened GTG DPC 3

kf5.kio.core: Refilling KProtocolInfoFactory cache in the hope to find ""
QProcess: Destroyed while process ("/home/karmo/Dev/lmms/build/plugins/RemoteVstPlugin") is still running.
unique ID: dpc3
RemotePlugin::DebugMessage: inputs: 0  output: 2
RemotePlugin::DebugMessage: creating editor
m_windowID 9000001
RemotePlugin::DebugMessage: editor successfully created
m_pluginWindowID 9000001
window 0x5571bdb80820
RemotePlugin::DebugMessage: failed getting shared memory

Interestingly GTG DPC 3 once opened correctly but I couldn't reproduce it.

@jasp00
Copy link
Member Author

jasp00 commented Apr 2, 2017

Because embedding native windows on Qt 5 is not reliable on some systems, I propose to let Wine handle the window interface. There is an issue with this procedure:

  1. User closes the window to hide it.
  2. User wants to show the window again.
  3. Window manager may not bring the window to front.

This may happen because Wine has already accepted the close event. This solution affects usability, but it is the best compromise.

@jasp00
Copy link
Member Author

jasp00 commented Apr 10, 2017

Continued at #3497.

@jasp00 jasp00 closed this Apr 10, 2017
@jasp00 jasp00 deleted the qt5-embed branch April 10, 2017 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants