This project has moved and is read-only. For the latest updates, please go here.

Refresh Parameter Count

Oct 17, 2015 at 2:42 AM
At some point the DAW will call GetPluginInfo() on my VST. How do I get it to call it again so I can tell it that there are new parameters? Is there some other way to tell the DAW that my VST has changed its params?
Oct 19, 2015 at 6:55 AM
Kruddler wrote:
At some point the DAW will call GetPluginInfo() on my VST. How do I get it to call it again so I can tell it that there are new parameters? Is there some other way to tell the DAW that my VST has changed its params?
Hi,
If you declare your VSTPlugInfo instance outside of GetPluginInfo, and let GetPluginInfo set the info when it is initially called, then you can reset your VSTPlugInfo instance properties (for example, _pluginInfo.ParameterCount), but then you have to call _hostStub.UpdatePluginInfo(_pluginInfo).

At least that has worked for me so far :-)

Cheers,
Oct 25, 2015 at 1:22 AM
Hey Msav, thanks heaps for the idea.

I've implemented that strategy and of course, it seems like this would be thew way to go. You would think that _hostStub.UpdatePluginInfo(_pluginInfo) would force the host to refresh the info right? Well, it doesn't seem to in Ableton. I debugged my code, and I'm definitely setting the number of parameters to 1 from 0. I.e. I incremented PluginInfo.ParameterCount but, Ableton never calls GetParameterLabel(int index), GetParameterDisplay(int index), or GetParameterName(int index). So, I'm left wondering if there is something else I need to do...
Oct 25, 2015 at 8:27 AM
Kruddler wrote:
Hey Msav, thanks heaps for the idea.

I've implemented that strategy and of course, it seems like this would be thew way to go. You would think that _hostStub.UpdatePluginInfo(_pluginInfo) would force the host to refresh the info right? Well, it doesn't seem to in Ableton. I debugged my code, and I'm definitely setting the number of parameters to 1 from 0. I.e. I incremented PluginInfo.ParameterCount but, Ableton never calls GetParameterLabel(int index), GetParameterDisplay(int index), or GetParameterName(int index). So, I'm left wondering if there is something else I need to do...
Interesting you should mention that :-)
I'm finding my host (Acoustica Mixcraft) doesn't seem to call GetParameterLabel/Display/Name either. :(
Either that or Im not doing something right.

Calling UpdatePluginInfo definitely changes the properties associated with the instance of _pluginInfo because I can report the new Parameter count, but the above Functions/Subs for me never seem to get called...
Oct 28, 2015 at 1:26 AM
Yeah, I'm left wondering if Ableton cares that I've called UpdatePluginInfo() ...

I'm not sure how to test if Ableton has actually received the message to do the update, or if there is something else I need to call on the host.
Oct 28, 2015 at 10:44 AM
Edited Oct 28, 2015 at 10:46 AM
The UpdatePluginInfo updates the C++ structure that is passed from the plugin to the host at startup, with values from the passed VstPluginInfo object. It also calls IOChanged on the host to give it a kick so to speak.

Whether or not these updated values are actually picked up at runtime is dependent on how the host is implemented. Some keep (a reference to) that structure around, others seem to copy over the values into their own data structures - these will not notice updates.

Another strategy may be to pre-allocate a number of parameters and re-assign these from 'NotUsed' to 'InUse' whenever you need more parameters... (Note that you can derive from VstParameter to maintain more info)

[2c]
Oct 31, 2015 at 12:15 AM
It seems as though Ableton simply does not care that VST.Net is sending an IOChanged message. That's a shame but I'll try our other strategy.

If I were to pre-allocate a number of parameters. How do I set an individual parameter to "NotUsed" or "InUse"? Can I do this through the normal IVstPluginCommandStub interface? Bare in mind that I'm not using the VstParameterManager. I'm building my own manager for this stuff because of the complex routing that I am trying to implement.
Nov 4, 2015 at 1:00 PM
NotUsed/InUse is not something defined in VST. It is simply a tag you use in your own code to know what parameters to take into account.
The VST host will always see all parameters - and the user may try to change/automate them...
Nov 5, 2015 at 7:50 PM
Hmmm... Unfortunately, that's not really a solution.

Other synths like Reaktor are able to add an remove parameters seamlessly in Ableton. That's the functionality I need to recreate. Perhaps I'm doing something wrong?
Nov 5, 2015 at 9:23 PM
Are these plugins affiliated with the host manufacturer? If so, they might be using hidden (non-VST 2.4) interfaces...
Nov 5, 2015 at 9:35 PM
No not at all. The host is Ableton, and the synth is Reaktor. Reaktor is by Native Instruments. Reaktor is somewhat similar to my synth in design. It is a modular synth and parameters are added and removed during the usage of the VST. I don't know if they are doing any kind of trickery.

You have given me an idea though. Perhaps I can hope Reaktor, and see if it is calling UpdatePluginInfo in order to tell my host that the parameters have changed...
Unfortunately, my synth always crashes when I try to load Reaktor as a plugin.
Nov 5, 2015 at 9:47 PM
You could also try the VST.NET WrapperPlugin sample? http://vstnet.codeplex.com/SourceControl/latest#Source/Samples/Jacobi.Vst.Samples.WrapperPlugin/PluginCommandStubAdapter.cs

It doesn't do much but you can turn on VST.NET tracing to see what calls are made.

If you attach a debugger to the host and then load your plugin and then load the Reaktor plugin (that is how it works right?), you should be able to see what the problem is.
Nov 9, 2015 at 9:06 AM
I'm really struggling with this.

The interface Jacobi.Vst.Core.Host.IVstHostCommandStub does not have the method UpdatePluginInfo. So, how is Reaktor supposed to let me know that the number of parameters has changed? Which method should I be looking at?

Or, should I be constantly polling the number of parameters with GetPluginInfo?
Nov 9, 2015 at 9:42 AM
Have you found out what methods are getting called?

There is no way for the plugin to communicate that it has updated its plugin info - other than the UpdateIO host method.
You can poll by calling AcceptPluginInfoData on the VstPluginContext (optionally raising events)...
Nov 9, 2015 at 10:02 AM
Have you found out what methods are getting called?

I'm looking in to it...

There is no way for the plugin to communicate that it has updated its plugin info - other than the UpdateIO host method

Where can I find that? Do you mean the IoChanged changed method? I am calling that.
Nov 9, 2015 at 10:09 AM
Reaktor calls:
UpdateDisplay when it is changing patches
SetParametersAutomated when I twiddle a knob
It doesn't call IoChanged
Nov 9, 2015 at 10:10 AM
I am calling SetParametersAutomated on the host, but it never calls back to ask for

GetParameterLabel
GetParameterDisplay
GetParameterName
Nov 9, 2015 at 10:11 AM
BTW: I have found that Reaktor starts with 1000 parameters and never changes, so I guess Ableton waits for one of those to change before it displays the parameter as automated.
Nov 9, 2015 at 10:19 AM
Once again, I go to bed unfulfilled...

Oh well! Getting closer I suspect. At least I got over the other humps today.
Nov 9, 2015 at 10:44 AM
Sorry, yes IOChanged().

Let me get this straight: Your plugin hosts Reaktor and want to pass on the changes in Reaktor?
And you are calling IOChanged on your plugin's host?

I keep getting confused...
Nov 9, 2015 at 10:58 AM
At this point, I'd be happy if ableton would just accept that my plug in has a parameter and it asked me what that parameter is called so it could be displayed in ableton.

At some point I got it half working. I.e. The parameter name showed up in ableton. But since then - nothing!
Nov 9, 2015 at 11:01 AM
But to answer your question Yes! I would like to route automation from ableton in to my synth and then route that to the instance of reaktor in my synth.
Nov 9, 2015 at 11:25 AM
So your'plugin republishes all parameters of all plugins you host yourself.

Hmmm, Parameters should be relatively simpel. I always find that isolating the problem in a separate test project that only focuses on the one issue resolves this type of thing quickly. I would suggest you through together a skeleton plugin that focuses on publishing parameters and get that working first...
Nov 9, 2015 at 7:40 PM
Edited Nov 9, 2015 at 9:10 PM
I'm not republishing every parameter. Actually, I've stripped it back to 1 parameter. I just want ableton to recognize 1 parameter and send me automation for it. I will try isolating the problem in a new app. Which sample would be the best for doing this? Ps: it doesn't have to host a vst. Getting parameters from the vst is not my issue right now.
Nov 10, 2015 at 8:57 AM
You could try to load the Delay sample plugin. It has parameters - but it is build with Framework. Still should demonstrate the concept quite well...
Nov 10, 2015 at 10:30 AM
I've had a look through this before, but I can't really figure out how this works. I think I'd have to dig deep in to the framework to understand how it works.

Off the top of your head, what call do you think I should be calling on the host to tell it I have a parameter for it to automate?
Nov 10, 2015 at 10:48 AM
Edited Nov 10, 2015 at 10:49 AM
As a plugin respond to GetParameter, SetParameter, CanParameterBeAutomated (optional: GetParameterLabel, GetParameterDisplay, GetParameterName, String2Parameter)
But most of all set a non-zero value in VstPluginInfo.ParameterCount

When the plugin changes a value of one of its parameters (internally) then you should call SetParameterAutomated on the host.

That's it.
Nov 10, 2015 at 10:52 AM
Yep. I'm convinced that I'm doing the right things. It's all very straight forward. For some reason, my Host Ableton is just not getting my messages.

I tried this as a test (I grabbed it from a sample):
            VstFileSelect fileSelect = new VstFileSelect();
            fileSelect.Command = VstFileSelectCommand.FileLoad;
            fileSelect.FileTypes = new VstFileType[2];
            fileSelect.FileTypes[0] = new VstFileType();
            fileSelect.FileTypes[0].Name = "Text Files";
            fileSelect.FileTypes[0].Extension = "txt";
            fileSelect.FileTypes[1] = new VstFileType();
            fileSelect.FileTypes[1].Name = "All Files";
            fileSelect.FileTypes[1].Extension = "*";
            fileSelect.Title = "Select a file";

            if (_MySynthPluginStub.HostStubAdapter.OpenFileSelector(fileSelect))
            {
            }
No file dialog is displayed. I think there's something wrong with my host object.
Nov 10, 2015 at 10:55 AM
Edited Nov 10, 2015 at 11:08 AM
Did you check the Host's CanDo 'OpenFileSelector' ??

And what's that HostStubAdapter?
Nov 10, 2015 at 7:50 PM
Edited Nov 10, 2015 at 7:55 PM
Some more pieces of the puzzle...

I forgot to mention this, but at some point, I'm not sure when, this VS error started coming up when I start Ableton from the debugger:

Exception thrown at 0x74A137F3 (rpcrt4.dll) in Ableton Live 9 Suite.exe: 0xC0000005: Access violation reading location 0x00000002.

Did you check the Host's CanDo 'OpenFileSelector' ??

I checked, and I get "Unknown".

what's that HostStubAdapter?

I get this from the GetPluginInfo method of my plugin stub. I'm not doing anything funny. It's just the raw object that gets passed in. It's of type Jacobi.Vst.Core.Plugin.VstPluginInfo Like this:
        public plugin.VstPluginInfo GetPluginInfo(plugin.IVstHostCommandStub hostCmdStub)
        {
            try
            {
                _HostStubAdapter = hostCmdStub;

                System.Diagnostics.Debug.WriteLine(hostCmdStub.GetProductString());
                System.Diagnostics.Debug.WriteLine(hostCmdStub.GetCurrentPluginID());
                System.Diagnostics.Debug.WriteLine(hostCmdStub.GetVersion());

                //TODO: Unhard code this 
                var uiDLLName = "MySynth.WPF.dll";
                GetEditorControl(uiDLLName);

                UpdatePluginInfo();
                return GetPluginInfo();
            }
            catch (Exception ex)
            {
                return null;
            }
        }
Here's the debug output BTW:

Live
1234
2400

This is my UpdatePluginInfo method. Although this doesn't change throughout the lifespan
        public void UpdatePluginInfo()
        {
            _PluginInfo = new plugin.VstPluginInfo();
            _PluginInfo.AudioInputCount = 2;
            _PluginInfo.AudioOutputCount = 2;
            _PluginInfo.ProgramCount = 1;
            _PluginInfo.Flags = VstPluginFlags.HasEditor | VstPluginFlags.CanReplacing | VstPluginFlags.IsSynth | VstPluginFlags.ProgramChunks;
            _PluginInfo.PluginID = 1234;
            _PluginInfo.PluginVersion = 1;
            _PluginInfo.ParameterCount = 1000;

        }
Nov 11, 2015 at 8:35 AM
I've got the sample Jacobi.Vst.Samples.WrapperPlugin.Clr4 working. It's perfect. It maps parameters directly. Now,I've just gotta figure out what it's doing differently.
Nov 11, 2015 at 9:39 AM
Great.

I still have a feeling you're doing something 'wrong' in your startup/bootstrap code -how you link up the objects- but I cannot put my finger on it.

Perhaps you can look at the way the Framework implemented the PluginCommandStub - it may give you an idea of what is different.
http://vstnet.codeplex.com/SourceControl/latest#Source/Code/Jacobi.Vst.Framework/Plugin/StdPluginCommandStub.cs

This class is created when the plugin is loaded. The derived class (of the actual plugin) implements CreatePluginInstance where it news up an instance of the plugins "root class". The other methods just translate between the raw VST spec and the Framework - those may not be very interesting to you. You may want to check out: GetPluginInfo (at the top) and CreatePluginInfo (at the bottom).

GetPluginInfo basically just collects all necessary objects needed for a working plugin: the Plugin root class (CreatePluginInstance), it wraps the IVstHostCommandStub for the plugin to talk back to the host and it creates the PluginInfo based on the capabilities of the plugin (root class) (CreatePluginInfo). Note that the VstPluginContext used here (Framework) is NOT the same you use when loading a plugin (Interop).
Nov 11, 2015 at 10:14 AM
AHHHH!!!!

I got it working, and then I changed the code and now it's not working again, and I don't know what I did!!! I didn't check in my change.

That's what Git is there for!!!! Ahhhh.
Nov 11, 2015 at 10:44 AM
OK. I got it working to a certain extent.

God knows how...

So, it seems that Ableton doesn't like it when you say you have 1000 parameters. I don't know why. Reaktor does is it...

But, the thing was that it was working all this time. It just doesn't work after loading a patch. I was testing on a project I was already loading. When I create a new instance of the synth without pre-loading a patch, it works fine. So, I'll have to figure out what is happening during the "SetChunk" process that makes it stop working.

Also, it lists all my parameters 0-8, even though I only want to display 1.

The good news is that Ableton now automates my hosted Vsts, and My synth can automate the parameters in Ableton so a great step forward at least.

I'll keep at it...