Add support for asynchronous out-of-process loading of AuV3 extensions

This commit is contained in:
Zakk 2020-02-23 01:01:33 -05:00
parent 639c53003c
commit 805fef9159
8 changed files with 76 additions and 57 deletions

View file

@ -48,11 +48,6 @@
}
-(bool)createNode:(CAMultiAudioGraph *)forGraph
{
[super createNode:forGraph];
return YES;
}
-(void)detachCaptureSession

View file

@ -149,9 +149,9 @@
-(bool)createNode:(CAMultiAudioGraph *)forGraph
-(bool)createNode
{
[super createNode:forGraph];
[super createNode];
//Create the input and output elements

View file

@ -24,6 +24,23 @@
}
-(void)setAudioUnit:(AudioUnit)audioUnit
{
[super setAudioUnit:audioUnit];
if (audioUnit && _auClassData)
{
CFDictionaryRef cfValue = (__bridge CFDictionaryRef)_auClassData;
UInt32 size = sizeof(cfValue);
AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &cfValue, size);
}
[self setAudioUnitBypass];
}
-(void)setAudioUnitBypass
{
UInt32 bypassVal;
@ -159,36 +176,6 @@
}
-(bool)createNode:(CAMultiAudioGraph *)forGraph
{
bool ret = [super createNode:forGraph];
if (ret && !self.name)
{
AudioComponent comp = AudioComponentFindNext(NULL, &unitDescr);
CFStringRef cName;
AudioComponentCopyName(comp, &cName);
self.name = CFBridgingRelease(cName);
}
if (self.audioUnit && _auClassData)
{
CFDictionaryRef cfValue = (__bridge CFDictionaryRef)_auClassData;
UInt32 size = sizeof(cfValue);
AudioUnitSetProperty(self.audioUnit, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &cfValue, size);
}
[self setAudioUnitBypass];
return ret;
}
-(void)selectPresetNumber:(SInt32)presetNumber
{

View file

@ -79,8 +79,11 @@
}
}
if ([newNode createNode:self])
if ([newNode createNode])
{
newNode.graph = self;
newNode.engine = self.engine;
[newNode willInitializeNode];
OSStatus err = AudioUnitInitialize(newNode.audioUnit);

View file

@ -43,7 +43,8 @@
-(instancetype)initWithSubType:(OSType)subType unitType:(OSType)unitType;
-(instancetype)initWithSubType:(OSType)subType unitType:(OSType)unitType manufacturer:(OSType)manufacturer;
-(bool)createNode:(CAMultiAudioGraph *)forGraph;
-(bool)createNode:(void(^)(void))completionHandler;
-(bool)createNode;
-(void)willConnectToNode:(CAMultiAudioNode *)node inBus:(UInt32)inBus outBus:(UInt32)outBus;
-(void)connectedToNode:(CAMultiAudioNode *)node inBus:(UInt32)inBus outBus:(UInt32)outBus;

View file

@ -205,35 +205,64 @@ UInt32 inNumberFrames,
-(bool)createNode:(CAMultiAudioGraph *)forGraph
-(bool)createNode
{
if (!forGraph)
return [self createNode:nil];
}
-(bool)createNode:(void(^)(void))completionHandler
{
if (_audioUnit)
{
return NO;
//Already created
return YES;
}
OSStatus err;
AudioComponent auComponent = AudioComponentFindNext(NULL, &unitDescr);
if (!auComponent)
{
return NO;
}
err = AudioComponentInstanceNew(auComponent, &_audioUnit);
if (err)
{
NSLog(@"AudioComponentInstanceNew failed for %@, err: %d", self, err);
_audioUnit = NULL;
return NO;
}
self.graph = forGraph;
self.engine = forGraph.engine;
self.effectsHead = self;
self.headNode = self;
AudioComponentDescription fullDesc;
AudioComponentGetDescription(auComponent, &fullDesc);
bool requiresAsync = (fullDesc.componentFlags & kAudioComponentFlag_RequiresAsyncInstantiation) > 0;
if (requiresAsync)
{
AudioComponentInstantiate(auComponent, kAudioComponentInstantiation_LoadOutOfProcess, ^(AudioComponentInstance _Nullable auUnit, OSStatus osErr) {
self.audioUnit = auUnit;
if (completionHandler)
{
dispatch_async(dispatch_get_main_queue(), completionHandler);
}
});
} else {
AudioUnit newUnit;
err = AudioComponentInstanceNew(auComponent, &newUnit);
if (err)
{
NSLog(@"AudioComponentInstanceNew failed for %@, err: %d", self, err);
_audioUnit = NULL;
return NO;
}
self.audioUnit = newUnit;
if (completionHandler)
{
dispatch_async(dispatch_get_main_queue(), completionHandler);
}
}
return YES;
}

View file

@ -21,9 +21,9 @@
}
-(bool)createNode:(CAMultiAudioGraph *)forGraph
-(bool)createNode
{
bool ret = [super createNode:forGraph];
bool ret = [super createNode];
AudioTimeStamp ts = {0};

View file

@ -34,7 +34,11 @@
CAMultiAudioEffect *newEffect = clickedEffect.copy;
[self.effectArrayController addObject:newEffect];
[newEffect createNode:^{
[self.effectArrayController addObject:newEffect];
}];
}