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); /// Get the current playback mode #[tauri::command] pub fn playback_mode_get_current( manager: State<'_, PlaybackModeManagerWrapper>, ) -> Result { 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 { 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 { 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, pub is_playing: bool, pub now_playing_item: Option, }