将旧式视图(音频单元视图)合并到自动布局中



我想将音频单元创建的自定义视图嵌入到使用自动布局的窗口中。在尝试了数十种组合之后,我仍然没有找到一种方法来做到这一点,它适用于大量的音频单元。

目标是使用音频单元视图作为子视图创建容器NSView对象,并以容器大小与 AU 视图的大小匹配的方式设置约束,包括后者调整自身大小时。容器应该translatesAutoresizingMaskIntoConstraints设置为NO,因此它可以与窗口的其余部分很好地配合使用。

我的第一个尝试是创建两个约束,简单地强制两个(容器和 AU(视图的大小相等。这将失败,因为 AU 视图随后折叠到非常小的大小。

另一个尝试是为容器视图创建固定大小约束,这些约束初始化以匹配 AU 视图,侦听 AU 视图的NSViewFrameDidChangeNotification,并根据需要调整固定大小。一旦 AU 视图想要调整自身大小,就会崩溃。原因是当我增加容器的大小以匹配 AU 视图时,自动调整大小掩码约束指示 AU 视图再次增加其大小,从而导致无限循环。

到目前为止,最有效的方法是关闭 AU 视图的translatesAutoresizingMaskIntoConstraints,并通过侦听帧更改通知来设置容器的大小。这似乎适用于所有 AUv2 音频单元,但对于 AUv3 音频单元(特别是 Apple 的演示 AUv3(,我总是得到 (1,1( 的视图大小,这显然是无用的。我将非常感谢有关如何使这项工作的任何见解......

根据您提供的示例项目,这应该可以工作:

@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]];
}
}
@end

相关内容

  • 没有找到相关文章

最新更新