The receiver that switches its own mode

A small Python script on the Mac watches which app is playing and tells the studio's Yamaha TSR-700 to use Dolby Surround for movies and All-Channel Stereo for music.

In use since 21 October 2026.

Try the rules

This runs the same decision the script makes every four seconds.

What is playing on the Mac?
Override file
The studio receiver switches to Dolby Surround

A movie app is playing. (Only if the receiver is switched on.)

The problem

One receiver, two jobs. Movies want the Dolby Surround decoder. Music and whatever is playing in a browser sound better here in All-Channel Stereo. Switching by remote every time is the kind of chore that never gets done.

How it works

  1. Every four seconds the script asks macOS which apps are holding the system awake for audio or video playback, using the built-in pmset -g assertions command.
  2. It checks that list against two short lists of app names in a rules file.
  3. If a movie app is playing, it wants Dolby Surround. Movie apps win ties, so a trailer in Chrome during a Stremio film does not flip it.
  4. If only a music or browser app is playing, it wants All-Channel Stereo.
  5. If nothing is playing, it leaves the receiver alone.
  6. When the wanted mode changes, it asks the receiver for its status over Yamaha's local network API, and only if the receiver is on does it send the new sound program.

The rules file

Changing behaviour means editing a list, not code. The receiver's address is left out here.

{
  "receiver_ip": "<receiver address>",
  "poll_seconds": 4,
  "dolby": ["Stremio", "TV", "VLC"],
  "stereo": ["Google Chrome", "Safari", "TIDAL"]
}

The override

Sometimes the rules are wrong for the moment. A file called override next to the script, containing dolby or stereo, pins that mode. Delete it and the script goes back to automatic.

The heart of it

def want_mode():
    ov = HERE / "override"
    if ov.exists() and ov.read_text().strip() in MODES:
        return ov.read_text().strip()
    apps = playing_apps()
    for mode in ("dolby", "stereo"):          # movie apps win ties
        for key in CFG[mode]:
            if any(key.lower() == a.lower() or (len(key) > 3 and key.lower() in a.lower()) for a in apps):
                return mode
    return None

One day in the log

Every switch is logged. From 28 October 2026:

08:48:13 -> dolby
11:37:39 -> stereo
16:16:36 -> stereo
16:46:34 -> dolby
17:43:04 -> stereo

It runs in the background as a macOS launch agent, so it starts with the Mac. When the receiver does not answer, the script logs the error and simply tries again on the next round; the log shows one such timeout, on 25 October, followed by a normal switch half a minute later.