Fixed readme
Build and Release / Build furumi-linux-x86_64 (push) Failing after 14s
Build and Release / Build furumi-macos-x86_64 (push) Has been cancelled
Build and Release / Build furumi-windows-x86_64 (push) Has been cancelled
Build and Release / Publish release assets (push) Has been cancelled
Build and Release / Build furumi-linux-x86_64 (push) Failing after 14s
Build and Release / Build furumi-macos-x86_64 (push) Has been cancelled
Build and Release / Build furumi-windows-x86_64 (push) Has been cancelled
Build and Release / Publish release assets (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
name: Build and Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
pull_request:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build ${{ matrix.asset_name }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
asset_name: furumi-linux-x86_64
|
||||||
|
archive_name: furumi-linux-x86_64.tar.gz
|
||||||
|
binary_name: furumi
|
||||||
|
- os: macos-13
|
||||||
|
asset_name: furumi-macos-x86_64
|
||||||
|
archive_name: furumi-macos-x86_64.tar.gz
|
||||||
|
binary_name: furumi
|
||||||
|
- os: windows-latest
|
||||||
|
asset_name: furumi-windows-x86_64
|
||||||
|
archive_name: furumi-windows-x86_64.zip
|
||||||
|
binary_name: furumi.exe
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Linux build dependencies
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev pkg-config
|
||||||
|
|
||||||
|
- name: Show Rust version
|
||||||
|
run: rustc --version && cargo --version
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --release --locked
|
||||||
|
|
||||||
|
- name: Package
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
package_dir="dist/${{ matrix.asset_name }}"
|
||||||
|
mkdir -p "$package_dir"
|
||||||
|
cp "target/release/${{ matrix.binary_name }}" "$package_dir/"
|
||||||
|
cp README.md "$package_dir/"
|
||||||
|
|
||||||
|
if [[ "${{ runner.os }}" == "Windows" ]]; then
|
||||||
|
(cd dist && 7z a "../${{ matrix.archive_name }}" "${{ matrix.asset_name }}")
|
||||||
|
else
|
||||||
|
tar -C dist -czf "${{ matrix.archive_name }}" "${{ matrix.asset_name }}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.asset_name }}
|
||||||
|
path: ${{ matrix.archive_name }}
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
publish:
|
||||||
|
name: Publish release assets
|
||||||
|
needs: build
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
|
||||||
|
- name: Upload assets to release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||||
|
run: gh release upload "$RELEASE_TAG" artifacts/*/* --clobber
|
||||||
@@ -1,44 +1,186 @@
|
|||||||
# furumi
|
# furumi
|
||||||
|
|
||||||
Terminal client (TUI) for the furumusic server. Cross-platform: Linux,
|

|
||||||
macOS, Windows.
|
|
||||||
|
|
||||||
## Building
|
`furumi` is a cross-platform terminal client for a furumusic server. It
|
||||||
|
provides a fast TUI for browsing the library, playing music, managing the
|
||||||
|
queue and playlists, controlling devices, and inspecting logs without leaving
|
||||||
|
the terminal.
|
||||||
|
|
||||||
Rust 1.88+ (edition 2024).
|
## Features
|
||||||
|
|
||||||
|
- Browse the full artist library in tile or table view.
|
||||||
|
- Open artist pages, releases, and track lists from inside the TUI.
|
||||||
|
- Search artists, releases, and tracks with `/`.
|
||||||
|
- Play local audio with seek, volume, shuffle, repeat, and like controls.
|
||||||
|
- Add tracks next in queue, append them to the queue, or clear the queue.
|
||||||
|
- Browse playlists, liked tracks, and add tracks to playlists.
|
||||||
|
- Pick the active playback device and control remote devices.
|
||||||
|
- Use OS media keys through MPRIS/system media controls.
|
||||||
|
- Inspect live in-app logs and a persistent log file.
|
||||||
|
- Customize key bindings with a TOML keymap.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Requires Rust 1.88+.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo build --release # binary: target/release/furumi
|
cargo build --release
|
||||||
|
./target/release/furumi
|
||||||
|
```
|
||||||
|
|
||||||
|
The release binary is named `furumi`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run --release --bin furumi
|
||||||
```
|
```
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
Sound output needs the system ALSA library — the one and only system
|
Audio output needs the system ALSA library. PipeWire and PulseAudio are used
|
||||||
build dependency (PipeWire/PulseAudio are reached through the ALSA
|
through the ALSA compatibility layer at runtime.
|
||||||
compatibility layer at runtime):
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Debian / Ubuntu
|
# Debian / Ubuntu
|
||||||
sudo apt install libasound2-dev pkg-config
|
sudo apt install libasound2-dev pkg-config
|
||||||
|
|
||||||
# Fedora
|
# Fedora
|
||||||
sudo dnf install alsa-lib-devel pkgconf-pkg-config
|
sudo dnf install alsa-lib-devel pkgconf-pkg-config
|
||||||
|
|
||||||
# Arch
|
# Arch
|
||||||
sudo pacman -S alsa-lib pkgconf
|
sudo pacman -S alsa-lib pkgconf
|
||||||
```
|
```
|
||||||
|
|
||||||
Everything else is pure Rust: TLS is rustls, MPRIS media keys go through
|
Everything else is handled by Rust dependencies: TLS uses `rustls`, MPRIS uses
|
||||||
zbus (no libdbus), images and audio decoding are Rust crates.
|
`zbus`, and image/audio decoding is provided by Rust crates.
|
||||||
|
|
||||||
### macOS / Windows
|
### macOS and Windows
|
||||||
|
|
||||||
No system packages required.
|
No extra system packages are required.
|
||||||
|
|
||||||
|
## First Run
|
||||||
|
|
||||||
|
On startup, `furumi` opens the login screen:
|
||||||
|
|
||||||
|
1. Enter your furumusic server URL.
|
||||||
|
2. Sign in with username/password or SSO.
|
||||||
|
3. After a successful login, the session is saved locally.
|
||||||
|
|
||||||
|
The SSO flow opens your browser automatically. If the loopback callback is not
|
||||||
|
available, `furumi` shows the URL and accepts either a pasted `furumi://...`
|
||||||
|
callback link or the short `furu_mx_...` code.
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
Common key bindings:
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
| --- | --- |
|
||||||
|
| `?` | Show key binding help |
|
||||||
|
| `q`, `Ctrl-C` | Quit |
|
||||||
|
| `Tab`, `Shift-Tab` | Next / previous tab |
|
||||||
|
| `1`...`4` | Jump to a tab |
|
||||||
|
| `j` / `k`, arrows | Move down / up |
|
||||||
|
| `h` / `l`, arrows | Move left / right |
|
||||||
|
| `Enter` | Open or select item |
|
||||||
|
| `Esc`, `Backspace` | Go back |
|
||||||
|
| `Space` | Play / pause |
|
||||||
|
| `n`, `p` | Next / previous track |
|
||||||
|
| `.`, `,` | Seek 10 seconds forward / backward |
|
||||||
|
| `+`, `-` | Volume up / down |
|
||||||
|
| `s` | Toggle shuffle |
|
||||||
|
| `r` | Cycle repeat mode |
|
||||||
|
| `x` | Like / unlike |
|
||||||
|
| `a` | Add track next |
|
||||||
|
| `Shift-A` | Add track to the end of the queue |
|
||||||
|
| `Shift-P` | Add track to a playlist |
|
||||||
|
| `Shift-D` | Open device picker |
|
||||||
|
| `v` | Toggle tile/table view |
|
||||||
|
| `/` | Search |
|
||||||
|
| `:` | Open command line |
|
||||||
|
|
||||||
|
Command line examples:
|
||||||
|
|
||||||
|
```text
|
||||||
|
:q
|
||||||
|
:logout
|
||||||
|
:volume 40
|
||||||
|
:seek +30
|
||||||
|
:seek -10
|
||||||
|
:seek 1:30
|
||||||
|
:shuffle
|
||||||
|
:repeat off
|
||||||
|
:repeat one
|
||||||
|
:repeat all
|
||||||
|
:clear
|
||||||
|
:next
|
||||||
|
:prev
|
||||||
|
:play
|
||||||
|
:pause
|
||||||
|
:devices
|
||||||
|
:logs debug
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
- `keymap.toml` in the config dir — keybinding overrides, see
|
`furumi` stores configuration in the platform app config directory:
|
||||||
`src/config/default_keymap.toml` for the format and defaults.
|
|
||||||
Config dir: `~/.config/furumi` on Linux,
|
- Linux: `~/.config/furumi`
|
||||||
`~/Library/Application Support/furumi` on macOS.
|
- macOS: `~/Library/Application Support/furumi`
|
||||||
- `credentials.json` in the same dir — created on login (0600).
|
- Windows: `%APPDATA%\furumi`
|
||||||
- Logs: in-app on the Logs tab (`5`), and in the cache dir
|
|
||||||
(`furumi-cli.log`), filtered by `RUST_LOG`.
|
Important files:
|
||||||
|
|
||||||
|
- `credentials.json` - saved login session. On Unix it is written with `0600`
|
||||||
|
permissions.
|
||||||
|
- `device_id` - stable identifier for this TUI client during device sync.
|
||||||
|
- `keymap.toml` - user key binding overrides.
|
||||||
|
|
||||||
|
See [`src/config/default_keymap.toml`](src/config/default_keymap.toml) for the
|
||||||
|
default format. Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[keymaps]]
|
||||||
|
key_sequence = "ctrl-n"
|
||||||
|
command = "NextTrack"
|
||||||
|
|
||||||
|
[[keymaps]]
|
||||||
|
key_sequence = "ctrl-f"
|
||||||
|
command = { SeekForward = { seconds = 30 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
A user binding replaces the default binding with the same key sequence and
|
||||||
|
context.
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
|
||||||
|
The Logs tab shows a live in-memory ring buffer inside the TUI. You can jump
|
||||||
|
to it and set the level filter with:
|
||||||
|
|
||||||
|
```text
|
||||||
|
:logs error
|
||||||
|
:logs warn
|
||||||
|
:logs info
|
||||||
|
:logs debug
|
||||||
|
:logs trace
|
||||||
|
```
|
||||||
|
|
||||||
|
The persistent log file is written to the platform cache directory as
|
||||||
|
`furumi-cli.log`. File logging is filtered by `RUST_LOG`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RUST_LOG=furumi_tui=debug cargo run --release --bin furumi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
At a glance:
|
||||||
|
|
||||||
|
- UI: `ratatui` + `crossterm`.
|
||||||
|
- Runtime: `tokio`.
|
||||||
|
- HTTP: `reqwest` + `rustls`.
|
||||||
|
- Audio: `rodio` + `stream-download`.
|
||||||
|
- Keymap config: `crokey` + TOML.
|
||||||
|
- State model: one `AppState`, events, and an update loop.
|
||||||
|
|
||||||
|
See [`ARCHITECTURE.md`](ARCHITECTURE.md) for more detail.
|
||||||
|
|||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
Reference in New Issue
Block a user