# AU Wrapper Broken For Legacy Parameters

**URL:** <https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382>\
**Category:** Audio Plugins\
**Created:** [April 23, 2018, 9:21pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382 "2018-04-23T21:21:47Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![alassandro](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/alassandro/32/4297_2.png) [@alassandro](https://forum.juce.com/u/alassandro)\
**Post date:** [April 23, 2018, 9:21pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/1 "2018-04-23T21:21:47Z")

</div>

Enabling `JUCE_FORCE_USE_LEGACY_PARAM_IDS` breaks AU plugins at runtime

Specifically, juce\_AU\_Wrapper.mm Line 1858:

```auto
// Consider yourself very unlucky if you hit this assertion. The hash code of your
// parameter ids are not unique.
jassert (! paramMap.contains (static_cast<int32> (auParamID)));

```

I commented out the assertion and checked the hashmap. After the loop (`for (auto* param : juceParameters.params)`) runs 39 times for my 39 parameters, `paramMap.size()` only shows the map contains one entry.

I’m on commit `e89c4d5d4e5e9beed4adf7c21fc25e6b4a70e72f` from `develop`

Seems like this issue arises from [https://github.com/WeAreROLI/JUCE/commit/e05a1549f226b2ae4567551508f1082c8d220058](https://github.com/WeAreROLI/JUCE/commit/e05a1549f226b2ae4567551508f1082c8d220058)?

---

<div class="post-metadata">

**Author:** ![alassandro](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/alassandro/32/4297_2.png) [@alassandro](https://forum.juce.com/u/alassandro)\
**Post date:** [April 23, 2018, 9:36pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/2 "2018-04-23T21:36:59Z")

</div>

Specifically what is happening when I step-through:

```auto
 static String getParamID (AudioProcessorParameter* param, bool forceLegacyParamIDs) noexcept
    {
        if (auto* legacy = dynamic_cast<LegacyAudioParameter*> (param))
        {
            return legacy->getParamID(); /* <------- returns here, using the parameter's string ID */
        }
        else if (auto* paramWithID = dynamic_cast<AudioProcessorParameterWithID*> (param))
        ...

```

gets called, and its result is used in `generateAUParameterID` where it converts the value to an int via `juce::String::getIntValue()`… which will obviously yield 0 for every parameter I have.

Suggested correction:

```auto
 static String getParamID (AudioProcessorParameter* param, bool forceLegacyParamIDs) noexcept
    {
        if (auto* legacy = dynamic_cast<LegacyAudioParameter*> (param))
        {
            return String (legacy->idx); 
        }
        else if (auto* paramWithID = dynamic_cast<AudioProcessorParameterWithID*> (param))
        ...

```

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [April 24, 2018, 6:41am UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/3 "2018-04-24T06:41:51Z")

</div>

The next few commits should address that issue - please try using the tip of the `develop` branch.

---

<div class="post-metadata">

**Author:** ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)\
**Post date:** [April 24, 2018, 7:17am UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/4 "2018-04-24T07:17:58Z")

</div>

I know that just looking at the code would probably provide the answer, but i’m sure that a lot of us would be curious as to how you @t0m figured out the solution to this problem, and what exactly was causing it. I know for myself, I like hearing how a developer solved a problem and their explanation for what was causing it.

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [April 24, 2018, 8:11am UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/5 "2018-04-24T08:11:29Z")

</div>

Well as you said - looking at the code provides the answer:

> <https://github.com/WeAreROLI/JUCE/commit/20ced1662e7dfb758e747210a5cae623693c52a2>

There really isn’t much of a story behind this one. We noticed the same problem as @TonyAtHarrison encountered about a week ago; we were also hitting the `jassert` in some plug-in code I was experimenting with. It’s a little confusing because we’re dealing with three interacting situations: `forceUseLegacyParamIDs` from a preprocessor macro (which overrides everything), and managed vs unmanaged parameters. Additionally the existing behaviour has been broken for _years_, which was pretty surprising since no one has ever mentioned anything on here… but we just worked our way through the various combinations of options and made sure the right thing happened in each case.

---

<div class="post-metadata">

**Author:** ![frankfilipanits](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/frankfilipanits/32/545_2.png) [@frankfilipanits](https://forum.juce.com/u/frankfilipanits)\
**Post date:** [April 24, 2018, 12:55pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/6 "2018-04-24T12:55:23Z")

</div>

> [@t0m](#):
>
> Additionally the existing behaviour has been broken for years, which was pretty surprising since no one has ever mentioned anything on here…

While this specific bug may not have been called out, the fact that parameters have never worked 100% properly through the various iterations of AudioProcessorParameter/AudioProcessorParameterWithID/AudioProcessorValueTreeState HAS been mentioned. Many times. For example:

> [@Breaking Change: Hosted AudioProcessorParameter improvements](https://forum.juce.com/t/breaking-change-hosted-audioprocessorparameter-improvements/26537/3):
>
> Just stop. This is the FOURTH JUCE attempt in about as many years at getting plug-in parameters right and at this point I have ZERO confidence in it doing anything except breaking a lot of code and creating headaches for people who have legacy plug-ins to support. As lalala said: Don’t give us another 90% “solution” and forcibly break things for those who have rolled their own custom classes that work 100%.

Please stop reinventing parameters in the pursuit of “improving the interface” and put in the time and effort to (a) truly understand the nuances of parameter implementations for the various plug-in formats and (b) chase down the corner cases that make the difference between a 90% solution (“Look, the demo with two sliders works in one host!”) and a 100% solution (works in every major host, displays correctly for “generic” UIs, works properly with automation in all modes, works properly with control surfaces, all types of controls work properly (toggle/stepped/continuous, integer/float/named), handles forward/backward compatibility gracefully - including addition, deletion, or reordering of parameters). Yes, these things are hard and time consuming… which is why those of us who invested time in developing custom classes to do all of that are resistant to breaking changes forced on us without a similarly comprehensive solution.

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [April 24, 2018, 1:53pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/7 "2018-04-24T13:53:51Z")

</div>

This bug primarily affected people who are rolling their own parameter classes. If you are **not** using the AudioProcessorParameter classes then overriding `AudioProcessor::getParameterID (int index)` to return anything other than `String (index)` would have caused problems.

I understand that you’re concerned about the latest parameter changes, but it’s far more compelling and productive to highlight specific problems rather than just broadcast unsubstantiated FUD. As I asked in the other thread: could you please provide some examples of things which are not possible using a subclass of `AudioProcessorParameter`?

If you wanted to preserve existing behaviour you could simply create a wrapper parameter class which just forwards calls to the corresponding methods of your `AudioProcessor` subclass:

```
class ParameterWrapper : public AudioProcessorParameter
{
public:
    ParameterWrapper (YourAudioProcessor& yourProcessor, int audioParameterIndex)
        : processor (yourProcessor), parameterIndex (audioParameterIndex)
    {
    }

    float getValue() const override { return processor->getParameter (parameterIndex); }
    bool isBoolean() const override { return false; }
    String getCurrentValueAsText() const override { return processor->getParameterText (parameterIndex); }
    ...

    YourAudioProcessor& processor;
    const int parameterIndex;
}

```

The only significant methods of `AudioProcessorParameter` that don’t have a direct mapping are

```
float getValueForText (const String&) const
String getText (float, int) const

```

but these are not particularly difficult to implement, and I suspect most people will already have the necessary code available to do this.

---

<div class="post-metadata">

**Author:** ![pflugshaupt](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pflugshaupt/32/13206_2.png) [@pflugshaupt](https://forum.juce.com/u/pflugshaupt)\
**Post date:** [April 25, 2018, 12:53pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/8 "2018-04-25T12:53:01Z")

</div>

> [@t0m](#):
>
> The next few commits should address that issue - please try using the tip of the develop branch.

I am confused… did these commits already happen? The one you linked to is the one that created the missing params in AU or am I misunderstanding something? I noticed I’m not seeing any parameters anymore in my AU version of one plugin that still uses legacy ids and then I went back to a stable version of Juce and now I don’t understand whether it’s save to go to the tip again.

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [April 25, 2018, 12:57pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/9 "2018-04-25T12:57:57Z")

</div>

Sorry, I should have been clearer: the next few commits _after e89c4d5d4e5e9beed4adf7c21fc25e6b4a70e72f_ (which were made a week or so ago) will fix the problem; the tip should be safe. Please let us know if you encounter any issues!

---

<div class="post-metadata">

**Author:** ![schabtach](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/schabtach/32/4616_2.png) [@schabtach](https://forum.juce.com/u/schabtach)\
**Post date:** [April 27, 2018, 12:26am UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/10 "2018-04-27T00:26:42Z")

</div>

> [@t0m](#):
>
> If you wanted to preserve existing behaviour you could simply create a wrapper parameter class which just forwards calls to the corresponding methods of your `AudioProcessor` subclass:

This is exactly what I’m attempting to do in order to update our code for version 5.3, and as it happens I had already built a wrapper class previously. However, it inherits from AudioProcessorParameterWithID rather than AudioProcessorParameter. Since AudioProcessorParameter::processor is declared private, I can’t do the call-forwarding to my AudioProcessor that you describe. So, this leads me to my question: why is AudioProcessorParameter::processor private, and does it have to remain that way?

---

<div class="post-metadata">

**Author:** ![anthony-nicholls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/anthony-nicholls/32/1246_2.png) [@anthony-nicholls](https://forum.juce.com/u/anthony-nicholls)\
**Post date:** [April 27, 2018, 6:03am UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/11 "2018-04-27T06:03:54Z")

</div>

> [@schabtach](#):
>
> Since AudioProcessorParameter::processor is declared private, I can’t do the call-forwarding to my AudioProcessor that you describe. So, this leads me to my question: why is AudioProcessorParameter::processor private, and does it have to remain that way?

If I remember correctly the private data member `processor` is now only used in a few places, all of which are commented to say that the method being called is deprecated and therefore it seems likely this member will disappear shortly anyway. Therefore you’re probably better off storing a reference to the AudioProcessor directly in your wrapper parameters.

---

<div class="post-metadata">

**Author:** ![schabtach](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/schabtach/32/4616_2.png) [@schabtach](https://forum.juce.com/u/schabtach)\
**Post date:** [April 27, 2018, 2:11pm UTC](https://forum.juce.com/t/au-wrapper-broken-for-legacy-parameters/27382/12 "2018-04-27T14:11:22Z")

</div>

Oh. Heh. I guess that was just a little too simple for me to think of myself! Thanks for the help–much appreciated.
