Random questions from me about vst

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

So I'm going to dedicate this thread to asking questions about how vst and related programming works. It's not a thread for asking RTFM type questions, but rather how to go about writing good code without having to resort to debugging both host and plugin. And here is my first question.

Is it correct to call CreateWindow() in the dispatch to effEditOpen? Basically, is it necessary to call CreateWindow() when the host closes the parent?

Post

camsr wrote: Thu Sep 12, 2019 5:24 am Is it correct to call CreateWindow() in the dispatch to effEditOpen? Basically, is it necessary to call CreateWindow() when the host closes the parent?
Assuming you are writing a plugin, you will receive a HWND as part of effEditOpen and you are supposed to CreateWindow() a child (ie. your editor window) with the host supplied HWND as parent.

Since you're asking about effEditOpen and CreateWindow() I'm not sure what you mean by "closes the parent" though. The parent HWND should exists at least until you receive an effEditClose.

Post

I misphrased that.. I meant it in the context of re-opening the window.
AFAIK the host destroys the parent window? So any attempt to hide/show the child window would be pointless is what I'm guessing about.

I'm not too experienced with winapi coding, but I don't want to make extra work through the api or cause a memory leak in a subsystem I barely know about.

Post

camsr wrote: Fri Sep 13, 2019 10:14 am I misphrased that.. I meant it in the context of re-opening the window.
AFAIK the host destroys the parent window? So any attempt to hide/show the child window would be pointless is what I'm guessing about.
The basic version is that whenever you receive an effEditOpen, you CreateWindow() a child to whatever HWND was given to you and whenever you receive effEditClose you DestroyWindow() that child. In theory, if the host window is closed, your old window gets destroyed as well, but whether the host chooses to also close to parent window is host business.

If you want to play defensive against hosts that destroy the parent first before calling effEditClose or fail the pair the calls properly (not sure if these are real problems, but there are some pretty wacky hosts out there), then you can keep a flag tracking whether your editor is open or not, catch WM_DESTROY to mark the editor as closed and only call DestroyWindow() in effEditClose if the flag indicates the window is still open.

Either way, you can't really show/hide a single window (in the WinAPI sense), as you must recreate the system level window every time the editor is opened. That said, if you treat the system-level HWND as a simple "viewport" wrapper though, you can certainly make rest of your editor persistent and then just attach/detach the HWNDs as they are created/destroyed (ie. you logically show/hide the same editor object, but the actual system-level HWND is different every time).

Post

The host I'm using (fls 10) has already destroyed the child window before the call to effEditClose. effEditClose is also called before WM_DESTROY of my window_proc().

So in this situation, calling DestroyWindow(child) in effEditClose seems useless :(
But I think the point is that other hosts may do it differently?

I keep the window handle in my plugin instance, it is set when the call to effEditOpen and CreateWindow() is made. I just noticed that I do not reset it until the next effEditOpen call. The only references to it outside of the window process is in effEditIdle, when it is used to invalidate the window. Is it safe to assume that effEditIdle is only called when the editor is open?

Post

Second question, more of an inquiry to wtf is going on rather than how to do something.

I put some MessageBox calls inside my DllMain branches to display what is being called when. Sometimes when OTHER plugins are loaded or unloaded, these message boxes get called... so far it's only been the thread attach/detach branches.

And in another strange instance, I had calls to other message boxes inside vst related functions (like getParamLabel etc.) when loading a different plugin.

Post

camsr wrote: Fri Sep 13, 2019 10:00 pm I put some MessageBox calls inside my DllMain branches to display what is being called when. Sometimes when OTHER plugins are loaded or unloaded, these message boxes get called... so far it's only been the thread attach/detach branches.
There is nothing "WTF" about this: if the other plugin creates threads, your DllMain gets notified about those... but seriously there's usually no reason to worry about it.
And in another strange instance, I had calls to other message boxes inside vst related functions (like getParamLabel etc.) when loading a different plugin.
Hosts might query the information several times, whenever they please, whatever triggers hosts to refresh it's info. Again, really you shouldn't worry about it.

Post

Next question, to avoid redrawing my plugin window when the host is minimized, I attempted to use IsWindowVisible() to control the redraw call. However, on further inspection, the branch for the case that the window is not visible does not get taken when the host is minimized.

Code: Select all

if(IsWindowVisible(myWindowHandle))
{
	RedrawWindow(myWindowHandle, 0, 0, RDW_INVALIDATE);
}
else { MessageBox(0, "Window not visible", 0, MB_OK); }
About IsWindowVisible:
If the specified window, its parent window, its parent's parent window, and so forth, have the WS_VISIBLE style, the return value is nonzero. Otherwise, the return value is zero.

Because the return value specifies whether the window has the WS_VISIBLE style, it may be nonzero even if the window is totally obscured by other windows.
What else can I do to not render my window when it's not necessary?

Post

IsIconic
(Are you sure this is that "about vst" stuff? ;)

Post

Max M. wrote: Sun Sep 15, 2019 10:27 pm IsIconic
(Are you sure this is that "about vst" stuff? ;)
That one only applies to top-level windows.

Post

Thanks :hihi: I know I said no RTFM stuff but that one was just hiding in plain sight.
Last edited by camsr on Sun Sep 15, 2019 10:57 pm, edited 1 time in total.

Post

camsr wrote: Sun Sep 15, 2019 9:10 pm Next question, to avoid redrawing my plugin window when the host is minimized, I attempted to use IsWindowVisible() to control the redraw call. However, on further inspection, the branch for the case that the window is not visible does not get taken when the host is minimized.
You should probably not worry about that. When you do a RedrawWindow or InvalidateRect those parts of the window will get marked for repaint and you will get WM_PAINT as necessary. The emphasis here is on "as necessary" because in general Windows will only redraw what it needs to redraw and redrawing is also the second lowest priority GUI message (ie. only WM_TIMER is lower) so as long as there are other messages (ie. further user interaction or something), these will be handled first.

In other words: you can safely call RedrawWindow any time the contents of the window change and Windows will then issue a WM_PAINT (some time in the future) when it actually wants that stuff to be drawn. The system will take care of checking whether the window is actually visible, so you really don't need to worry about that.

Post

mystran wrote: Sun Sep 15, 2019 10:56 pm
In other words: you can safely call RedrawWindow any time the contents of the window change and Windows will then issue a WM_PAINT (some time in the future) when it actually wants that stuff to be drawn. The system will take care of checking whether the window is actually visible, so you really don't need to worry about that.
I suppose I can verify that by animating my drawing with an increment thing and see if it changes expectedly. While the window is minimized, it should not be calling WM_PAINT IOW?

Just tested that and you are correct.

Post

camsr wrote: Sun Sep 15, 2019 11:06 pm
mystran wrote: Sun Sep 15, 2019 10:56 pm
In other words: you can safely call RedrawWindow any time the contents of the window change and Windows will then issue a WM_PAINT (some time in the future) when it actually wants that stuff to be drawn. The system will take care of checking whether the window is actually visible, so you really don't need to worry about that.
I suppose I can verify that by animating my drawing with an increment thing and see if it changes expectedly. While the window is minimized, it should not be calling WM_PAINT IOW?
Windows might send a WM_PAINT if it wants to update the thumbnail (eg. for task-bar hovers or something), but seriously there's no need to worry about it, unless you're going to actually fetch the actual update regions in order to avoid drawing outside that area.

Note that you can also get WM_PAINT at various times without calling RedrawWindow. This typically happens when a hidden window becomes visible or when Windows lost the contents of the window (or part of the window, when another window moves on top, etc) for whatever reason. It is usually best to assume WM_PAINT is called "as necessary" and not make too many assumptions about when exactly this happens.

While I realise you're probably talking about debug-animations here, for any actual animations you should always use a proper timer of some sort (eg. call RedrawWindow repeatedly and then check the actual time in WM_PAINT). Otherwise your animation speed might vary quite randomly depending on when Windows decides to send you the WM_PAINTs.

Post

Edit: Syncing the threads is a pain.

Post Reply

Return to “DSP and Plugin Development”