Creating Audio Units with Cocoa Views on Mac OS X 10.7 (Lion)

So far, I’ve gotten more questions about getting Cocoa Views to work in Audio Units than other requests, so here we go.

Since I’ve been on a lengthy vacation, I didn’t think too much about it until I tried using the built-in template for Audio Unit Effects in Xcode 4.x. It doesn’t make it at all clear how to get it all working. Fortunately, it’s not terribly difficult. It just takes a bunch of changes to the files and projects that are generated by the template.

Also, there have been some changes in Mac OS X Lion that require attention to make this (and any new Audio Units) work.

Create the Project

First off, go ahead and create a new project. In the project sheet, select Audio Unit Effect as your project type and click Next.

In the next sheet you will be naming your effect. Make note of your Company Identifier, as you’ll be needing that later. Ensure that with Cocoa View is checked and click Next.

Go ahead and save your project as you normally would.

In my case, I’m using the simple project name of CV. So, wherever you see CV (in italics) in the following code, just insert your project name.

Tweak the Project

Once the project is created, we’ll start to adjust various project settings along with adding and removing some files to make things work on Lion.

First off, find the following files in your Xcode project’s AUPublic folder and delete them:

  • AUDebugDispatch.h
  • AUDebugDispatch.cpp

Next, and this is part of the Lion changes, Control-Click on your AUPublic folder and select “Add Files to CV…”

In the sheet that appears, navigate to /Developer/Extras/CoreAudio/AudioUnits/AUPublic/AUBase and select the following files for addition.

  • AUPluginDispatch.h
  • AUPluginDispatch.cpp

We now have one more file to add. Right click on CV (or your project folder in Xcode) and select New File…

Create an empty file and name it CV-Prefix.pch.

Now, we could just turn the prefix setting in the build settings to not look for this file, but for consistency with the FilterDemo sample code, I just figured we’d put it in there in the event we want to use it later on for precompiled headers.

Last, we need to decide what architecture(s) we want to build this for. For simplicity’s sake, I build a universal component for 64-bit and 32-bit platforms. You’ll need to decide for yourself and make the changes accordingly. Here’s how.

Select your project in the left-most pane of Xcode. It will probably be right at the top of the pane and list how many Targets you have.

Selecting the Xcode Project

Once you’ve selected your target, you can make modifications to your build settings. Of particular interest are Architectures and Build Active Architecture Only. If you want to test both the 32 and 64-bit versions, you’ll need to set the following:

  • Architectures – Standard (32/64-bit Intel)
  • Build Active Architecture Only – No (for both Debug and Release – see below)

This is a point of confusion for many people. Basically, this is where you’re telling the compiler which versions to build. By default, the Debug setting is Yes. Which means that on any machines sold today, it will build only 64-bit versions since all the machines now are 64-bit. The problem  with that is that AULab runs, by default, in 32-bit mode, so you won’t ever see your Audio Unit in the list.

Now, let’s modify some files…

Changing the Files

I’m just going to list the files to change along with the changes to make.

CV.h

Locate the following lines and remove them.

#if AU_DEBUG_DISPATCHER
	#include "AUDebugDispatcher.h"
#endif

CV.cpp

Locate the following lines and remove them.

#if AU_DEBUG_DISPATCHER
	mDebugDispatcher = new AUDebugDispatcher (this);
#endif

Locate the following line:

COMPONENT_ENTRY(CV)

and change it to:

AUDIOCOMPONENT_ENTRY(AUBaseFactory, CV)

This is one piece of a fairly significant change the Apple is making with respect to Audio Units and the move away from Component Manager.

Locate this line in your GetProperty method:

CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.audiounit.CV") );

This needs to reflect the bundle identifier (typically your Company Identifier + ‘.audiounit.’ + projectname) of your target. For me it is com.squishycat.audiounit.CV . This is typically set when you create the project and specify the name. So, change that line to something like…

CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.yourcompany.audiounit.CV") );

CV.exp

Add the line:

_CVFactory

Be sure to put a carriage return at the end of the line to avoid syntax warnings.

CV-Info.plist

You need to add a set of properties that used to belong in CV.r. Basically, you just add these just before the last </dict> tag. Obviously, put your own company and text in where you see SquishyCat, etc. Take a look at TechNote TN2276 for more information on this change.

	<key>AudioComponents</key>
	<array>
	<dict>
	<key>description</key>
	<string>SquishyCat Cocoa View</string>
	<key>factoryFunction</key>
	<string>CVFactory</string>
	<key>manufacturer</key>
	<string>SquishyCat</string>
	<key>name</key>
	<string>SquishyCat: Cocoa View Test</string>
	<key>subtype</key>
	<string>Pass</string>
	<key>type</key>
	<string>aufx</string>
	<key>version</key>
	<string>65536</string>
	</dict>
	</array>

CVVersion.h

Modify the CV_COMP_MANF to your 4-digit company code (Get that from Apple)
Modify the CV_COMP_SUBTYPE to something more appropriate for you AU (See Apple Documentation on Component Subtypes)

Finally, Build That Sucker!!!

HOLD ON!!! HOLD ON!!! Before slamming those fingers down on Command-B, make sure that your Scheme is set to compile your Component, not just the View bundle. For some reason, every time I set one of these up, Xcode defaults to wanting to build the ViewFactory rather than the Actual component. Since the component is set to have a dependency on the View, it’ll force the view to be built automagically.

Once you do that, see if you can’t successfully build the project. Once it’s built, move the component (just the component, you don’t need to manually move the View bundle) to either /Library/Audio/Plug-ins/Components or ~/Library/Audio/Plug-ins/Components, then start up AULab and see if your new component with Cocoa View shows up.

8 thoughts on “Creating Audio Units with Cocoa Views on Mac OS X 10.7 (Lion)

  1. Thanks so much for making this, worked great, however my au passes validation in Logic Pr0 9 on Lion. however on snow leopard it crashes validation at the start, tried to build against 10.6 SDK however it throws up 100+ errors, any idea on what i should do?

    • Not sure about the Snow Leopard validation. Unfortunately, I can’t test it as I’m on vacation and only have my Air with me running Lion.

      As for building against the 10.6 SDK, that doesn’t surprise me, as this makes use of changes in the 10.7 SDK per Tech Note 2276. However, building on Lion shouldn’t necessitate that it run only on Lion. Be sure that all of the pre-lion stuff is in place, though. For example, ensure that your .r file has all of your component information(RES_ID, COMP_TYPE, COMP_SUBTYPE, COMP_MANUF, VERSION, NAME, DESCRIPTION, ENTRYPOINT) even though it is now duplicated in the Info.plist for Lion. Also, make sure your .exp file has the older style entry point in addition to the new one (i.e.: _AUNameEntry and _AUNameFactory)

      Once I get back to home base, I’ll run these on Snow Leopard and see what’s up.

    • I just fired up Xcode 4.2 for the first time the other day (been working on a new job). It looks liked they’ve removed the templates completely. I’m hoping it’s because they’re out of date and are replacing them in an update…but I’m not holding my breath.

      When I get a little time, I’ll see if I can set up some directions for creating it from scratch. It really shouldn’t be too hard, as it’s mainly steps in setting up the project.

      • Urgh. Just wasted about 2 hours of my life downloading/reinstalling Xcode and trying to work out why I didn’t have the Audio Unit template.

        Looks like I won’t be doing any AU hacking this weekend… 🙁

  2. Pingback: ∇xE=-∂B/∂x | Audio Units Programming, Lion Issue

Leave a Reply