Background-audio handoff for video + repository/player refactor
Hand video playback off to a native audio-only stream when the app is backgrounded or locked, with no on-device video decode (UR-040). Adds player_enter/exit_background_audio commands, an audio-only stream URL for video items across the repository layer, and the frontend handoff state machine wired into VideoPlayer. Includes accompanying repository/offline/player refactoring and regenerates the traceability matrix.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::sync::RwLock;
|
||||
use tauri::{AppHandle, Emitter};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::jellyfin::http_client::HttpClient;
|
||||
|
||||
@@ -170,9 +170,15 @@ impl ConnectivityReporter {
|
||||
if let Some(app_handle) = &self.app_handle {
|
||||
let event = ConnectivityChangeEvent { is_reachable };
|
||||
if let Err(e) = app_handle.emit("connectivity:changed", event) {
|
||||
log::error!("[ConnectivityMonitor] Failed to emit connectivity change event: {}", e);
|
||||
log::error!(
|
||||
"[ConnectivityMonitor] Failed to emit connectivity change event: {}",
|
||||
e
|
||||
);
|
||||
} else {
|
||||
log::info!("[ConnectivityMonitor] Emitted connectivity change: {}", is_reachable);
|
||||
log::info!(
|
||||
"[ConnectivityMonitor] Emitted connectivity change: {}",
|
||||
is_reachable
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,7 +187,10 @@ impl ConnectivityReporter {
|
||||
async fn emit_server_reconnected(&self) {
|
||||
if let Some(app_handle) = &self.app_handle {
|
||||
if let Err(e) = app_handle.emit("connectivity:reconnected", ()) {
|
||||
log::error!("[ConnectivityMonitor] Failed to emit reconnection event: {}", e);
|
||||
log::error!(
|
||||
"[ConnectivityMonitor] Failed to emit reconnection event: {}",
|
||||
e
|
||||
);
|
||||
} else {
|
||||
log::info!("[ConnectivityMonitor] Emitted server reconnected event");
|
||||
}
|
||||
@@ -233,7 +242,14 @@ impl ConnectivityMonitor {
|
||||
// Check new server immediately
|
||||
log::info!("[ConnectivityMonitor] Checking reachability of new server...");
|
||||
let is_reachable = self.check_reachability().await;
|
||||
log::info!("[ConnectivityMonitor] New server is {}", if is_reachable { "REACHABLE" } else { "UNREACHABLE" });
|
||||
log::info!(
|
||||
"[ConnectivityMonitor] New server is {}",
|
||||
if is_reachable {
|
||||
"REACHABLE"
|
||||
} else {
|
||||
"UNREACHABLE"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Get current connectivity status
|
||||
@@ -298,11 +314,16 @@ impl ConnectivityMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
log::info!("[ConnectivityMonitor] Starting connectivity monitoring (offline recovery probe)");
|
||||
log::info!(
|
||||
"[ConnectivityMonitor] Starting connectivity monitoring (offline recovery probe)"
|
||||
);
|
||||
|
||||
// Perform an immediate check so startup reflects reality quickly.
|
||||
let is_reachable = self.check_reachability().await;
|
||||
log::info!("[ConnectivityMonitor] Initial connectivity check: {}", if is_reachable { "ONLINE" } else { "OFFLINE" });
|
||||
log::info!(
|
||||
"[ConnectivityMonitor] Initial connectivity check: {}",
|
||||
if is_reachable { "ONLINE" } else { "OFFLINE" }
|
||||
);
|
||||
|
||||
let is_monitoring = Arc::clone(&self.is_monitoring);
|
||||
let server_url = Arc::clone(&self.server_url);
|
||||
@@ -452,7 +473,9 @@ mod tests {
|
||||
let reporter = test_reporter();
|
||||
|
||||
// Force offline.
|
||||
reporter.apply_probe_result(false, Some("down".to_string())).await;
|
||||
reporter
|
||||
.apply_probe_result(false, Some("down".to_string()))
|
||||
.await;
|
||||
assert!(!is_reachable(&reporter).await);
|
||||
|
||||
// A single success brings us straight back online.
|
||||
@@ -490,7 +513,9 @@ mod tests {
|
||||
assert!(!is_reachable(&reporter).await);
|
||||
|
||||
// Should not panic or change state.
|
||||
reporter.report_network_failure(Some("still down".to_string())).await;
|
||||
reporter
|
||||
.report_network_failure(Some("still down".to_string()))
|
||||
.await;
|
||||
assert!(!is_reachable(&reporter).await);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user