//! Playlist interne (non exposée publiquement) pub mod core; pub mod record; use self::core::{PlaylistConfig, PlaylistCore}; use self::record::Record; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::{Arc, Weak}; use std::time::SystemTime; use tokio::sync::RwLock; /// État d'une playlist #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] enum PlaylistState { Active = 0, Deleted = 1, } impl From for PlaylistState { fn from(value: u8) -> Self { match value { 1 => PlaylistState::Deleted, _ => PlaylistState::Active, } } } /// Playlist interne (gérée par le PlaylistManager) pub struct Playlist { pub id: String, title: RwLock, state: Arc, pub core: Arc>, pub persistent: bool, last_change: RwLock, writer_lock: RwLock>>, } impl Playlist { /// Crée une nouvelle playlist pub fn new(id: String, title: String, config: PlaylistConfig, persistent: bool) -> Self { Self { id, title: RwLock::new(title), state: Arc::new(AtomicU8::new(PlaylistState::Active as u8)), core: Arc::new(RwLock::new(PlaylistCore::new(config))), persistent, last_change: RwLock::new(SystemTime::now()), writer_lock: RwLock::new(None), } } /// Vérifie si la playlist est active pub fn is_alive(&self) -> bool { PlaylistState::from(self.state.load(Ordering::SeqCst)) == PlaylistState::Active } /// Marque la playlist comme supprimée pub fn mark_deleted(&self) { self.state.store(PlaylistState::Deleted as u8, Ordering::SeqCst); } /// Met à jour le timestamp de dernière modification pub async fn touch(&self) { *self.last_change.write().await = SystemTime::now(); } /// Récupère le titre pub async fn title(&self) -> String { self.title.read().await.clone() } /// Change le titre pub async fn set_title(&self, title: String) { *self.title.write().await = title; self.touch().await; } /// Timestamp du dernier changement pub async fn last_change(&self) -> SystemTime { *self.last_change.read().await } /// Tente d'acquérir le write lock pub async fn acquire_write_lock(&self) -> Result, ()> { let mut guard = self.writer_lock.write().await; // Vérifier si un writer existe déjà if let Some(weak) = guard.as_ref() { if weak.strong_count() > 0 { return Err(()); // Lock déjà pris } } // Créer un nouveau token let token = Arc::new(()); *guard = Some(Arc::downgrade(&token)); Ok(token) } }