Skip to content

Start recording when playback starts, not only when the track changes - #34

Merged
revtex merged 1 commit into
mainfrom
fix/record-when-playback-starts
Aug 15, 2026
Merged

Start recording when playback starts, not only when the track changes#34
revtex merged 1 commit into
mainfrom
fix/record-when-playback-starts

Conversation

@revtex

@revtex revtex commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Stacked on #33 — review that one first. The diff against main will collapse to just this change once #33 merges.

What was wrong

Press record while Spotify is paused, then press play: the meter moves, the counter runs, the page names the song, and nothing is ever recorded until you stop and start again.

Being played is half of what makes a track recordable (Track.IsNormalPlaying, via RecordingPolicy.IsTypeAllowed), and that check ran only in OnTrackChanged. Track.Equals ignores the play state on purpose — so that a pause mid-song does not read as a new song — which means a track that starts playing raises no track change at all. It raises PlayStateChanged, which only reported a stage.

So the session passed the track over once as not recordable and then waited for a change that had already happened:

22:15:27 [Information] "Listening for Spotify."
22:15:27 [Information] "Not a recordable track: Small Town Kid - When the Feeling Is Gone."
22:15:46 [Information] "Stopped."

The predecessor never met this — Watcher.SetSpotifyAudioSessionAndWaitToStart() blocks on Spotify producing audio before it begins watching. Offstream starts listening the moment record is pressed, which is the better behaviour and worth keeping.

What changed

The admission check moves into Consider(track), called from OnTrackChanged as before and now from OnPlayStateChanged too. The resume path is deliberately narrower than the track-changed one:

  • Only when nothing is being recorded — a pause mid-song must leave the running recorder alone rather than start a second one on top of it.
  • Not once the recording timer has elapsed — the session is winding down, and reporting "recording timer elapsed" would be a lie about a resume.
  • Only for the track already showing. One poll can see both a new song and a change of play state — starting with Spotify already playing is exactly that case — and TrackChanged is raised straight after, carrying the stop-the-outgoing-recorder handling this path does not have. Admitting from both would start a recorder only for the other to tear it down, discarding the fragment as too short.

PlayStateChangedEventArgs now carries the track it observed. PollOnceAsync does not store the observation until the poll finishes, so a handler reading poller.CurrentTrack gets the previous one — whose play state is precisely the one that just stopped being true.

Testing

  • Session_WhenPlaybackStartsOnTheTrackAlreadyShowing_RecordsIt — the reported sequence. Confirmed failing against the unfixed session.
  • Session_WhenPlaybackIsAlreadyUnderWay_StartsOneRecorder — guards the third bullet above. Passes before and after, by design: it is there to catch the regression this fix could have introduced, not the bug it fixes.
  • 1094 tests green, run three times over. dotnet format --verify-no-changes clean.

🤖 Generated with Claude Code

@revtex
revtex deleted the branch main August 15, 2026 02:52
@revtex revtex closed this Aug 15, 2026
@revtex revtex reopened this Aug 15, 2026
@revtex
revtex changed the base branch from fix/now-playing-vs-report-subject to main August 15, 2026 02:52
Pressing record with Spotify paused and then pressing play recorded nothing.
The level meter moved, the counter ran and the page named the song, but no
file appeared until the user pressed stop and start again.

Being played is half of what makes a track recordable, and the admission check
ran only on a track change. Track equality ignores the play state on purpose,
so that a pause mid-song does not read as a new song — which means a track that
starts playing raises no track change at all. The session had already passed
it over once as not recordable, and went on waiting for something that had
already happened.

The predecessor never met this: it blocked on Spotify producing audio before it
began watching. Offstream starts listening the moment record is pressed, which
is the better behaviour and is worth keeping.

The admission check moves into Consider, called from the track-changed handler
as before and now from the play-state handler too. The resume path is narrower
than the track-changed one, deliberately:

- only when nothing is being recorded, so a pause mid-song leaves the running
  recorder alone rather than starting a second one on top of it;
- not once the recording timer has elapsed, since the session is winding down
  and "recording timer elapsed" would be a lie about a resume;
- only for the track already showing. One poll can see both a new song and a
  change of play state — starting with Spotify already playing is exactly that
  — and the track change is raised straight after, with the stop-the-outgoing-
  recorder handling this path does not have. Admitting from both would start a
  recorder for the other to tear down, and discard the fragment as too short.

The play-state event now carries the track it observed. The poller does not
store the observation until the poll finishes, so a handler reading its current
track gets the previous one, whose play state is the one that just stopped
being true.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@revtex
revtex force-pushed the fix/record-when-playback-starts branch from d07ded0 to cc21036 Compare August 15, 2026 02:53
@revtex
revtex merged commit 63a00d9 into main Aug 15, 2026
6 checks passed
@revtex
revtex deleted the fix/record-when-playback-starts branch August 15, 2026 02:55
Sign up for free to 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