use clap::{Parser, ValueEnum}; #[derive(Parser, Debug)] #[command( name = "pixelpass", version, about = "P2P screen sharing over iroh", long_about = "Run with no arguments for an interactive Host/View menu. \ Pass a ticket positionally to skip the menu and view headlessly." )] pub struct Cli { /// iroh ticket. If present, runs as viewer. If absent, runs as host. pub ticket: Option, // ── host options ────────────────────────────────────────────────── /// Run as host without the interactive menu. Equivalent to picking /// "Host" in the menu, but headless — for scripting and the --gui /// front-end, which drives this binary as a child process. #[arg(long)] pub host: bool, /// Pick a single window instead of the whole screen. #[arg(long)] pub window: bool, /// Capture only this app's audio (per-app PipeWire routing). #[arg(long, value_name = "NAME")] pub app: Option, /// Override display server autodetection. #[arg(long, value_enum)] pub display_server: Option, /// Quality preset. Bundles a max video height, bitrate, and framerate. /// `auto` derives them from the saved bandwidth pre-flight (falls back to /// `medium` when no measurement exists). Defaults to `auto`; in the /// interactive menu, omitting this shows a picker instead. #[arg(long, value_enum)] pub quality: Option, /// Cap the encoded video height (px); width follows the source aspect. /// Power-user override — takes precedence over the preset's height. #[arg(long, value_name = "N")] pub max_height: Option, /// Encode bitrate in kbps. Overrides the quality preset's bitrate. #[arg(long)] pub bitrate: Option, /// Capture framerate. Overrides the quality preset's framerate. #[arg(long)] pub framerate: Option, /// Disable VAAPI HW encode; force software x264. #[arg(long)] pub no_hwencode: bool, /// Maximum number of concurrent viewers. Additional connections are /// politely refused with a "host full" message. Defaults to the /// connection-aware recommendation from the bandwidth pre-flight if /// available, otherwise 2. #[arg(long)] pub max_viewers: Option, // ── viewer options ──────────────────────────────────────────────── /// Local TCP port for the viewer to expose (default: random). #[arg(long, default_value_t = 0)] pub port: u16, // ── global ──────────────────────────────────────────────────────── /// Emit machine-readable events on stdout (one JSON object per line) /// alongside the human banner on stderr. For scripts and the --gui /// front-end. Currently only `json` is supported. #[arg(long, value_enum, value_name = "FORMAT")] pub output: Option, /// Trace-level logging. #[arg(long, short)] pub verbose: bool, /// Clean up orphaned PipeWire state from a crashed host run, then exit. #[arg(long)] pub repair: bool, /// Re-run the bandwidth pre-flight test, save the result, then exit. /// Use this if your connection has changed (new ISP, moved house, etc.) /// or if the previously saved test result is stale. #[arg(long)] pub reconfigure: bool, } #[derive(ValueEnum, Clone, Copy, Debug)] pub enum DisplayServerArg { Wayland, X11, } #[derive(ValueEnum, Clone, Copy, Debug, PartialEq, Eq)] pub enum OutputFormat { /// One JSON object per line on stdout. Json, } /// Quality preset. Each fixed preset bundles a (max-height, bitrate, fps) /// tuple — resolution is a quality-per-bitrate knob, so the three only make /// sense together. `Auto` has no fixed tuple; it picks one of the others from /// the bandwidth pre-flight at host startup. See `host::quality`. #[derive(ValueEnum, Clone, Copy, Debug, PartialEq, Eq)] pub enum Quality { /// Native source resolution, 6000 kbps, 30 fps (no downscale). Source, /// Up to 1080p, 4000 kbps, 30 fps. High, /// Up to 720p, 2500 kbps, 30 fps. Medium, /// Up to 480p, 1000 kbps, 30 fps. Low, /// Derive from the measured upstream; falls back to `medium` when unmeasured. Auto, } #[derive(Debug, Clone)] pub struct HostOpts { pub window: bool, pub app: Option, pub display_server: Option, /// Chosen preset (Auto = derive at startup). Defaults to Auto. pub quality: Quality, /// Raw `--bitrate` override (kbps); None = use the preset's bitrate. pub bitrate: Option, /// Raw `--framerate` override; None = use the preset's framerate. pub framerate: Option, /// Raw `--max-height` override (px); None = use the preset's height. pub max_height: Option, pub no_hwencode: bool, pub max_viewers: Option, pub interactive: bool, } #[derive(Debug, Clone)] pub struct ViewerOpts { pub port: u16, pub interactive: bool, } impl Cli { pub fn into_host_opts(self, interactive: bool) -> HostOpts { HostOpts { window: self.window, app: self.app, display_server: self.display_server, // No `--quality` and nothing picked interactively → the documented // default, Auto. quality: self.quality.unwrap_or(Quality::Auto), bitrate: self.bitrate, framerate: self.framerate, max_height: self.max_height, no_hwencode: self.no_hwencode, max_viewers: self.max_viewers, interactive, } } pub fn into_viewer_opts(self, interactive: bool) -> ViewerOpts { ViewerOpts { port: self.port, interactive } } }