Commit Graph

11 Commits

Author SHA1 Message Date
Test User a03e3de84e build: put every provider, opus, and the spectrum behind cargo features
All on by default, so a plain build is unchanged (verified: the default
dependency set for crabidy-server is byte-identical to before). Tailor a
smaller binary with --no-default-features --features …
(architecture/build-features.md).

Compile-time features draw dependency boundaries; the existing
crabidy-server.toml providers list keeps doing per-mount runtime
toggling. The compile-time set bounds the runtime one: a provider built
out cannot be enabled from the config, and naming it earns one startup
warning rather than silence.

- crabidy-server: tidal · youtube · fyyd · abs · soundcloud · jamendo ·
  fs · opus · spectrum · web-ui, plus the all-providers group.
- fs is local files *and* persistent state (D5): the /fs mount, the
  content store behind /crabidy and /orphans, bookmarks/captures, queue
  persistence, and scan. Without it Capture/SaveQueue answer
  Unimplemented and scan says which feature is missing — never a panic.
- opus drops symphonia + symphonia-adapter-libopus, and with them the
  bundled libopus C build (no more cmake requirement). It also decides
  whether scan indexes .opus at all, so scan never indexes what this
  build cannot play. An Ogg-Opus file in an opus-less build reports the
  missing feature and is skipped like any undecodable file.
- spectrum drops realfft and the FFT task; clients just never receive a
  frame. cbd-tui gains notifications (notify-rust, a D-Bus stack).
- crabidy-server/cbd features print the compiled set, and startup logs
  it, so a tailored binary is self-describing.

Not gated, deliberately: [auth]/argon2 (a build ignoring configured
hashes would run open — fail-open security hole), and hls.rs /
spectrum_tap.rs / windowed_http.rs (no dependency of their own, so
gating them buys cfg noise and nothing else).

devenv gains check-features: the curated matrix (defaults, nothing, each
provider alone, each axis dropped, both worked examples, the client
crates) all clippy-clean under -D warnings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 03:15:32 +02:00
Test User 6abda3aa58 devenv: drop ninja so cmake's opusic-sys generator is deterministic
Adding ninja alongside cmake let the cmake crate auto-select the Ninja
generator whenever ninja happened to be on PATH. A build dir first cached under
Make (ninja absent) then rebuilt with ninja present fails with "Does not match
the generator used previously: Unix Makefiles". gnumake is already provided by
stdenv, so keeping only cmake pins the generator to Make everywhere.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 02:33:15 +02:00
Test User 9fba9708bf Audio: decode Ogg-Opus via libopus so opus streams play
rodio decodes through symphonia 0.5, which ships no Opus decoder, so raw
.opus sources (audiobookshelf files, and opus from any provider) failed
Decoder::build(). Add OpusSource, a rodio Source that demuxes Ogg with
symphonia own Ogg reader and decodes with libopus (via
symphonia-adapter-libopus, registered into an explicit codec registry), and
route to it by content-sniffing OggS+OpusHead in the player -- the abs stream
URL has no file extension, so the extension hint is not enough. The bundled
libopus builds with cmake/ninja (added to devenv).

Verified end-to-end with ffmpeg mono/stereo opus fixtures including seeking;
11 audio-player tests pass, clippy/fmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 02:10:02 +02:00
Test User 0a0d50f748 Implement the comprehensive CLI (stage 5)
Every binary is now a clap-derive CLI; no subcommand keeps the current
default (run server / TUI / both).

- cbd-cli: run_remote executes library/queue/global against a running
  server (mirrors RpcClient; direct Stop; connect+request timeouts;
  concise errors; human-readable listings).
- crabidy-server: guard (hash + write [auth], stdin fallback, --no-config),
  scan (walk + write .cbd-track.toml; --capture/--move via new
  CrabidyStore::ingest_file), ServerSettings::store; replaces hash-password.
- cbd-tui: auth writes the client config; config load+override keeps the
  first-run-defaults / flag-overrides-file behavior.
- cbd: union of server + client subcommands.
- build.rs in each binary generates shell completions + man pages
  (OUT_DIR, and CBD_ASSET_DIR when set); devenv gen-cli-assets → dist/.
- README CLI section; tests for parse, config writers, scan/ingest, guard.

Deviations (plan/summary.md): ClapSerde kept; connection flags top-level
(not clap-global, to avoid colliding with auth --address); Box<dyn Error>
CLI reports per existing convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 12:13:51 +02:00
Test User 435af91d9c Add a Leptos web client served by the server
crabidy-server now serves a browser client with the same functionality
as the TUI at its own address, behind the default-on web-ui feature.

The new cbd-web crate is a client-side Leptos/WASM app talking gRPC-web
(tonic-web-wasm-client) over the same crabidy-core client and proto the
TUI uses, so parity is structural: library browsing, search terms,
marks, bookmarks/captures with live progress and confirmed deletion,
the full queue and playback controls, and the update stream with
reconnect. Keys mirror the TUI; every key also has a clickable control.
Styling is hand-written modern CSS with a single crab orange-red accent
and light/dark themes.

The server wraps its existing gRPC service in tonic-web and composes one
axum router (auth layer -> grpc-web -> service, web bundle as fallback);
axum::serve replaces tonic transport, and native gRPC (h2c) still works.
The bundle is embedded via include_dir behind a build.rs that falls back
to a placeholder so a plain cargo build needs no wasm toolchain. To make
crabidy-core build for wasm, tonic is codegen-only there (transport
generation disabled) and native config loading is target-gated.

devenv gains the wasm toolchain and build-web/serve-web scripts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 22:43:06 +02:00
Test User 973bb7bbc6 Fetch streams in bounded windows and restore yt-dlp for stream URLs
YouTube caps tokenless stream URLs at exactly their leading 1 MiB:
plain, open-ended, and oversized requests get 403, and fresh URLs
refuse offset starts, so playback died mid-first-minute. PO tokens
would lift the cap but the token-capable Innertube clients need
signature deciphering that is broken in rustypipe upstream (botguard
was built and tested — ineffective through the iOS client).

The player now streams every http(s) source through a windowed
SourceStream (bounded ~1 MiB ranges, 200-body fallback, eager
seek/reconnect so rejected windows fail typed instead of retrying
forever) and the capture downloader windows the same way. Stream URLs
come from a minimal yt-dlp sidecar again — metadata stays on the
pure-Rust rustypipe extractor — whose cipher-solved URLs stream whole
files at a throttled ~32 KB/s; a missing binary degrades to 1 MiB
streams with a warning. botguard_bin is wired through so streams flip
back to pure Rust when upstream deciphering recovers. Live-verified on
the exact track from the failure log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 18:18:40 +02:00
Test User 6f787285bf Replace the yt-dlp subprocess with the pure-Rust rustypipe client
Playback of YouTube tracks was broken: bestaudio selects WebM/Opus and
the rodio+symphonia player has no Opus decoder. The new extractor picks
the highest-bitrate audio/mp4 (AAC) stream instead, which decodes —
and captures get playable .m4a files. rusty_ytdl, rustube, and
rust-yt-downloader were evaluated live and rejected (broken or stale);
rustypipe works end to end and is actively maintained. Provider logic
now tests against a fake Extract seam, login keeps the cookies.txt
setting with rustypipe caching the rotated cookie, saved playlists
replace the unvalidated feed scrape, and yt-dlp leaves devenv.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 17:12:40 +02:00
Test User c6e9f71cf4 Add a YouTube provider backed by yt-dlp
The new ytdy crate mounts /youtube: login-free search terms exactly
like tidal's (creatable, renamable, deletable, results as queueable
downloadable tracks) and, when a cookies file is configured, the
user's playlists. All extraction runs through one bounded subprocess
seam (argv-only, per-call timeout, stdout cap, typed errors) so tests
drive the provider with a fake script. yt-dlp is declared in devenv;
a failed binary probe disables the provider, never the server.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:01:58 +02:00
AI User 86ce63ae61 Document the as-built architecture
Records the current design in architecture/overview.md: crate topology,
the three concurrency domains and the channels between them, the
filesystem-like path addressing scheme, the span-carrying message
envelope used for tracing, and the Tidal device-flow auth.

Captures the trade-offs behind the load-bearing choices (paths vs opaque
ids, blocking engine thread, lossy broadcast) and the known gaps, so
later changes can see what was traded away.

Adds d2 to devenv for rendering the embedded diagrams.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 10:34:45 +02:00
AI User 6eb5a87b15 Update all dependencies to current versions
- tonic 0.9 -> 0.14 (tonic-prost/tonic-prost-build split), prost 0.14
- ratatui 0.20 -> 0.30 (Frame no longer generic, Line instead of Spans),
  crossterm 0.29
- rodio 0.17 -> 0.22: replace the custom symphonia decoder with rodio's
  built-in decoder, seeking (try_seek) and position tracking (get_pos);
  end-of-stream is now signalled via an EmptyCallback source with a
  generation counter so a replaced track can never emit a stale EOS
- replace the vendored stream-download crate with the published
  stream-download 0.24 (rustls), with a 30s open timeout
- reqwest 0.12->0.13 (rustls/webpki-roots/query features), base64 0.22
  Engine API, rand 0.10, flume 0.12, thiserror 2, dirs 6, toml 1
- unify everything under [workspace.dependencies]; drop unused deps
  (once_cell, serde_json in server; confique, secrecy in tidaldy)
- devenv: add protobuf (protoc) for prost-build

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 21:41:10 +02:00
AI User 91716daf84 Add devenv-based dev environment and README
Adds devenv.nix (with alsa-lib and pkg-config for rodio/cpal builds),
rust-toolchain.toml pinning stable, and updated .gitignore.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 21:29:23 +02:00