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:
janisslsmandClaude Opus 4.7 committed 2026-05-22 15:46:17 +03:00
1 parent f0ebb4b9a4
commit 093b13f03e
9 files changed
+661 -72

No files matched your search

+27
View File
@@ -59,6 +59,10 @@ pub struct Item {
pub runtime_ticks: Option<i64>,
#[serde(rename = "SeriesName", default)]
pub series_name: Option<String>,
/// Set for Episode items. Lets us fetch the full series episode list so a
/// queue started mid-show can continue past the current season.
#[serde(rename = "SeriesId", default)]
pub series_id: Option<String>,
#[serde(rename = "IndexNumber", default)]
pub index_number: Option<i32>,
#[serde(rename = "ParentIndexNumber", default)]
@@ -223,6 +227,29 @@ impl Client {
Ok(resp.items)
}
/// All episodes for a series, in playback order (season, then episode).
/// Used to build a multi-season playback queue starting from any episode.
pub async fn series_episodes(&self, series_id: &str) -> Result<Vec<Item>> {
let url = format!("{}/Shows/{}/Episodes", self.server, series_id);
let resp: ItemsResponse = self
.http
.get(&url)
.headers(self.headers())
.query(&[
("UserId", self.user_id.as_str()),
(
"Fields",
"ProductionYear,RunTimeTicks,SeriesName,UserData",
),
])
.send()
.await?
.error_for_status()?
.json()
.await?;
Ok(resp.items)
}
pub fn stream_url(&self, item_id: &str) -> String {
format!(
"{}/Videos/{}/stream?Static=true&api_key={}&DeviceId={}",