"""User settings, persisted to ~/.config/screencast/config.json.""" from __future__ import annotations from .util import config_dir, read_json, write_json DEFAULTS = { "fps": 30, "maxHeight": 1080, # the capture is scaled down to this before encoding "bitrate": 8000, # kbit/s "encoder": "auto", # auto | nvenc | vaapi | x264 | vp8 | vp9 "audio": True, # mix desktop audio into the stream "cursor": True, # draw the pointer into the capture "port": 8011, # local HTTP server the receiver pulls the stream from "lastDevice": "", # id of the device cast to last, for the "cast again" default "autoReconnect": True, # restart the pipeline if the receiver drops the stream "portVerified": False, # set once a receiver has actually fetched the stream } # Settings that only take effect on the next session (changing them mid-cast # restarts the pipeline instead of being ignored). PIPELINE_KEYS = {"fps", "maxHeight", "bitrate", "encoder", "audio", "cursor"} class Config: def __init__(self) -> None: self.path = config_dir() / "config.json" self.values = dict(DEFAULTS) self.values.update(read_json(self.path, {}) or {}) def __getitem__(self, key): return self.values.get(key, DEFAULTS.get(key)) def get(self, key, default=None): return self.values.get(key, DEFAULTS.get(key, default)) def update(self, patch: dict) -> set[str]: """Apply a patch, returning the keys that actually changed.""" changed = set() for key, value in (patch or {}).items(): if key not in DEFAULTS: continue want = _coerce(key, value) if want is None or self.values.get(key) == want: continue self.values[key] = want changed.add(key) if changed: self.save() return changed def save(self) -> None: write_json(self.path, self.values) def _coerce(key, value): ref = DEFAULTS[key] try: if isinstance(ref, bool): return bool(value) if isinstance(ref, int): v = int(value) if key == "fps": return max(5, min(60, v)) if key == "maxHeight": return max(360, min(2160, v)) if key == "bitrate": return max(500, min(50000, v)) if key == "port": return max(1024, min(65535, v)) return v return str(value) except (TypeError, ValueError): return None