The music player macOS deserves. No Electron. No Catalyst. No subscription. No cloud. Just your music, played beautifully.
Most Mac music players are either abandoned, Electron-wrapped, or stripped-down streaming clients that barely tolerate local files. Bòcan is the answer to all three: a native Swift 6 app built entirely around owning and enjoying your own library, the way iTunes used to before it became a content storefront.
- True gapless playback with nanosecond
AVAudioTimeanchoring. Classical transitions, live albums, and DJ mixes play as the artist intended, with zero silence and zero clicks. - 10-band graphic EQ, bass boost, stereo expander, binaural crossfeed, and a peak limiter, a full DSP chain between your files and your ears.
- ReplayGain applied at playback time; analyses missing tags in the background using EBU R128 loudness.
- Configurable crossfade (0–12 s), playback speed (0.5×–2.0×) with pitch correction, and a sleep timer that fades gracefully rather than cutting mid-note.
- Everything AVFoundation handles natively: FLAC, ALAC, AAC, MP3, WAV, AIFF, CAF, M4A.
- The awkward ones too, via an integrated FFmpeg bridge: Ogg Vorbis, Opus, APE (Monkey's Audio), WavPack, DSD. No plug-ins, no extra installs.
- Folder-based, non-destructive. Point it at your music directory and it indexes without touching a single file.
- Live FSEvents watcher picks up new or changed files automatically; mtime + fingerprint deduplication keeps your library clean.
- AcoustID fingerprinting against MusicBrainz. Identify any track, preview every proposed tag change side-by-side with what you have now, tick the fields you want to update, and apply.
- In-app tag editor with multi-track batch editing, embedded cover-art drag-and-drop, and undo.
- Three-pane browser: Albums grid, Tracks list, Artists view, and Recently Added.
- Smart Playlists built from a rule editor, compiled to live SQL and updated automatically as your library changes.
- Import / export M3U, PLS, and XSPF playlists, with fuzzy track matching on import.
- Real-time visualisers: spectrum bars, oscilloscope, and a Metal GPU fluid shader, dockable or full-screen with
⌘⇧F. - Mini Player in four layouts (Strip, Compact, Square, Visualizer) with always-on-top mode.
- Last.fm, ListenBrainz, and Rocksky scrobbling, offline-resilient with Keychain auth and a dead-letter queue.
- Subsonic / Navidrome / Airsonic servers as first-class sources alongside your local library. Federated search across every server, per-server status dots, offline banners with one-tap retry,
⌘⇧1–⌘⇧9to jump straight to a server, and drag a streamed song straight into Up Next. - In-app Log Console : open Help -> Log Console (
⌘⇧L) to tail every log line since launch, filtered by level or category, with free-text search, live tailing, pause and resume, copy to clipboard, and export to a.logfile. Diagnose a problem without ever leaving the app.
I've tried hard to ensure Bòcan is fully navigable without a mouse or a screen:
- VoiceOver-first track list : each row announces "Title, Artist, Album, Duration" as a single spoken sentence rather than reading every column individually.
- Live now-playing announcements : when the track changes, VoiceOver speaks the new track name automatically, without you having to navigate to the transport bar.
- Full keyboard navigation with logical focus sections and no focus traps.
- Dynamic Type throughout : every label, badge, and table cell scales with your macOS text size setting.
- Album cells, artist rows, and genre chips are grouped with
.combineso VoiceOver reads them as single logical elements. - Transport controls carry state via
accessibilityValue(e.g. "Shuffle, on, button") so you always know what you're toggling. - EQ band sliders report their gain in the format "80 Hz, +3.0 dB" rather than a raw number.
- Swift 6 strict concurrency :
@MainActorisolation,Sendableeverywhere it matters, zero data races by design. - Ten clean SPM modules with no upward imports and their own test suites.
- 80% line-coverage gate in CI; the build fails if coverage drops.
- GRDB 7 with typed repositories, FTS5 full-text search, and
ValueObservation-based reactive streams. - XcodeGen project generation : no hand-edited
.pbxprojfiles in the repo. - CodeQL, SwiftLint, SwiftFormat, and Dependabot on every pull request.
Naming things is hard. I was up from midnight to almost 3 am trying to figure out a name that wasn’t already taken for another app. In the end, I couldn’t find one that was free, so I went with the name I’ve used on the internet since the internet existed.
Bocán (Old Irish) means a young male deer, the root of which is cognate with the Welsh "boc" and the Breton "bok", both meaning "buck".
Bòcan (Scottish Gaelic, roughly BAW-khan) is a hobgoblin or a household spirit.
Bòcan curates your music library while you sleep. The short version is that computers don't like ò, so the binary, bundle, and repository all use bocan:
| Property | Value |
|---|---|
| Display name | Bòcan |
| Binary / package name | bocan |
| Bundle ID | io.cloudcauldron.bocan |
| Log subsystem | io.cloudcauldron.bocan |
| Minimum macOS | 15.0 (Sequoia) |
- File management tools: move, rename, and organise files directly from the library.
- More visualisers: new render modes beyond spectrum bars, oscilloscope, and the fluid shader.
- Remote control: iPhone and Android apps to control playback on the Mac; the Mac stays the source.
- Accessibility: ongoing work; VoiceOver coverage is good but there's more to do.
Contributions and ideas welcome. Open an issue or a pull request.
Download the DMG from bocan.app/download or the GitHub Releases page. Open it, drag Bòcan to Applications, done.
Homebrew: add the tap once, then install:
brew tap bocan/bocan
brew install bocanSparkle keeps the app current automatically. brew upgrade --greedy bocan does the same from the terminal if you prefer.
See DEVELOPMENT.md for prerequisites, environment setup, the build system, common make targets, FFmpeg and fpcalc notes, and contribution guidelines.
| Module | Description |
|---|---|
Observability |
Structured logging (AppLogger), in-process ring buffer (LogStore), log console support, telemetry, MetricKit |
Persistence |
GRDB schema + migrations, repositories, reactive ValueObservation |
AudioEngine |
AVFoundation + FFmpeg decoder graph, ring buffer, DSP chain, playback actor |
Metadata |
TagLib read/write, cover-art extraction, LRC lyric parser |
Acoustics |
Chromaprint fingerprinting, AcoustID + MusicBrainz lookup |
Subsonic |
Subsonic / Navidrome / Airsonic client, capability detection, Keychain credentials |
Library |
Folder scanner, FSEvents watcher, conflict resolver, cover-art cache |
Playback |
Queue, history, shuffle strategies, gapless + crossfade scheduler, MPNowPlaying, sleep timer |
Scrobble |
Last.fm / ListenBrainz / Rocksky providers, offline-resilient scrobble queue |
UI |
SwiftUI views, view models, mini player, settings, theming, snapshot tests |
See LICENSE.
Much love to the giants whose shoulders I stand on:
- Christopher Snowhill, maintainer of of the excellent Cog. The patron saint of native macOS music players and Cog is the direct spiritual ancestor of what I've built here.
- Fabrice Bellard, creator of FFmpeg, and QEMU, and TinyCC, and a dozen other earth-shaking projects. The reason Bòcan can play Ogg, Opus, APE, WavPack, and DSD without making users install plugins.
- Christopher "Monty" Montgomery and the Xiph.Org Foundation: Vorbis, FLAC, Opus, Speex. The entire free codec stack on which lossless audio on the open web is built.
- Peter Pawlowski, maintainer of foobar2000, solo since 2002. Even though no foobar code touches Bòcan, foobar's design DNA (modular DSP, smart playlists, gapless, format breadth) is the spiritual blueprint of every audiophile-flavour music player that has followed.
- Lukáš Lalinský, creator of Chromaprint and AcoustID. The entire fingerprinting and auto-tagging pipeline in Bòcan exists because of his work. Also a long-time TagLib contributor. A one-person open-source music-metadata hero.
- Scott Wheeler and the TagLib contributors: without TagLib, I'd be reimplementing ID3v2.4 + Vorbis comments + APE tags + MP4 atoms by hand.
- Robert Kaye and the MetaBrainz Foundation: MusicBrainz, ListenBrainz, Cover Art Archive. Bòcan's auto-tagging, lookup, and open scrobbling all sit on this stack.
- Gwendal Roué, maintainer of GRDB.swift. Quietly one of the best-maintained Swift libraries in existence, solo for over a decade. My entire persistence layer is built on it.
- Justin Frankel, co-creator of Winamp (back in his Nullsoft days), later REAPER, NSIS, gnutella, and most of Cockos. Winamp basically invented the modern desktop music player. Anyone building one stands on this work whether they realise it or not.
- Jean-Marc Valin, primary author of Opus (and Speex before that), one of the great open codec achievements of the last twenty years.
- Yonas Kolb, creator of XcodeGen. Saved me (and everyone else) from hand-editing
.pbxprojand weeping in merge conflicts. - Nick Lockwood, author of SwiftFormat. Keeps my codebase from looking like it was written by seven different people on seven different keyboards.
- JP Simard, creator of SwiftLint, the linter that enforces my
.swiftlint.ymlon every commit. - Mathieu Dubart, builder of SwiftSonic and Cassette. Bòcan's entire Subsonic / Navidrome / Airsonic stack rides on SwiftSonic; without it, talking to OpenSubsonic servers would be a hand-rolled mess.
- Tsiry Sandratraina, builder of Rocksky. The third leg of Bòcan's scrobbling stool, alongside Last.fm and ListenBrainz.
