0

I'm probably doing something really dumb here but this has got me stuck. I'm trying to display the view for an audio unit (if it has one). My understanding is that the AU factory class should return an NSView (I'm not worried about the option for some v3 units to return a ViewController). I have this method:

func getAUcocoaView(_ audioUnit: AudioUnit ) -> NSView {
    
    var dataSize = UInt32(MemoryLayout<AudioUnitCocoaViewInfo>.size)
    var cocoaViewInfoRawPtr = UnsafeMutableRawPointer.allocate(byteCount: MemoryLayout<AudioUnitCocoaViewInfo>.size, alignment: MemoryLayout<AudioUnitCocoaViewInfo>.alignment)

    defer {
        cocoaViewInfoRawPtr.deallocate()
    }

    let result = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, 0, cocoaViewInfoRawPtr, &dataSize)
    if result != 0 {
        print("Couldn't get AudioUnit property: kAudioUnitProperty_CocoaUI")
    }
    let cocoaViewInfo = cocoaViewInfoRawPtr.bindMemory(to: AudioUnitCocoaViewInfo.self, capacity: 1).pointee
    
    let factoryClassNameCF = cocoaViewInfo.mCocoaAUViewClass
    let factoryClassName = factoryClassNameCF.takeUnretainedValue() as String
    let cocoaViewBundlePathCF = cocoaViewInfo.mCocoaAUViewBundleLocation
    let cocoaViewBundlePath = cocoaViewBundlePathCF.takeUnretainedValue()

    let bundle = Bundle(url: cocoaViewBundlePath as URL)
    let factoryClass = bundle!.classNamed(factoryClassName) as! NSObject.Type
    let auView = factoryClass.init()
    return auView as! NSView
}

Everything appears to work as expected up until the final attempted cast to NSView. My understanding was that the AU factory class returns an NSView but this attempt at casting results in: "Could not cast value of type 'JUCE_AUCocoaViewClass_ab7d1f643f11dc89' (0x600000e5a730) to 'NSView' (0x7fff8ceab778)." I'm probably missing something incredibly silly but either: a) how does one get the NSView from this? or; b) if not that way, how does one invoke the AU view?

Any help much appreciated.

Obmit
  • 21
  • 1

1 Answers1

0

Ok, it seems like it simply isn't possible to call the necessary method in Swift. I don't know why I spent so long banging my head against a wall trying to do so when it's trivial easy in Objective C. So I just took the bundle and classname et voila:

NSView * getAUCocoaView( AudioUnit mAudioUnit, NSSize size, NSBundle *viewBundle, NSString * viewClassName) { Class viewClass = [viewBundle classNamed: viewClassName];

id<AUCocoaUIBase> factory = [[viewClass alloc] init];
NSView * theView = [factory uiViewForAudioUnit: mAudioUnit withSize: size];
return theView;

}

Obmit
  • 21
  • 1