130 lines
4.2 KiB
Rust
130 lines
4.2 KiB
Rust
use std::sync::Arc;
|
|
use tauri::State;
|
|
|
|
use crate::playback_mode::{PlaybackMode, PlaybackModeManager};
|
|
|
|
/// Wrapper for PlaybackModeManager to manage in Tauri state
|
|
pub struct PlaybackModeManagerWrapper(pub Arc<PlaybackModeManager>);
|
|
|
|
/// Get the current playback mode
|
|
#[tauri::command]
|
|
pub fn playback_mode_get_current(
|
|
manager: State<'_, PlaybackModeManagerWrapper>,
|
|
) -> Result<PlaybackMode, String> {
|
|
Ok(manager.0.get_mode())
|
|
}
|
|
|
|
/// Set the playback mode (internal/testing use)
|
|
#[tauri::command]
|
|
pub fn playback_mode_set(
|
|
manager: State<'_, PlaybackModeManagerWrapper>,
|
|
mode: PlaybackMode,
|
|
) -> Result<(), String> {
|
|
manager.0.set_mode(mode);
|
|
Ok(())
|
|
}
|
|
|
|
/// Check if currently transferring between playback modes
|
|
#[tauri::command]
|
|
pub fn playback_mode_is_transferring(
|
|
manager: State<'_, PlaybackModeManagerWrapper>,
|
|
) -> Result<bool, String> {
|
|
Ok(manager.0.is_transferring())
|
|
}
|
|
|
|
/// Transfer playback from local device to a remote Jellyfin session
|
|
#[tauri::command]
|
|
pub async fn playback_mode_transfer_to_remote(
|
|
manager: State<'_, PlaybackModeManagerWrapper>,
|
|
session_id: String,
|
|
) -> Result<(), String> {
|
|
log::info!(
|
|
"[PlaybackModeCommands] Transferring to remote session: {}",
|
|
session_id
|
|
);
|
|
manager.0.transfer_to_remote(session_id).await
|
|
}
|
|
|
|
/// Transfer playback from remote session back to local device
|
|
///
|
|
/// Parameters:
|
|
/// - current_item_id: The Jellyfin item ID currently playing on remote
|
|
/// - position_ticks: Current playback position in ticks (10,000 ticks = 1ms)
|
|
#[tauri::command]
|
|
pub async fn playback_mode_transfer_to_local(
|
|
manager: State<'_, PlaybackModeManagerWrapper>,
|
|
current_item_id: String,
|
|
position_ticks: i64,
|
|
) -> Result<(), String> {
|
|
log::info!(
|
|
"[PlaybackModeCommands] Transferring to local: item_id={}, position={}",
|
|
current_item_id,
|
|
position_ticks
|
|
);
|
|
manager
|
|
.0
|
|
.transfer_to_local(current_item_id, position_ticks)
|
|
.await
|
|
}
|
|
|
|
/// Get remote session status (for polling position/duration)
|
|
#[tauri::command]
|
|
pub async fn playback_mode_get_remote_status(
|
|
manager: State<'_, PlaybackModeManagerWrapper>,
|
|
player: State<'_, crate::commands::PlayerStateWrapper>,
|
|
) -> Result<RemoteSessionStatus, String> {
|
|
let mode = manager.0.get_mode();
|
|
|
|
if let crate::playback_mode::PlaybackMode::Remote { session_id } = mode {
|
|
// Get Jellyfin client from player controller - clone before await
|
|
let client = {
|
|
let controller = player.0.lock().await;
|
|
let client_arc = controller.jellyfin_client();
|
|
let client_opt = client_arc.lock().map_err(|e| e.to_string())?;
|
|
client_opt.as_ref().ok_or("Jellyfin client not configured")?.clone()
|
|
};
|
|
|
|
// Get session info
|
|
match client.get_session(&session_id).await {
|
|
Ok(Some(session)) => {
|
|
let position_ticks = session.play_state.as_ref()
|
|
.and_then(|ps| ps.position_ticks)
|
|
.unwrap_or(0);
|
|
|
|
let duration_ticks = session.now_playing_item.as_ref()
|
|
.and_then(|item| item.run_time_ticks)
|
|
.unwrap_or(0);
|
|
|
|
let is_paused = session.play_state.as_ref()
|
|
.and_then(|ps| ps.is_paused)
|
|
.unwrap_or(true);
|
|
|
|
Ok(RemoteSessionStatus {
|
|
position: position_ticks as f64 / 10_000_000.0,
|
|
duration: if duration_ticks > 0 {
|
|
Some(duration_ticks as f64 / 10_000_000.0)
|
|
} else {
|
|
None
|
|
},
|
|
is_playing: !is_paused,
|
|
now_playing_item: session.now_playing_item.clone(),
|
|
})
|
|
}
|
|
Ok(None) => Err("Remote session not found".to_string()),
|
|
Err(e) => Err(format!("Failed to get session status: {}", e)),
|
|
}
|
|
} else {
|
|
Err("Not in remote playback mode".to_string())
|
|
}
|
|
}
|
|
|
|
/// Remote session status for UI updates
|
|
#[derive(serde::Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RemoteSessionStatus {
|
|
pub position: f64,
|
|
pub duration: Option<f64>,
|
|
pub is_playing: bool,
|
|
pub now_playing_item: Option<crate::jellyfin::NowPlayingItem>,
|
|
}
|