2026-02-09 07:18:13 +01:00
|
|
|
//! État partagé du renderer (backend ↔ navigateur)
|
|
|
|
|
|
|
|
|
|
use parking_lot::RwLock;
|
|
|
|
|
use std::sync::Arc;
|
2026-02-21 20:54:22 +01:00
|
|
|
use tokio::sync::mpsc;
|
2026-02-09 07:18:13 +01:00
|
|
|
|
2026-02-21 20:54:22 +01:00
|
|
|
use crate::messages::{PlaybackState, ServerMessage};
|
2026-02-09 07:18:13 +01:00
|
|
|
|
|
|
|
|
/// État temps-réel du renderer (partagé backend ↔ navigateur)
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct RendererState {
|
|
|
|
|
pub playback_state: PlaybackState,
|
|
|
|
|
pub current_uri: Option<String>,
|
|
|
|
|
pub current_metadata: Option<String>,
|
2026-02-21 10:16:49 +01:00
|
|
|
pub next_uri: Option<String>,
|
|
|
|
|
pub next_metadata: Option<String>,
|
2026-02-09 07:18:13 +01:00
|
|
|
pub position: Option<String>,
|
|
|
|
|
pub duration: Option<String>,
|
|
|
|
|
pub volume: u16,
|
|
|
|
|
pub mute: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for RendererState {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
playback_state: PlaybackState::Stopped,
|
|
|
|
|
current_uri: None,
|
|
|
|
|
current_metadata: None,
|
2026-02-21 10:16:49 +01:00
|
|
|
next_uri: None,
|
|
|
|
|
next_metadata: None,
|
2026-02-09 07:18:13 +01:00
|
|
|
position: None,
|
|
|
|
|
duration: None,
|
|
|
|
|
volume: 100,
|
|
|
|
|
mute: false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Alias pour l'état partagé
|
|
|
|
|
pub type SharedState = Arc<RwLock<RendererState>>;
|
2026-02-21 20:54:22 +01:00
|
|
|
|
|
|
|
|
/// Sender WebSocket partagé et remplaçable entre les reconnexions.
|
|
|
|
|
///
|
|
|
|
|
/// Les handlers UPnP capturent ce `Arc` à la création du device. À chaque
|
|
|
|
|
/// reconnexion WebSocket (reload de page), on remplace le sender interne via
|
|
|
|
|
/// `set()`, sans avoir à recréer le device ni ses handlers.
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct SharedSender(Arc<RwLock<Option<mpsc::UnboundedSender<ServerMessage>>>>);
|
|
|
|
|
|
|
|
|
|
impl SharedSender {
|
|
|
|
|
pub fn new(sender: mpsc::UnboundedSender<ServerMessage>) -> Self {
|
|
|
|
|
Self(Arc::new(RwLock::new(Some(sender))))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Envoie un message au navigateur. Ignore silencieusement si déconnecté.
|
|
|
|
|
pub fn send(&self, msg: ServerMessage) {
|
|
|
|
|
if let Some(tx) = self.0.read().as_ref() {
|
|
|
|
|
let _ = tx.send(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Remplace le sender (appelé à la reconnexion WebSocket).
|
|
|
|
|
pub fn set(&self, sender: mpsc::UnboundedSender<ServerMessage>) {
|
|
|
|
|
*self.0.write() = Some(sender);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retire le sender (appelé à la déconnexion).
|
|
|
|
|
pub fn clear(&self) {
|
|
|
|
|
*self.0.write() = None;
|
|
|
|
|
}
|
|
|
|
|
}
|