View Full Version : SqueezeSlave: External USB audio interface (Mac OS X)

2010-12-19, 05:35

first of all a praise for ralphy: SqueezeSlave is great work! I'm new to the Squeezebox system, own a Mac mini and a Cambridge Audio DAC connected via USB. The latter fact made me look beyond SqueezePlay as a client for the mini in the first place (SqueezePlay does only support standard audio).

Everything's perfect until the external USB audio is being switched off (I do not leave it on all the time). Then, squeezeslave falls back to standard audio and won't come back to USB audio unless I restart the squeezeslave process, which makes it impossible to use for the Mrs.

Investing a few hours, I fudged together a workaround which consists of

1. a small service (based on the USBPrivateDataSample on the Apple developers site; sorry, I'm not yet allowed to post links) listening to USB (dis)connects and spawning actions for connect and disconnect
2. connect and disconnect actions which relaunch the squeezeslave service and bring USB audio back to life

I'm happy with the result (so is the Mrs), so I'd like to share the results and leave them to the community or the SqueezeSlave developer (ralphy) for further improvements.

But it's not packaged or anything, I don't have much time, and I'm a total noob when it comes to programming in C or Apple Core Foundation (although quite proficient in Python and Java), so I'd prefer to leave the code on a bilateral basis, to begin with. In particular, because I'm moving in the small niche "mac+usb dac". Anyone interested?


2010-12-20, 04:57
Yes, I'm interested.

If you're willing to share the code I'll add it to the squeezeslave source repository and include a compiled version in the mac release package.

We can also update the wiki with setup instructions.

Thanks for sharing your findings.

2010-12-21, 10:37
I attached code and configuration files to this post. It's quite a bunch of little puzzle pieces, but I like it that way because it's in fact not restricted to a use in the squeezeslave context, but more of a generic USB event handler triggering any kind of actions.

Feel free to comment or change anything you would do different (C or Bash code, error handling, permissions, paths, etc.).

Installation Instructions
1. The content of the folder Application Support goes to /Library/Application Support.
2. The binary usb-detect goes to /usr/local/sbin.
3. Modify the user permissions, product ID, vendor ID, and audio device ID according to your situation.

In the zip, we have the following components:

A compiled executable which detects (dis)connects of a specified USB device. It runs on my OS X 10.6 Intel Mac mini. (No idea whether the binary is universal or downward compatible; did I mention that I don't know much about Mac programming? :-) It accepts the two decimal integer parameters vendor ID and product ID, which for my USB DAC looks like

>/usr/local/sbin/usbdetect 3468 12
The vendor ID 3468 (hex 0x0d8c) and product ID 12 (hex 0x000c) of my USB DAC I could tell from the following command:

>system_profiler SPUSBDataType
C-Media USB Headphone Set :

Product ID: 0x000c

Source code for detection of USB devices. It has to be linked with the frameworks CoreFoundation and IOKit. It's based upon the Apple code on http://developer.apple.com/library/mac/#samplecode/USBPrivateDataSample/Introduction/Intro.html

Application Support/usb-detect/usb-detect.plist
A sample launchd service parameterization file. It runs an instance of the usb-detect binary for my USB DAC.

Application Support/usb-detect/vendor-3468-product-12/device-added
This script restarts the squeezeslave service by changing to folder /Library/Application Support/squeezeslave and running the script

/Library/Application Support/squeezeslave>./restart 2
The 2 stands for the audio device ID squeezeslave associates to the USB DAC and can be infered from

>squeezeslave -L
* 1: (Core Audio) Built-in Output (1/10)
2: (Core Audio) C-Media USB Headphone Set (2/29)

Application Support/usb-detect/vendor-3468-product-12/device-removed
Same as device-added. The reason for this is that the restart action will effectively shut down the service if the audio device is not available, see below.

Application Support/squeezeslave/squeezeslave
A wrapper script for the squeezeslave binary. Example:

/Library/Application Support/squeezeslave>./squeezeslave 2
checks whether the audio device 2 is up and launches an instance of squeezeslave for that device on mac 00:00:00:00:00:02 if the device is up.

Application Support/squeezeslave/start
Accepts a command line parameter for the audio device ID and launches a service running a squeezeslave instance dedicated to this output:

/Library/Application Support/squeezeslave>./start 2
The parameter 2 tells the script to use squeezeslave.2.plist as the service definition file, see below. If the service doesn't come up for some reason (in my case, the main reason is when the USB device is not connected), it shuts down the service right away.

Application Support/squeezeslave/stop
The antagonist of Application Support/squeezeslave/start.

/Library/Application Support/squeezeslave>./stop 2

Application Support/squeezeslave/restart
Combines stop with a subsequent start:

/Library/Application Support/squeezeslave>./restart 2

Application Support/squeezeslave/squeezeslave.[12].plist
Service definition files for audio device 1 and 2, respectively.

2010-12-22, 04:54
Thank-you for the code and detailed instructions.

I'll set it up on my mini over the holidays.