Skip to content

Sync songs to the phone while connected to Clementine - #62

Open
hatstand wants to merge 3 commits into
mainfrom
claude/project-thread-wugi27-sync-connection
Open

hatstand wants to merge 3 commits into
mainfrom
claude/project-thread-wugi27-sync-connection

Conversation

@hatstand

@hatstand hatstand commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Builds on #61 (the sync engine), and through it #57 (the store). Until they merge, review only the commit "Sync songs to the phone while connected to Clementine" (089994f). #58 has merged.

It's part of media sync, which keeps music from Clementine on the phone to play offline. The design doc describes the whole of it.

This connects the sync engine to the Clementine the app is connected to, as Android-Remote#362 does on Android:

  • RemoteSession.syncing says whether this Clementine can sync: it advertises SERVER_FEATURE_SYNC and sends a server_id, and the build has TestingFeatures.enabled. downloadsAllowed follows Clementine's allow downloads setting. Without all of them, nothing about sync shows.
  • ClementineSyncConnection asks for a manifest over the session's connection and waits for the answer for the same source (a minute at most), through SyncManifests. It fetches songs from Clementine's HTTP server on the address and port the phone connected to, resolving paths as the renderer does.
  • Syncer runs the engine each time a Clementine that can sync connects, and when asked (syncNow), once more if asked while running. Its status says whether it's running and each rule's outcome, for the Sync screen.
  • Synced songs go to Documents/Clementine/Synced, beside downloaded songs, so the Files app shows them. The Downloads tab leaves that folder out of the songs on the phone. The store is opened in Application Support, and only in builds with the testing features.

There's nothing to sync yet: making rules comes with the next pull request. Tests cover the sync state from Clementine's info, waiting for the right manifest, giving up when Clementine doesn't answer, fetching over HTTP from a local server, and a whole sync when Clementine connects.

Songs are fetched over plain HTTP, which App Transport Security allows on the local network (NSAllowsLocalNetworking). Syncing with a Clementine reached over the internet would need an exception as well, which can come later.


Generated by Claude Code

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Screenshots

From run 40992277753, against a real Clementine. Left: main. Right: this pull request, light and dark.

Screen main This PR This PR, dark
01_connect
02_queue
03_player
04_connection
05_settings
06_library
07_library_album
08_search
09_outputs
10_internet
11_internet_radio
fold_outer_player –

Screens at a failure

dark_failure

failure

Copy link
Copy Markdown
Contributor Author

package failed on f604129 in ConnectionTests.nobodyThere(), which timed out after 5 s waiting for a connection to a closed port to fail. This PR doesn't touch the connection code: the push only changes SyncRule.kind to the protocol's enum in the syncer's tests. Every other test in the run passed, including all the sync ones. I'll re-run the failed job once when the rest of the workflow has finished. If it fails again, I'll treat it as real.


Generated by Claude Code

The phone's record of what it keeps for offline listening: the sync
rules, the songs and covers it has downloaded, which rules want which
songs, and plays made on the phone, all kept per Clementine by its
server id. A song is stored once however many rules want it, and goes
once no rule wants it and it isn't pinned. It has the same tables as
the Android client's, and nothing uses it yet.

The database wrapper learns NULLs, blobs and typed rows for it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R2bAq6kZW6eyymkA3zsd4p
SyncEngine brings the phone's songs in line with the rules for one
Clementine: it asks for each rule's manifest, downloads the songs that are
new or changed into the synced songs' folder as Artist/Album/NN Title, and
deletes the songs no rule or pin wants any more. A song in several rules is
downloaded once, a rule that fails keeps its songs and lets the others carry
on, and a sync cut short keeps what it downloaded. It talks to Clementine
through SyncConnection, so the tests run it against a fake one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R2bAq6kZW6eyymkA3zsd4p
RemoteSession.syncing says whether this Clementine can sync: it has
SERVER_FEATURE_SYNC and a server id, the build has the testing features,
and Clementine lets the phone download songs. When one connects, the
Syncer runs the sync engine against it: ClementineSyncConnection asks for
manifests over the session's connection, waiting at most a minute for each
source's answer, and fetches songs from Clementine's HTTP server, as the
renderer does. Songs go to Documents/Clementine/Synced, which the Downloads
tab leaves out of the songs on the phone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R2bAq6kZW6eyymkA3zsd4p
@hatstand
hatstand force-pushed the claude/project-thread-wugi27-sync-connection branch from f604129 to e03e403 Compare October 30, 2026 02:32
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