I have a great idea (or had one a long time ago) for Breakaway to use information about what is playing through the speakers to decide whether or not to unpause iTunes. My first leap was when I found the CoreAudio constant kAudioDevicePropertyDeviceIsRunningSomewhere. I've included code for how I did it, just because I had such a hard time working with CoreAudio.
AudioDeviceID defaultDevice;
UInt32 audioDeviceSize = sizeof defaultDevice;
AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,&audioDeviceSize,&defaultDevice);
UInt32 runningSomewhere;
UInt32 uint32Size = sizeof runningSomewhere;
AudioDeviceGetProperty(defaultDevice,0,0,kAudioDevicePropertyDeviceIsRunningSomewhere,&uint32Size,&runningSomewhere);
Get the default output device, and check if it is running somewhere; simple enough. It's disheartening though, to find out that "is running somewhere" is not what you may think it to mean. The documentation says:
... [T]he device can be running even if there are no active IOProcs such as by calling AudioDeviceStart() and passing a NULL IOProc.Unfortunately, lots of applications tend to do this. VLC and any Flash video through Safari come to mind, and I'm sure there are plenty of other examples. So the application grabs the audio and says it's playing, but it really isn't. It's like calling someone on the telephone, and never actually saying anything (or more appropriately, there is no microphone connected).
But good news; if get 0, you are guaranteed no audio to be playing. But if you get 1, well, you are pretty much in the dark.
So since there are no simple properties to look at, the next logical step would be to look ourselves at the device and see what data is flowing. There is a function called AudioDeviceRead(), and Apple has provided some documentation on how to use it, but I couldn't get it working. It referenced some old code that I wasn't able to find, as well as used some (presumably) dated constructs that I couldn't find much about. In the documentation, Apple states that the functionality of AudioDeviceRead() can be found in aggregate devices, so that function could be marked for depreciation in the future. To make a long story short, I tried virtually everything CoreAudio could offer me at face value; I just couldn't get it working. At first, I thought I was just missing the elephant in the room, but then I looked at other applications I know grab system audio.
The application called iShowU uses a virtual audio device called Soundflower. Apparently, the iShowU developers came to the same conclusion I did about CoreAudio, so they turned to this loopback type of device. So, I download that, and give it a shot. I had to set the Soundflower device as my default output, but I was still able to analyze the system sound! Unfortunately, Soundflower likes to blow up when you do something crazy, like pull out/put in the headphones (which, unfortunately, is what Breakaway basically does). In addition, you have to set the default output, which requires a wait for it to get configured, then switch it back afterwards (also associated with a wait). And you must remember that humans can easily pick up breaks in audio, and these .1 second breaks waiting for the audio devices to reconfigure are easily picked up. Soundflower works for it's intended audience, but it does not work in the critical environment I demand.
The next application is of many awards and praises: ScreenFlow. I have used ScreenFlow before and remembered how eloquently it handled audio. When I try to capture system output with that application, it says you must install a kernel extension for it to run correctly. A dive into the resources reveals this extension as VaraAudio.kext. The beauty of how ScreenFlow captures their audio is that it is (apparently) completely devoid of any CoreAudio hooks. Why? Because you can watch the default output, and it never changes. That and the fact that it's a kernel extension raises a flag that some serious low level work is going on. The perfect solution.
Gaining complete system audio output and bypass CoreAudio? It's so pure, like a fountain of data ready to be captured, without having to go through all the pipes and values of CoreAudio. I tried to interface with this kext, look at its properties, but I couldn't figure out what the magic code was to communicate with it. In hope, I emailed the actual developers of ScreenFlow asking for help. A few days later, they said that the code was proprietary, and could not help me; I was stunned that they actually replied to me. Not one, but two emails: one to say that my email was being forwarded to the developer team, and another with their response. Most of the time, requests like this are thrown away at first glance and the sender is shown the door by a canned response. Though, it was only a fool's hope, my pursuit for this code. I expected them to not reveal it, because if they gave me the code, anyone could use it (most notably competing screencast developers). But a sliver of chance is worth taking. I also figured since the audio in the demo is unstamped (unlike the video, which is watermarked), they are giving out their audio recording capability "for free", as it is easy to rip the audio from a video into your encoding of choice. But unfortunately, their code is, understandably, too critical to be handed out.
So what does that mean for the future of Breakaway? Well, I don't see my glorious idea ever coming into play. Patching Soundflower or developing my own .kext would prove to be very difficult and time consuming. It sounds like a very fun challenge, but I think that my time could be spend better elsewhere, implementing different features and making better applications.
Unless, that is, you, the Reader, have any suggestions?