Sort la partie média renderer de pmoupnp pour en faire une crate independante

This commit is contained in:
2025-10-16 21:43:08 +02:00
parent 5eef699a60
commit 68b0c89130
71 changed files with 199 additions and 91 deletions

11
Cargo.lock generated
View File

@@ -10,6 +10,7 @@ dependencies = [
"pmoapp",
"pmoconfig",
"pmocovers",
"pmomediarenderer",
"pmoserver",
"pmoupnp",
"serde_json",
@@ -2333,6 +2334,16 @@ dependencies = [
"utoipa-swagger-ui",
]
[[package]]
name = "pmomediarenderer"
version = "0.1.0"
dependencies = [
"bevy_reflect",
"once_cell",
"pmodidl",
"pmoupnp",
]
[[package]]
name = "pmoparadise"
version = "0.1.0"

View File

@@ -1,3 +1,3 @@
[workspace]
resolver = "3"
members = ["PMOMusic", "pmoupnp","pmoconfig", "pmoutils", "pmodidl", "pmoserver", "pmoapp", "pmocache", "pmocovers", "pmoaudiocache", "pmoaudio", "pmoqobuz", "pmoparadise"]
members = ["PMOMusic", "pmoupnp", "pmomediarenderer", "pmoconfig", "pmoutils", "pmodidl", "pmoserver", "pmoapp", "pmocache", "pmocovers", "pmoaudiocache", "pmoaudio", "pmoqobuz", "pmoparadise"]

View File

@@ -6,6 +6,7 @@ edition = "2024"
[dependencies]
pmoconfig = { path = "../pmoconfig" }
pmoupnp = { path = "../pmoupnp"}
pmomediarenderer = { path = "../pmomediarenderer" }
pmoserver = { path = "../pmoserver" }
pmocovers = { path = "../pmocovers", features = ["pmoserver"] }
pmoapp = { path = "../pmoapp", features = ["pmoserver"] }

View File

@@ -1,9 +1,9 @@
use pmoupnp::{
mediarenderer::MEDIA_RENDERER,
ssdp::SsdpServer,
upnp_api::UpnpApiExt,
UpnpServer,
};
use pmomediarenderer::MEDIA_RENDERER;
use pmoserver::{
logs::LoggingOptions,
ServerBuilder

View File

@@ -0,0 +1,11 @@
[package]
name = "pmomediarenderer"
version = "0.1.0"
edition = "2024"
[dependencies]
pmoupnp = { path = "../pmoupnp" }
pmodidl = { path = "../pmodidl" }
once_cell = "1.20"
bevy_reflect = "0.17.1"

View File

@@ -0,0 +1,88 @@
# pmomediarenderer
Implémentation d'un MediaRenderer UPnP audio-only conforme à la spécification UPnP AV Architecture.
## Description
Cette crate fournit un MediaRenderer UPnP qui permet de recevoir et lire du contenu audio depuis un serveur UPnP (MediaServer). Elle a été extraite de la crate `pmoupnp` pour permettre une meilleure modularité.
## Architecture
Le MediaRenderer est composé de trois services obligatoires :
- **AVTransport** : Contrôle de la lecture (play, pause, stop, seek, next, previous, etc.)
- **RenderingControl** : Contrôle du volume et du mute
- **ConnectionManager** : Gestion des connexions et des protocoles supportés
## Device UPnP
- Type : `urn:schemas-upnp-org:device:MediaRenderer:1`
- Services : AVTransport:1, RenderingControl:1, ConnectionManager:1
## Utilisation
```rust
use pmomediarenderer::MEDIA_RENDERER;
use pmoupnp::UpnpServer;
// Le device est déjà configuré avec tous ses services
let renderer = MEDIA_RENDERER.clone();
// Créer une instance du renderer
let instance = renderer.create_instance();
// Enregistrer le renderer sur un serveur UPnP
server.register_device(renderer).await?;
```
## Dépendances
- `pmoupnp` : Fournit l'infrastructure UPnP de base (devices, services, actions, state variables)
- `pmodidl` : Pour la gestion des métadonnées DIDL-Lite
- `once_cell` : Pour les initialisations lazy
- `bevy_reflect` : Pour la réflexion et l'introspection
## Services
### AVTransport
Service de contrôle de transport audio conforme UPnP AVTransport:1. Gère la lecture de contenu audio.
**Actions supportées :**
- SetAVTransportURI
- SetNextAVTransportURI
- Play
- Pause
- Stop
- Seek
- Next
- Previous
- GetTransportInfo
- GetPositionInfo
- GetMediaInfo
- GetDeviceCapabilities
- GetTransportSettings
- GetCurrentTransportActions
### RenderingControl
Service de contrôle de rendu conforme UPnP RenderingControl:1. Gère le volume et le mute.
**Actions supportées :**
- GetVolume
- SetVolume
- GetMute
- SetMute
### ConnectionManager
Service de gestion des connexions conforme UPnP ConnectionManager:1. Gère les protocoles supportés.
**Actions supportées :**
- GetProtocolInfo
- GetCurrentConnectionIDs
- GetCurrentConnectionInfo
## Licence
Voir le fichier LICENSE à la racine du projet.

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static GETCURRENTTRANSPORTACTIONS = "GetCurrentTransportActions" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static GETDEVICECAPABILITIES = "GetDeviceCapabilities" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, NUMBEROFTRACKS, CURRENTTRACK, AVTRANSPORTURI, AVTRANSPORTURIMETADATA, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, NUMBEROFTRACKS, CURRENTTRACK, AVTRANSPORTURI, AVTRANSPORTURIMETADATA, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA};
use pmoupnp::define_action;
define_action! {
pub static GETMEDIAINFO = "GetMediaInfo" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, CURRENTTRACK, CURRENTTRACKDURATION, AVTRANSPORTURI, AVTRANSPORTURIMETADATA, RELATIVETIMEPOSITION, ABSOLUTETIMEPOSITION};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, CURRENTTRACK, CURRENTTRACKDURATION, AVTRANSPORTURI, AVTRANSPORTURIMETADATA, RELATIVETIMEPOSITION, ABSOLUTETIMEPOSITION};
use pmoupnp::define_action;
define_action! {
pub static GETPOSITIONINFO = "GetPositionInfo" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, TRANSPORTSTATE, TRANSPORTSTATUS};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, TRANSPORTSTATE, TRANSPORTSTATUS};
use pmoupnp::define_action;
define_action! {
pub static GETTRANSPORTINFO = "GetTransportInfo" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static GETTRANSPORTSETTINGS = "GetTransportSettings" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static NEXT = "Next" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static PAUSE = "Pause" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, TRANSPORTPLAYSPEED};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, TRANSPORTPLAYSPEED};
use pmoupnp::define_action;
define_action! {
pub static PLAY = "Play" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static PREVIOUS = "Previous" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_SEEKMODE, CURRENTTRACKDURATION};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_SEEKMODE, CURRENTTRACKDURATION};
use pmoupnp::define_action;
define_action! {
pub static SEEK = "Seek" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA};
use pmoupnp::define_action;
define_action! {
pub static SETNEXTAVTRANSPORTURI = "SetNextAVTransportURI" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, AVTRANSPORTURI, AVTRANSPORTURIMETADATA};
use crate::define_action;
use crate::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, AVTRANSPORTURI, AVTRANSPORTURIMETADATA};
use pmoupnp::define_action;
define_action! {
pub static SETAVTRANSPORTURI = "SetAVTransportURI" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
use crate::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use pmoupnp::define_action;
define_action! {
pub static STOP = "Stop" {

View File

@@ -89,7 +89,7 @@
//! - [UPnP AVTransport:1 Service Template](https://www.upnp.org/specs/av/UPnP-av-AVTransport-v1-Service.pdf)
//! - [UPnP AV Architecture](https://upnp.org/specs/av/)
use crate::define_service;
use pmoupnp::define_service;
pub mod variables;
pub mod actions;

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_INSTANCE_ID: UI4 = "A_ARG_TYPE_InstanceID"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_PLAY_SPEED: String = "A_ARG_TYPE_PlaySpeed"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_SEEKMODE: String = "A_ARG_TYPE_SeekMode" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static AVTRANSPORTURI: String = "AVTransportURI"

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use crate::state_variables::{StateVariable, StateVariableError};
use crate::variable_types::StateVarType;
use pmoupnp::state_variables::{StateVariable, StateVariableError};
use pmoupnp::variable_types::StateVarType;
use bevy_reflect::Reflect;
use once_cell::sync::Lazy;
use pmodidl::{DIDLLite, MediaMetadataParser};

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTMEDIADURATION: String = "CurrentMediaDuration"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTPLAYMODE: String = "CurrentPlayMode" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTTRACKMETADATA: String = "CurrentTrackMetaData"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTTRACKURI: String = "CurrentTrackURI"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
// Valeurs pour un MediaRenderer audio uniquement (suppression des formats vidéo)
define_variable! {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static POSSIBLEPLAYBACKSTORAGEMEDIA: String = "PossiblePlaybackStorageMedia"

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use crate::state_variables::StateVariable;
use crate::variable_types::StateVarType;
use pmoupnp::state_variables::StateVariable;
use pmoupnp::variable_types::StateVarType;
use once_cell::sync::Lazy;
pub static POSSIBLERECORDSTORAGEMEDIA: Lazy<Arc<StateVariable>> = Lazy::new(|| -> Arc<StateVariable> {

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use crate::state_variables::StateVariable;
use crate::variable_types::StateVarType;
use pmoupnp::state_variables::StateVariable;
use pmoupnp::variable_types::StateVarType;
use once_cell::sync::Lazy;
pub static RECORDSTORAGEMEDIUM: Lazy<Arc<StateVariable>> = Lazy::new(|| -> Arc<StateVariable> {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static SEEKMODE: String = "SeekMode"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTTRACK: String = "CurrentTrack" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTTRACKDURATION: String = "CurrentTrackDuration" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static TRANSPORTPLAYSPEED: String = "TransportPlaySpeed" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
// États pour un MediaRenderer audio uniquement (suppression des états d'enregistrement)
define_variable! {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static TRANSPORTSTATUS: String = "TransportStatus" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::connectionmanager::variables::CURRENTCONNECTIONIDS;
use crate::define_action;
use crate::connectionmanager::variables::CURRENTCONNECTIONIDS;
use pmoupnp::define_action;
define_action! {
pub static GETCURRENTCONNECTIONIDS = "GetCurrentConnectionIDs" {

View File

@@ -1,8 +1,8 @@
use crate::mediarenderer::connectionmanager::variables::{
use crate::connectionmanager::variables::{
A_ARG_TYPE_CONNECTIONID, A_ARG_TYPE_RCSID, A_ARG_TYPE_AVTRANSPORTID,
A_ARG_TYPE_PROTOCOLINFO, A_ARG_TYPE_DIRECTION, A_ARG_TYPE_CONNECTIONSTATUS
};
use crate::define_action;
use pmoupnp::define_action;
define_action! {
pub static GETCURRENTCONNECTIONINFO = "GetCurrentConnectionInfo" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::connectionmanager::variables::{SOURCEPROTOCOLINFO, SINKPROTOCOLINFO};
use crate::define_action;
use crate::connectionmanager::variables::{SOURCEPROTOCOLINFO, SINKPROTOCOLINFO};
use pmoupnp::define_action;
define_action! {
pub static GETPROTOCOLINFO = "GetProtocolInfo" {

View File

@@ -53,7 +53,7 @@
//! - [UPnP ConnectionManager:1 Service Template](https://upnp.org/specs/av/UPnP-av-ConnectionManager-v1-Service.pdf)
//! - [UPnP AV Architecture](https://upnp.org/specs/av/)
use crate::define_service;
use pmoupnp::define_service;
pub mod variables;
pub mod actions;

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_AVTRANSPORTID: I4 = "A_ARG_TYPE_AVTransportID"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_CONNECTIONID: I4 = "A_ARG_TYPE_ConnectionID"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_CONNECTIONSTATUS: String = "A_ARG_TYPE_ConnectionStatus" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_DIRECTION: String = "A_ARG_TYPE_Direction" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_PROTOCOLINFO: String = "A_ARG_TYPE_ProtocolInfo"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_RCSID: I4 = "A_ARG_TYPE_RcsID"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static CURRENTCONNECTIONIDS: String = "CurrentConnectionIDs" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
// Pour un MediaRenderer audio, liste les protocoles/formats audio supportés
define_variable! {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static SOURCEPROTOCOLINFO: String = "SourceProtocolInfo" {

View File

@@ -3,13 +3,11 @@
use once_cell::sync::Lazy;
use std::sync::Arc;
use pmoupnp::devices::Device;
use crate::{
devices::Device,
mediarenderer::{
avtransport::AVTTRANSPORT,
renderingcontrol::RENDERINGCONTROL,
connectionmanager::CONNECTIONMANAGER,
},
avtransport::AVTTRANSPORT,
renderingcontrol::RENDERINGCONTROL,
connectionmanager::CONNECTIONMANAGER,
};
/// Device MediaRenderer UPnP.
@@ -32,7 +30,7 @@ use crate::{
/// # Exemple
///
/// ```ignore
/// use pmoupnp::mediarenderer::MEDIA_RENDERER;
/// use pmomediarenderer::MEDIA_RENDERER;
/// use pmoupnp::UpnpModel;
///
/// // Créer une instance du renderer

View File

@@ -20,7 +20,7 @@
//! # Utilisation
//!
//! ```ignore
//! use pmoupnp::mediarenderer::MEDIA_RENDERER;
//! use pmomediarenderer::MEDIA_RENDERER;
//!
//! // Le device est déjà configuré avec tous ses services
//! let renderer = MEDIA_RENDERER.clone();

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, MUTE};
use crate::define_action;
use crate::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, MUTE};
use pmoupnp::define_action;
define_action! {
pub static GETMUTE = "GetMute" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, VOLUME};
use crate::define_action;
use crate::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, VOLUME};
use pmoupnp::define_action;
define_action! {
pub static GETVOLUME = "GetVolume" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, MUTE};
use crate::define_action;
use crate::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, MUTE};
use pmoupnp::define_action;
define_action! {
pub static SETMUTE = "SetMute" {

View File

@@ -1,5 +1,5 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, VOLUME};
use crate::define_action;
use crate::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, VOLUME};
use pmoupnp::define_action;
define_action! {
pub static SETVOLUME = "SetVolume" {

View File

@@ -49,7 +49,7 @@
//! - [UPnP RenderingControl:1 Service Template](https://upnp.org/specs/av/UPnP-av-RenderingControl-v1-Service.pdf)
//! - [UPnP AV Architecture](https://upnp.org/specs/av/)
use crate::define_service;
use pmoupnp::define_service;
pub mod variables;
pub mod actions;

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_CHANNEL: String = "A_ARG_TYPE_Channel" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_INSTANCE_ID: UI4 = "A_ARG_TYPE_InstanceID"

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static MUTE: Boolean = "Mute" {

View File

@@ -1,4 +1,4 @@
use crate::define_variable;
use pmoupnp::define_variable;
define_variable! {
pub static VOLUME: UI2 = "Volume" {

View File

@@ -5,7 +5,6 @@ pub mod upnp_server;
pub mod upnp_api;
pub mod actions;
pub mod devices;
pub mod mediarenderer;
pub mod services;
pub mod soap;
pub mod ssdp;