ADR-0011: iTunes Is Read by Remote Pairing, the Way the Phone Remote Does It
| Status | Accepted
2026-10-10, after pairing with the real iTunes; see Evidence. Opened the same day as Proposed |
| Date | 2026-10-10 |
| Scope | How the iTunes driver learns of track changes and gets artwork. |
| Extended by | ADR-0020: the pairing is also used to play, pause, skip and set the volume |
| Related | ADR-0006, ADR-0007, ADR-0010 |
Context
The PCs run classic iTunes for Windows, not the Microsoft Store build and not the newer Apple Music app. A phone remote app already sees and controls it, after a one-time pairing and with no Apple ID sign-in. That pairing has to keep working for as long as Apple supports it.
Options considered
The remote protocol (DACP). What phone remotes speak: HTTP on port 3689,
found by Bonjour. A remote advertises itself, the user types its four-digit
code into iTunes once, and from then on it logs in with a stored pairing
GUID. A request to playstatusupdate carrying the last revision number
hangs until something changes, which is push notification without
polling. Artwork is one more request. It works from any machine on the same
LAN, in any language.
The COM automation interface. iTunes.Application and its events. No
pairing, and it still appears to work: two tools that depend on it shipped
releases in 2025. But it is Windows-only and must run on the iTunes PC, its
play event is reported not to fire reliably so those tools poll as well, and
creating the object launches iTunes unless the process is checked for first.
The Windows media controls. Classic iTunes does not report to them; it would need a separate bridge program that itself uses COM.
Home Sharing. The protocol’s other login, tied to an Apple ID. Not wanted, and probably closed to third-party code.
Decision
The iTunes driver speaks the remote protocol and pairs the way the phone remote does: a four-digit code typed into iTunes once, never an Apple ID or Home Sharing. It registers as an additional remote and does not disturb one already paired.
Its loop: log in with the stored pairing GUID; long-poll
playstatusupdate; on each return publish the state; fetch
nowplayingartwork when the album changes; on any error report offline, back
off and start again.
Fallback: the COM interface, in a Windows-only driver behind the same interface, if pairing proves closed.
Consequences
- The driver need not run on the iTunes PC. It runs on the relay (ADR-0010).
- It can be developed on a Mac against the Music app, if that speaks the same protocol — unverified.
- Track changes arrive pushed, with title, artist, album, play state and times, and the artwork comes from the player itself.
- Setup costs one code typed into iTunes, and the firewall on the PC must admit iTunes and Bonjour.
- The pairing GUID is state the driver must keep; lose it and pairing is repeated.
- The driver must detect a dead connection itself. What the long-poll does when iTunes quits or the PC sleeps is not documented.
- It works only while the PC stays on classic iTunes. The Apple Music app for Windows supports neither the Remote app nor Home Sharing, and installing it reduces iTunes to podcasts and audiobooks.
- There is no Go implementation to reuse; the client is written here, with
pyatv’s
dmapmodule as the reference.
Evidence
2026-10-10 — paired with classic iTunes 12.13.10.3 on Windows 11, from the
test client (npagent pair, npagent watch) on a Mac on the same LAN.
- Pairing was accepted. With the remote advertised, iTunes showed its
Remote button; the code was typed in; iTunes called back to
/pairand the client then logged in with the pairing GUID. No Apple ID, no Home Sharing. - The phone remote still works. It was already paired, stayed paired, and connected afterward. iTunes holds several remotes.
- Changes are pushed. Play, next track, pause and a change of album each arrived within the same second, on the request left hanging for them.
- The cover comes from iTunes. Three covers, as JPEG (41 KB, 48 KB) and PNG (363 KB), 500 px square, each fetched in 55-186 ms.
- A new album is distinguishable from a new track: the album id changed with the album and not between two tracks on one.
What the driver has to allow for, seen in the same run:
- iTunes answers several times per action. One click produced two or three identical reports, with the revision number jumping by more than one. The driver drops repeats.
- Stop is reported as pause. iTunes has no stopped state for a loaded
track; it reported
paused. - A stopped player with nothing loaded reports no track at all.
Bonjour on the PC was the only obstacle, and it was Windows, not iTunes.
No Remote button appeared at first. iTunes was reachable on port 3689 and
answered server-info, but the PC answered no Bonjour query, so iTunes never
saw the remote’s advertisement. The cause: the network was set to Private
and the firewall allowed Bonjour Service on Public networks only.
Checking Private for Bonjour Service (and for iTunes) under Allow an app
through Windows Firewall fixed it at once. Worth checking first on any other
PC: from another machine, dig @224.0.0.251 -p 5353 -x <the PC's address>
answers with its name when Bonjour is getting through.
Still to be seen
None of these would change the decision; each shapes the driver.
- What happens to the hanging request when iTunes quits or the PC sleeps.
- Whether the Music app on macOS accepts the same pairing, which decides whether the driver can be developed against it.
- Whether the pairing survives an iTunes update.
Sources
- Apple: use the iTunes Remote app (iTunes 12.13 for Windows) — both pairing modes still documented
- DACP, reverse-engineered (2008) — pairing, login, the long-poll, the response tags
- pyatv protocol notes and its pairing code
- OwnTone’s server side — confirms the long-poll’s behavior
- Report: Remote button missing on 12.13.3.2
- Apple Music for Windows does not support the Remote app
- iTunes-SMTC — COM in use in 2025, and “the iTunes OnPlayerPlayEvent does not always fire”