feat: Implémentation complète de la source Radio France avec intégration UPnP et serveur HTTP
Ajout de la source Radio France avec : - Implémentation du trait MusicSource pour l'intégration UPnP - Routes HTTP API REST pour l'accès aux stations et flux AAC - Proxy streaming avec tracking des connexions - Génération dynamique de l'arborescence UPnP - Cache multi-niveaux (stations, métadonnées, covers) - Support des ~70 stations (standalone, groupes, radios ICI) Fichiers créés : - pmoradiofrance/src/source.rs (implémentation MusicSource) - pmoradiofrance/src/server_ext.rs (routes HTTP et proxy streaming) - pmoradiofrance/assets/radiofrance-logo.webp (logo placeholder) Fichiers modifiés : - pmoradiofrance/src/lib.rs (re-exports et modules) - pmoradiofrance/Cargo.toml (dépendances server) - Cargo.toml (workspace) - pmomediaserver/Cargo.toml (feature radiofrance) - PMOMusic/Cargo.toml (feature radiofrance) - PMOMusic/src/main.rs (enregistrement automatique) Tests et validation : compilation OK, pattern respecté, feature-gating cohérent
This commit is contained in:
@@ -25,6 +25,7 @@ axum = { version = "0.8", optional = true }
|
||||
utoipa = { version = "5.3", optional = true }
|
||||
pmoqobuz = { path = "../pmoqobuz", optional = true }
|
||||
pmoparadise = { path = "../pmoparadise", optional = true }
|
||||
pmoradiofrance = { path = "../pmoradiofrance", optional = true }
|
||||
pmoconfig = { path = "../pmoconfig", optional = true }
|
||||
anyhow = { version = "1.0", optional = true }
|
||||
pmoaudiocache = { path = "../pmoaudiocache", optional = true }
|
||||
@@ -52,3 +53,10 @@ paradise = [
|
||||
]
|
||||
# Feature pour activer l'API REST de Radio Paradise (en plus de la source UPnP)
|
||||
paradise-api = ["paradise", "pmoparadise/pmoserver"]
|
||||
# Feature pour activer le support Radio France
|
||||
radiofrance = [
|
||||
"api",
|
||||
"dep:pmoradiofrance",
|
||||
"pmoradiofrance/server",
|
||||
"dep:pmoconfig"
|
||||
]
|
||||
|
||||
@@ -93,3 +93,6 @@ pub use paradise_streaming::ParadiseStreamingExt;
|
||||
// Re-export sources when features are enabled
|
||||
#[cfg(feature = "qobuz")]
|
||||
pub use pmoqobuz;
|
||||
|
||||
#[cfg(feature = "radiofrance")]
|
||||
pub use pmoradiofrance;
|
||||
|
||||
@@ -18,6 +18,10 @@ pub enum SourceInitError {
|
||||
#[error("Failed to initialize Radio Paradise: {0}")]
|
||||
ParadiseError(String),
|
||||
|
||||
#[cfg(feature = "radiofrance")]
|
||||
#[error("Failed to initialize Radio France: {0}")]
|
||||
RadioFranceError(String),
|
||||
|
||||
#[error("Configuration error: {0}")]
|
||||
ConfigError(String),
|
||||
|
||||
@@ -117,6 +121,25 @@ pub trait SourcesExt {
|
||||
/// ```
|
||||
#[cfg(feature = "paradise")]
|
||||
async fn register_paradise(&mut self) -> Result<()>;
|
||||
|
||||
/// Enregistre la source Radio France
|
||||
///
|
||||
/// Cette méthode crée automatiquement un `RadioFranceSource` avec cache activé.
|
||||
/// Radio France ne nécessite pas d'authentification.
|
||||
///
|
||||
/// # Erreurs
|
||||
///
|
||||
/// Retourne une erreur si :
|
||||
/// - La connexion au client Radio France échoue
|
||||
/// - La feature "radiofrance" n'est pas activée
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// server.register_radiofrance().await?;
|
||||
/// ```
|
||||
#[cfg(feature = "radiofrance")]
|
||||
async fn register_radiofrance(&mut self) -> Result<()>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -217,6 +240,35 @@ impl SourcesExt for Server {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "radiofrance")]
|
||||
async fn register_radiofrance(&mut self) -> Result<()> {
|
||||
use pmoradiofrance::{RadioFranceSource, RadioFranceStatefulClient};
|
||||
|
||||
tracing::info!("Initializing Radio France source...");
|
||||
|
||||
// Obtenir l'URL de base du serveur
|
||||
let base_url = self.base_url();
|
||||
|
||||
// Créer le client stateful depuis la config
|
||||
let client = RadioFranceStatefulClient::from_config()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
SourceInitError::RadioFranceError(format!("Failed to create client: {}", e))
|
||||
})?;
|
||||
|
||||
// Créer la source depuis le registry (avec cache)
|
||||
let source = RadioFranceSource::from_registry(client, base_url).map_err(|e| {
|
||||
SourceInitError::RadioFranceError(format!("Failed to create source: {}", e))
|
||||
})?;
|
||||
|
||||
// Enregistrer la source
|
||||
self.register_music_source(Arc::new(source)).await;
|
||||
|
||||
tracing::info!("✅ Radio France source registered successfully");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user