Bypassing a hosted plugin

Hmmm… adding this feature in a non-breaking way that makes sense is actually quite hard. I’ve got @t0m 's suggestion sitting on a branch but @anthony-nicholls correctly points out that this would result in confusing behaviour. But then we also have processBlockBypassed vs. processBlock which all still needs to make sense no matter if you are a plug-in or a host. We also need to think of the use case when you are implementing an editor for your plug-in and want to bypass your own plug-in (when the user clicks on a bypass button in your editor).

The only way I can think of making this all work is the following:

  1. we add setBypass/isBypassed to the AudioProcessor class. These are not callbacks but methods that both a host and a plug-in can call. As a host you can call these methods to bypass the plug-in or check if the user has bypassed the plug-in (to update your host’s UI, for example). As a plug-in you can also call setBypass to bypass your own plug-in (for example from your plug-in’s editor).
  2. We add a bypassChanged callback to AudioProcessorListener
  3. processBlock/processBlockBypassed: to remain backward compatible, your plug-in will still receive processBlockBypassed calls when the plug-in is bypassed. To ensure this even if you are hosting an internal AudioProcessor (i.e. not a plug-in: what @yfede points out), any code hosting an AudioProcessor will always need to query AudioProcessor::isBypassed and then call either processBlock/processsBlockBypassed depending on the value. This makes hosting AudioProcessors more complicated but I don’t see a way around this.
  4. What happens if you, as a host of a VST/VST3/AU, call processsBlockBypassed even if isBypassed is currently false (or vice versa: call processsBlock when isBypassed is true)? First of all, in the future, hosts should not do this, but for the sake of backward compatibility, I think that processsBlockBypassed always takes precedence regardless of what isBypassed actually is currently. If the plug-in is currently not bypassed then a call to processsBlockBypassed will bypass the plug-in until processBlock is called again. Getting this right (without any race conditions) in JUCE’s plug-in code will be a bit of a challenge but I think it’s doable.

What do you guys think? I’m I missing anything?