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]
