Skip to content

Phase 7: raise the TFM, and make SMTC the primary track source - #13

Merged
revtex merged 2 commits into
mainfrom
feat/phase-7-tfm-smtc
Aug 14, 2026
Merged

Phase 7: raise the TFM, and make SMTC the primary track source#13
revtex merged 2 commits into
mainfrom
feat/phase-7-tfm-smtc

Conversation

@revtex

Copy link
Copy Markdown
Owner

Phase 7's first two items. The remaining three — device hot-plug, long-path support, VB-CABLE detection — are not in this PR.

Raise the TFM (the prerequisite)

net10.0-windowsnet10.0-windows10.0.22621.0. SMTC lives in Windows.Media.Control, which only exists to bind against once the CsWinRT projections are on, and the version on the TFM is what turns them on. 22621 rather than Windows 11's 22000 floor because it is the oldest build still in support, so targeting lower gains nothing.

The plan warned that this changes what the compiler generates around WinRT types and that the hand-rolled IAudioPolicyConfig interop should be re-checked. It is unaffected by construction: the routing code names Windows.Media.Internal.AudioPolicyConfig only as a runtime-class string, and otherwise uses ComImport and raw P/Invoke — there is no WinRT type in the type system for the projections to claim. Verified at runtime rather than argued: it still binds the 21H2 IID and completes a COM round-trip on build 26200.

build.ps1 held a second copy of the TFM in its publish path and pointed at a directory that stopped existing the moment this changed. It reads the value from Directory.Build.props now.

SMTC as the primary track source

The window title is only readable while Spotify has a window. Minimised to the tray it has none, and detection stopped dead — the recorder could sit idle through a whole session because the user tidied the taskbar.

It is also better information. The title is one string that must be split back into artist and title on a separator that can legitimately appear inside either of them. SMTC hands over separate fields, and an album with them. Confirmed against the live session, which reported an album (… (Expanded Edition)) that no window title carries.

"Prefers" means "answers", nothing cleverer. The preferred source wins whenever it returns a track at all — not by being newer, more detailed, or more confident. An idle answer is still an answer and is not second-guessed; only a null, meaning "I cannot see Spotify", reaches the fallback. Anything more sophisticated means two detectors disagreeing mid-track and a recording whose tags change halfway through.

A failing SMTC is treated as a silent one. It is a system service Offstream does not control, so a fault costs the better metadata and never the recording — logged once per transition rather than per poll, since this runs several times a second. Cancellation is exempt: that is the session stopping, and it propagates.

Advertisements use the same two rules as the title path — the placeholder title, or playing with no artist attached — because Spotify announces them the same way to both. A paused session is never an ad: the placeholder lingers after playback stops, and treating it as one would suppress the next real track. An undetected ad is written to the library as a song, which is a worse failure than a missing tag.

The WinRT call is kept free of decisions. Everything decidable sits behind ISmtcSessions; WindowsSmtcSessions only talks to the system. So the mapping and the handover are tested without a media session, an audio endpoint, or Spotify installed. The session manager is fetched once and kept — RequestAsync is a cross-process call and this is polled several times a second.

928 tests green (760 core + 168 UI), up from 906. Twenty-two new, covering the mapping rules, ad detection including the paused case, and every handover branch.

Not verified here

The plan's exit criterion is a clean VM, which I cannot run. What I did verify on this machine: routing still binds under the new TFM, and the real SMTC reader returns Spotify's live session. Worth testing manually: minimise Spotify to the tray and confirm a recording still starts and tags. That is the behaviour this exists for and the one thing a unit test cannot prove.

🤖 Generated with Claude Code

revtexand others added 2 commits August 13, 2026 20:00
SMTC lives in Windows.Media.Control, which only exists to bind against
when the CsWinRT projections are on, and the projections are switched on
by the TFM carrying a version. Phase 7 makes SMTC the primary track
source, so this has to land first.
22621 rather than Windows 11's 22000 floor: it is the oldest build still
in support, so targeting lower gains nothing. Offstream is Windows 11
only, so this costs no supported user.
The plan flagged that raising this changes what the compiler generates
around WinRT types and that the hand-rolled IAudioPolicyConfig interop
should be re-checked. It is unaffected by construction — it names
Windows.Media.Internal.AudioPolicyConfig only as a runtime-class string
and otherwise uses ComImport and raw P/Invoke, so there is no WinRT type
in the type system for the projections to claim. Verified at runtime
rather than argued: it still binds the 21H2 IID and completes a COM
round-trip on build 26200.
build.ps1 held a second copy of the TFM in its publish path, which went
stale the moment this changed and pointed the success message at a
directory that no longer existed. It reads the value from
Directory.Build.props now, so the next bump cannot desync it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The window title is only readable while Spotify has a window. Minimised
to the tray it has none, and detection stopped dead — the recorder could
sit idle through a whole session because the user tidied the taskbar. The
media session Spotify publishes for the lock screen and volume overlay
survives that, so it becomes the primary source.
It is also better information. The window title is one string that has to
be split back into artist and title on a separator that can legitimately
appear inside either of them; SMTC hands over separate fields, and an
album with them. Confirmed against the live session, which reported an
album no window title carries.
"Prefers" means "answers", nothing cleverer: the preferred source wins
whenever it returns a track at all, never by being newer or more
detailed. An idle answer is still an answer and is not second-guessed —
only a null, meaning "I cannot see Spotify", reaches the fallback.
Anything more sophisticated means two detectors disagreeing mid-track and
a recording whose tags change halfway through.
A failing SMTC is treated as a silent one. It is a system service
Offstream does not control, so a fault costs the better metadata and
never the recording, logged once per transition rather than per poll.
Cancellation is exempt — that is the session stopping.
Advertisements use the same two rules as the title path, because Spotify
announces them the same way to both: the placeholder title, or playing
with no artist attached. A paused session is never an ad; the placeholder
lingers after playback stops and treating it as one would suppress the
next real track.
The WinRT call is kept free of decisions — everything decidable sits
behind ISmtcSessions in pure code, so all of it is tested without a media
session, an audio endpoint, or Spotify installed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@revtex
revtex merged commit fe9c21c into mainAug 14, 2026
1 of 2 checks passed
@revtex
revtex deleted the feat/phase-7-tfm-smtc branch August 14, 2026 22:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@revtex