Before this commit it was possible for the plugin to transfer control
to its internal MessageThread and call
IComponentHandler::restartComponent() from it.
Previously, activateBus would fail if the new BusesLayout wasn't
supported, as reported by isBusesLayoutSupported. However, according to
the VST3 docs, a host is allowed to enable and disable buses in any
combination, and the plugin should be able to handle this gracefully.
The ability to enable/disable individual buses without failure is
particularly important because there's no VST3 API to set a complete bus
layout in one go. That is, the only way to set all buses active or all
buses inactive is to set the appropriate state on each bus individually,
which in turn means that at some point, some buses will be active and
some will be inactive. Disallowing such 'intermediate' states may
prevent the host from putting the plugin into other (valid) states.
To ensure that the VST3 wrapper always accepts activateBus calls, it now
keeps track of the activation state of each bus as requested by the
host. When the host tries to change the activation state, the wrapper
will try to set the host's "ideal" bus layout on the AudioProcessor. If
this fails, the AudioProcessor will retain its previous bus layout.
The buffer remapping inside the process callback has been made more
robust, to handle cases where the host and the AudioProcessor disagree
about the activation state of each bus:
For input buses:
- If the host has activated the bus, but the AudioProcessor decided to
keep the bus inactive, the host's input will be ignored.
- If the host deactivated the bus, but the AudioProcessor wanted to keep
the bus active, the AudioProcessor will be provided with silence on
that bus.
For output buses:
- If the host has activated the bus, but the AudioProcessor decided to
keep the bus inactive, the wrapper will clear the host's output
bus buffers.
- If the host deactivated the bus, but the AudioProcessor wanted to keep
the bus active, the AudioProcessor's output on that bus will be
ignored.
The AudioBuffer passed to the wrapped AudioProcessor will no longer
contain any pointers from the host's ProcessData. Instead, the host's
inputs will be copied (in JUCE channel order) to a temporary buffer,
and this temporary buffer will be passed to
AudioProcessor::processBlock. After processBlock, the buffer contents
will be copied to the host's output buffers.
This change is intended to avoid a potential issue when reordering
channels into JUCE order, which may necessitate copying a host input
channel to a different host output channel. In the case that the host is
using the same buffers for both inputs and outputs, copying an input to
an output channel may end up overwriting another input channel, breaking
the plugin's inputs.
Previously, activateBus would fail if the new BusesLayout wasn't
supported, as reported by isBusesLayoutSupported. However, according to
the VST3 docs, a host is allowed to enable and disable buses in any
combination, and the plugin should be able to handle this gracefully.
The ability to enable/disable individual buses without failure is
particularly important because there's no VST3 API to set a complete bus
layout in one go. That is, the only way to set all buses active or all
buses inactive is to set the appropriate state on each bus individually,
which in turn means that at some point, some buses will be active and
some will be inactive. Disallowing such 'intermediate' states may
prevent the host from putting the plugin into other (valid) states.
To ensure that the VST3 wrapper always accepts activateBus calls, it now
keeps track of the activation state of each bus as requested by the
host. When the host tries to change the activation state, the wrapper
will try to set the host's "ideal" bus layout on the AudioProcessor. If
this fails, the AudioProcessor will retain its previous bus layout.
The buffer remapping inside the process callback has been made more
robust, to handle cases where the host and the AudioProcessor disagree
about the activation state of each bus:
For input buses:
- If the host has activated the bus, but the AudioProcessor decided to
keep the bus inactive, the host's input will be ignored.
- If the host deactivated the bus, but the AudioProcessor wanted to keep
the bus active, the AudioProcessor will be provided with silence on
that bus.
For output buses:
- If the host has activated the bus, but the AudioProcessor decided to
keep the bus inactive, the wrapper will clear the host's output
bus buffers.
- If the host deactivated the bus, but the AudioProcessor wanted to keep
the bus active, the AudioProcessor's output on that bus will be
ignored.
The AudioBuffer passed to the wrapped AudioProcessor will no longer
contain any pointers from the host's ProcessData. Instead, the host's
inputs will be copied (in JUCE channel order) to a temporary buffer,
and this temporary buffer will be passed to
AudioProcessor::processBlock. After processBlock, the buffer contents
will be copied to the host's output buffers.
This change is intended to avoid a potential issue when reordering
channels into JUCE order, which may necessitate copying a host input
channel to a different host output channel. In the case that the host is
using the same buffers for both inputs and outputs, copying an input to
an output channel may end up overwriting another input channel, breaking
the plugin's inputs.
This is intended to fix two issues:
- In REAPER, setting automation recording to 'Latch', recording some
automation, saving and reloading the project, then starting playback causes
automation data to be overwritten. This appears to be because REAPER
interprets parameter change messages sent during state restoration as
originating from the user.
- In Ableton Live, automation lanes are sometimes disabled when loading
projects. This also seems to be because the setStateInformation call
may send parameter change messages back to the host.
According to the docs for kAudioUnitProperty_ClassInfo, the host is
required to notify all parameter listeners that the parameter values may
have changed, implying that the plugin need not send its own parameter
change notifications during state restoration.
Some AUv3 presets crash when querying the set of presets in Loopy Pro.
The issue seems to be because `addPresets` may end up being called
concurrently with the host's queries.
Some AUv3 presets crash when querying the set of presets in Loopy Pro.
The issue seems to be because `addPresets` may end up being called
concurrently with the host's queries.
The following was observed for a VST3 plugin hosted in Live 11.1 with
auto-scaling disabled:
- It never calls setContentScaleFactor on the plugin's UI, so the
wrapper has to check the current display on a timer and update the
current scale factor when necessary.
- It calls canResize on the plugin view after opening it, but doesn't
seem to respect the result of this call. According to the VST3
documentation, a host is supposed to only call checkSizeConstraint
during a live resize operation (which should only happen if the plugin
reports it can resize), but Live calls this function every time the
user drags the editor. It also passes the result of this function to
onSize, whether or not checkSizeConstraints reported success.
- When dragging an editor between displays, Live will continue to call
checkSizeConstraint and onSize with the editor’s old size in physical
pixels. In some cases, JUCE's "scale factor check" timer callback
fires, resizes the view to the correct size, and then Live
asynchronously calls onSize again with the editor's old size in
physical pixels, resulting in the editor being set to the wrong
logical size.
This patch ensures that checkSizeConstraint always returns the current
size of a nonResizable editor. This means that the logical size of the
editor should not change when the result of checkSizeContraint is used
to resize the window.