feat: add casting module scaffolding (disabled)
Import Chromecast, AirPlay, and DLNA casting scaffolding from separate branches. The module is currently disabled due to: - Thread safety issues: rust_cast uses Rc internally (not Send) - API compatibility: rupnp methods have changed The scaffolding includes: - Chromecast: mDNS discovery, device connection, media server - AirPlay: Discovery scaffolding (RAOP playback pending) - DLNA/UPnP: SSDP discovery scaffolding (playback pending) To enable casting in the future: 1. Fix rust_cast thread safety (or use spawn_blocking) 2. Update rupnp API calls for current version 3. Add Deserialize derive to metadata types 4. Uncomment cast module in lib.rs 5. Wire up commands in invoke_handler
This commit is contained in:
1 parent
e908d334c1
commit
145186a06a
19 files changed
+1966
No files matched your search
@@ -0,0 +1,124 @@
|
||||
//! Tauri commands for DLNA/UPnP casting (discovery + scaffolding)
|
||||
|
||||
use std::sync::Arc;
|
||||
use tauri::State;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::cast::dlna::{
|
||||
DiscoveredDlnaDevice, DlnaConnection, DlnaDiscovery, DlnaError, DlnaMetadata, DlnaStatus,
|
||||
};
|
||||
|
||||
/// DLNA state shared across commands
|
||||
pub struct DlnaState {
|
||||
pub discovery: Arc<Mutex<DlnaDiscovery>>,
|
||||
pub connection: Arc<Mutex<Option<DlnaConnection>>>,
|
||||
}
|
||||
|
||||
impl DlnaState {
|
||||
pub fn new() -> Result<Self, DlnaError> {
|
||||
Ok(Self {
|
||||
discovery: Arc::new(Mutex::new(DlnaDiscovery::new())),
|
||||
connection: Arc::new(Mutex::new(None)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// === Discovery ===
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_start_discovery(state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut discovery = state.discovery.lock().await;
|
||||
discovery
|
||||
.start_discovery()
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_stop_discovery(state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut discovery = state.discovery.lock().await;
|
||||
discovery.stop_discovery().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_get_devices(
|
||||
state: State<'_, DlnaState>,
|
||||
) -> Result<Vec<DiscoveredDlnaDevice>, String> {
|
||||
let discovery = state.discovery.lock().await;
|
||||
Ok(discovery.get_discovered_devices())
|
||||
}
|
||||
|
||||
// === Connection ===
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_connect(device_id: String, state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let device = {
|
||||
let discovery = state.discovery.lock().await;
|
||||
discovery
|
||||
.get_device(&device_id)
|
||||
.ok_or_else(|| DlnaError::DeviceNotFound(device_id.clone()))
|
||||
.map_err(|e| e.to_string())?
|
||||
};
|
||||
|
||||
let connection = DlnaConnection::connect(device).map_err(|e| e.to_string())?;
|
||||
let mut state_connection = state.connection.lock().await;
|
||||
*state_connection = Some(connection);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_disconnect(state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut connection = state.connection.lock().await;
|
||||
if let Some(conn) = connection.as_mut() {
|
||||
conn.disconnect().map_err(|e| e.to_string())?;
|
||||
}
|
||||
*connection = None;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_get_status(state: State<'_, DlnaState>) -> Result<DlnaStatus, String> {
|
||||
let connection = state.connection.lock().await;
|
||||
let conn = connection.as_ref().ok_or_else(|| "Not connected".to_string())?;
|
||||
Ok(conn.get_status())
|
||||
}
|
||||
|
||||
// === Playback (stubs) ===
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_load_media(
|
||||
metadata: DlnaMetadata,
|
||||
state: State<'_, DlnaState>,
|
||||
) -> Result<(), String> {
|
||||
let mut connection = state.connection.lock().await;
|
||||
let conn = connection.as_mut().ok_or_else(|| "Not connected".to_string())?;
|
||||
conn.load_media(metadata).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_play(state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut connection = state.connection.lock().await;
|
||||
let conn = connection.as_mut().ok_or_else(|| "Not connected".to_string())?;
|
||||
conn.play().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_pause(state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut connection = state.connection.lock().await;
|
||||
let conn = connection.as_mut().ok_or_else(|| "Not connected".to_string())?;
|
||||
conn.pause().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_stop(state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut connection = state.connection.lock().await;
|
||||
let conn = connection.as_mut().ok_or_else(|| "Not connected".to_string())?;
|
||||
conn.stop().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn dlna_set_volume(volume: f32, state: State<'_, DlnaState>) -> Result<(), String> {
|
||||
let mut connection = state.connection.lock().await;
|
||||
let conn = connection.as_mut().ok_or_else(|| "Not connected".to_string())?;
|
||||
conn.set_volume(volume).map_err(|e| e.to_string())
|
||||
}
|
||||
Reference in new issue
Block a user