Ajout de la gestion de la position en temps réel et amélioration de la gestion de la durée

Ajout de l'événement Position pour envoyer la position courante ~1/s pendant la lecture.

Modification de la gestion de la durée dans le registry pour ne pas écraser une durée déjà connue par la source (priorité à la source pour les flux radio).

Mise à jour du handler position_update pour utiliser update_duration au lieu de update_position, et suppression de la gestion de position_sec qui est maintenant gérée par PlayerEvent::Position.

Le serveur gère maintenant la position via les événements Position émis par PlayerSource, et la durée est uniquement utilisée comme fallback pour les sources sans durée connue.
This commit is contained in:
2026-03-01 23:55:40 +01:00
parent f57754b5f8
commit 2b0def806a
4 changed files with 29 additions and 7 deletions

View File

@@ -162,6 +162,9 @@ async fn run_event_listener(
s.playback_state = PlaybackState::Stopped;
s.position = None;
}
PlayerEvent::Position { position_sec } => {
state.write().position = Some(seconds_to_upnp_time(position_sec));
}
PlayerEvent::TrackEnded => {
#[cfg(feature = "pmoserver")]
{

View File

@@ -68,12 +68,14 @@ pub struct PositionUpdateRequest {
}
/// POST /api/webrenderer/{id}/position
/// position_sec est ignoré (géré par PlayerEvent::Position côté serveur).
/// duration_sec est utilisé comme fallback si la source ne connaît pas la durée (flux radio).
pub async fn position_update_handler(
State(registry): State<Arc<RendererRegistry>>,
Path(instance_id): Path<String>,
Json(req): Json<PositionUpdateRequest>,
) -> impl IntoResponse {
registry.update_position(&instance_id, req.position_sec, req.duration_sec);
registry.update_duration(&instance_id, req.duration_sec);
StatusCode::NO_CONTENT
}

View File

@@ -152,15 +152,19 @@ impl RendererRegistry {
.map(|i| i.device_instance.clone())
}
/// Met à jour la position et la durée depuis le navigateur (audio.currentTime).
pub fn update_position(&self, instance_id: &str, position_sec: f64, duration_sec: Option<f64>) {
/// Met à jour la durée depuis le navigateur.
/// La position est gérée par PlayerSource via PlayerEvent::Position.
/// On n'utilise duration_sec que si la source ne la connaît pas (flux radio sans durée).
pub fn update_duration(&self, instance_id: &str, duration_sec: Option<f64>) {
let instances = self.instances.read();
if let Some(instance) = instances.get(instance_id) {
let mut s = instance.state.write();
s.position = Some(crate::pipeline::seconds_to_upnp_time(position_sec));
if let Some(dur) = duration_sec {
if dur > 0.0 {
s.duration = Some(crate::pipeline::seconds_to_upnp_time(dur));
// N'écraser la durée que si elle n'est pas déjà connue (la source est prioritaire)
if s.duration.is_none() {
if let Some(dur) = duration_sec {
if dur > 0.0 {
s.duration = Some(crate::pipeline::seconds_to_upnp_time(dur));
}
}
}
}