Skip to content

bocan/bocan-music

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

926 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Bòcan Music

CI CodeQL GitHub release License: MIT

macOS 15+ Xcode 26 Swift 6

The music player macOS deserves. No Electron. No Catalyst. No subscription. No cloud. Just your music, played beautifully.

Bòcan Songs view


Why Bòcan?

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.

🔊 It sounds better

  • True gapless playback with nanosecond AVAudioTime anchoring. 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.

📻 It plays everything

  • 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.

📚 It respects your library

  • 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.

🎨 It's a pleasure to use

  • 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⌘⇧9 to 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 .log file. Diagnose a problem without ever leaving the app.

♿ It's accessible

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 .combine so 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.

🏗️ It's engineered properly

  • Swift 6 strict concurrency : @MainActor isolation, Sendable everywhere 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 .pbxproj files in the repo.
  • CodeQL, SwiftLint, SwiftFormat, and Dependabot on every pull request.

On the name

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)

What's next

  • 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.


Install

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 bocan

Sparkle keeps the app current automatically. brew upgrade --greedy bocan does the same from the terminal if you prefer.


Building from source

See DEVELOPMENT.md for prerequisites, environment setup, the build system, common make targets, FFmpeg and fpcalc notes, and contribution guidelines.

Modules

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

Licence

See LICENSE.

And Last but Not Least

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 .pbxproj and 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.yml on 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.

About

A native macOS music player and library built with Swift 6 and SwiftUI. Features gapless playback, AcoustID fingerprinting, smart playlists, lyrics, visualizers, scrobbling, and a DSP/EQ engine powered by FFmpeg

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors