我想将音频单元创建的自定义视图嵌入到使用自动布局的窗口中。在尝试了几十种组合后,我仍然没有找到一种方法来处理大量的音频单元。
目标是创建一个以音频单元视图作为子视图的容器NSView对象,并以容器的大小与AU视图的大小匹配的方式设置约束,包括当AU视图调整自身大小时。容器应该将translatesAutoresizingMaskIntoConstraints设置为NO,这样它就可以很好地处理窗口的其余部分。
我的第一个尝试是创建两个约束,简单地强制两个视图(容器和AU)的大小相等。这会失败,因为AU视图随后会折叠到非常小的尺寸。
另一种尝试是为容器视图创建固定大小约束,这些约束被初始化为与AU视图匹配,侦听AU视图的NSViewFrameDidChangeNotification,并根据需要调整固定大小。只要AU视图想要调整自己的大小,它就会崩溃。原因是,当我增加容器的大小以匹配AU视图时,自动调整掩码约束指示AU视图再次增加其大小,从而导致无限循环。
到目前为止,最有效的方法是关闭AU视图的translatesAutoresizingMaskIntoConstraints,并通过监听帧更改通知来设置容器的大小。这似乎适用于所有的AUv2音频单元,但对于AUv3音频单元(特别是苹果的演示AUv3),我总是得到(1,1)的视图大小,这显然是无用的。我将非常感谢任何关于如何使其工作的见解……
发布于 2020-06-22 22:27:02
基于您提供的示例项目,这应该是可行的:
@interface MyViewController ()
{
NSLayoutConstraint *widthConstraint, *heightConstraint;
}
@end
@implementation MyViewController
-(void)setFormatForBus:(AUAudioUnitBus*)bus
{
AudioStreamBasicDescription fmt = {44100, kAudioFormatLinearPCM, kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked, 4, 1, 4, 2, 32, 0}; // Stereo audio on each bus
AVAudioFormat* format = [[AVAudioFormat alloc] initWithStreamDescription:&fmt];
NSError* error = nil;
if (![bus setFormat:format error:&error]) {
NSLog(@"Couldn't set the format for bus... %@", error);
return;
}
bus.enabled = YES;
}
-(void)doLoad:(AVAudioUnit*)node controller:(NSViewController*)viewController
{
NSView* auView = nil;
if (viewController == nil) {
auView = [[AUGenericView alloc] initWithAudioUnit:node.audioUnit displayFlags:(AUViewPropertiesDisplayFlag | AUViewParametersDisplayFlag)];
auView.frame = self.view.frame;
[self.view addSubview:auView];
}
else {
self.auViewController = viewController;
auView = self.auViewController.view;
auView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:auView];
}
NSSize size = _auViewController.view.frame.size;
widthConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:size.width];
heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:size.height];
[self.view addConstraints:@[widthConstraint, heightConstraint]];
NSLayoutConstraint* top = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:auView
attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint* bottom = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:auView
attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
NSLayoutConstraint* left = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:auView
attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
NSLayoutConstraint* right = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:auView
attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
[self.view addConstraints:@[top, bottom, left, right]];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSArray* list = [[AVAudioUnitComponentManager sharedAudioUnitComponentManager] componentsPassingTest: ^BOOL(AVAudioUnitComponent *comp, BOOL *stop) {
return [comp.typeName containsString:@"Effect"];
}];
AVAudioUnitComponent* component = nil;
for (AVAudioUnitComponent* comp in list) {
if ([comp.name containsString:@"MultibandCompressor"]) // That allows itself to be squashed. Also, it doesn't resize itself when "details" is toggled
// if ([comp.name containsString:@"FilterDemo"]) // That one is squashed both vertically and horizontally... (Apple's sample AUv3 Audio Unit, needs to be installed first.)
// if ([comp.name containsString:@"GraphicEQ"]) // That one is squashed vertically
// if ([comp.name containsString:@"AUDelay"])
component = comp;
}
[AVAudioUnit instantiateWithComponentDescription:component.audioComponentDescription options:0
completionHandler:^(__kindof AVAudioUnit *audioUnit, NSError *error) {
if (error) {
NSLog(@"Error instantiating AU: %@", error);
return;
}
self.audioUnit = audioUnit;
AUAudioUnitBusArray* inputBusses = audioUnit.AUAudioUnit.inputBusses;
AUAudioUnitBusArray* outputBusses = audioUnit.AUAudioUnit.outputBusses;
if (!inputBusses.count || !outputBusses.count) {
NSLog(@"No busses...");
return;
}
[self setFormatForBus:[inputBusses objectAtIndexedSubscript:0]];
[self setFormatForBus:[outputBusses objectAtIndexedSubscript:0]];
NSError* AUerror = nil;
if (![audioUnit.AUAudioUnit allocateRenderResourcesAndReturnError:&AUerror]){
NSLog(@"Error allocating resources: %@", AUerror);
return;
}
[audioUnit.AUAudioUnit requestViewControllerWithCompletionHandler:^(NSViewController* viewController) {
dispatch_async(dispatch_get_main_queue(), ^{
[self doLoad:audioUnit controller:viewController];
});
}];
}];
}
- (void)viewWillLayout
{
[super viewWillLayout];
if(_auViewController != nil) {
[self.view removeConstraints:@[widthConstraint, heightConstraint]];
NSSize size = _auViewController.view.frame.size;
widthConstraint.constant = size.width;
heightConstraint.constant = size.height;
[self.view addConstraints:@[widthConstraint, heightConstraint]];
}
}
@endhttps://stackoverflow.com/questions/62511212
复制相似问题