---
title: "Turning my turntable on with Siri"
description: "A tiny Homebridge switch that sends my turntable from a Mac to the Living Room HomePods through Airfoil."
pubDate: "2026-07-31"
heroImage: "/turntable-vinyl.jpg"
---

I wanted to say one very normal thing:

> “Hey Siri, turn on the Turntable.”

And have the turntable start playing through the HomePods in the living room.

I was connecting via VNC to the Mac mini, opening Airfoil, finding the right speakers and selecting them. Then I could put on a record and hear it through the HomePods. A bit much every time I wanted to listen to a record, isn't it?

<figure>
  <img src="/turntable-vinyl.jpg" alt="A vinyl record on a turntable" loading="lazy" />
  <figcaption>Photo by <a href="https://www.pexels.com/photo/a-vinyl-record-on-a-turntable-5657556/">Alessandro Nofi</a> on Pexels.</figcaption>
</figure>

This is one of those tiny home-automation problems that sounds almost silly until you try to make it feel natural.

## The Shortcut almost worked

The turntable is connected to a Mac mini. [Airfoil](https://rogueamoeba.com/airfoil/mac/) can pick its USB audio input and send it to my `Living Room` HomePod group, so the actual Mac part was straightforward. It's a bit overkill to use a Mac mini just for that, I agree. But it is also running `gemma-4-e2b-it-4bit` via oMLX, serving a chat app I'm experimenting with and outputting 50 tokens per second... but that's a story for another post.

Back to the turntable, I first made an iPhone Shortcut that ran a script over SSH. Tap it, and it worked.

But Siri has its own ideas about language. Say “turn the turntable on” and it hears a HomeKit accessory command, not a request to run a Shortcut. I could say “Run Turntable On,” but that is not how I want to talk in my own house.

So the real solution was not a better Shortcut. It was making **Turntable** a **HomeKit accessory**.

## Airfoil was the easy bit

Airfoil exposes AppleScript, which meant I could select the turntable input, called `USB AUDIO  CODEC`, and connect the `Living Room` speakers like this:

```applescript
tell application "Airfoil"
    set current audio source to first device source whose name is "USB AUDIO  CODEC"
    connect to (every speaker whose name is "Living Room")
end tell
```

Turning it off is just disconnecting that group:

```applescript
tell application "Airfoil"
    disconnect from (every speaker whose name is "Living Room")
end tell
```

That part was pleasantly uneventful. The fun started when Siri got involved.

## A virtual switch named Turntable

I run [Homebridge](https://homebridge.io/) on the Mac mini, with the [`homebridge-script2`](https://github.com/ppanagos/homebridge-script2) plugin. It exposes a normal switch called `Turntable`, whose on and off actions run two shell scripts.

```json
{
  "accessory": "Script2",
  "name": "Turntable",
  "on": "/Users/<user>/.homebridge/scripts/airfoil-on.sh",
  "off": "/Users/<user>/.homebridge/scripts/airfoil-off.sh",
  "fileState": "/Users/<user>/.homebridge/scripts/turntable-on.flag"
}
```

Now Siri knows what the Turntable is. That small naming change was the whole point.

## HomeKit is impatient

My first version asked Airfoil whether `Living Room` was connected whenever HomeKit asked for the switch state. Reasonable, right?

Not really. AppleEvents to Airfoil can take longer than HomeKit is willing to wait. Siri would understand the command, start doing the right thing, then tell me the accessory had “failed to respond.” Annoying, especially while the music was literally about to play.

The fix was to separate the immediate answer from the slower action. The flag file is the HomeKit state. Touch it when turning on, remove it when turning off, and run Airfoil in the background.

`airfoil-on.sh`:

```bash
#!/bin/bash
set -euo pipefail

flag=/Users/<user>/.homebridge/scripts/turntable-on.flag
log=/Users/<user>/.homebridge/logs/airfoil-actions.log
touch "$flag"

/usr/bin/osascript <<'APPLESCRIPT' >>"$log" 2>&1 &
with timeout of 30 seconds
    tell application "Airfoil"
        set current audio source to first device source whose name is "USB AUDIO  CODEC"
        connect to (every speaker whose name is "Living Room")
    end tell
end timeout
APPLESCRIPT
```

And off:

```bash
#!/bin/bash
set -euo pipefail

flag=/Users/<user>/.homebridge/scripts/turntable-on.flag
log=/Users/<user>/.homebridge/logs/airfoil-actions.log
rm -f "$flag"

/usr/bin/osascript <<'APPLESCRIPT' >>"$log" 2>&1 &
with timeout of 30 seconds
    tell application "Airfoil"
        disconnect from (every speaker whose name is "Living Room")
    end tell
end timeout
APPLESCRIPT
```

This is slightly optimistic. HomeKit gets an immediate “yes, it is on,” then Airfoil catches up in the background. For this setup, it feels much better than waiting for a perfect answer and getting a timeout instead.

## The bridge that Home did not see

Then Homebridge was running perfectly, but it would not show up in Apple Home under **Add Accessory → More Options**.

The clue was in the logs: its built-in multicast advertiser was getting `EHOSTUNREACH` while trying to advertise the service.

I worked around that by using macOS's native Bonjour tool, `dns-sd`, to advertise Homebridge's existing HAP service. After that, it appeared in Apple Home and paired normally.

I keep both pieces alive with LaunchAgents, one for Homebridge and another for the mDNS advertisement. The second one runs `advertise-homebridge.sh`, which reads Homebridge's persistent state and publishes the required `_hap._tcp` TXT records.

One important thing, if you end up down this rabbit hole: publish **your own** HAP identity, setup hash and pairing code. Those are part of the bridge's identity, not values to copy from another machine.

## The command I wanted

The bridge is called `Mac mini Bridge`. The accessory Siri controls is `Turntable`.

> “Hey Siri, turn on the Turntable.”
>
> “Hey Siri, turn off the Turntable.”

That is it. The Mac mini needs to stay on and reachable, and [Caffeine](https://apps.apple.com/app/caffeine/id411246225) takes care of that. macOS also needs permission for `osascript` to control Airfoil. Once that is in place, the interaction disappears, which is exactly what I wanted.

Now I can put on a record and say one sentence. **A tiny bit ridiculous, maybe**. Also very satisfying.
