-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Fix VST effect bugs #4294
Fix VST effect bugs #4294
Conversation
It tests fine like before but I'm not heavily into VSTs and wouldn't know what to look for. |
@@ -47,7 +47,8 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : | |||
m_pluginWidget( NULL ), | |||
|
|||
m_plugin( NULL ), | |||
tbLabel( NULL ) | |||
tbLabel( NULL ), | |||
m_needsEmbed( false ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to be equivalent to m_plugin && m_plugin->embetMethod() != "none"
. If so, can we remove the variable and make it a method instead in order to reduce redundancy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't, because VstEffectControlDialog::showEvent
may modify the value? I guess it would be safe to replace embed_vst
with this variable if showEvent
is never called while construction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_needsEmbed
is a flag to indicate that the VST GUI needs to be embedded but hasn't been yet. The VST GUI seems to be deleted on Qt4 with X11 embedding if the first thing it's added into isn't currently part of the main window hierarchy, so I deferred the embedding to the first time showEvent
is called, when the VstEffectControlDialog
will be safely inside its subwindow. This could be replaced by m_plugin && m_plugin->embetMethod() != "none"
, but the GUI would be re-added to the dialog every time showEvent
is called.
SLOT( togglePluginUI( bool ) ) ); | ||
} else { | ||
connect( btn, SIGNAL( clicked() ), | ||
m_plugin.data(), SLOT( toggleUI() ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this change needed? Can we fix it within togglePluginUI
or toggleUI
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The toggled(bool)
signal isn't emitted if the button isn't checkable, so when the plugin isn't embedded we have to connect to clicked
instead. The trouble with connecting clicked(bool)
to togglePluginUI(bool)
is that when the button isn't checkable, the parameter is always false
. This could be worked around by doing something like
if( m_plugin->embedMethod() == "none" ) {
m_plugin->toggleUI();
return;
}
inside togglePluginUI
, but togglePluginUI
is called from VstEffectControls::createView
to set the visibility of the UI to what's in the project file, which this would break. Thus we can't sensibly use togglePluginUI
, so I connected straight to VstPlugin::toggleUI
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
toggled(bool)
signal isn't emitted if the button isn't checkable
If we can uncheck the button when VST window is closed, we can always make the button checkable. AFAIK we do something similar for ZynAddSubFX.
@@ -67,7 +67,7 @@ class VstEffectControlDialog : public EffectControlDialog | |||
PixmapButton * m_managePluginButton; | |||
PixmapButton * m_savePresetButton; | |||
|
|||
QSharedPointer<VstPlugin> m_plugin; | |||
QPointer<VstPlugin> m_plugin; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we get rid of the Windows-specific behaviour instead? Maybe the bug this workaround was made for has been fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workaround is very old(more than 5 years ago): 1c9c76f#diff-e3cda83bb57677b7ecd60d7e5e1fe92cR156
There have been so many changes after that(Qt version change, VST bug fixes, etc.) I think we should test whether the bug still exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the workaround, I can still reproduce the issue:
- Enable "One instrument track window mode"
- Create a project with at least two instruments
- Add a VST effect to one of them
- Open the other instrument's window
- Open the first instrument's window again and show the VST effect dialog
The VST GUI will have disappeared.
I'm sure there's a better way to work around this, but the X11 embedding on Qt4 seems to be especially fragile and I'm not going to have access to a Linux machine again for a couple of months, so I didn't want to touch this any more. If you can produce something better, it would be very welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the workaround, I can still reproduce the issue:
Could you tell me your OS and Qt version the embedding method you used? If I can reproduce that, I'll try to figure out what's going on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windows 10 64-bit, Qt 5.4.2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can reproduce the bug on GNU/Linux, too. (Edit: Qt5 only)
I found that the plugin widget is destroyed when VstEffectControlDialog
is destroyed because of parenting. Simple unparenting seems to fix this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, go ahead 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unparenting approach dosen't work well for XEmbed + Qt4. So I think I need to wrap that with QT version check macro if I do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like destroying parent window also destroys child windows on Windows. I guess it was the reason for the workaround.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms632682(v=vs.85).aspx
Might it be better to use a separate helper class to handle win32
embedding?
Maybe out of scope... I have a fix for #1727. Is it fine to include the fix here? |
Depends on the size of the patch, though this PR already fixes a lot of things, your fix probably could be more suited as a separate PR, unless the fix is dependent on the changes made in this PR. |
The fix changes a few lines and not directly related to this PR. |
Then I guess you could push here so we avoid the conflicts |
m_subWindow->setFixedSize( m_subWindow->size() ); | ||
if (m_subWindow->layout()) { | ||
m_subWindow->layout()->setSizeConstraint(QLayout::SetFixedSize); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lukas-w I don't know if it's needed, but isn't it safe to keep previous behavior(probably with else
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PhysSong I don't think it's needed, setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed )
already does that in the else
case.
I've |
@DomClark Is there anything left to do here? I'm testing this and the few vst effects I have open up fine and gui show/hide is remembered. |
@zonkmachine: As far as I know, @PhysSong still wanted to make some adjustments. |
I want to make two changes(one is fixing |
I got small issue, minor one with this PR.
Expected behaviour: Now: |
plugins/vestige/vestige.cpp
Outdated
@@ -127,6 +177,13 @@ void vestigeInstrument::loadSettings( const QDomElement & _this ) | |||
{ | |||
m_plugin->loadSettings( _this ); | |||
|
|||
m_plugin->createUI( nullptr ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why Do we need this call? At this moment loadFile
already have created UI, so this call will cause the bug reported by @qnebra.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, interesing. Also I will check, if I can of course with my noob skills.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PhysSong this call make a issue. I commented this out, compile lmms and check. Cloning works correctly.
Should we do a rebase and squash fixup commits? Squashing everything doesn't look good, but ordinary merge might mess up commit history. |
There is also the 'Rebase and merge' option. |
I've done #4294 (comment) on top of rebased branch. Would it be fine to (force-)push that? |
Yes. I think so. |
Fixes bugs where during project loading (observed with VST effects), empty widgets and sub-windows would be left floating around. These were caused by inconsistencies between the way VST UIs were created when loading a project and when adding an effect in an existing project. In some situations, this caused createUI to be called twice, leaving over multiple empty widgets. This commit refactors some code in order to avoid creating unnecessary sub- windows, which aren't needed with VST effects, but were still created, usually being invisible. All sub-window related code was moved out of VstPlugin into vestige.cpp, which is the only place where sub-window VSTs are actually used. A new sub-class of VstPlugin, VstInstrumentPlugin, now handles VST sub-windows and is used by vestigeInstrument. "guivisible" attribute loading was moved out of VstPlugin as well and is now done in VstEffectControls' and vestigeInstrument's loadSettings method respectively. This causes some minor code duplication unfortunately. Closes #4110
QMdiSubWindow::setSizePolicy doesn't have any effect because QMdiSubWindow uses a layout. This patch uses QMdiSubWindow::layout()->setSizeConstraint instead. This may cause effects that don't have a layout and don't implement sizeHint() to now be resizable. For effects that do though, it fixes the size constraint.
From MSDN: "In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator." Also calculate the required window size using AdjustWindowRect, rather than hard-coding some constants.
4f526b1
to
d6ae46e
Compare
I've done a interactive rebase and cleaned up the commit history. A fix for #4294 (comment) is included in 9449c07(the original commit 102345b was the cause of this bug). |
I get a crash when testing this with mda Detune (as used in #1727). Crash occurs in the controls window when opening the control button (control VST-plugin from LMMS host) after pressing the Show/Hide button a bunch of times.
|
It looks like an old bug. To reproduce:
I'll look into this bug. |
I think we should disable this button when the effect has no GUI. Is it worth to disable it for VSTi too? |
#4294 (comment) seems to be introduced in 908591b. The problem is |
Yes.
For VSTi's without a gui? Yes to this also. |
Unset Qt::WA_DeleteOnClose for the dialog to avoid deletion when closed
Fixed a crash reported by @zonkmachine. I think Show/Hide button should be disabled for VSTs without GUI, but I think that's an UI/UX enhancement rather than a bug fix. So I think this one could be merged after enough reviews/tests. |
Fix confirmed.
👍 |
Testing with mda Detune (with setting 'Sync VST plugins to host playback' ticked). I can adjust the settings of it but I need to save/reload the project in order for the changes to take effect. Changes done via automation will not take effect. This works fine for Nyquist EQ so it may be an issue with mda Detune. Edit: mda Degrade simlilarly don't have a gui and works fine. |
I've tested this some more and find nothing else to comment on. The mda Detune issue above I ascribe to mda Detune. |
Should we wait for more testings, or merge this soon? |
Merge. It's gone through plenty of testing. 🚜 |
Fixes #4110, and a couple of other VST effect bugs.
Summary of my changes, since I neglected to put any with my commits (Lukas-W's are with his commits):
VstEffectControlDialog
is added to theSubWindow
.SubWindow
then causes a segfault trying to access properties of itswidget()
, which is still null. I've just added null checks where appropriate.stable-1.2
.this was a regression on Windows only, caused by a8311a7. On Windows, effect control dialogs are kept around even when the view that opened them is deleted:
EffectView::~EffectView()
{
#ifdef LMMS_BUILD_LINUX
delete m_subWindow;
#else
if( m_subWindow )
{
// otherwise on win32 build VST GUI can get lost
m_subWindow->hide();
}
#endif
}
Now cbf8cbd replaces it.lmms/src/gui/widgets/EffectView.cpp
Lines 162 to 176 in e554a4c
As a result, the
QSharedPointer
inVstEffectControlDialog
keeps theVstPlugin
instance alive even when the effect has been removed. I've changed this to a plainQPointer
, so it maintains the nullify-on-delete behaviour but lets the plugin exit properly.Edited by @PhysSong: Original fix eb560a7 have been dropped and cbf8cbd have been added instead. Another new commit d6ae46e fixes #1727.