One of Mountain Lions big features is AirPlay mirroring to send your OS X desktop to a big screen tv. However there is nothing in the press materials on streaming audio only. Something all apps on iOS devices have been able to do for a while now, but was limited to iTunes on OS X Lion and earlier.
Turns out this is perfectly possible on Mountain Lion but the documentation is a bit lacking on the subject. To encourage more applications to adopt AirPlay audio streaming I’ll explain how to add this to your application. (Yes, that’s a hint to SoundCloud and Spotify).
Spotify, Rdio or Soundcloud user? Check out Airwaves on the Mac App Store, a small utility to stream system audio to one or multiple AirPlay speakers.
This will be quite a technical read, for the impatient: a demo app is available on bitbucket.org.
System wide AirPlay streaming
This is the easy way that requires no modification to existing applications.
The Sound preferences pane in Mountain Lion now offers the ability to redirect all system sound to an AirPlay system. This will allow you to stream audio for applications other than iTunes over AirPlay.
But because this is a system wide setting your audio will be mixed with sounds from other applications. Also redirecting your users to the System preference to change some settings is not ideal.
Per application AirPlay streaming
Ideally every application would offer it’s own AirPlay configuration options like we’re used to in iTunes or on iOS. To achieve this effect you will have to redirect your audio from the system to an AirPlay enabled system somehow. On OS X you will have to use the C based CoreAudio framework for this.
1. Finding the AirPlay audio device
In CoreAudio you interact with audio devices for input and output. Each audio device is identified by a value of the CoreAudio AudioDeviceID
type. There are devices for the internal speakers, the headphones audio jack and the line in. When there are nearby AirPlay systems available a single new audio device will become available.
To get the AudioDeviceID
for this AirPlay device you loop over all available devices and query it’s transport type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
2. Finding all individual AirPlay destinations
Even when you have multiple AirPlay systems available only one audio device will be detected. When you start playing audio to this device only one system will output sound, the other systems available will stay silent. The CoreAudio documentation doesn’t mention anything related to AirPlay and completely fails to mention how to configure the AirPlay device and target individual AirPlay speaker systems.
It turns out that all AirPlay systems are listed in the AudioSource list property on an AudioDevice. To list all individual AirPlay speakers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
To get the name for an AudioSource:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
3. Selecting one or more AirPlay destinations to play to
Now that you know what the AirPlay audio device is, and what actual AirPlay systems are available as audio source you can configure your device to play to one or more sources. To do this you write to the audio source property, it accepts the id’s for one or more audio source.
1 2 3 4 5 6 7 8 9 10 11 |
|
4. Playing actual audio
There are two ways that I know of to play audio to a specific AudioDeviceID.
- The easy way for short sounds is by using
-[NSSound setPlaybackDeviceIdentifier:]
. - When using
AudioQueue
s to play audio set thekAudioQueueProperty_CurrentDevice
property.
Both methods accept a string identifier value which can be obtained from an AudioDeviceID
by querying it’s kAudioDevicePropertyDeviceUID
property.
Sample application
The demo applications demonstrates how to pick an AirPlay data source and redirect audio playing on an AudioQueue to the AirPlay audio device.
AirPlayStreaming demo app on bitbucket.org