local playback v1
This commit is contained in:
@@ -942,3 +942,57 @@ fn aria2_front_status(state: &Arc<Mutex<DownloadState>>) -> Option<String> {
|
||||
let res = aria2_rpc_call("aria2.tellStatus", json!([gid, ["status"]])).ok()?;
|
||||
res.get("status").and_then(|v| v.as_str()).map(|s| s.to_string())
|
||||
}
|
||||
|
||||
|
||||
/// If this item_id has a local download marker, return the local media file path.
|
||||
/// Marker files are written alongside the media file as:
|
||||
/// <media_filename>.<DOWNLOAD_MARKER_EXT>
|
||||
/// where DOWNLOAD_MARKER_EXT == "cj-jftui.json"
|
||||
pub fn local_media_path_for_item_id(item_id: &str) -> Option<PathBuf> {
|
||||
fn walk(dir: &Path, item_id: &str) -> Option<PathBuf> {
|
||||
if !dir.exists() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let rd = fs::read_dir(dir).ok()?;
|
||||
for ent in rd {
|
||||
let p = ent.ok()?.path();
|
||||
|
||||
if p.is_dir() {
|
||||
if let Some(found) = walk(&p, item_id) {
|
||||
return Some(found);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = p.file_name().and_then(|s| s.to_str()).unwrap_or("");
|
||||
if !name.ends_with(DOWNLOAD_MARKER_EXT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let raw = fs::read_to_string(&p).ok()?;
|
||||
let v: Value = serde_json::from_str(raw.trim()).ok()?;
|
||||
let id = v.get("item_id").and_then(|x| x.as_str())?;
|
||||
|
||||
if id == item_id {
|
||||
// Marker file is "<media_filename>.<DOWNLOAD_MARKER_EXT>"
|
||||
// So the media file path is the same path with that suffix stripped.
|
||||
let suffix = format!(".{DOWNLOAD_MARKER_EXT}");
|
||||
if !name.ends_with(&suffix) {
|
||||
continue;
|
||||
}
|
||||
let media_name = &name[..name.len() - suffix.len()];
|
||||
let media_path = p.with_file_name(media_name);
|
||||
|
||||
if media_path.exists() {
|
||||
return Some(media_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
let root = downloads_root().ok()?;
|
||||
walk(&root, item_id)
|
||||
}
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@@ -694,7 +694,11 @@ 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);
|
||||
let url = if let Some(p) = crate::core::downloads::local_media_path_for_item_id(&item_id) {
|
||||
p.to_string_lossy().to_string()
|
||||
} else {
|
||||
build_jellyfin_play_url(&cfg, &item_id)
|
||||
};
|
||||
|
||||
if let Some(mpv) = &app.mpv {
|
||||
match mpv_load_url(&cfg, mpv, &url) {
|
||||
@@ -733,7 +737,11 @@ 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);
|
||||
let url = if let Some(p) = crate::core::downloads::local_media_path_for_item_id(&item_id) {
|
||||
p.to_string_lossy().to_string()
|
||||
} else {
|
||||
build_jellyfin_play_url(&cfg, &item_id)
|
||||
};
|
||||
|
||||
if let Some(mpv) = &app.mpv {
|
||||
match mpv_load_url(&cfg, mpv, &url) {
|
||||
|
||||
Reference in New Issue
Block a user