Automation Parameter for Preset Change

My own VST3 host can correctly load VST3 plugins.
On some plugins, preset selection works fine, on others it does not work. What could be the reason?
I obtain the ProgramChangeParameterId from :

	FUnknownPtr<IUnitInfo> unitInfo(App_editController);
	if (unitInfo)
	{
		const unsigned int program_list_count = unitInfo->getProgramListCount();
			ProgramListInfo programlist_info = {};
			for (unsigned int i = 0; i < program_list_count; ++i)
			{
				tresult t = unitInfo->getProgramListInfo(i, programlist_info);
				if (!t) // 0=kResultTrue
				{
					BankPreset.bank_id = programlist_info.id;

					if (found_i == 0)
					{						
						ProgramChangeParameterId = programlist_info.id; // Program Change Parameter ID 
		            }    
                 }

            }
     }        

And I get the exact same value when obtaining it from:

	const unsigned int ParameterCount = (const unsigned int)App_editController->getParameterCount();
	Steinberg::Vst::ParameterInfo info = {};
	for (unsigned int i = 0; i < ParameterCount; ++i)
	{
		tresult t = App_editController->getParameterInfo(i, info);
		if (!t)
		{
			const int isProgramChange = (int)((info.flags & info.kIsProgramChange) != 0);
			if (isProgramChange) { ProgramChangeParameterId = info.id; }
        }
    }

Then, when its applied:

double valueNormalized  = (double)id / (double)preset_count
paramTransferrer.addChange (ProgramChangeParameterId, valueNormalized , sampleOffset);

paramTransferrer is a member of AudioClient as
defined in the SDK

Then its correctly processed in the preprocess method.
and then send to the plugin.
This all works for some plugins, but for others it does not, although for those plugins the presets can be changed from within other DAW’s over the DAW’s preset menu.

Thank you.

On start of the video a plugin, where preset selection works in my own VST3; At second 11 in the video the 2nd plugin, where the selection does not work. Only the internal preset menu of the plugin works there. Both plugin’s preset selection works without problems in another DAW.

Did you try the plug-ins example of the VST SDK: VST 3 Plug-in Examples - VST 3 Developer Portal (steinbergmedia.github.io) and VST 3 Plug-in Examples - VST 3 Developer Portal (steinbergmedia.github.io) ?

note: it is recommended to use:
if (t == kResultTrue)

Thank you for your answer.
I changed (!t) into (t == kResultTrue) in my code.
Then I tried out programchange.vst3,
in the file PlugController::setParamNormalized I found:
componentHandler->restartComponent (kParamValuesChanged)
which is simply ignored by my own VST3 host.
Cause in this post its said, that “kParamValuesChanged) will only trigger the host to invalidate its caches for the parameter titles and values. It will not send parameter changes to the processor in its process function and it will not deactivate and activate the processor.”
So do I actually need to implement anything there?

when a preset is selected from the generic menu in programchange.vst3, yet my host processes :
Selected Preset: 47 (0-based; “Prog 48” in the generic UI)
AudioClient::setParameter with id=1
=> paramTransferrer.addChange
=> paramTransferrer.transferChangesTo (inputParameterChanges);
=> a derivative of AudioClient::process
which reports:

processData.inputParameterChanges=1fc84759a18h
processData.inputParameterChanges->getParameterCount()=1
processData.inputParameterChanges->getParameterData()=1fc847aa8e0h
param_id=1h count =1  
point[0] @Sample:0 Value=0.470000

and it calls
processor->process(processData)
which succeeds with kResultOk
In all plugins i tested this all worked, but in some plugins the preset was not changed (although other DAW’s correctly change it) and in
programchange.vst3 to me its a bit unclear, how I should investigate further from now.

Since I (additionally) added
App_editController->setParamNormalized ( ProgramChangeParameterId, valueNormalized);
now ComponentHandler::restartComponent is called. [If I only call setParamNormalized without the paramTransferrer calls, then the first plugin in the video of last post does not anymore change its preset]
App_editController was initialialized this way:
App_editController = _plugProvider->getController();

So obviously I need to call PlugController::setParamNormalized additionally to adding the program change parameter to the transferrer list?

my host builds this generic UI for it:

my host finds this preset information when loading programchange.vst3:

ParameterCount=3
Parameter: 0
getParameterInfo returns t= 0
ParamID (info.id): 0
canAutomate: 1
isBypass: 1
isProgramChange: 0
autoparam.id: 0
autoparam.bypass: 1
autoparam.selectPreset: 0
autoparam.defaultNormValue: 0.000000
autoparam.defaultValue: 0.000000
autoparam.minValue: 0.000000
autoparam.maxValue: 1.000000
autoparam.automation_identifier: Bypass
autoparam.unit_descriptor: Bypass
autoparam.params.steps: 1
autoparam.params.unitId: 0
Parameter: 1
getParameterInfo returns t= 0
ParamID (info.id): 1
canAutomate: 0
isBypass: 0
isProgramChange: 1
autoparam.id: 1
autoparam.bypass: 0
autoparam.selectPreset: 1
autoparam.defaultNormValue: 0.000000
autoparam.defaultValue: 0.000000
autoparam.minValue: 0.000000
autoparam.maxValue: 99.000000
autoparam.automation_identifier: Bank
autoparam.unit_descriptor: Bank
autoparam.params.steps: 99
autoparam.params.unitId: 0
Parameter: 2
getParameterInfo returns t= 0
ParamID (info.id): 2
canAutomate: 1
isBypass: 0
isProgramChange: 0
autoparam.id: 2
autoparam.bypass: 0
autoparam.selectPreset: 0
autoparam.defaultNormValue: 1.000000
autoparam.defaultValue: 1.000000
autoparam.minValue: 0.000000
autoparam.maxValue: 1.000000
autoparam.automation_identifier: Gain
autoparam.unit_descriptor: Gain
autoparam.params.steps: 0
autoparam.params.unitId: 0
unit_count=1
unitInfo 0 info.id=0
unitInfo 0 info.name=Root
unitInfo 0 info.programListId=1
selected_unit=0
unitInfo->getProgramListCount() returns program_list_count=1
program_count=100
programlist_info.id=1
programlist_info.name=Bank
unitInfo->getUnitCount=1
progname 0 =Prog 1
preset.preset_identifier=Prog 1
progname 1 =Prog 2
preset.preset_identifier=Prog 2
progname 2 =Prog 3
preset.preset_identifier=Prog 3
...
preset.preset_identifier=Prog 99
progname 99 =Prog 100
preset.preset_identifier=Prog 100
autoparams_count=3

However, since calling additionally
App_editController->setParamNormalized ( ProgramChangeParameterId, valueNormalized);
some other plugins now work correctly.

I noticed, that most of the plugins, for which the preset selection does not work properly, seam all to be SINGLE COMPONENT and also their audio output is not present on some. Is it required that those single component plugins run always on one thread? Currently they are running on 2 threads: one UI thread and a “processing” thread, which runs the “process” method; The preset handling is done in the “processing” thread. Could that be the reason? Should it better be done on the UI thread?

I moved the call to App_editController->setParamNormalized () into the UI thread; And while it works for most plugins, its still failing on the second one mentioned in the video in a previous post of this thread.

It seems, that I have found the root cause. Somehow the automation parameter id is not correctly processed in my host for that plugin. If I enter that parameter id in the code, now the preset-change works.

The code, which caused the problem is in my first post within this thread:
ProgramChangeParameterId = programlist_info.id;
during reading from the unitInfo for that plugin gives a different result, than the code when enumerating through the parameters
if (isProgramChange) { ProgramChangeParameterId = info.id; }

I used uinfo.programListId as automation parameter id (as seen in the first post in thisthread) cause I found it here
uinfo.programListId = kProgramChangeParamID;
in this post
And also in the mentioned sample mdaBaseProcessor.cpp its used this way: uinfo.programListId = kPresetParam;
Did i misunderstand something? So is there a difference between MIDI program change and Automation Parameter Program Change?
Some plugins call their presets “MIDI Programs”.
So please tell me, what is the correct way ?
I also contacted the developer of that plugin to clarify this.