Skip to content

feat: reconnect after sleep and lost connections - #3

Merged
parda21 merged 2 commits into
feat/macos-follow-outputfrom
feat/macos-sleep-wake
Oct 15, 2026
Merged

parda21 merged 2 commits into
feat/macos-follow-outputfrom
feat/macos-sleep-wake

Conversation

@yk-sgr

@yk-sgr yk-sgr commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #2.

Problem

When the connection to Spotify drops, librespot shuts its session down (TODO: Optionally reconnect in session.rs), and the Spirc loop exits. cloofy spawned that task and never looked at it again. So after the Mac slept long enough, or the network was gone for a while, playback stayed unavailable until cloofy was restarted.

What changes

  • Reconnecting (all platforms). playback::spawn is now a small supervisor: it connects again whenever the connection ends without being asked to.
    • It reuses the player and mixer with a new session through player.set_session, as librespot's own binary does.
    • Failed attempts, and connections that drop within 30 s, wait with backoff: 1 s, doubling up to 60 s. Stable connections reconnect right away.
    • Waking up cuts a running wait short.
    • There is deliberately no hard limit. librespot's binary gives up after five reconnects in ten minutes because it can simply exit; in the TUI, giving up left a dead player that still looked connected.
    • The TUI shows "Connection to Spotify lost, reconnecting…". Afterwards, space continues the last track where it stopped, as after a restart.
  • macOS sleep and wake. cloofy-os::power reports both through IOKit's IORegisterForSystemPower, which, unlike NSWorkspace, reaches processes without a Cocoa app.
    • cloofy pauses before the Mac sleeps, as Music and Spotify do. macOS waits a second for that.
    • After more than a minute asleep, it reconnects right away instead of waiting a minute or two for the keep-alive to time out.
  • The saved volume now applies. On main it never did: the app restored it with set_volume, which librespot ignores while the device isn't active (SetVolume(36043) will be ignored while Not Active in the log). cloofy always started at 50% and then saved 50%. The volume is now the device's initial_volume, and reconnecting keeps the current one.

Verified

  • I ran the real TUI with a temporary patch (not committed) that fires a fake wake after 12 s. The log shows connection to Spotify lost, connecting again, followed by a fresh Authenticated as ….
  • In the same run, the player bar showed the saved volume (54%) and librespot no longer ignored any volume command. state.json was unchanged after the run.
  • Quitting still takes 0.1 s.
  • cargo run -p cloofy-os --example sleep_wake registers with IOKit and prints sleep and wake events.

Not included

cloofy connect (headless) still exits when the connection drops, as before.

To test by hand

  • Play, close the lid for 2+ minutes, open it: playback paused before sleep, and within seconds space continues
  • Turn Wi-Fi off for a minute while cloofy runs, then on: it reconnects by itself
  • Change the volume, quit, start again: it starts at that volume

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4f2052d8-9fc9-4087-b1ef-6204dba2e666

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

yk-sgr and others added 2 commits October 15, 2026 16:45
When the connection to Spotify dropped, librespot shut its session down
and the Spotify Connect task ended. cloofy never looked at that task
again, so after the computer slept long enough, or the network was gone
for a while, playback stayed unavailable until a restart.

- The TUI keeps the device connected: a supervisor connects again
  whenever the connection ends without being asked to, with backoff
  while Spotify can't be reached and librespot's limit of five
  reconnects in ten minutes. What played gets ready to continue, as
  after a restart. This works on every OS.
- macOS: cloofy-os reports sleep and wake through IOKit's power
  notifications, which reach non-Cocoa processes too. cloofy pauses
  before the Mac sleeps, which waits a second for it, and reconnects as
  soon as it wakes after more than a minute asleep, instead of waiting
  for the keep-alive to time out.

The saved volume never applied: librespot ignores volume commands until
the device is active, so cloofy always started at 50% and then saved
that. It is now the device's initial volume, and reconnecting keeps the
current one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The supervisor gave up after five reconnects in ten minutes, like
librespot's binary. That left a dead player in the app, which still
looked connected and only answered with channel errors until a restart.
Forced reconnects after sleep counted toward the limit too, and a
connection that dropped right after it started was retried at once.

Now a connection that drops within 30 seconds waits like a failed
attempt, with the backoff doubling up to a minute, so Spotify isn't
hammered. There's no limit and so no dead end. Waking up cuts a running
wait short, for the case where Spotify was out of reach before sleep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yk-sgr
yk-sgr force-pushed the feat/macos-follow-output branch from 629ad77 to 015e57f Compare October 15, 2026 14:47
@yk-sgr
yk-sgr force-pushed the feat/macos-sleep-wake branch from 8498fe1 to 5e9aeac Compare October 15, 2026 14:47
@parda21
parda21 merged commit 5e9aeac into feat/macos-follow-output Oct 15, 2026
3 checks passed
@parda21

parda21 commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Merged through #7, unchanged. It met the audit work's own retry for failed connections; your supervisor now does all the retrying and feeds the loader's session state (see the note in its commit message). Fixed on top, 151f4da:

  • When the connection dropped by itself, the shared player kept playing a downloaded track while the app showed it paused and offered to resume. The player is now stopped before PlayerLost.
  • The wake signal was sent with notify_waiters while the supervisor still sat in task.await, so it got lost, and the forced reconnect then waited out the backoff. It now uses notify_one, and a reconnect cloofy forces goes ahead at once.

🤖 Generated with Claude Code

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.

2 participants