Repository navigation
Mac: Spotify pill and a richer Apple Music card - #246
Merged
Merged
Conversation
Spotify (GitHub build): a new integration_spotify pill. Its card shows the album cover, title, artist and album, a progress bar you drag or click to seek, play/pause, previous/next, shuffle, repeat and volume. State comes from Spotify's com.spotify.client.PlaybackStateChanged notification and AppleScript; nothing polls and Spotify is never launched by Coucou. The cover comes from Spotify's `artwork url`, or from its public oEmbed before Automation is allowed. Apple Music: the card gets the same layout, with the cover (from Music, or Apple's public iTunes Search API when the track has none), seek, shuffle, repeat all/one, volume and a favorite heart. The pill ID, the hover pill and the Automation-denied card are unchanged. The cover, bar, volume and buttons live in NowPlayingViews.swift and are shared by both cards; each player keeps its own controller. Mochi dances for either. Privacy page, README, SPEC, INTEGRATIONS and CHANGELOG updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Hey Louis! I've got a few PRs open from my fork and their CI is waiting on you to hit "Approve and run" (GitHub blocks workflows from forks until the repo owner says ok):
All of them build on my side (macOS, Linux and Windows on my fork's CI). Whenever you have a minute, no rush. And if you'd like anything changed, just tell me! Thanks a lot |
…anch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… into the Spotify / Apple Music branch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ternaries and String parameters were shown verbatim, so the help texts, the idle and denied states and the Settings hint now go through String(localized:) or LocalizedStringKey, with their 19 strings in the catalog for the 10 languages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fy / Apple Music branch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Apple Music branch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y / Apple Music branch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Louis-CFM
added a commit
that referenced
this pull request
Oct 8, 2026
Spotify pill (#246), Apple Music card unchanged
JhoanG956
pushed a commit
to JhoanG956/coucou
that referenced
this pull request
Oct 8, 2026
…sign Keeps the Spotify pill, its card, the shared now-playing views it uses, the dance rules and the Spotify docs. Restores MusicController and the Apple Music card exactly as they ship (CLAUDE.md: never restyle a shipped view unless asked), and the Apple Music privacy paragraphs and README line that described the redesign. The project file is left to XcodeGen; the release notes are written at release time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LJm3SRL9k3gBPaVtfPhwcT
Owner
|
Merged in #330 — thank you @JhoanG956! The Spotify pill is great: no polling, never launches Spotify, and Automation is only asked when the pill is turned on. 🙌 One thing I left out on purpose: the Apple Music card redesign. A rule of the project is that shipped views don't change look unless that's the goal of the PR, so Apple Music keeps its current card for now. Generated by Claude Code |
Contributor
Author
|
Sounds good! 😎 |
JhoanG956
pushed a commit
to JhoanG956/coucou
that referenced
this pull request
Oct 8, 2026
The Mac has a Spotify pill (Louis-CFM#246) and Mochi dances while music plays; the Windows and Linux app had neither. Linux has what the Mac gets from Spotify's notification and AppleScript in MPRIS, Spotify's D-Bus interface, so the pill comes to Linux first. Rust (src-tauri/src/spotify.rs, Linux only): - A small MPRIS client on libdbus (`dbus` 0.9.12, already in Cargo.lock through keyring: nothing new is downloaded). While the pill is declared, one thread blocks on the session bus and wakes only for Spotify's PropertiesChanged and Seeked signals and NameOwnerChanged (Spotify starting or quitting): no polling, 0 % CPU when nothing happens. Undeclaring the pill pings that thread off the bus. - Track (id, title, artist, album, length, cover URL), status, position, shuffle, loop status and volume, cleaned like the Mac (shortTitle, shortArtist). Position isn't signalled: it is read when the status or the track changes and when the card shows, and the page runs it on from a timestamp, as SpotifyController.position(at:). - Controls: PlayPause, Next, Previous, SetPosition (Seek on older builds), Shuffle, LoopStatus, Volume. Open raises Spotify, else starts `spotify` from PATH, the Flatpak or the Snap, else opens the download page. - Covers: the CSP keeps remote images out of the page, so Rust fetches them (Spotify's CDN only, or a local track's file), checks the bytes are an image and hands a data URL over; nothing is fetched while paused. Page: - `integration_spotify` in the catalog (Mac values), with a new `linux` support next to `windows`: offered on Linux only, nothing to set up; declared from Settings → Integrations. - SpotifyPill and SpotifyCardView ported: dancing mini Mochi with play/pause and next on hover; cover, title, artist · album, progress with seek, shuffle / previous / play-pause / next / repeat, volume; the idle card says Not playing or Spotify not installed with Open / Get Spotify. Mac strings, in every language already. - The Mac's BotEngine dance (setDancing, applyDance, happy eyes) in mochi/engine.ts, with the Mac's rules: the compact island whenever music plays, expanded on the Spotify card, the pill's mini Mochi, and Mochi on the desktop (the island sends him `dancing`). Music starting shows the hidden island without the peek sound. On Windows nothing reports music, so nothing changes there. Tests: MPRIS parsing from dbus variants and plain values, position extrapolation, track ids, covers' sources and types (Rust, plus an end-to-end test against a fake Spotify on a private bus, run with `dbus-run-session -- cargo test -p coucou --lib spotify -- --ignored`); the dance math, the dance rules, the catalog's Linux-only filtering, report handling and the views (Node). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LJm3SRL9k3gBPaVtfPhwcT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spotify: a new pill
integration_spotify, GitHub build only like Apple Music (the App Store sandbox would need an Apple Events exception for Spotify).com.spotify.client.PlaybackStateChangeddistributed notification, then one AppleScript read for what the notification lacks (position, shuffle, repeat, volume, artwork URL). The position is extrapolated in the card, with aTimelineViewpaused unless the card is on screen and playing. The card re-reads the position when it appears, since seeks made in Spotify's own window post no notification.artwork url(i.scdn.co). Before Automation is allowed, Spotify's public oEmbed (open.spotify.com/oembed) gives it from the track link. Only*.scdn.co/*.spotifycdn.comimages are fetched; the last 12 covers are cached in memory.Apple Music: the same card
The Apple Music card gets the Spotify layout. Its pill ID, its hover pill and its Automation-denied card are unchanged.
raw data of artwork 1). When the track has none (some streams), it's looked up in Apple's public iTunes Search API with the artist and album names; only*.mzstatic.comimages are fetched.repeat.1icon), volume, and a favorite heart next to the title (favorited, shown only when Music can favorite the track; it reverts if Music refuses).MusicControllerreads typed AppleScript results now (numbers, booleans, data) instead of strings only, and follows the same anchor/extrapolation model as Spotify.Shared pieces
The cover, progress bar, volume slider and buttons live in
NowPlayingViews.swiftand are used by both cards. Each player keeps its own controller and pill.Also
NSAppleEventsUsageDescriptionmentions Spotify (project.ymland the regeneratedInfo.plist).project.pbxprojis left toxcodegen, as onmain.Testing
NotchBuddy) and App Store (CoucouAppStore) schemes.🤖 Generated with Claude Code