Transition from 4.1.0 to 4.3.1 and AAX I/O issue


We have released an effect compiled against 4.1.0 with previously revised I/O management using setPreferredBusArrangement() and now we need to update to 4.3.1 which use another new I/O management using isBusesLayoutSupported().

Plugin needs only very basic configurations - {1,2} and {2,2} - and is working as expected both on 4.1.0 and on new 4.3.1.

The problems is that ProTools sessions saved with 4.1.0 plugin inserted as Mono->Stereo can’t be restored properly with new 4.3.1 updated version - PT is telling that plugin can’t be found.
However new instance of 4.3.1 in the same configuration can be put on the track without any problems.

Projects with Stereo->Stereo configuration can be restored without any issues.

Can anybody tell if there is any way for smooth transition in such case?

Or maybe my I/O definition for 4.3.1 is wrong:

bool Plugin::isBusesLayoutSupported (const AudioProcessor::BusesLayout& layouts) const
  const AudioChannelSet& mainInput  = layouts.getMainInputChannelSet();
  const AudioChannelSet& mainOutput = layouts.getMainOutputChannelSet();

  // do not allow disabling the main buses
  if (mainInput.isDisabled()) 
    return false;

  // only {1,2} and {2,2}
  if ((mainInput.size() == 1 || mainInput.size() == 2) && mainOutput.size() == 2)
    return true;

  return false;

…and if needed the old implementation was

bool Plugin::setPreferredBusArrangement (bool isInputBus, int busIndex, const AudioChannelSet& preferred)
  const int numChannels = preferred.size ();

  if (numChannels > 2)
    return false;

  if (! isInputBus && numChannels == 1)
    return false;

  return AudioProcessor::setPreferredBusArrangement (isInputBus, busIndex, preferred);

Any help very appreciated :slight_smile:


Uh… thank you for this post! I got multiple customer reports of this issue but so far had no idea how to reproduce the issue. I thought something was wrong with code signing or dependencies, because of the “plugin cannot be found” error. Unfortunately I do not have any ideas how to solve the issue, but now I at least know where to search for a solution and hopefully the JUCE team will join the hunt.

Your isBusesLayoutSupported code looks perfect. I think this has something to do with these lines in the AAX wrapper:

properties->AddProperty (AAX_eProperty_PlugInID_Native,     'jcaa' + configIndex);

The AAX wrapper goes through all possible bus layouts of your plug-in and gives every possible layout a new plug-in id. It could be that 4.1.0 did this in a different order. I can have a go at fixing this but can you confirm that this is the problem by checking which AAX_eProperty_PlugInID_Native was used for your 4.1.0 plug-in and forcing this id in the 4.3.0 version?

You’re perfectly right.
4.1.0 calls AAX wrapper’s createDescriptor() with {2,2} first and then {1,2}.
4.3.0 calls it with {1,2} and {2,2}

It gives different values for incremented configIndex variable and that’s problem.
I’ve changed configIndex in 4.3.0 to match the 4.1.0 behavior and the problem dissapears.

Can you provide some solution for backward compatibility for plugins released with 4.1.0 and updated on 4.3.0?


Urgh… this is a bad problem then. This broke project loading for all customers who bought my plugin early. When they updated to the version using Juce 4.3 they couldn’t load their songs anymore. If the order is now fixed, projects will break for all customers that started out with the newer version :(.

From what you all wrote it seems impossible to find a solution that would work both ways.


The best solution would have been to somehow encode the io config into that id, so the order of configs wouldn’t matter. The current code probably also means project compatibility breaks if the developer changes io configs in an update. Before the whole multibus changes it probably depended on the manual config order. Since then it just depends on how the code comes up with the order which seems unreliable and might break again with future updates.


I agree. We need a flag for compatibility. Can we have something like JUCE_FORCE_USE_LEGACY_PARAM_IDS to switch between old and new layout logic?

We need a decision whether the current logic is faulty or whether it’ll stay like this from now on. I need to figure out what to tell my customers based on that.
There should be a clear definition what the “correct” order of the IDs is and that should be put next to that line in code so it doesn’t break again in the future. At the same time it would be nice to have a solution that doesn’t change IDs randomly if IO configuration is changed for an update.

Oh Oh, thats really bad! Hopefully this will be fixed!

PS: I would prefer a solution without macros whenever possible, the number of plugin depending macros grows and grows, It is becoming increasingly difficult to manage this to ensure compatibility.

I’m not AAX-Expert, but does every channel-layout needs an own plugin-id?

I’m also no AAX expert but now I had a look and as far as I can tell the reason why JUCE uses these enumerated ids is that every layout needs its own id.

As I can see in the AAX examples there are also different (fixed) plugin IDs used for different I/O configurations.

Juce AAX wrapper’s approach uses an increasing indexation added to fixed base value. But consecutive indexes are assigned to the I/O configurations in the order of their acceptance. IMO it’s not the best approach - when you update a plugin adding more I/O configs to deal with the indexes can change and it’ll break the project restoring.

I don’t know if it’s possible in all cases but maybe it’d be also better to use fixed IDs for all possible I/O configs. I mean some routine which could translate Juce’s bus layouts to fixed plugin IDs.

My problem was ‘only’ that 4.1.0 was indexing I/O configurations different than 4.3.1. I’ve made some tweaks to AAX wrapper to be able to affect the configIndex value used for plugin IDs indexation to keep them the same as they were in the version compiled on 4.1.0.

It works but some common solution would be much better for this and especially for solving this problem with dynamic indexation as it could lead to really big issues even if one uses only Juce 4.3.1 or later.

It would be easily possible to use fixed IDs for all io configs. AAX currently only supports 18 + 2 types of stem formats (visible in the aax headers). The wrapper uses in and out configs for the enumeration, so there are only 400 possibilities and the id is a 32 bit value.

However changing the system to something using the encoded config would break project compatibility again for developers updateing JUCE.

I apologize for the nag, but I try to release a plugin since a week and this issue is holding me back. JUCE team, what are you planning to do about this issue? I just really don’t want to release a new product and have AAX projects break from a fix that’s maybe just days away. Or maybe you decide the 4.3.1 behaviour will be kept. That would also be fine with me. Not knowing whether this is going to change soon is the problem. Thanks!

I think that current approach should be changed - otherwise we’ll always have a solution when no plugin update is possible if you want to add supported I/O.

So everyone who release a plugin with one I/O settings will stuck with no chance to smooth update even if it comes to simple adding new supported layout. And then the only way would be releasing new product with another name/binaries etc. - which is nonsense for small update.

This approach (continued from the very beginning of AAX wrapper) is unfortunately against the AAX SDK assumptions and IMO it should be fixed.

Just my two cents :slight_smile:

Yes this sounds like the right thing to do here. I’ll add this to the code…

Ok that sounds great for future plugins. For existing ones, there probably needs to be a way to still use the old behaviour(s). Otherwise no one using AAX can update JUCE for existing plugins.

OK I just pushed a fix for this to develop. I’ve also added a new callback to AudioProcessor called getAAXPluginIDForMainBusConfig. By overriding this method, you can return any AAX plug-in id for any bus configuration. This way you can return your old AAX plug-in ids to remain backward compatible.

1 Like

Many thanks for that fix :slight_smile:
Could you also apply it on the master branch?

I think we’ll leave this on the develop branch for now. We normally only push fixes for crashes, security issues or major Projucer usability issues to the master branch. However, it should be no problem to cherry pick this fix onto your branch of master.

Thanks. I didn’t dare to suggest a callback :slight_smile: thanks for that. However I see three issues with the change:

  • “uniqueFormatId = (uniqueFormatId * 16) + aaxFormatIndex” Why limit this to 16 configs? AAX currently has 18 and 2 special ones and you now have 13, but 16 is too close in my opinion. Give it some safety for the future!
  • How are people updating JUCE going to realize they need to implement the callback to get backwards compatibility? This is a major problem.
  • How do we know what to put in there for backwards compatibility? Do we really need to dump what old builds were using? Could you provide information how the enumeration worked for 4.1 and 4.3 so we can make this a bit less painful?
1 Like