[package] name = "jellytau" # The app. Named explicitly because the crate also builds # `player-conformance`, and a second binary makes a bare `cargo run` — # which `tauri dev` issues — ambiguous. default-run = "jellytau" version = "0.11.0" description = "A cross-platform Jellyfin client" authors = ["Duncan Tourolle "] license = "MIT" repository = "https://gitea.tourolle.paris/dtourolle/jellytau" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] # The `_lib` suffix may seem redundant but it is necessary # to make the lib name unique and wouldn't conflict with the bin name. # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 name = "jellytau_lib" crate-type = ["staticlib", "cdylib", "rlib"] # Keep debug info minimal to reduce target/ size in CI (line numbers in # backtraces are preserved; the bulky full debuginfo is dropped). [profile.dev] debug = "line-tables-only" [build-dependencies] tauri-build = { version = "2", features = [] } [dependencies] # protocol-asset serves cached thumbnails to the webview (asset://localhost on # Linux/macOS, http://asset.localhost on Windows/Android); without it # convertFileSrc yields a URL nothing answers. Paired with # app.security.assetProtocol in tauri.conf.json, which scopes it to # $APPDATA/thumbnails/** — the one directory still read through this protocol. # Downloaded media went the same way until DR-137 moved it to the loopback media # server, so the database, the encrypted-token fallback file and downloads/ are # all outside the grant now. # TRACES: UR-012, UR-071 | DR-134, DR-137, DR-198 tauri = { version = "2", features = ["protocol-asset"] } tauri-plugin-opener = "2" tauri-plugin-os = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" uuid = { version = "1", features = ["v4"] } rand = "0.8" tokio = { version = "1", features = ["sync", "rt-multi-thread", "time", "fs", "io-util", "macros"] } tokio-util = "0.7" reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "stream", "json"] } urlencoding = "2" futures-util = "0.3" async-trait = "0.1" # SQLite for offline storage tokio-rusqlite = "0.6" rusqlite = { version = "0.32", features = ["bundled"] } chrono = { version = "0.4", features = ["serde"] } directories = "5" # Secure credential storage (system keyring with encrypted file fallback) keyring = "3" aes-gcm = "0.10" base64 = "0.22" sha2 = "0.10" getrandom = "0.2" log = "0.4" env_logger = "0.11" # Persistent, rotating, redacted logging on every platform -- and on Android the # only thing that puts Rust output into logcat at all (env_logger writes to # stdout, which Android discards, which is why the backend was invisible on the # platform where the hardest bugs live). # # TRACES: UR-078 | DR-218 tauri-plugin-log = "2" # Zip for the diagnostics export bundle. zip = { version = "2", default-features = false, features = ["deflate"] } tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] } specta-typescript = "=0.0.9" specta = { version = "=2.0.0-rc.22", features = ["chrono", "derive"] } tiny_http = { version = "0.12.0", default-features = false } # In-app update, desktop only. # # `cfg(desktop)` is not decoration: tauri-plugin-updater does not support # Android at all -- an APK cannot replace itself, that is the package manager's # job -- and building it for the Android target fails. Android is offered the # releases page through tauri-plugin-opener instead (see the frontend's # updateCheck module). tauri-plugin-process supplies the relaunch that has to # follow a desktop install. # # The cfg is spelled out as "not android, not iOS" rather than `cfg(desktop)`: # Cargo evaluates a [target.'cfg(...)'] table against *target-triple* cfgs only # (target_os, target_arch, target_family, unix/windows). `desktop` is a cfg # Tauri's build script emits for use in Rust source, so `cfg(desktop)` here # matches nothing, silently drops the dependency, and the build then fails much # later with "Permission updater:default not found". # # TRACES: UR-077 | DR-217 [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] tauri-plugin-updater = "2" tauri-plugin-process = "2" # Linux-specific dependencies [target.'cfg(target_os = "linux")'.dependencies] hostname = "0.4" libc = "0.2" # The crates.io release of libmpv predates the MPV versions we support, so this # tracks the upstream git repo. # # Pinned by `rev`, not `branch = "master"`. With a branch, the revision is # whatever Cargo.lock happens to hold and any `cargo update` silently swaps in # new upstream code -- for the one dependency here that is not from crates.io, # is not signed, and links a C library into the player. The rev below is the # commit the lockfile already resolved to, so this pins current behaviour rather # than changing it. To take upstream fixes, bump this deliberately. libmpv = { git = "https://github.com/ParadoxSpiral/libmpv-rs.git", rev = "3e6c389b716f52a595cc5e8e3fa1f96cb76b3de7" } # The raw FFI bindings behind `libmpv`, pinned to the *same* revision so the two # can never describe different ABIs. # # Needed because the safe crate's `render` module is an empty stub at this # revision — the render API (`mpv_render_context_create` and friends) exists only # in the sys bindings, which do carry all of it. `Mpv::ctx` is public, so the # render context can be built over the same handle the safe wrapper drives. This # is what makes native video reachable *without* first completing the libmpv2 # migration, which the spike's use of `libmpv2-sys` had implied was a # prerequisite. # # TRACES: UR-080 | DR-230, IR-033 libmpv-sys = { git = "https://github.com/ParadoxSpiral/libmpv-rs.git", rev = "3e6c389b716f52a595cc5e8e3fa1f96cb76b3de7" } # Same major as the one Tauri/wry already resolve, so `gtk_window()` and # `default_vbox()` hand back types this crate can name rather than a second, # incompatible GTK. gtk = "0.18" # JNI for Android ExoPlayer integration [target.'cfg(target_os = "android")'.dependencies] jni = "0.21" ndk-context = "0.1" [dev-dependencies] tempfile = "3.24.0" [features] # Exposes the MediaPlayer conformance suite and the `player-conformance` binary # to non-test builds, so an engine that cannot run in-process — ExoPlayer on a # device — is driven by the same cases as the ones that can, rather than by a # second checklist that drifts. conformance = [] # A standalone runner for the conformance suite. Deliberately a separate binary: # it links libmpv and nothing else, so a wrapper can be verified without building # or launching the app. [[bin]] name = "player-conformance" path = "src/bin/player_conformance.rs" required-features = ["conformance"]