ceol 0.2.4

A polished local-first GTK music player with a compact desktop widget
# Ceol

**Ceol** is a polished, local-first music player for Linux by
**Knott Dynamics** and **Trevor Knott**. It combines a complete GTK desktop
player with a purpose-built compact widget, backed by GStreamer for dependable
local playback.

[![crates.io](https://img.shields.io/crates/v/ceol.svg)](https://crates.io/crates/ceol)
[![docs.rs](https://docs.rs/ceol/badge.svg)](https://docs.rs/ceol)
[![license](https://img.shields.io/crates/l/ceol.svg)](https://github.com/Tknott95/KnottMusic/blob/main/LICENSE)

Ceol has no account, telemetry, advertising, or network service. Your music
paths and playback state stay on your machine.

## Highlights

- Add individual tracks, recursively import one or more folders, or drop either
  directly onto the window
- Open local M3U and M3U8 manifests with ordered relative paths, nested playlist
  support, cycle protection, and safe duplicate removal
- Remember several library folders, switch between them, or combine all online
  sources from one dedicated Library page
- Save the current queue as a named playlist, update it in place, replace the
  queue from it, append it, export it as portable M3U8, or remove it without
  touching audio files
- Launch against a library or selection with `ceol ~/Music album.flac`
- Reorder, remove, and clear a durable local playback queue
- Instantly filter the queue across title, artist, album, format, codec, and
  folder without changing its playback order
- Play, pause, seek, skip, mute, and adjust volume from either layout
- Repeat off/all/one and no-repeat shuffle cycles with real back/forward history
- Embedded cover art plus title, artist, album, codec, and bitrate metadata
- Exact-track and position resume, resilient when earlier files disappear
- Persistent, track-specific saved points with previous/next wraparound
- Audio-reactive 56-band spectrum display and animated signal view
- Four persistent visual moods—Signal, Ember, Ultraviolet, and Daylight—that
  coordinate every surface, control, artwork placeholder, and spectrum color
- A dedicated compact widget that preserves artwork, timeline, playback state,
  eight transport controls, a direct Queue Peek, and one-step expansion
- Keyboard-first operation, native drag-and-drop, and desktop `Open With`
  integration
- MP3, FLAC, Ogg, Opus, WAV, M4A, and AAC through installed GStreamer plugins

## Install from crates.io

Ceol needs GTK 4, GStreamer, and the GStreamer plugins for the formats you use.
On Ubuntu or Debian, install them first:

```sh
sudo apt install libgtk-4-dev libgstreamer1.0-dev \
  gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
  gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly
```

Then install and launch the native player:

```sh
cargo install ceol --locked
ceol
```

Point Ceol at any mix of files and folders:

```sh
ceol ~/Music ~/Downloads/new-album track.flac
```

Folders are scanned recursively in a stable, case-insensitive name order.
Unreadable locations and unsupported files are skipped safely.

Local `.m3u` and `.m3u8` manifests work through the file picker, drag-and-drop,
desktop **Open With**, and command-line paths. Relative entries resolve from the
manifest's folder, local `file://` entries are accepted, and nested manifests
retain their declared order. Ceol ignores remote playlist URLs because playback
is intentionally local-first and network-free.

## Library folders and playlists

Select **Library** or press `Ctrl+L` to open the full Library & Playlists page.
Use **Add Folders** to point Ceol at one or more locations. Ceol remembers those
locations so you can later select a folder and **Load Selected**, or merge every
available source with **Load All**. Offline drives remain visibly marked rather
than being silently forgotten.

The playlist side captures the current queue—including its order—under a name.
Saving an existing name updates it. A playlist can replace the current queue or
append only tracks that are currently available. The export action writes a
portable UTF-8 M3U8 atomically, using relative entries for audio beneath the
chosen destination and encoded local file URIs elsewhere. Offline entries are
preserved so a temporarily disconnected drive does not silently erase part of
the playlist. Forgetting a library folder or removing a playlist never deletes
or modifies an audio file.

## Themes and motion

Open **Library** to choose a complete visual mood from the Appearance strip.
**Signal** is the original electric-cyan console, **Ember** is warm and tactile,
**Ultraviolet** uses midnight ink and violet bloom, and **Daylight** provides a
calm high-contrast light surface. The selection applies to the player, library,
animated spectrum, album placeholder, and compact widget, then persists for the
next launch. The adjacent motion control cycles **Still**, **Calm**, and
**Alive** profiles. Still preserves audio-reactive bars without ambient drift,
Calm softens motion and transitions, and Alive enables the complete animated
presentation. `Ctrl+T` cycles themes and `Ctrl+Shift+T` cycles motion from
anywhere in Ceol.

## Build from source

```sh
git clone https://github.com/Tknott95/KnottMusic.git
cd KnottMusic
cargo run --release -- ~/Music
```

For a user-local release build, app-menu launcher, and scalable icon:

```sh
./scripts/install.sh
```

The binary goes to `$XDG_BIN_HOME`, or `$HOME/.local/bin` by default. Remove
those installed desktop files with `./scripts/uninstall.sh`.

## Compact widget

Compact mode is a real alternate surface, not a squeezed desktop window. It
keeps the active artwork, title and metadata, elapsed and total time, direct
seeking, shuffle, repeat, ±10-second seek, previous/next, play/pause, mute, and
live status. Its bookmark menu can save the current timestamp and flip through
saved points without expanding. Queue Peek shows up to six tracks around the
current position, prioritizes upcoming items, backfills earlier context near the
end, marks shuffle selection honestly, and plays any visible item with one
click. The speaker action still clicks to mute, and now accepts 5% mouse-wheel
volume steps with live icon and percentage-tooltip feedback; scrolling a muted
speaker restores audible playback. Press `Ctrl+M` or select **Widget**; the
**Expand** action always returns to the full queue and visualizer. The current
desktop beauty gate measures this complete surface at a compact `520 × 191`.

## Queue search

Press `Ctrl+F` from any view to return to the full player and focus **Find in
queue**. Search is case-insensitive and supports multiple terms across track
title, artist, album, codec, format, parent folder, and full path. Matching rows
keep their original queue numbers and order. Activating the search plays the
first result; Escape clears the filter. Reorder and remove actions continue to
target the underlying queue item rather than the filtered row position.

The release gate compares the full and compact surfaces alongside established
GNOME adaptive-layout guidance and Apple Music's MiniPlayer pattern in the
[UX beauty gate](https://github.com/Tknott95/KnottMusic/blob/main/docs/UX_BEAUTY_GATE.md).

## Keyboard shortcuts

| Key | Action |
| --- | --- |
| `Space` | Play or pause |
| `Ctrl+O` | Add music files |
| `Ctrl+L` or `Ctrl+Shift+O` | Open Library & Playlists |
| `Ctrl+F` | Find in the playback queue |
| `Ctrl+Right` / `Ctrl+Left` | Next / previous track |
| `Ctrl+M` | Toggle compact widget mode |
| `Ctrl+T` | Cycle the visual theme |
| `Ctrl+Shift+T` | Cycle Still / Calm / Alive motion |
| `Ctrl+S` | Toggle shuffle |
| `Left` / `Right` | Seek backward / forward 10 seconds |
| `Up` / `Down` | Raise / lower volume |
| `M` | Mute or unmute |
| `R` | Cycle repeat off / all / one |
| `B` or `Ctrl+B` | Save or remove a point at the current time |
| `[` / `]` | Jump to the previous / next saved point |
| `Alt+Up` / `Alt+Down` | Reorder the selected track |
| `Delete` | Remove the selected track |
| `Ctrl+Delete` | Clear the queue |

## Local data and package boundary

At runtime, Ceol writes only its resumable playback session—including saved
points, remembered folder paths, playlists, theme choice, and motion profile—beneath
`$XDG_STATE_HOME/ceol/session.json` (normally
`~/.local/state/ceol/session.json`). Delete that file to reset the queue and
playback state.

The crates.io artifact uses an explicit allowlist. It contains the Rust source,
native artwork, desktop integration, installer scripts, documentation, license,
and Cargo manifests only. It excludes runtime sessions, logs, `target/`, web
dependencies, local caches, and generated Studio builds.

## Repository workspace

The repository also contains **KnottMusic Studio**, a browser-based local
composer with a seeded generator, pattern editor, mixer, arrangement controls,
audio-reactive Three.js view, autosave, and WAV/MIDI/project export. The Studio
is developed with Node.js 20.19+ (or 22.12+):

```sh
npm install
npm run dev
```

Run `npm test` for its focused tests and `npm run build` for a production build.
The Studio is intentionally not bundled in the `ceol` Cargo package.

## Development checks

```sh
cargo fmt --check
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo doc --locked --no-deps
cargo package --locked
```

Ceol is released under the
[MIT License](https://github.com/Tknott95/KnottMusic/blob/main/LICENSE).
Product direction and design are by Knott Dynamics; created by Trevor Knott.