rncbc / qtractor

Qtractor - An Audio/MIDI multi-track sequencer
https://qtractor.org
GNU General Public License v2.0
511 stars 91 forks source link

VST3 plugin size request #328

Open oldcastlehq opened 2 years ago

oldcastlehq commented 2 years ago

Hi Rui,

I noticed that the plugin https://www.fullbucket.de/music/whispair.html have window sizing issue (this is a Windows plugin, and I'm using Yabridge to run it on Linux).

Screenshot_20220310_230023

The plugin offers a VST2 version, which works fine. So, Robbert (Yabridge's author) suspected that Qtractor does not ask the plugin (VST3) for its size at all, so the window does not have the correct size. So, it's a problem only for VST3 plugins.

rncbc commented 2 years ago

is that the only VST3 plugin (via yabridge) that shows with incorrect size?

most VST3 plugins do report their intended editor window (GUI) size alright, at least the Linux native VST3 ones (I don't test any under any wine bridge, so you and Robert are to delve on that suspicion a little further, sorry)

oldcastlehq commented 2 years ago

After more digging, it seems that the issue only happens with Full Bucket plugins. I could not replicate the issue with other plugins at all.

Thanks!

oldcastlehq commented 2 years ago

Sorry. I was too fast to closed it. More digging is happening :-)

robbert-vdh commented 2 years ago

The problem is that Qtractor never even queries the editor's size. This is an excerpt from yabridge's tracing:

trace ``` 13:42:31 [whispair-4AJacdky] [host -> vst] >> 0: IEditController::createView(name = "editor") 13:42:31 [whispair-4AJacdky] [host <- vst] 13:42:31 [whispair-4AJacdky] [host -> vst] >> 0: IPlugView::isPLatformTypeSupported(type = "X11EmbedWindowID" (will be translated to "HWND")) 13:42:31 [whispair-4AJacdky] [host <- vst] kResultOk 13:42:31 [whispair-4AJacdky] [host -> vst] >> 0: IPlugView::setFrame(frame = ) 13:42:31 [whispair-4AJacdky] [host <- vst] kResultOk 13:42:31 [whispair-4AJacdky] [host -> vst] >> 0: IPlugView::attached(parent = 90177685, type = "X11EmbedWindowID" (will be translated to "HWND")) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: host_window: 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: parent_window: 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: wrapper_window: 104857600 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: wine_window: 109051907 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Reparenting 104857600 to 90177685 succeeded 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Reparenting 109051907 to 104857600 succeeded 13:42:31 [whispair-4AJacdky] [Wine STDERR] 0128:fixme:imm:ImeSetActiveContext (0x1990a60, 1): stub 13:42:31 [whispair-4AJacdky] [Wine STDERR] 0128:fixme:imm:ImmReleaseContext (0000000000010062, 0000000001990A60): stub 13:42:31 [whispair-4AJacdky] [Wine STDERR] 0128:fixme:dwrite:dwritefontface5_HasVariations 00000000019A1B00: stub 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Resizing wrapper window to 1127x776 13:42:31 [whispair-4AJacdky] [host <- vst] kResultOk 13:42:31 [whispair-4AJacdky] [host -> vst] >> 0: IPlugView::canResize() 13:42:31 [whispair-4AJacdky] [Wine STDERR] 0090:fixme:imm:ImeSetActiveContext (0x274fb0, 0): stub 13:42:31 [whispair-4AJacdky] [Wine STDERR] 0090:fixme:imm:ImmReleaseContext (0000000000010020, 0000000000274FB0): stub 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: ReparentNotify for window 104857600 to new parent 90177685, generated from 104857600 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Removing XdndAware properties from window 90177685 and all of its ancestors 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Unhandled X11 event 19 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: ConfigureNotify for window 104857600 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (0, 0) 13:42:31 [whispair-4AJacdky] [host <- vst] kResultFalse 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: ConfigureNotify for window 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (0, 0) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: ReparentNotify for window 90177685 to new parent 10493449, generated from 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Removing XdndAware properties from window 90177685 and all of its ancestors 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Unhandled X11 event 19 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: VisibilityNotify for window 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: FocusIn for window 90177685 (wine window active) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (1083, 526) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Active keyboard modifiers: 0 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Not grabbing input focus for window 90177685(already focused) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: VisibilityNotify for window 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: ConfigureNotify for window 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (1083, 526) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: EnterNotify for window 104857600 (wine window active) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (1083, 526) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Active keyboard modifiers: 0 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Not grabbing input focus for window 90177685(already focused) 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: ConfigureNotify for window 90177685 13:42:31 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (1083, 526) 13:42:33 [whispair-4AJacdky] [Wine STDERR] DEBUG: LeaveNotify for window 104857600 (wine window active, detail: 1, pointer pos: 1041, 736, pointer is not in Wine window) 13:42:33 [whispair-4AJacdky] [Wine STDERR] DEBUG: Not grabbing input focus for window 90177685(already focused) 13:42:33 [whispair-4AJacdky] [Wine STDERR] DEBUG: Unhandled X11 event 10 13:42:33 [whispair-4AJacdky] [Wine STDERR] DEBUG: EnterNotify for window 104857600 (wine window inactive) 13:42:33 [whispair-4AJacdky] [Wine STDERR] DEBUG: Spoofing local coordinates to (1083, 526) 13:42:33 [whispair-4AJacdky] [Wine STDERR] DEBUG: LeaveNotify for window 104857600 (wine window inactive, detail: 4, pointer pos: 1058, 763, pointer is not in Wine window) 13:42:49 [whispair-4AJacdky] [host -> vst] >> 0: IAudioProcessor::setProcessing(state = false) 13:42:49 [whispair-4AJacdky] [host <- vst] kResultOk ...after this there are only some more audio processor related things until the IPlugView::removed() call when clsoing the editor ```

After that IPlugView::canResize() (to which the plugin returned kResultFalse) there are no more IPlugView method calls until the editor gets closed again.

rncbc commented 2 years ago

and? what do you propose?

the host (qtractor) calls IPlugView::canResize() under IPlugFrame::resizeView() , which is supposed to catch the intended initial size anyway... the plugin replies it cannot resize, and then qtractor (the host) makes it fixed-size forever more with the exact size given... what gives?

robbert-vdh commented 2 years ago

This plugin does not call IPlugFrame::resizeView() however. And since Qtractor never asks the plugin how large its GUI is, the window is left at whatever the default size is.

rncbc commented 2 years ago

This plugin does not call IPlugFrame::resizeView() however.

maybe the question is why that is the case? (most) other plugins do, only these don't? baffles me.

anyway, if the above is true, the gui is still user resizeable or it is not?

robbert-vdh commented 2 years ago

If the plugin doesn't need to resize its view, why would it need to call IPlugFrame::resizeView()?

rncbc commented 2 years ago

good call, and then, yet again, what do you propose? when do you think the host should call IPlugView::canResize() ? or how should the host know the dang initial size anyway?

robbert-vdh commented 2 years ago

You can call IPlugView::canResize() before or after attached(), that shouldn't matter. But the problem here is that Qtractor enver sets the editor window's size to IPlugView::getSize(). The correct sequence of events would be:

  1. Qtractor creates a (hidden/not yet mapped) window for the editor.
  2. Qtractor should set the plug frame with IPlugView::setFrame() so the plugin can request a resize.
  3. Qtractor uses IPlugView::isPlatformTypeSupported() to check if the plugin supports X11 GUIs.
  4. Qtractor sets the DPI scale with IPlugViewContentScale::setContentScale(), if Qtractor handles HiDPI and the plugin supports it.
  5. (optional, you may still need step 6 anyways for misbehaving plugins) Qtractor asks the plugin how large its editor is with IPlugView::getSize() and resizes its own window accordingly. This returned size is already multiplied by the content scale factor.
  6. Qtractor calls IPlugView::attached() to allow the plugin to embed itself itself in the editor window.
  7. Repeat of step 4, in case the plugin does something wonky.
  8. Qtractor calls IPlugView::onSize() with the size it has resized its editor window to.
  9. Qtractor calls IPlugView::canResize() (can also do this before creating the window at all, but just like getSize() there may be one or two plugins that report the incorrect value before the attached() call. If the plugin returns kResultOk, make the editor window resizable and call IPlugView::checkSizeConstraint() followed by a window resize and IPlugView::onSize() if the plugin accepts the new size whenever the window is being resized.
  10. Not really part of this sequence, but whenever the plugin calls IPlugFrame::resizeView(), resize the window to that new size and call IPlugView::onSize() with the new size. Keep track of the current size to prevent sending this size twice since resizing the window would also trigger the behavior from 9).
  11. Finally Qtractor should map the window/make it visible.
rncbc commented 2 years ago

@robbert-vdh really appreciated, wholly thanks for the extensive explanation

unfortunately this isn't going to fly any day soon, at least from my keyboard, sorry (truth is, I don't feel the need, as said, most of VST3 plugins I love do work the way it is now; so why bother?)

let there be no restraints whatsoever for an incoming PR ntl. :) cheers

ps. fwiw. qtractor does all of the above in that sequence, but steps 4 and 5. -- mind you, the call to IPlugFrame::resizeView()(step 10) is always expected to occur under the auspices to IPlugView::attached() (step 6): a plugin failing to do so or never calling it might be the reason for the OP behavior -- so maybe a PR should probably focus on introducing step 5.

rncbc commented 2 years ago

please check whether df98d329 goes any better

robbert-vdh commented 2 years ago

That indeed fixes the issue with Whispair, Kontakt, and the other plugins that were affected by this!