Add episode queueing picker and configurable mpv video output
Activating an episode now opens a scope picker (episode / season / whole show) and plays the chosen queue back-to-back in one mpv instance, with only the first item honoring its resume position. A new mpv `vo` driver setting (CLI flag, env var, config file, and settings TUI) lets users opt into terminal-based vos like sixel/kitty/tct, which auto-enable mpv's terminal input so playback keys still work. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
1 parent
f0ebb4b9a4
commit
093b13f03e
9 files changed
+661
-72
No files matched your search
@@ -28,6 +28,11 @@ pub struct CliArgs {
|
||||
#[arg(long, env = "EMBY_SUBTITLE_LANG")]
|
||||
pub subtitle_lang: Option<String>,
|
||||
|
||||
/// mpv video output driver (e.g. `gpu`, `gpu-next`, `sixel`, `kitty`,
|
||||
/// `drm`, `tct`). Forwarded to mpv's `vo`. Leave unset for mpv's default.
|
||||
#[arg(long, env = "EMBY_VIDEO_OUTPUT")]
|
||||
pub video_output: Option<String>,
|
||||
|
||||
/// Path to config file. Defaults: ./config.toml then $XDG_CONFIG_HOME/emby-client/config.toml
|
||||
#[arg(short, long)]
|
||||
pub config: Option<PathBuf>,
|
||||
@@ -44,6 +49,7 @@ pub struct FileConfig {
|
||||
pub password: Option<String>,
|
||||
pub audio_lang: Option<String>,
|
||||
pub subtitle_lang: Option<String>,
|
||||
pub video_output: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -53,6 +59,9 @@ pub struct Config {
|
||||
pub password: String,
|
||||
pub audio_lang: Option<String>,
|
||||
pub subtitle_lang: Option<String>,
|
||||
/// mpv `vo` driver, e.g. `gpu`, `sixel`, `kitty`, `drm`, `tct`. `None`
|
||||
/// means we don't touch the property and mpv picks its default.
|
||||
pub video_output: Option<String>,
|
||||
}
|
||||
|
||||
pub fn load(args: &CliArgs) -> Result<(Option<Config>, Option<PathBuf>)> {
|
||||
@@ -63,6 +72,7 @@ pub fn load(args: &CliArgs) -> Result<(Option<Config>, Option<PathBuf>)> {
|
||||
let password = args.password.clone().or(file_cfg.password);
|
||||
let audio_lang = args.audio_lang.clone().or(file_cfg.audio_lang);
|
||||
let subtitle_lang = args.subtitle_lang.clone().or(file_cfg.subtitle_lang);
|
||||
let video_output = args.video_output.clone().or(file_cfg.video_output);
|
||||
|
||||
let cfg = match (server, user, password) {
|
||||
(Some(server), Some(user), Some(password)) => Some(Config {
|
||||
@@ -71,6 +81,7 @@ pub fn load(args: &CliArgs) -> Result<(Option<Config>, Option<PathBuf>)> {
|
||||
password,
|
||||
audio_lang,
|
||||
subtitle_lang,
|
||||
video_output,
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
@@ -124,6 +135,7 @@ pub fn save(path: &Path, cfg: &Config) -> Result<()> {
|
||||
password: Some(cfg.password.clone()),
|
||||
audio_lang: cfg.audio_lang.clone(),
|
||||
subtitle_lang: cfg.subtitle_lang.clone(),
|
||||
video_output: cfg.video_output.clone(),
|
||||
};
|
||||
let text = toml::to_string_pretty(&file_cfg).context("serializing config")?;
|
||||
std::fs::write(path, text).with_context(|| format!("writing {}", path.display()))?;
|
||||
|
||||
Reference in new issue
Block a user