From b987decb8dbd815fce9e98f1e8d4324e8e1f5436 Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Wed, 4 Feb 2026 16:20:15 +0100 Subject: [PATCH] =?UTF-8?q?Impl=C3=A9mentation=20d'un=20MediaRenderer=20UP?= =?UTF-8?q?nP=20priv=C3=A9=20par=20navigateur=20avec=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout de la documentation et de l'architecture pour le MediaRenderer UPnP privé par navigateur avec token, ainsi que les améliorations du client et serveur SSDP pour gérer les réseaux bloquant le multicast. --- Blackboard/ToThinkAbout/webrenderer.md | 139 +++++++++++++++++++++++++ pmoupnp/src/ssdp/client.rs | 87 +++++++++++++--- pmoupnp/src/ssdp/server.rs | 136 +++++++++++++++++++++--- 3 files changed, 337 insertions(+), 25 deletions(-) create mode 100644 Blackboard/ToThinkAbout/webrenderer.md diff --git a/Blackboard/ToThinkAbout/webrenderer.md b/Blackboard/ToThinkAbout/webrenderer.md new file mode 100644 index 00000000..b678f635 --- /dev/null +++ b/Blackboard/ToThinkAbout/webrenderer.md @@ -0,0 +1,139 @@ +Parfait. Voici un **schéma fonctionnel minimal** pour un **MediaRenderer UPnP privé par navigateur** avec **token**. L’idée est de rester fidèle à ton backend Rust existant et à la webapp Vue.js. En s'appuyant sur l'architecture de PMOMusic, j'aimerais que tu proposes un plan détaillé pour implémenter un tel système de Média Renderer. + +- L'application web se trouve dans: [@webapp](file:///Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/pmoapp/webapp) +- Tu as un prototype de Média Renderer dans: [@pmomediarenderer](file:///Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/pmomediarenderer) +- Le contrôle point est dans : [@pmocontrol](file:///Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/pmocontrol) +- Tu implémenteras ce nouveau système de Média Renderer dans la CRATe pmowebrenderer + +Tu mettras une version du plan en Markdown dans le répertoire Architecture. + +--- + +## 1. Flow général + +``` +Browser (Vue.js Control Point) + ┌───────────────┐ + │ UI / audio │ + │ WebSocket │ + └───────▲───────┘ + │ token + │ + ▼ +Rust backend (UPnP MediaRenderer) + ┌───────────────────────────┐ + │ Token → Renderer mapping │ + │ Device XML / SOAP endpoints│ + │ Play/Pause/Stop → WS → Browser │ + └───────────────────────────┘ +``` + +--- + +## 2. Étapes détaillées + +### a) Création du renderer + +1. Le navigateur se connecte via WebSocket ou HTTP. +2. Rust génère un token unique pour ce client : + + ```rust + use uuid::Uuid; + let token = Uuid::new_v4().to_string(); + ``` +3. Rust crée une instance MediaRenderer **privée**, associée à ce token : + + * Device description XML : `/renderer//desc.xml` + * AVTransport SOAP : `/renderer//avtransport` + * RenderingControl SOAP : `/renderer//renderingcontrol` + +--- + +### b) Control Point + +* La webapp Vue.js reçoit le token et la “déclare” au Control Point : + +```js +const renderer = { + token: "abcd-1234-efgh", + name: "Browser Renderer" +}; + +// Ajout au control point local +controlPoint.addRenderer(renderer); +``` + +* Toutes les commandes Play/Pause/Stop incluent ce token : + +```js +ws.send(JSON.stringify({ + token: renderer.token, + action: "play", + uri: "http://localhost:8080/media.mp3" +})); +``` + +--- + +### c) Backend Rust : dispatcher les commandes + +* Rust reçoit le JSON avec le token. +* Vérifie que le token correspond à un renderer actif. +* Transmet la commande au navigateur via WebSocket (ou HTTP push) : + +```rust +match msg.action.as_str() { + "play" => send_ws_to_browser(&token, format!("play:{}", msg.uri)), + "pause" => send_ws_to_browser(&token, "pause".to_string()), + "stop" => send_ws_to_browser(&token, "stop".to_string()), + _ => (), +} +``` + +* Rust met à jour l’état du renderer (AVTransport/RenderingControl) pour le Control Point. + +--- + +### d) Lecture côté navigateur + +* Le navigateur reçoit la commande via WebSocket et pilote `