Skip to content
This repository has been archived by the owner. It is now read-only.
[ABANDONED] The unofficial JACK audio device driver for OS/X
C Makefile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
CaptainJack.driver/Contents
src
.editorconfig
.gitignore
LICENSE
Makefile
README.md
me.junon.CaptainJack.plist

README.md

	,---.         .              ,-_/
	|  -' ,-. ,-. |- ,-. . ,-.   '  | ,-. ,-. . ,
	|   . ,-| | | |  ,-| | | |      | ,-| |   |/
	`---' `-^ |-' `' `-^ ' ' '      | `-^ `-' |\
	          |                  /  |         ' `
	          '                  `--'
	          captain jack audio device
	         github.com/qix-/captainjack

	        copyright (c) 2016 josh junon
	        released under the MIT license

I've halted production on Captain Jack until JACK has improved. See #3.

Captain Jack

Captain Jack is a JACK-enabled audio device for OS/X.

Through the use of the new AudioServerPlugin API (since 10.5), Captain Jack provides a means of routing system audio into the JACK subsystem through either a system mix port or one or more per-application (namely, per-process) audio ports.

Installing

You must have an implementation of JACK installed on the system. You can (and should) do this by downloading and building the latest source from either JACK1 or JACK2, though it's worth mentioning JACK2 does not currently build on OS/X.

To build Captain Jack:

$ make

To install Captain Jack:

$ sudo make install

To start Captain Jack:

$ sudo make start

Developing

Debugging

Use Console.app (in /Applications/Utilities). Select system.log on the side and filter for CaptainJack.

All daemon log messages have the CaptainJack tag, and all device messages have the CaptainJack-Device tag.

Layout

Captain Jack is made up of two pieces: the device and the daemon.

Device

The Captain Jack Device is a CoreAudio HAL Plugin .driver bundle that uses the latest APIs in lieu of the deprecated AudioHardwarePlugin APIs.

The device is a user-space plugin that requires no Kext signing nor does it require disabling of SIP.

Since coreaudiod, the system service that manages audio and thus loads Captain Jack's device plugin, resides within the System bootstrap space, and since coreaudiod runs everything inside a sandbox, getting audio out of coreaudiod and into JACK requires some clever IPC.

XPC is Apple's version of IPC and is one of the two methods of IPC really available to Mach services. Its major (and deal-breaking) drawback is that it requires some sort of main dispatch loop, which isn't possible in an AudioServerPlugin bundle since everything inside of the device is just a callback and anything that blocks would effectively block not only coreaudiod but other launch daemons as well (I notice my RGB key board freeze up if Captain Jack blocks!).

Therefore, the network was the only other means of IPC (I heard that shared memory regions were allowed, but I never could figure out how to get them to work).

When a connection has been established to the daemon (a user-space launchd daemon; see below), all callbacks forward their data to an Xmit RPC call (see src/xmit.c) that in turn passes the data along the loopback socket and into the less-restrictive daemon process.

The reason why the daemon is even necessary and why the device cannot simply connect to JACK directly is that the sandbox prevents any IPC other than network IPC. Since we can't really guarantee that JACK is going to support network communication this becomes unreliable. As well, things like RO filesystem calls, the inability to trigger window apps or even look up PID process names were very restrictive, and the device quickly turned into a trampoline for audio events.

Daemon

The Captain Jack Daemon is a user-space launchd LaunchDaemon that relays Xmit-RPC'd audio data from the device to JACK. It also manages a light state for whatever might be necessary to track (e.g. client name => PID map, etc).

Xmit

The device and daemon communicate over a very opaque and light network layer dubbed Xmit (see src/xmit.c) that uses read buffer polling to achieve asynchronicity. Since it uses the TCP protocol, there is little chance of audio frames to be mixed up during transmission.

Using the network also gives us nearly free IPC with almost zero added latency (assuming the loopback interface is used, which it is in this case).

The only externalized Xmit calls are those that set up the callback functions. All transportation specifics are statically defined and managed inside of xmit.c.

License

Captain Jack is licensed under the MIT License. All JACK works are licensed under their respective licenses.

You can’t perform that action at this time.