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
42 lines
1.6 KiB
Rust
42 lines
1.6 KiB
Rust
mod avtransport_client;
|
|
mod connection_manager_client;
|
|
mod openhome_client;
|
|
mod rendering_control_client;
|
|
|
|
pub use crate::upnp_clients::avtransport_client::{AvTransportClient, PositionInfo};
|
|
pub use crate::upnp_clients::connection_manager_client::{
|
|
ConnectionInfo, ConnectionManagerClient, ProtocolInfo,
|
|
};
|
|
pub use crate::upnp_clients::openhome_client::{
|
|
OPENHOME_PLAYLIST_HEAD_ID, OhInfoClient, OhPlaylistClient, OhProductClient, OhRadioClient,
|
|
OhTimeClient, OhTrack, OhTrackEntry, OhVolumeClient,
|
|
};
|
|
pub use crate::upnp_clients::rendering_control_client::RenderingControlClient;
|
|
|
|
/// Resolve a possibly relative controlURL against the description URL.
|
|
///
|
|
/// - If `control_url` is already absolute (starts with http:// or https://), it is returned as-is.
|
|
/// - Otherwise, it is resolved against the scheme://host:port of `description_url`.
|
|
pub fn resolve_control_url(description_url: &str, control_url: &str) -> String {
|
|
if control_url.starts_with("http://") || control_url.starts_with("https://") {
|
|
return control_url.to_string();
|
|
}
|
|
|
|
// Extract "scheme://host[:port]" from description_url
|
|
if let Some((scheme, rest)) = description_url.split_once("://") {
|
|
if let Some(pos) = rest.find('/') {
|
|
let authority = &rest[..pos];
|
|
let base = format!("{}://{}", scheme, authority);
|
|
|
|
if control_url.starts_with('/') {
|
|
return format!("{}{}", base, control_url);
|
|
} else {
|
|
return format!("{}/{}", base, control_url);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback: just return the raw control_url if we cannot parse
|
|
control_url.to_string()
|
|
}
|