Hi Jeff,

You mention that Carbon has a flat namespace, but it's important to note that 
Cocoa has a flat namespace, too.

Languages like C and C++ use functions, which are linked by address. Loading 
the same C or C++ code twice should probably only update the function 
addresses, and if the new code is compatible with the old code then nothing 
should break. It might be wasteful to load the same code twice, but it's a 
simpler process that definitely overwrites any previous addresses during the 
dynamic linking.

Objective C uses methods, which are looked up in a hash table by the runtime 
rather than by following a linkable address. When dynamically loading a bundle, 
such as an AudioUnit, the Objective C runtime adds information about all of the 
methods in the bundle, whether they be category methods for existing classes or 
instance methods for entirely new classes. I've never investigated the 
consequences of loading the exact same classes twice, but I wouldn't be 
surprised that the Objective C runtime gets confused when the second copy of 
the same class gets loaded into its data structures. We already have warnings 
about category methods, because the runtime does not make any guarantees if 
there is more than one category method override in a collection of multiple 
bundles. Similarly, I would expect that loading the same class twice is also 
"not supported" by the runtime. Granted, the Objective C runtime has changed 
many times over the years, particularly with ObjC2, and some of the most 
dangerous features have been deprecated, but this still seems like going beyond 
what is supported.

The AudioUnit documentation from Apple - what little there is - is plainly 
explicit that each plugin must use a unique class name for its Cocoa UI. 
Violating this requirement results in unpredictable results because it is 
unsupported. You need to avoid having multiple plugins with the same ObjC 
classes in them.

I'm actually surprised that Live does not call 
GetProperty(kAudioUnitProperty_CocoaUI) for your second plugin. Without 
accessing that property, Live should have no way of knowing anything about the 
Cocoa UI, whether it's functional or not. You mention that no breakpoints in 
-uiViewForAudioUnit:withSize: are hit, and that makes total sense, because that 
is Objective C code in a class that has potentially been mangled to the point 
of being inaccessible.

Are you absolutely certain that GetProperty(kAudioUnitProperty_CocoaUI) is not 
being called on the second instance of your plugin? More importantly, are both 
of your plugins sharing the same Manufacturer, Type and SubType? If they do not 
have unique Manufacturer/Type/SubType identifiers, then Live is correct to 
assume that the second instance is identical to the first in terms of the ObjC 
information, even though the actual runtime information may have been mangled 
enough that those classes no longer are accessible. Note that you cannot merely 
change the Info.plist, because the Manufacturer/Type/SubType information is 
also complied into the binary.

You probably need to find some way to make sure that the Cocoa UI bundle is not 
loaded more than once. That means you probably cannot copy the CocoaUI bundle 
into every plugin, but instead need to make sure that it's only part of one 
bundle. Seems like your wrapper could be a separate plugin that provides the 
generic UI, while all wrapped units would not have their own CocoaUI bundle 
inside. Instead, wrapped plugins could refer to the CocoaUI for the wrapper. 
Then again, I don't know whether your wrapper is installed separately, since 
that might be confusing for users.

Brian Willoughby



On Nov 27, 2017, at 2:59 PM, Jeff McClintock <[email protected]> wrote:
> 
> Hi All,
> 
> I've written a wrapper to host my (non-AU) plugins in Audio Units.
> 
> How it works is I built a single AU component (the "wrapper"), each target 
> plugin is placed in a copy of the AU wrapper bundle, and I edit the wrappers 
> "Info.plist" file to create (what looks like) a unique AU. My wrapper then 
> forwards all AU function calls to the target plugin ("wraps" it).
> 
> This all works pretty well until I load two different wrapped plugins into 
> Ableton Live. Both plugins pass auval, both function OK as far as audio 
> processing, but I can only open the view of the first plugin loaded. The 
> other plugin refuses to show its view.
> 
> Now, I realize Carbon has a "flat namespace" and auval warns me that "Class 
> 'SynthEditPluginCocoaView_1344' is implemented in (both components). One of 
> the two will be used. Which one is undefined."
> 
> Correct me if I'm wrong, but I figured since both binaries are identical, 
> then both View classes are identical and it doesn’t matter that Cocoa will 
> use the same view class for both AUs.
> 
> I placed breakpoints in the plugins, in the first plugin instance, Live calls 
> GetProperty(kAudioUnitProperty_CocoaUI) and displays the view, in the second 
> plugin, Live does not call this method, and does not instantiate the view 
> class nor hit any breakpoints in the [uiViewForAudioUnit: withsize] creation 
> function. It's like Live simply does not try to open the view.
> 
> If I change my view class's name to make it unique, then rebuild and apply 
> the new wrapper to one of the two plugins, then both plugin views open OK. So 
> clearly there is some problem with having the same Cocoa class name in two 
> plugins. I just don't understand why this is a problem? (when the classes are 
> identical).
> 
> Note: This wrapper is intended for non-techical end-users, I wish to avoid 
> having to rebuild the wrapper for each target "wrapped" plugin.
> 
> Any hints appreciated.
> 
> Jeff McClintock
> 
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to