iOS AUv3 size negotiation

Has anyone actually successfully used the size negotiation for iOS AUv3? Is there an example somewhere of it in action? I see it is in the AUv3 wrapper, but I can’t for the life of me get it to work, and there are (naturally) no Apple docs about it.

I don’t know of a public example, but it’s used by the ROLI software team. What isn’t working?

Example instrument would be Moog Model 15 and Effect would be FAC Maxima

Hey, Tom, we’re finally at the point where we need to attack this for our latest, and I could really use some help, or at least face me in the right direction. I see the two methods in the AUv3 wrapper (getSupportedViewConfigurations and selectViewConfiguration) but from the Processor level where we work, we don’t actually have access to these methods, best I can tell.

My thinking was that I would access the holder the way I would for the standalone holder (e.g. including the Standalone wrapper and something like auto holder = StandalonePluginHolder::getInstance();

The obvious problem there is that the AUv3 wrapper is .mm. I’m compiling PluginProcessor.cpp as Obj-C++, because I need access to NSFileManager and NSURL, but if I try to include an .mm, it’s turtles all the way down. To paraphrase JWZ, now I have two problems.

So, just a tiny smidge of code to point me in the right direction would be appreciated.

EDIT: Obviously, I’d be more than happy to do this in Editor rather than Processor. We store the size in our globals which are dealt with in Processor’s constructor, so I naturally thought to put the negotiation there, but whatevs.

Do you need access to the whole negotiation process? What do you want the outcome to be?

At the moment JUCE uses the editor’s constrainer and the result of the virtual method supportsHostMIDIControllerPresence to determine if configuration is supported:

(Edit: link fixed)

That link is a 404, but I know the method you mean, and I was briefly bemused that that seemed to be the only entry point.

In any case, to answer your question, here’s the problem: the only way the UI will have access to the full screen button in Garageband or open its full window on first instance in AUM and apematrix is if the size negotiation took place, and we allowed a 3:2 ratio in addition to the normal 3:1 ratio, unless I’m reading things totally wrong. So the aspect of the negotiation I need access to is the ability to see the proffered ratios and allow and prepare for them. There’s nothing to be gained if I don’t know what ratios were negotiated. So, to use your terminology, yes, I need access to the whole negotiation process.

Now, all that said, we need to make this a public accessible function like the IAA host icon and switching mechanism; in that vein, I’d suggest adding the two negotiation methods to juce_audio_plugin_client_utils.cpp like the IAA stuff, so we can just deal with it on our own time.

EDIT: Ah, I see. That function rolls through the available configs and asks the constrainer if they’ll work; if they will, it adds them to the index. Got it. Back to the salt mines.

Yep, that’s it.

The approach might be problematic if you wanted to rule out some intermediate sizes though.


Yeah. We’re definitely going to need a more sophisticated approach in the long term, but as far as getting the little fucker to full-screen in Garageband, this’ll do the trick. Just have to figure out the right aspects to return.

Did you manage to get full-screen in Garageband?
I tried it with (in some variations):

setResizeLimits (512, 335, 1366, 1024);
setResizable (true, false);

This works for Cubasis, but in Garageband, I unfortenately don’t get the full-screen button.

Here is what I am doing:

auto r = Desktop::getInstance().getDisplays().getMainDisplay().totalArea;
setResizeLimits(r.getWidth() - 100, r.getHeight() / 5, r.getWidth()+100, r.getHeight());
setResizable(true /* allowHostToResize /, false / useBottomRightCornerResizer */);

It works in Garageband , I’m getting the ‘full-screen’ button – not tested in Cubasis

Thank you for sharing!
Unfortunately your snippet doesn’t change the behaviour in Garageband. It seems, that I miss something else, but what could it be? (Some Project setting?)

You’re right there was something else needed to make it work , too bad I forgot what I had to do exactly (I remember it took me some time…). It seems it was related to not calling ‘setSize’ in the plugin , and reacting to the resized() callback in the AudioProcessorEditor

Thank you very much. If I get it, I’ll let people know here.

Remember that in an AUv3, setSize has no effect on the host; it is just telling JUCE what your drawing surface is going to be, but the host is going to do whatever it wants. When the host changes its window size, resized() is called, and you can ask for the size there and in the top of paint().

For the full screen to work, your resizeLimits have to contain the possible aspect ratios that the host can throw, but the host doesn’t really care about your hopes and dreams otherwise. For instance, in Quanta, here’s my resizer setup, in entirety:

addAndMakeVisible (resizer = new ResizableCornerComponent (this, &resizeLimits));
resizeLimits.setSizeLimits (450, 279, 1800, 1116); // Smallest X/Y , largest X/Y

If you follow through the sizing mechanism in the AUv3 wrapper, you’ll see that the iOS part doesn’t ever ask what your size is; rather, it throws the available sizes at the constrainer, and if they fit within the possible bounds (and note they ignore the fixedAspectRatio), it returns true for those sizes to the host. Realistically, there are only two: the 3:1 ratio and the 5:3 ratio (those numbers are estimates, but I just woke up.) There is a third one that is common, and that’s one where the keyboard is showing in GarageBand on a 12.9" iPad Pro, but the mod and pitch wheels are not. This one is like 4:1. I believe this one is also possible on an iPhone X.

You still have to have a setSize, of course. But this is more for JUCE than iOS. At the top of your resized(), you figure out what the host has handed you, and draw accordingly.

Hope this helps.

Great input input, thanks, but some questions arise…

your resizeLimits have to contain the possible aspect ratios that the host can throw

…you mean, that the AudioProcessorEditor resizeLimits should be that big, that it includes all possible host sizes? That’s what jbo and I do with setResizeLimits (minWidth, minHeight, maxWidth, maxHeight) and setResizable (true, …).

The problem is, that Garageband hides the full screen button, although I allow resize and I allow very big sizes.

Could it be, that I do this not at the right position (AudioProcessorEditor constructor) or in the wrong order?

Are you assigning the constrainer? Without this, it will not work, as the host is asking the constrainer, not the resizer directly.


Do you create resizeLimits before? Where does it come from? I can’t access a variable with that name.

setConstrainer() is a normal public member of AudioProcessorEditor. If it’s not there, you might need to check your version. That said, I put my whole resizer rig (as copied above) in the constructor of the editor. It can go anywhere, as long as it is before setSize() (which calls resized() – you have to have done all that before the first resized().)

Oh, I see. You want to see what resizeLimits looks like. In private: do this

ComponentBoundsConstrainer resizeLimits;

And that should sort you. Other code as above.

EDIT: Note that the AUv3 host doesn’t care what the resize limits are; you have to set them to something, but it ignores those values, other than to see that the largest possible one can contain all the AUv3 aspects.