From c030bbb155a5adb414f0ff27eb157ad3cc9edbbb Mon Sep 17 00:00:00 2001 From: cwj3rcb Date: Mon, 16 Feb 2026 02:48:38 -0600 Subject: [PATCH] Resume Functionality Restored and Transcoding Entirely Removed. --- src/core/config.rs | 26 ----------- src/main.rs | 108 ++++----------------------------------------- 2 files changed, 8 insertions(+), 126 deletions(-) diff --git a/src/core/config.rs b/src/core/config.rs index 1ec0b8b..fa5b873 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -7,8 +7,6 @@ pub struct Config { pub base_url: String, pub access_token: Option, pub user_id: Option, - pub transcode_mbps: Option, - pub transcode_default_on: Option, } @@ -47,8 +45,6 @@ fn parse_config(s: &str) -> Result { let mut base_url: Option = None; let mut access_token: Option = None; let mut user_id: Option = None; - let mut transcode_mbps: Option = None; - let mut transcode_default_on: Option = None; for (i, line) in s.lines().enumerate() { let line = line.trim(); @@ -72,18 +68,6 @@ fn parse_config(s: &str) -> Result { "base_url" => base_url = Some(val), "access_token" => access_token = Some(val), "user_id" => user_id = Some(val), - - "transcode_mbps" => { - transcode_mbps = val.parse::().ok(); - } - - "transcode_default_on" => { - transcode_default_on = match val.as_str() { - "true" => Some(true), - "false" => Some(false), - _ => None, - }; - } _ => {} } } @@ -94,8 +78,6 @@ fn parse_config(s: &str) -> Result { base_url, access_token, user_id, - transcode_mbps, - transcode_default_on, }) } @@ -118,14 +100,6 @@ pub fn save_config(cfg: &Config) -> Result<(), ConfigError> { out.push_str(&format!("user_id = \"{}\"\n", u)); } - if let Some(m) = cfg.transcode_mbps { - out.push_str(&format!("transcode_mbps = {}\n", m)); - } - - if let Some(b) = cfg.transcode_default_on { - out.push_str(&format!("transcode_default_on = {}\n", b)); - } - std::fs::write(path, out)?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index f700b1b..0f34955 100644 --- a/src/main.rs +++ b/src/main.rs @@ -182,9 +182,6 @@ struct App { autoplay_eof_latched: bool, autoplay_prev_time_pos: Option, - transcode_on: bool, - transcode_mbps: u32, - // Cache: container item id -> has resumable episode under it parent_progress: std::collections::HashMap, @@ -200,16 +197,6 @@ impl Default for App { fn default() -> Self { let loaded = core::config::load_config().ok(); - let default_mbps = loaded - .as_ref() - .and_then(|c| c.transcode_mbps) - .unwrap_or(5); - - let default_on = loaded - .as_ref() - .and_then(|c| c.transcode_default_on) - .unwrap_or(false); - let (view_stack, config_status) = match &loaded { Some(cfg) if cfg.access_token.is_some() => ( vec![View::Categories], @@ -263,8 +250,6 @@ impl Default for App { autoplay_next_index: None, autoplay_eof_latched: false, autoplay_prev_time_pos: None, - transcode_on: default_on, - transcode_mbps: default_mbps, parent_progress: std::collections::HashMap::new(), } } @@ -415,7 +400,6 @@ fn handle_key(app: &mut App, code: KeyCode) { } return; } - KeyCode::Char('C') => { reload_config(app); return; } KeyCode::Char(c) => { match app.login_focus { @@ -607,7 +591,7 @@ fn handle_key(app: &mut App, code: KeyCode) { app.mpv_now_playing = Some(item_name); // If mpv running -> replace, else spawn - let url = build_jellyfin_play_url(&cfg, &item_id, app.transcode_on, app.transcode_mbps); + let url = build_jellyfin_play_url(&cfg, &item_id); if let Some(mpv) = &app.mpv { match mpv_load_url(&cfg, mpv, &url) { @@ -646,7 +630,7 @@ fn handle_key(app: &mut App, code: KeyCode) { app.autoplay_next_index = if selected + 1 < len { Some(selected + 1) } else { None }; // load/replace or spawn - let url = build_jellyfin_play_url(&cfg, &item_id, app.transcode_on, app.transcode_mbps); + let url = build_jellyfin_play_url(&cfg, &item_id); if let Some(mpv) = &app.mpv { match mpv_load_url(&cfg, mpv, &url) { @@ -666,15 +650,6 @@ fn handle_key(app: &mut App, code: KeyCode) { } return; } - KeyCode::Char('t') => { - app.transcode_on = !app.transcode_on; - app.status = if app.transcode_on { - format!("Transcoding ON ({}Mbps)", app.transcode_mbps) - } else { - "Transcoding OFF".into() - }; - return; - } KeyCode::Char('r') => { app.autoplay = false; app.autoplay_next_index = None; @@ -699,7 +674,7 @@ fn handle_key(app: &mut App, code: KeyCode) { app.mpv_now_playing = Some(item_name); - let url = build_jellyfin_play_url(&cfg, &item_id, app.transcode_on, app.transcode_mbps); + let url = build_jellyfin_play_url(&cfg, &item_id); if let Some(mpv) = &app.mpv { match mpv_cmd(&mpv.socket_path, &format!(r#"{{"command":["loadfile","{}","replace"]}}"#, url)) { @@ -753,7 +728,7 @@ fn handle_key(app: &mut App, code: KeyCode) { app.autoplay_next_index = if selected + 1 < len { Some(selected + 1) } else { None }; app.autoplay_eof_latched = false; - let url = build_jellyfin_play_url(&cfg, &item_id, app.transcode_on, app.transcode_mbps); + let url = build_jellyfin_play_url(&cfg, &item_id); if let Some(mpv) = &app.mpv { match mpv_cmd(&mpv.socket_path, &format!(r#"{{"command":["loadfile","{}","replace"]}}"#, url)) { @@ -1444,14 +1419,8 @@ fn ui(frame: &mut Frame, app: &App) { .map(|c| c.base_url.as_str()) .unwrap_or("-"); - let tx_line = if app.transcode_on { - format!("Transcoding On ({}Mbps)", app.transcode_mbps) - } else { - "Transcoding Off".to_string() - }; - let right_text = format!( - "{connected}\n{tx_line}\n\np/P: play/autoplay\nq: quit\n/help: more help" + "{connected}\n\np/P: play/autoplay\nq: quit\n/help: more help" ); frame.render_widget( @@ -2034,7 +2003,7 @@ fn autoplay_tick(app: &mut App) { }; // Load next item - let url = build_jellyfin_play_url(&cfg, &next_id, app.transcode_on, app.transcode_mbps); + let url = build_jellyfin_play_url(&cfg, &next_id); if let Err(e) = mpv_load_url(&cfg, mpv, &url) { app.autoplay = false; @@ -2532,70 +2501,9 @@ fn clamp_mbps_to_bps(mbps: u32) -> u32 { mbps.saturating_mul(1_000_000) // Mb/s -> bits/s } -fn build_jellyfin_play_url( - cfg: &core::config::Config, - item_id: &str, - transcode_on: bool, - transcode_mbps: u32, -) -> String { +fn build_jellyfin_play_url(cfg: &core::config::Config, item_id: &str) -> String { let base = cfg.base_url.trim_end_matches('/'); - - let token = cfg - .access_token - .as_deref() - .unwrap_or(""); // if empty, server likely rejects anyway - - let bps = clamp_mbps_to_bps(transcode_mbps); - - if !transcode_on { - // Direct stream. - // - // We intentionally keep this "static=true" so mpv can see the full timeline/duration - // (many servers provide Content-Length only for static streams). - // - // Resume is implemented via mpv seeking (not startTimeTicks in the URL) to avoid the - // Jellyfin behavior where startTimeTicks may be ignored for static streams. - return format!( - "{}/Videos/{}/stream?static=true&api_key={}", - base, item_id, token - ); - } - - // Transcoded stream via HLS (fixes "duration == buffered" + enables seeking). - // - // IMPORTANT: Use Jellyfin's documented query param names: - // - videoBitRate (capital R) - // - segmentContainer - // - // Resume is implemented via mpv seeking (not startTimeTicks in the URL). - let mut url = format!( - "{}/Videos/{}/master.m3u8?api_key={}&static=false", - base, item_id, token - ); - - url.push_str(&format!("&maxStreamingBitrate={}", bps)); - url.push_str(&format!("&videoBitrate={}", bps)); // NOTE: lower-case 'r' matches your working version - url.push_str(&format!("&audioBitrate={}", bps)); - url.push_str("&enableAutoStreamCopy=false"); - url.push_str("&videoCodec=h264"); - url.push_str("&audioCodec=aac"); - url.push_str("&transcodingContainer=ts"); // NOTE: this is what your working build used - - url -} - - - - -fn reload_config(app: &mut App) { - if let Ok(cfg) = core::config::load_config() { - app.transcode_mbps = cfg.transcode_mbps.unwrap_or(5); - app.transcode_on = cfg.transcode_default_on.unwrap_or(false); - app.config = Some(cfg); - app.status = "Reloaded config".into(); - } else { - app.status = "Failed to reload config".into(); - } + format!("{}/Items/{}/Download", base, item_id) } fn mpv_cmd_reply(socket: &PathBuf, cmd: &str) -> Result {