Steinberg: No more VST2 Development

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

aciddose wrote:Actually those are what I was referring to. Both will lead to WM_PAINT immediately. I was surprised to find this with InvalidateRect.
It seems to be working now, so my comments about it being exactly the same are invalid.

My point still stands regarding the fact you're just deferring through the OS API though. The only way to ensure you get reliable animation framerates is to be in control of redraw directly from your own thread. A plugin launching a thread for animation doesn't seem like a brilliant idea in my opinion, whatever though if it works.

What doesn't work is calling InvalidateRect from your own timer thread however, so we're back to square one.

The host must provide idle() in the GUI thread to allow you to call InvalidateRect, which then defers the update until the host calls PeekMessage.

So we still need editor->idle() to make these updates work, even if InvalidateRect works correctly. It also is still not a very practical method to implement animation because the host can't control it directly and there is no way to know exactly how long the WM_PAINT message will be deferred or exactly how the invalid rectangles will be collated.

It is easy for the host to ensure 16ms calls to editor->idle, not for WM_PAINT.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

small note, slightly OT from thread brief - you should be using sendmessage for WM_PAINT, use postmessage. I realise that timings for animation can possibly become questionable under heavy CPU load, but if you have heavy CPU load, sendmessage is going to be suffering the same way..

But I agree that a sensible managed way of the host calling idle should be found. Whatever it uses, whether 16ms or some other arbitrary value, it would be better, or more useful, for the plugin to query the host for a ms value, and perform its own calculations on how many frames to skip between calls.
Image

Post

duncanparsons wrote:small note, slightly OT from thread brief - you should (ad: not?) be using sendmessage for WM_PAINT, use postmessage.
I would have never used sendmessage anyway, I just used the wrong example to illustrate my point about it. I should have said postmessage or invalidaterect of course.

The core of the issue is that these are then deferred to a later point in the same thread anyway, making the whole round-about way of dealing with the issue a bit ridiculous. The idea of adding the WM_PAINT to the queue only when it is empty is as I understand it of course to ensure redraw does not interfere with UI responsiveness or other more important messages and that makes a little sense, yes.

Still though the very same redraw will happen in the same way in the same thread at some point, and as soon as that starts to happen any other messages will have to wait! So from the perspective of a windowing system that has control of processes individually, that makes sense to prevent deadlocking the whole OS.

In terms of a single process however like a host, its windows including plugin windows, if any of these chooses to lock up you'll be stuck no matter whether it was in idle() or peekmessage(). Unless I'm wrong about that in some way I don't see the difference providing any significant benefit in the context of GUI updates happening in a single thread.

As for whatever rate the host calls idle, probably even a system where the plugin can make a request might make sense. Although in my opinion it would be better to just have a rule like "make an attempt to level idle calls to provide as close to the refresh rate as possible to all plugins" and if the host wants to use 30ms, 60ms, whatever that is fine. The plugin should use its own timing capability to figure out whether to update anything or just return from the idle call.

This is actually an interesting topic to discuss regarding plugin APIs; How much functionality should go into this and what would the advantages be? If the host is going to need to have the ms value as a float for this update anyway, why shouldn't that be made available to the plugin of course as the plugin would just add overhead calculating the same value for itself.

Perhaps someone should start a new thread about a plugin API to discuss this more seriously. I think the "No more VST2 Development" topic has already been settled unless we hear anything new about it.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

I think a way forward might be to get some small additions to VST2 together and approach Ableton, FL, Cockos, and some others to discuss them implementing a small number of new features in their hosts. It may come to nothing, but a Developers VST2.5 is certainly worth a shot. Use a clean-room VST-compatible implementation, and off we go..
Image

Post

aciddose wrote:My point still stands regarding the fact you're just deferring through the OS API though. The only way to ensure you get reliable animation framerates is to be in control of redraw directly from your own thread. A plugin launching a thread for animation doesn't seem like a brilliant idea in my opinion, whatever though if it works.
You dont need to spawn a thread. Just use SetTimer to attach a timer to your window and you'll get WM_TIMER messages sent via the message queue to your WindowProc.

Or you can use a TimerQueueTimer, and then use that callback to post a user/custom message to the window, and then handle that with RedrawWindow().

If the host is required to provide GUI:Idle() then how does it ensure that it doesn't call that concurrently with the OS calling the WindowProc? It cant. So either you mandate Idle() and all the GUi code needs locks, or you let the plugin handle it itself.

For such a simple thing it seems (to me at least) that putting this on the host makes things worse, more complicated, and unnecessarily so.
Chris Jones
www.sonigen.com

Post

duncanparsons wrote:I think a way forward might be to get some small additions to VST2 together and approach Ableton, FL, Cockos, and some others to discuss them implementing a small number of new features in their hosts. It may come to nothing, but a Developers VST2.5 is certainly worth a shot. Use a clean-room VST-compatible implementation, and off we go..
Why not just keep using VST2.4? I mean if some hosts implement 2.5 and some dont, do I now need to make two version of my plugin? I dont see any benefit from that.
Chris Jones
www.sonigen.com

Post

sonigen wrote:
aciddose wrote:My point still stands regarding the fact you're just deferring through the OS API though. The only way to ensure you get reliable animation framerates is to be in control of redraw directly from your own thread. A plugin launching a thread for animation doesn't seem like a brilliant idea in my opinion, whatever though if it works.
You dont need to spawn a thread. Just use SetTimer to attach a timer to your window and you'll get WM_TIMER messages sent via the message queue to your WindowProc.

Or you can use a TimerQueueTimer, and then use that callback to post a user/custom message to the window, and then handle that with RedrawWindow().

If the host is required to provide GUI:Idle() then how does it ensure that it doesn't call that concurrently with the OS calling the WindowProc? It cant. So either you mandate Idle() and all the GUi code needs locks, or you let the plugin handle it itself.

For such a simple thing it seems (to me at least) that putting this on the host makes things worse, more complicated, and unnecessarily so.
WM_TIMER is dispatched only when the host calls dispatch. If it does not, the message isn't dispatched. So it is exactly like idle(), just with added windows overhead.

Of course it can ensure that it doesn't call idle() with the OS calling the window proc, because they're all called from only one thread. The host manages the OS dispatching and unless you force a message bypassing the queue it all comes down to exactly the same place. Whether you call idle(), peekmessage+dispatch or both doesn't matter. In fact I recommend that you call idle() in the same location, but measure the time between calls to ensure 16ms has passed (or 1/refresh).

If the host then also wants to throttle calls to idle, it can measure the time between individual idle calls and increase the number of cycles to skip for any plugin taking long enough to put the total over 16ms. Just find the max time and throttle that idle() by 1, then next cycle find the max time and so forth until the total is below 16ms. This is the major advantage to the idle() method I propose which is simply not possible if you use the OS functions.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

If the host then also wants to throttle calls to idle, it can measure the time between individual idle calls and increase the number of cycles to skip for any plugin taking long enough to put the total over 16ms. Just find the max time and throttle that idle() by 1, then next cycle find the max time and so forth until the total is below 16ms. This is the major advantage to the idle() method I propose which is simply not possible if you use the OS functions.
I must have had a brain lapse over the threading, you're right the host GUI and plugin GUI should be in the same thread.

WM_TIMER already does that. It's a low priority message and is only sent when nothing more important in the message queue. It wont send a new message till the previous one is handled.

Anyway, from my point of view I'd rather handle it myself. But I can see other people would prefer the host to handle it. And I could imagine that host developers might like to have some control over it as you say.
Chris Jones
www.sonigen.com

Post

arne wrote:As already said: then ask on the vst mailing-list. I've never seen a question on the list about the asynchronous message stuff and that it may be a problem. That the SDK documentation needs to better is no secret, and hopefully will be better over time. But to be fair, it's much more than one single HTML page. Maybe you haven't read them all ?
As a developer with close to 20 years experience your documentation and the way you handle developer interaction, bug reports and so on are hardly examples for excellence and modernity, sorry.

Post

hokkaido wrote:
arne wrote:As already said: then ask on the vst mailing-list. I've never seen a question on the list about the asynchronous message stuff and that it may be a problem. That the SDK documentation needs to better is no secret, and hopefully will be better over time. But to be fair, it's much more than one single HTML page. Maybe you haven't read them all ?
As a developer with close to 20 years experience your documentation and the way you handle developer interaction, bug reports and so on are hardly examples for excellence and modernity, sorry.
:tu:

They should be ashamed of themselves and commit ritual suicide to honor their bosses.

Post

For the record, I went ahead and asked the question and got an answer. That however only helped us to decide to discard "full VST3" and rewrite our layer to "VST3 light" with no separation of GUI and DSP.

Post

Since there's absolutely no point in separating GUI and DSP unless you want to run them on different machines or as separate processes, both of which would be plain stupid for years to come, it's a good decision IMO.
"Until you spread your wings, you'll have no idea how far you can walk." Image

Post

Is there not a natural split between GUI and DSP because they operate on different threads? Shouldn't you take measures to make their interaction glitch (lock) free? Isn't that a best practice?

I always got the impression it was...
Grtx, Marc Jacobi.
VST.NET | MIDI.NET

Post

obiwanjacobi wrote:Is there not a natural split between GUI and DSP because they operate on different threads? Shouldn't you take measures to make their interaction glitch (lock) free? Isn't that a best practice?

I always got the impression it was...
Yes, for parameters that set structures, arrays or more than one process coefficient, you might need to. But in the case of parameters that are atomic variables, glitches are impossible.

Post

obiwanjacobi wrote:Is there not a natural split between GUI and DSP because they operate on different threads? Shouldn't you take measures to make their interaction glitch (lock) free? Isn't that a best practice?

I always got the impression it was...
The problem wasn't ever the separation for us, but the point where the cut was made. We store the information about parameters in our dsp modules, and the list of parameters is created when the dsp part is created. Unfortunately there's no obvious way for the VST3 controller to reliably retrieve that information from the dsp object, so we needed crude hacks to get there, including maintaining a phantom-dsp-object. Which then led to mashed up pointers because the UI can have pointers to the controller.

So actually, with asynchronous messages and no way to determine any guranteed point of time any information is available, this won't work ever.

It would work if it was done consequently, i.e. if host-plug-in communication was asynchronous too. It's kind of a strange decision to put the burden of asynchronous communication onto the plug-in while at the same time requiring immediate results when the host queries the plug-in.

Post Reply

Return to “DSP and Plugin Development”