AirPlay Audio Receiver

SwiftShellXcodeClaude CodeView Code

A lightweight macOS menu bar application that enables audio-only AirPlay streaming from iPhone to Mac. Unlike the built-in macOS AirPlay Receiver (which mirrors both video and audio), this app receives only audio, allowing you to use your Mac's speakers or connected headset as an AirPlay audio destination.

Features

  • Audio-only AirPlay receiver - Stream music from iPhone without screen mirroring
  • Seamless output switching - Switch between audio output devices (headset, speakers, etc.) without disconnecting iPhone
  • Menu bar app - Minimal, unobtrusive interface lives in your menu bar
  • Auto-discovery - iPhone automatically discovers "MacBook AirPlay" via Bonjour/mDNS
  • Native Swift - Lightweight, native macOS application

How It Works

┌─────────────┐     AirPlay      ┌──────────────────┐     Audio      ┌─────────────────┐
│   iPhone    │ ───────────────► │  shairport-sync  │ ─────────────► │  Output Device  │
│  (Music)    │   (via WiFi)     │  (AirPlay recv)  │  (via libao)   │ (Headset/Spkrs) │
└─────────────┘                  └──────────────────┘                └─────────────────┘
                                         ▲
                                         │ manages
                                         │
                                 ┌───────┴──────────────┐
                                 │ AirPlayAudioReceiver │
                                 │   (Menu Bar App)     │
                                 └──────────────────────┘

The app is a Swift wrapper around shairport-sync, an open-source AirPlay audio receiver. The menu bar app:

  1. Starts/stops the shairport-sync daemon
  2. Advertises "MacBook AirPlay" on the local network
  3. Allows switching the system default audio output device
  4. Audio automatically routes to whatever device is set as system default

Requirements

  • macOS 12.0 or later
  • Homebrew
  • shairport-sync (brew install shairport-sync)

Installation

1. Install shairport-sync

brew install shairport-sync

2. Build the app

cd /path/to/airplay-audio-receiver
./build.sh

This creates AirPlay Audio Receiver.app - a proper macOS application bundle.

3. Install the app

Option A: Automated installer (Recommended)

./install.sh

This script will:

  • Copy the app to /Applications
  • Optionally add it to Login Items (auto-start on login)
  • Offer to launch the app immediately

Option B: Manual installation

Drag AirPlay Audio Receiver.app to your /Applications folder, or run it directly:

open AirPlay Audio Receiver.app

The app will appear in your menu bar with an AirPlay icon (no Dock icon - it's a menu bar app).

Usage

  1. Start the app:
    • Open from Applications folder (search "AirPlay Audio Receiver" in Spotlight)
    • Or if added to Login Items during install, it starts automatically on login
  2. Connect from iPhone:
    • Open Control Center on iPhone
    • Tap the AirPlay icon
    • Select "MacBook AirPlay"
  3. Switch output devices - Click the menu bar icon and select your preferred output (Logi USB Headset, MacBook Pro Speakers, etc.)
  4. Play music - Audio from iPhone will play through your selected Mac output device

Menu Options

OptionDescription
Output: [Device]Shows current audio output device
Switch Output To:Lists available output devices to switch to
Stop/Start AirPlay ReceiverToggle the shairport-sync daemon
QuitStop receiver and exit app

Architecture

Files

FileDescription
AirPlayAudioReceiver.swiftMain application source code
build.shBuild script that creates the .app bundle
install.shInstallation script (copies to /Applications, optionally adds to Login Items)
AirPlay Audio Receiver.app/Compiled app bundle (not tracked in git)

Components

AudioDeviceManager

Handles CoreAudio interactions:

  • Lists available output devices
  • Gets/sets the system default output device
  • Filters out virtual devices (BlackHole, Multi-Output, etc.)
ShairportManager

Manages the shairport-sync process:

  • Starts shairport-sync with proper arguments
  • Stops and cleans up processes on exit
  • Outputs to system default device via libao's macosx driver
AppDelegate

Main application logic:

  • Creates and manages the menu bar interface
  • Handles device selection (changes system default output)
  • Listens for audio device changes to update menu

Technical Details

Why shairport-sync?

Apple's AirPlay protocol is proprietary. shairport-sync is a mature, open-source implementation that:

  • Supports AirPlay 1 (RAOP protocol)
  • Works reliably with iOS devices
  • Outputs audio via multiple backends (libao, ALSA, PulseAudio, etc.)

Audio Routing

The app uses libao's macosx driver which outputs to the system default audio device. When you switch outputs via the menu:

  1. The app calls CoreAudio APIs to change the system default output
  2. shairport-sync (via libao) automatically uses the new default
  3. No restart required - audio switches seamlessly

Port Usage

  • Port 5000 - RTSP control (AirPlay handshake)
  • Ports 6001-6010 - UDP audio data

Note: Disable macOS's built-in AirPlay Receiver (System Settings → General → AirDrop & Handoff → AirPlay Receiver) to avoid port conflicts.

Troubleshooting

"App is damaged or incomplete" error

This is a macOS Gatekeeper security feature. The build script now automatically fixes this by:

  1. Adding an ad-hoc code signature to the app
  2. Removing quarantine attributes

If you still see this error:

# Remove quarantine and re-sign
xattr -cr "AirPlay Audio Receiver.app"
codesign --force --deep --sign - "AirPlay Audio Receiver.app"

iPhone can't find "MacBook AirPlay"

  • Ensure shairport-sync is running (ps aux | grep shairport)
  • Check Bonjour advertisement: dns-sd -B _raop._tcp
  • Verify both devices are on the same WiFi network

"Unable to connect" error

  • Check if port 5000 is in use: lsof -i :5000
  • Kill any conflicting processes: pkill -9 shairport-sync
  • Disable built-in AirPlay Receiver in System Settings

No audio output

  • Verify system output device is correct in Sound settings
  • Check shairport-sync is using macosx driver: should see -o ao -- -d macosx in process args
  • Test audio output: say "test"

Audio plays but switching devices doesn't work

  • Ensure you're selecting devices from the menu bar app (not System Settings)
  • The app changes the system default, which should route audio immediately

Building from Source

Requirements

  • Xcode Command Line Tools (xcode-select --install)

Build and Install

# Build the app
./build.sh

# Install to /Applications
./install.sh

build.sh creates the app bundle:

  1. Creates the app bundle structure
  2. Generates the app icon (blue/purple gradient with AirPlay symbol)
  3. Compiles the Swift code into the bundle
  4. Signs the app with ad-hoc signature (fixes macOS Gatekeeper)
  5. Removes quarantine attributes

install.sh installs the app:

  1. Copies AirPlay Audio Receiver.app to /Applications
  2. Optionally adds to Login Items for auto-start
  3. Offers to launch immediately

Manual Run (without installing)

open AirPlay Audio Receiver.app

License

MIT License - See LICENSE file for details.

Acknowledgments

  • shairport-sync - The AirPlay receiver that makes this possible
  • libao - Cross-platform audio output library