This commit enhances the Radio France source by: 1. Updating the main.rs file to clarify the purpose of registering the Radio France source, including API route initialization 2. Modifying sources.rs to: - Add RadioFranceExt to the imports - Initialize API routes for Radio France after registering the source 3. Updating source.rs to: - Use a default logo for Radio France containers when server_base_url is configured - Apply the default logo to both group and 'Radios ICI' containers These changes improve the integration and visual presentation of Radio France content within the media server.
142 lines
4.9 KiB
Rust
142 lines
4.9 KiB
Rust
use pmoapp::{WebAppExt, Webapp};
|
|
use pmocontrol::ControlPointExt;
|
|
use pmomediarenderer::MEDIA_RENDERER;
|
|
use pmomediaserver::{
|
|
MEDIA_SERVER, MediaServerDeviceExt, ParadiseStreamingExt, sources::SourcesExt,
|
|
};
|
|
use pmoserver::Server;
|
|
use pmosource::MusicSourceExt;
|
|
use pmoupnp::UpnpServerExt;
|
|
use tracing::info;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
// ========== PHASE 1 : Infrastructure UPnP ==========
|
|
// #[cfg(tokio_unstable)]
|
|
// console_subscriber::init();
|
|
|
|
let server = Server::create_upnp_server().await?; // Routes personnalisées de l'application
|
|
server
|
|
.write()
|
|
.await
|
|
.add_route("/info", || async {
|
|
serde_json::json!({"version": "1.0.0"})
|
|
})
|
|
.await;
|
|
|
|
// Initialiser le système de gestion des sources musicales avec API REST
|
|
info!("📡 Initializing music sources management system...");
|
|
server
|
|
.write()
|
|
.await
|
|
.init_music_sources()
|
|
.await
|
|
.expect("Failed to initialize music sources API");
|
|
|
|
// ========== PHASE 2 : Configuration métier ==========
|
|
|
|
// Enregistrer les sources musicales
|
|
info!("🎵 Registering music sources...");
|
|
|
|
// Enregistrer Qobuz pour activer les lazy providers (QOBUZ:PK)
|
|
if let Err(e) = server.write().await.register_qobuz().await {
|
|
tracing::warn!("⚠️ Failed to register Qobuz source: {}", e);
|
|
}
|
|
|
|
// Initialiser les canaux de streaming Radio Paradise (pipelines + routes HTTP)
|
|
info!("📻 Initializing Radio Paradise streaming channels...");
|
|
if let Err(e) = server.write().await.init_paradise_streaming().await {
|
|
tracing::warn!("⚠️ Failed to initialize Paradise streaming: {}", e);
|
|
} else {
|
|
// Enregistrer la source Radio Paradise UPnP (inclut l'initialisation de l'API)
|
|
if let Err(e) = server.write().await.register_paradise().await {
|
|
tracing::warn!("⚠️ Failed to register Radio Paradise source: {}", e);
|
|
}
|
|
}
|
|
|
|
// Enregistrer la source Radio France (inclut l'initialisation des routes API)
|
|
info!("📻 Registering Radio France source...");
|
|
if let Err(e) = server.write().await.register_radiofrance().await {
|
|
tracing::warn!("⚠️ Failed to register Radio France source: {}", e);
|
|
}
|
|
|
|
// Lister toutes les sources enregistrées
|
|
let sources = server.read().await.list_music_sources().await;
|
|
info!("✅ {} music source(s) registered", sources.len());
|
|
for source in sources {
|
|
info!(" - {} ({})", source.name(), source.id());
|
|
}
|
|
|
|
// Enregistrer les devices UPnP (HTTP + SSDP automatique)
|
|
info!("📡 Registering UPnP devices...");
|
|
|
|
let renderer_instance = server
|
|
.write()
|
|
.await
|
|
.register_device(MEDIA_RENDERER.clone())
|
|
.await
|
|
.expect("Failed to register MediaRenderer");
|
|
|
|
let base_url = renderer_instance.base_url();
|
|
let desc_route = renderer_instance.description_route();
|
|
info!("✅ MediaRenderer ready at {}{}", base_url, desc_route);
|
|
|
|
let server_instance = server
|
|
.write()
|
|
.await
|
|
.register_device(MEDIA_SERVER.clone())
|
|
.await
|
|
.expect("Failed to register MediaServer");
|
|
|
|
// Enregistrer l'instance ContentDirectory pour les notifications GENA
|
|
if let Some(cd_service) = server_instance.get_service("ContentDirectory") {
|
|
pmomediaserver::contentdirectory::state::register_instance(&cd_service);
|
|
}
|
|
|
|
// Initialiser les ProtocolInfo du MediaServer
|
|
server_instance.init_protocol_info();
|
|
|
|
info!(
|
|
"✅ MediaServer ready at {}{}",
|
|
server_instance.base_url(),
|
|
server_instance.description_route()
|
|
);
|
|
|
|
// Enregistrer le Control Point (découverte renderers/serveurs + API REST + SSE)
|
|
info!("🎛️ Registering Control Point...");
|
|
let _control_point = server
|
|
.write()
|
|
.await
|
|
.register_control_point(5)
|
|
.await
|
|
.expect("Failed to register Control Point");
|
|
|
|
// Ajouter la webapp via le trait WebAppExt
|
|
info!("📡 Registering Web application...");
|
|
server
|
|
.write()
|
|
.await
|
|
.add_webapp_with_redirect::<Webapp>("/app")
|
|
.await;
|
|
|
|
// ========== PHASE 3 : Démarrage du serveur ==========
|
|
|
|
info!("🌐 Starting HTTP server...");
|
|
server.write().await.start().await;
|
|
|
|
info!("✅ PMOMusic is ready!");
|
|
info!("Press Ctrl+C to stop...");
|
|
|
|
// Attendre le signal Ctrl+C et l'arrêt du serveur HTTP
|
|
server.write().await.wait().await;
|
|
|
|
// Le serveur HTTP est arrêté, mais des threads (ControlPoint, etc.) peuvent encore tourner
|
|
// Attendre 2 secondes pour laisser le temps aux threads de se terminer
|
|
info!("Waiting for background threads to finish...");
|
|
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
|
|
|
// Forcer l'arrêt du processus (les threads du ControlPoint tournent en boucle infinie)
|
|
info!("✅ PMOMusic stopped");
|
|
std::process::exit(0);
|
|
}
|