Open petrikaj opened 1 year ago
Looking at the MrsWatson source code, this seems to be where the 'Programs' is being printed:
It reads from:
data->pluginHandle->numPrograms
data->pluginHandle effGetProgramNameIndexed
nameBuffer->data
data->pluginHandle effGetProgramName
nameBuffer->data
Googling for effGetProgramNameIndexed
, it seems to be part of the VST2 SDK or similar.
Eg. Here's a go package that implements bindings for it:
Build vst2 plugins and hosts with Go
vst2 implements VST2 SDK API. It provides capabilities to build both VST2 hosts and plugins.
// EffGetProgramNameIndexed passed to get program name by index.
// Index: program index.
// Ptr: *[maxProgNameLen]uint8 buffer for program name.
// Return: true for success.
EffGetProgramNameIndexed
Pedalboard doesn't seem to support VST2, but not sure if there is an equivalent function in VST3. We can start by looking at the VST3 SDK:
VST 3 Plug-In SDK
Searching for effGetProgramNameIndexed
doesn't seem to turn up any results there (neither does GetProgramName
/ ProgramName
)
Clicking through from that repo lead me to:
And searching that repo for GetProgramName
lead me to this definition:
IUnitInfo describes the internal structure of the plug-in.
- The root unit is the component itself, so getUnitCount must return 1 at least.
- The root unit id has to be 0 (kRootUnitId).
- Each unit can reference one program list - this reference must not change.
- Each unit, using a program list, references one program of the list.
/** Component intern program structure. */
/** Gets the count of Program List. */
virtual int32 PLUGIN_API getProgramListCount () = 0;
/** Gets for a given index the Program List Info. */
virtual tresult PLUGIN_API getProgramListInfo (int32 listIndex, ProgramListInfo& info /*out*/) = 0;
/** Gets for a given program list ID and program index its program name. */
virtual tresult PLUGIN_API getProgramName (ProgramListID listId, int32 programIndex, String128 name /*out*/) = 0;
/** Gets for a given program list ID, program index and attributeId the associated attribute value. */
virtual tresult PLUGIN_API getProgramInfo (ProgramListID listId, int32 programIndex,
CString attributeId /*in*/, String128 attributeValue /*out*/) = 0;
/** Basic Program List Description.
\see IUnitInfo
*/
struct ProgramListInfo
{
ProgramListID id; ///< program list identifier
String128 name; ///< name of program list
int32 programCount; ///< number of programs in this list
};
Then we can find the definition for ProgramListID
in the following:
typedef int32 ProgramListID; ///< program list identifier
So it definitely seems like the concept of 'programs' still exists in the VST3 SDK.
Looking at an example CLI app for using the vst-rs
Rust bindings for VST2, they don't seem to print the 'programs' details either; but they do have a section called 'presets':
// Get the plugin information
let info = instance.get_info();
println!(
"Loaded '{}':\n\t\
Vendor: {}\n\t\
Presets: {}\n\t\
Parameters: {}\n\t\
VST ID: {}\n\t\
Version: {}\n\t\
Initial Delay: {} samples",
info.name, info.vendor, info.presets, info.parameters, info.unique_id, info.version, info.initial_delay
);
Tracing through the code a bit, I found the definition for Info
, which again doesn't mention 'program', but does mention 'presets':
Tracing through the code a bit more I found this implementation of PluginInstance
, which seems to equate presets with programs:
plug.info = Info {
// ..snip..
presets: effect.numPrograms,
// ..snip..
preset_chunks: flags.intersects(PluginFlags::PROGRAM_CHUNKS),
}
Looking at the vst3-sys
Rust bindings for VST3:
pub type ProgramListID = i32;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ProgramListInfo {
pub id: i32,
pub name: [u16; 128],
pub program_count: i32,
}
#[com_interface("3D4BD6B5-913A-4FD2-A886-E768A5EB92C1")]
pub trait IUnitInfo: IUnknown {
// ..snip..
unsafe fn get_program_list_count(&self) -> i32;
unsafe fn get_program_list_info(&self, list_index: i32, info: *mut ProgramListInfo) -> tresult;
unsafe fn get_program_name(&self, list_id: i32, program_index: i32, name: *mut u16) -> tresult;
unsafe fn get_program_info(
&self,
list_id: i32,
program_index: i32,
attribute_id: *const u8,
attribute_value: *mut u16,
) -> tresult;
unsafe fn has_program_pitch_names(&self, id: i32, index: i32) -> tresult;
unsafe fn get_program_pitch_name(
&self,
id: i32,
index: i32,
pitch: i16,
name: *mut u16,
) -> tresult;
// ..snip..
#[com_interface("8683B01F-7B35-4F70-A265-1DEC353AF4FF")]
pub trait IProgramListData: IUnknown {
unsafe fn program_data_supported(&self, list_id: i32) -> tresult;
unsafe fn get_program_data(
&self,
list_id: i32,
program_idx: i32,
stream: SharedVstPtr<dyn IBStream>,
) -> tresult;
unsafe fn set_program_data(
&self,
id: i32,
idx: i32,
stream: SharedVstPtr<dyn IBStream>,
) -> tresult;
}
Here's less technical explanation on the github docs:
Just wanted to note that #297 just got merged, which may provide one potential angle of a solution here:
Apologies that this took so long - I've just made a couple changes and merged this, and it should be available as of v0.9.6 (released later today).
I did rename this property to
raw_state
instead of juststate
, as the state data is often (but not always) encoded in a format that I hope we can parse and expose as a.state
parameter later. (i.e.: if the state of a VST3 is valid XML, Pedalboard could unwrap and parse that XML directly to make the client code simpler.)Originally posted by @psobot in https://github.com/spotify/pedalboard/issues/297#issuecomment-2119315514
Docs:
A bytes object representing the plugin’s internal state. For the VST3 format, this is usually an XML-encoded string prefixed with an 8-byte header and suffixed with a single null byte.
A bytes object representing the plugin’s internal state. For the Audio Unit format, this is usually a binary property list that can be decoded or encoded with the built-in plistlib package.
I have tried to access and change iZotope's VST plugins' Program presets but it seems they are not exposed.
Parameters work ok.
Here's what MrsWatson prints out from plugin —display-info
Notice it's not part of the parameters.
Using plugin.show_editor() allows to access those presets and changing them will change the parameters accordingly after quitting the showeditor(/).
MrsWatson allows to change it while loading the plugin: "mrswatson64 --plugin 'plugin_name,preset_name’ -i input.wav -o output.wav"