macOS Plugin View Behaviour

I’ve got a plugin crash that I’m currently investigating and it stems from the following code:

struct AutoResizingNSViewComponentWithParent  : public AutoResizingNSViewComponent,
                                                private Timer
{
    AutoResizingNSViewComponentWithParent()
    {
        JUCE_IOS_MAC_VIEW* v = [[JUCE_IOS_MAC_VIEW alloc] init];
        setView (v);
        [v release];

        startTimer (30);
    }

    JUCE_IOS_MAC_VIEW* getChildView() const
    {
        if (JUCE_IOS_MAC_VIEW* parent = (JUCE_IOS_MAC_VIEW*) getView())
        {
            if ([[parent subviews] count] > 0)
                return [[parent subviews] objectAtIndex: 0];
        }

        return nil;
    }

    void timerCallback() override
    {
        if (JUCE_IOS_MAC_VIEW* child = getChildView())
        {
            stopTimer();
            setView (child);
        }
    }
};

What happens is:

  1. This AutoResizingNSViewComponentWithParent gets created and allocates and sets its own internal view (which you can see in the constructor)
  2. VSTPluginWindow::openPluginWindow is then called, passing in this newlyt created NSView
  3. The plugin takes a reference to that NSView
  4. After 30ms the timer callback happens and the AutoResizingNSViewComponentWithParent looks inside the view it created for any subviews and assigns one of those to the owned view
  5. The originally juce-created NSView is now deleted and the plugin holds a dangling reference to it
  6. The plugin tries to attach a new NSView (like a popup menu) to the dangling NSView
  7. Plugin crashes

Is there a reason for this async reassignment of the child?
And does anyone know if it’s valid for plugins to take a reference to the NSView passed in to the Vst2::effEditOpen call?

Hmm, thinking about this a bit more this is probably so that if the NSView that the plugin creates changes size, the AutoResizingNSViewComponentWithParent can respond to that?

Do we know exactly which plugins require this behaviour?

I’m going to have to raise this again as I’ve got several users complain that Softube plugins are crashing when their UIs are opened on macOS now and I can replicate the problem.

If I comment out that startTimer call in AutoResizingNSViewComponentWithParent, the plugin UIs successfully open. This problem is also evident in pluginval.


I’d like to say all plugin developers would update their plugins and not keep a reference to the passed in NSView but unfortunately I don’t think that’s going to happen and I’ve had several developers already tell me they won’t make that change.

Do we have any examples of plugins that resize a nested view but not the top level NSView?
I did try retaining the created NSView until the destruction of the AutoResizingNSViewComponentWithParent but that results in a blank UI.

I’m struggling to see other alternatives.

Ok, I’ve found a case that breaks if I remove the startTimer call: FabFilter Pro-C.
If I do this, the UI appears 1/4 size in the bottom left:

I’ve spent ages trying to get both Softube plugins to load and this plugin but to no avail.
I’ve tried forcing resizes all over the place, retaining the original view, passing the actual window to openPluginWindow and even closing and reopening the window to try and pass the child view back in to itself.


Basically I’m at a bit of a dead end. One thing I can say after speaking to some plugin developers is that they definitely don’t expect the pointer passed to Vst2::effEditOpen to be deleted on them.
The only thing I can think of at this time is to start adding exceptions for certain plugin manufacturers to not start the timer.

Any better ideas?