Files
furumi_tui/ARCHITECTURE.md
T

149 lines
5.8 KiB
Markdown
Raw Normal View History

2026-07-26 02:07:07 +03:00
# furumi architecture
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
`furumi` is a single Rust binary organized around an Elm-style state/update
loop. The UI state remains synchronous and deterministic; filesystem, SQLite,
audio, networking, artwork, and media-control work is performed by runtime
services and reported back as application events.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Runtime flow
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
```text
terminal/media/player/network events
|
v
app::event::AppEvent
|
v
input/keymap -> Action
|
v
app::update()
mutates AppState and
requests an Effect
|
v
app runtime performs I/O
|
+----> new AppEvent
2026-06-10 16:11:09 +01:00
```
2026-07-26 02:07:07 +03:00
`AppState` is the single UI source of truth. Rendering modules receive shared
state and do not own background tasks. Blocking database and file operations
run outside the terminal event loop.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Module layout
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
```text
2026-06-10 16:11:09 +01:00
src/
2026-07-26 02:07:07 +03:00
main.rs process, terminal, Tokio, and OS-media setup
app/
state.rs UI and navigation state
action.rs semantic user actions
event.rs runtime-to-UI events
update.rs pure state transitions and requested effects
update_tests.rs update/selection/queue behavior tests
mod.rs runtime orchestration and effect execution
popup.rs popup submission behavior
input.rs editable text input
command.rs command model
cmdline.rs command-line execution
library/
mod.rs SQLite-backed library operations
import.rs tags, audio metadata, and directory import
models.rs library-facing data types
tests.rs library integration tests
player/
mod.rs rodio playback controller
analyzer.rs visualization audio analysis
federation/
mod.rs DHT manager, search, downloads, and caching
catalog.rs peer catalog protocol and merge logic
audio.rs peer audio transport
tests.rs federation ranking/appearance tests
devices/
tests.rs trusted-device sync tests
devices.rs trusted-device operation log and wire protocol
ui/ ratatui rendering by screen
config/ settings, logging, and keymaps
media.rs platform media-key/now-playing integration
visualizer.rs Rhai visualization host
visualizations/ bundled Rhai scripts
art.rs image decode and terminal-cell preparation
share.rs share-link parsing and generation
streaming.rs growing-file reader used during downloads
2026-06-10 16:11:09 +01:00
```
2026-07-26 02:07:07 +03:00
Large orchestration modules are intentionally separated from their tests.
When they are split further, boundaries should follow services rather than
line count: playback coordination, network-library maintenance, device
storage, and device transport are the natural seams.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Local library
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
`library::Library` owns a mutex-protected SQLite connection. It is the only
layer that issues library SQL and returns typed models to the rest of the
application. The schema covers artists, releases, tracks, artist relations,
playlists, likes, playback history, federated pending tracks, and cached
network artists.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
Imports read tags with `lofty`, inspect audio properties, calculate content
identifiers, and upsert normalized library records. File paths remain
device-local.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Playback
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
`player::Controller` owns the rodio audio thread. The application maintains
the logical queue and playback state, while the controller receives play,
pause, seek, volume, and prefetch commands. The next source is opened early
for gapless transitions. The analyzer publishes levels and scope samples for
Rhai visualization scripts.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
OS media commands enter through `media.rs`; current metadata and position are
published back to the platform now-playing surface.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Federation
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
Federation uses `music-dht` for discovery and byte streams:
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
- the local library publishes metadata-only item specifications;
- search merges DHT records, peer catalogs, and cached metadata;
- catalog requests provide richer artist/release views;
- audio requests stream content from peers;
- downloads may remain cached or be imported into the local library.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
Federation is disabled until configured by the user. Paths are never
published as portable identifiers; content hashes and peer item IDs are used
instead.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Trusted-device sync
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
`devices.rs` implements a separate trusted-device protocol over a dedicated
ALPN. Likes, playlists, membership changes, and playback control are
represented as an append-only operation log with materialized SQLite tables.
Hybrid logical timestamps and acknowledgements make offline merging and
tombstone compaction deterministic.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
Pairing uses short-lived invites. Device-local file paths are deliberately
excluded from synchronized playback tracks; receiving devices resolve them
through content IDs, their own library, or federation metadata.
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
## Configuration and persistence
2026-06-10 16:11:09 +01:00
2026-07-26 02:07:07 +03:00
The `directories` crate selects platform-standard config, data, and cache
locations. Settings, keymaps, device identity, and federation configuration
are separate files. SQLite databases and downloaded covers/audio are stored
under application data/cache directories rather than the repository.
## Reliability rules
- Terminal raw mode, bracketed paste, and keyboard enhancements are restored
on normal exit and panic.
- stderr from native audio libraries is captured into tracing so it cannot
corrupt the alternate screen.
- Blocking work is kept out of the UI loop.
- Runtime failures are converted to visible status/events where recovery is
possible.
- Device paths are not treated as portable network identities.
- Formatting, all-target compilation, Clippy, and unit tests should pass
before a release tag is pushed.