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

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;

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static GETCURRENTTRANSPORTACTIONS = "GetCurrentTransportActions" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static GETDEVICECAPABILITIES = "GetDeviceCapabilities" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,14 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, NUMBEROFTRACKS, CURRENTTRACK, AVTRANSPORTURI, AVTRANSPORTURIMETADATA, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA};
use crate::define_action;
define_action! {
pub static GETMEDIAINFO = "GetMediaInfo" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
out "NrTracks" => NUMBEROFTRACKS,
out "CurrentTrack" => CURRENTTRACK,
out "CurrentURI" => AVTRANSPORTURI,
out "CurrentURIMetaData" => AVTRANSPORTURIMETADATA,
out "NextURI" => AVTRANSPORTNEXTURI,
out "NextURIMetaData" => AVTRANSPORTNEXTURIMETADATA,
}
}

View File

@@ -1,14 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, CURRENTTRACK, CURRENTTRACKDURATION, AVTRANSPORTURI, AVTRANSPORTURIMETADATA, RELATIVETIMEPOSITION, ABSOLUTETIMEPOSITION};
use crate::define_action;
define_action! {
pub static GETPOSITIONINFO = "GetPositionInfo" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
out "Track" => CURRENTTRACK,
out "TrackDuration" => CURRENTTRACKDURATION,
out "TrackURI" => AVTRANSPORTURI,
out "TrackMetaData" => AVTRANSPORTURIMETADATA,
out "RelTime" => RELATIVETIMEPOSITION,
out "AbsTime" => ABSOLUTETIMEPOSITION,
}
}

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, TRANSPORTSTATE, TRANSPORTSTATUS};
use crate::define_action;
define_action! {
pub static GETTRANSPORTINFO = "GetTransportInfo" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
out "CurrentTransportState" => TRANSPORTSTATE,
out "CurrentTransportStatus" => TRANSPORTSTATUS,
}
}

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static GETTRANSPORTSETTINGS = "GetTransportSettings" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,30 +0,0 @@
mod getcurrenttransportactions;
mod getdevicecapabilities;
mod getmediainfo;
mod getpositioninfo;
mod gettransportinfo;
mod gettransportsettings;
mod next;
mod pause;
mod play;
mod previous;
mod seek;
mod setavtransportnexturi;
mod setavtransporturi;
mod stop;
pub use getcurrenttransportactions::GETCURRENTTRANSPORTACTIONS;
pub use getdevicecapabilities::GETDEVICECAPABILITIES;
pub use getmediainfo::GETMEDIAINFO;
pub use getpositioninfo::GETPOSITIONINFO;
pub use gettransportinfo::GETTRANSPORTINFO;
pub use gettransportsettings::GETTRANSPORTSETTINGS;
pub use next::NEXT;
pub use pause::PAUSE;
pub use play::PLAY;
pub use previous::PREVIOUS;
pub use seek::SEEK;
pub use setavtransportnexturi::SETNEXTAVTRANSPORTURI;
pub use setavtransporturi::SETAVTRANSPORTURI;
pub use stop::STOP;

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static NEXT = "Next" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static PAUSE = "Pause" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,9 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, TRANSPORTPLAYSPEED};
use crate::define_action;
define_action! {
pub static PLAY = "Play" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "Speed" => TRANSPORTPLAYSPEED,
}
}

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static PREVIOUS = "Previous" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_SEEKMODE, CURRENTTRACKDURATION};
use crate::define_action;
define_action! {
pub static SEEK = "Seek" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "Unit" => A_ARG_TYPE_SEEKMODE,
in "Target" => CURRENTTRACKDURATION,
}
}

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA};
use crate::define_action;
define_action! {
pub static SETNEXTAVTRANSPORTURI = "SetNextAVTransportURI" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "NextURI" => AVTRANSPORTNEXTURI,
in "NextURIMetaData" => AVTRANSPORTNEXTURIMETADATA,
}
}

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::avtransport::variables::{A_ARG_TYPE_INSTANCE_ID, AVTRANSPORTURI, AVTRANSPORTURIMETADATA};
use crate::define_action;
define_action! {
pub static SETAVTRANSPORTURI = "SetAVTransportURI" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "CurrentURI" => AVTRANSPORTURI,
in "CurrentURIMetaData" => AVTRANSPORTURIMETADATA,
}
}

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::avtransport::variables::A_ARG_TYPE_INSTANCE_ID;
use crate::define_action;
define_action! {
pub static STOP = "Stop" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
}
}

View File

@@ -1,157 +0,0 @@
//! # AVTransport Service - Service de contrôle de transport UPnP
//!
//! Ce module implémente le service AVTransport:1 selon la spécification UPnP AV.
//! Le service AVTransport permet de contrôler la lecture de médias **audio**
//! sur des rendus multimédias (MediaRenderer Audio).
//!
//! ## Fonctionnalités
//!
//! Le service AVTransport permet :
//! - **Contrôle de lecture** : Play, Pause, Stop
//! - **Navigation** : Next, Previous, Seek
//! - **Gestion des URIs** : SetAVTransportURI, SetNextAVTransportURI
//! - **Information d'état** : GetTransportInfo, GetPositionInfo, GetMediaInfo
//! - **Capacités** : GetDeviceCapabilities, GetCurrentTransportActions
//!
//! ## Conformité UPnP
//!
//! Cette implémentation suit la spécification **UPnP AVTransport:1 Service Template**.
//! Toutes les actions obligatoires (Required) sont implémentées :
//!
//! - ✅ SetAVTransportURI
//! - ✅ GetMediaInfo
//! - ✅ GetTransportInfo
//! - ✅ GetPositionInfo
//! - ✅ GetDeviceCapabilities
//! - ✅ GetTransportSettings
//! - ✅ GetCurrentTransportActions
//! - ✅ Stop, Play, Pause
//!
//! Et certaines actions optionnelles :
//! - ✅ SetNextAVTransportURI
//! - ✅ Seek, Next, Previous
//!
//! ## Variables d'état
//!
//! Le service expose 24 variables d'état conformes à la spécification :
//!
//! ### État du transport
//! - [`TRANSPORTSTATE`] : État actuel (PLAYING, STOPPED, PAUSED_PLAYBACK, etc.)
//! - [`TRANSPORTSTATUS`] : Status du transport (OK, ERROR_OCCURRED)
//! - [`TRANSPORTPLAYSPEED`] : Vitesse de lecture
//!
//! ### Information sur les pistes
//! - [`CURRENTTRACK`] : Numéro de la piste actuelle
//! - [`NUMBEROFTRACKS`] : Nombre total de pistes
//! - [`CURRENTTRACKDURATION`] : Durée de la piste actuelle
//! - [`CURRENTTRACKURI`] : URI de la piste actuelle
//! - [`CURRENTTRACKMETADATA`] : Métadonnées de la piste
//!
//! ### Positionnement
//! - [`RELATIVETIMEPOSITION`] : Position relative dans la piste
//! - [`ABSOLUTETIMEPOSITION`] : Position absolue
//!
//! ### URIs et métadonnées
//! - [`AVTRANSPORTURI`] : URI de la ressource en cours
//! - [`AVTRANSPORTURIMETADATA`] : Métadonnées associées
//! - [`AVTRANSPORTNEXTURI`] : URI de la ressource suivante
//! - [`AVTRANSPORTNEXTURIMETADATA`] : Métadonnées de la ressource suivante
//!
//! ### Modes et capacités
//! - [`CURRENTPLAYMODE`] : Mode de lecture (NORMAL, SHUFFLE, REPEAT_ONE, etc.)
//! - [`PLAYBACKSTORAGEMEDIUM`] : Support de lecture (NETWORK, HDD, CD-DA, etc.)
//! - [`POSSIBLEPLAYBACKSTORAGEMEDIA`] : Supports de lecture possibles
//!
//! ## Examples
//!
//! ```rust
//! use pmoupnp::mediarenderer::avtransport::AVTTRANSPORT;
//! use pmoupnp::UpnpTyped;
//!
//! // Accéder au service
//! let service = &*AVTTRANSPORT;
//! println!("Service: {}", service.name());
//! println!("Type: {}", service.service_type());
//!
//! // Lister les actions disponibles
//! for action in service.actions() {
//! println!(" Action: {}", action.get_name());
//! }
//!
//! // Lister les variables d'état
//! for variable in service.variables() {
//! println!(" Variable: {}", variable.get_name());
//! }
//! ```
//!
//! ## Références
//!
//! - [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;
pub mod variables;
pub mod actions;
use actions::{
GETCURRENTTRANSPORTACTIONS, GETDEVICECAPABILITIES, GETMEDIAINFO,
GETPOSITIONINFO, GETTRANSPORTINFO, GETTRANSPORTSETTINGS, NEXT, PAUSE,
PLAY, PREVIOUS, SEEK, SETNEXTAVTRANSPORTURI, SETAVTRANSPORTURI, STOP
};
use variables::{
ABSOLUTETIMEPOSITION, AVTRANSPORTNEXTURI, AVTRANSPORTNEXTURIMETADATA,
AVTRANSPORTURI, AVTRANSPORTURIMETADATA, A_ARG_TYPE_INSTANCE_ID,
A_ARG_TYPE_PLAY_SPEED, A_ARG_TYPE_SEEKMODE, CURRENTMEDIADURATION,
CURRENTPLAYMODE, CURRENTTRACK, CURRENTTRACKDURATION, CURRENTTRACKMETADATA,
CURRENTTRACKURI, NUMBEROFTRACKS, PLAYBACKSTORAGEMEDIUM,
POSSIBLEPLAYBACKSTORAGEMEDIA, RELATIVETIMEPOSITION, SEEKMODE,
TRANSPORTPLAYSPEED, TRANSPORTSTATE, TRANSPORTSTATUS
};
// Service AVTransport:1 conforme à la spécification UPnP AV pour MediaRenderer audio
// Voir la documentation du module pour plus de détails
define_service! {
pub static AVTTRANSPORT = "AVTransport" {
variables: [
ABSOLUTETIMEPOSITION,
A_ARG_TYPE_INSTANCE_ID,
A_ARG_TYPE_PLAY_SPEED,
A_ARG_TYPE_SEEKMODE,
AVTRANSPORTNEXTURI,
AVTRANSPORTNEXTURIMETADATA,
AVTRANSPORTURI,
AVTRANSPORTURIMETADATA,
CURRENTMEDIADURATION,
CURRENTPLAYMODE,
CURRENTTRACK,
CURRENTTRACKDURATION,
CURRENTTRACKMETADATA,
CURRENTTRACKURI,
NUMBEROFTRACKS,
PLAYBACKSTORAGEMEDIUM,
POSSIBLEPLAYBACKSTORAGEMEDIA,
RELATIVETIMEPOSITION,
SEEKMODE,
TRANSPORTPLAYSPEED,
TRANSPORTSTATE,
TRANSPORTSTATUS,
],
actions: [
GETCURRENTTRANSPORTACTIONS,
GETDEVICECAPABILITIES,
GETMEDIAINFO,
GETPOSITIONINFO,
GETTRANSPORTINFO,
GETTRANSPORTSETTINGS,
NEXT,
PAUSE,
PLAY,
PREVIOUS,
SEEK,
SETNEXTAVTRANSPORTURI,
SETAVTRANSPORTURI,
STOP,
]
}
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_INSTANCE_ID: UI4 = "A_ARG_TYPE_InstanceID"
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_PLAY_SPEED: String = "A_ARG_TYPE_PlaySpeed"
}

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_SEEKMODE: String = "A_ARG_TYPE_SeekMode" {
allowed: ["TRACK_NR", "REL_TIME", "ABS_TIME"],
}
}

View File

@@ -1,9 +0,0 @@
use crate::define_variable;
define_variable! {
pub static AVTRANSPORTURI: String = "AVTransportURI"
}
define_variable! {
pub static AVTRANSPORTNEXTURI: String = "AVTransportNextURI"
}

View File

@@ -1,31 +0,0 @@
use std::sync::Arc;
use crate::state_variables::{StateVariable, StateVariableError};
use crate::variable_types::StateVarType;
use bevy_reflect::Reflect;
use once_cell::sync::Lazy;
use pmodidl::{DIDLLite, MediaMetadataParser};
fn avtransporturimetadataparser(value: &str) -> Result<Box<dyn Reflect>, StateVariableError> {
// Parse DIDL-Lite
let didl = DIDLLite::parse(value)
.map_err(|e| StateVariableError::ParseError(format!("Failed to parse DIDL-Lite: {}", e)))?;
// Retourne le résultat sous forme de Box<dyn Reflect>
Ok(Box::new(didl) as Box<dyn Reflect>)
}
pub static AVTRANSPORTURIMETADATA: Lazy<Arc<StateVariable>> = Lazy::new(|| -> Arc<StateVariable> {
let mut sv = StateVariable::new(StateVarType::String, "AVTransportURIMetaData".to_string());
sv.set_value_parser(Arc::new(avtransporturimetadataparser)).expect("Failed to set parser");
Arc::new(sv)
});
pub static AVTRANSPORTNEXTURIMETADATA: Lazy<Arc<StateVariable>> = Lazy::new(|| -> Arc<StateVariable> {
let mut sv = StateVariable::new(StateVarType::String, "AVTransportNextURIMetaData".to_string());
sv.set_value_parser(Arc::new(avtransporturimetadataparser)).expect("Failed to set parser");
Arc::new(sv)
});

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTMEDIADURATION: String = "CurrentMediaDuration"
}

View File

@@ -1,8 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTPLAYMODE: String = "CurrentPlayMode" {
allowed: ["NORMAL", "SHUFFLE", "REPEAT_ONE", "REPEAT_ALL", "RANDOM", "DIRECT_1", "INTRO"],
default: "NORMAL",
}
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTTRACKMETADATA: String = "CurrentTrackMetaData"
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTTRACKURI: String = "CurrentTrackURI"
}

View File

@@ -1,47 +0,0 @@
mod a_arg_type_instanceid;
mod a_arg_type_playspeed;
mod a_arg_type_seekmode;
mod avtransporturi;
mod avtransporturimetadata;
mod currentmediaduration;
mod currentplaymode;
mod currenttrackmetadata;
mod currenttrackuri;
mod playbackstoragemedium;
mod possibleplaybackstoragemedia;
mod possiblerecordstoragemedia;
mod recordstoragemedium;
mod seekmode;
mod track;
mod trackduration;
mod transportplayspeed;
mod transportstate;
mod transportstatus;
pub use a_arg_type_instanceid::A_ARG_TYPE_INSTANCE_ID;
pub use a_arg_type_playspeed::A_ARG_TYPE_PLAY_SPEED;
pub use a_arg_type_seekmode::A_ARG_TYPE_SEEKMODE;
pub use avtransporturi::AVTRANSPORTURI;
pub use avtransporturi::AVTRANSPORTNEXTURI;
pub use avtransporturimetadata::AVTRANSPORTURIMETADATA;
pub use avtransporturimetadata::AVTRANSPORTNEXTURIMETADATA;
pub use currentmediaduration::CURRENTMEDIADURATION;
pub use currentplaymode::CURRENTPLAYMODE;
pub use currenttrackmetadata::CURRENTTRACKMETADATA;
pub use currenttrackuri::CURRENTTRACKURI;
pub use playbackstoragemedium::PLAYBACKSTORAGEMEDIUM;
pub use possibleplaybackstoragemedia::POSSIBLEPLAYBACKSTORAGEMEDIA;
pub use possiblerecordstoragemedia::POSSIBLERECORDSTORAGEMEDIA;
pub use recordstoragemedium::RECORDSTORAGEMEDIUM;
pub use seekmode::SEEKMODE;
pub use track::CURRENTTRACK;
pub use track::NUMBEROFTRACKS;
pub use trackduration::ABSOLUTETIMEPOSITION;
pub use trackduration::CURRENTTRACKDURATION;
pub use trackduration::RELATIVETIMEPOSITION;
pub use transportplayspeed::TRANSPORTPLAYSPEED;
pub use transportstate::TRANSPORTSTATE;
pub use transportstatus::TRANSPORTSTATUS;

View File

@@ -1,12 +0,0 @@
use crate::define_variable;
// Valeurs pour un MediaRenderer audio uniquement (suppression des formats vidéo)
define_variable! {
pub static PLAYBACKSTORAGEMEDIUM: String = "PlaybackStorageMedium" {
allowed: [
"UNKNOWN", "CD-ROM", "CD-DA", "CD-R", "CD-RW", "SACD",
"MD-AUDIO", "DVD-AUDIO", "DAT", "HDD", "NETWORK",
"NONE", "NOT_IMPLEMENTED"
],
}
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static POSSIBLEPLAYBACKSTORAGEMEDIA: String = "PossiblePlaybackStorageMedia"
}

View File

@@ -1,10 +0,0 @@
use std::sync::Arc;
use crate::state_variables::StateVariable;
use crate::variable_types::StateVarType;
use once_cell::sync::Lazy;
pub static POSSIBLERECORDSTORAGEMEDIA: Lazy<Arc<StateVariable>> = Lazy::new(|| -> Arc<StateVariable> {
let sv = StateVariable::new(StateVarType::String, "PossibleRecordStorageMedia".to_string());
Arc::new(sv)
});

View File

@@ -1,10 +0,0 @@
use std::sync::Arc;
use crate::state_variables::StateVariable;
use crate::variable_types::StateVarType;
use once_cell::sync::Lazy;
pub static RECORDSTORAGEMEDIUM: Lazy<Arc<StateVariable>> = Lazy::new(|| -> Arc<StateVariable> {
let sv = StateVariable::new(StateVarType::String, "RecordStorageMedium".to_string());
Arc::new(sv)
});

View File

@@ -1,6 +0,0 @@
use crate::define_variable;
define_variable! {
pub static SEEKMODE: String = "SeekMode"
}

View File

@@ -1,14 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTTRACK: String = "CurrentTrack" {
evented: true,
}
}
define_variable! {
pub static NUMBEROFTRACKS: String = "NumberOfTracks" {
evented: true,
}
}

View File

@@ -1,20 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTTRACKDURATION: String = "CurrentTrackDuration" {
evented: true,
}
}
define_variable! {
pub static ABSOLUTETIMEPOSITION: String = "AbsoluteTimePosition" {
evented: true,
}
}
define_variable! {
pub static RELATIVETIMEPOSITION: String = "RelativeTimePosition" {
evented: true,
}
}

View File

@@ -1,9 +0,0 @@
use crate::define_variable;
define_variable! {
pub static TRANSPORTPLAYSPEED: String = "TransportPlaySpeed" {
allowed: ["1"],
default: "1",
}
}

View File

@@ -1,10 +0,0 @@
use crate::define_variable;
// États pour un MediaRenderer audio uniquement (suppression des états d'enregistrement)
define_variable! {
pub static TRANSPORTSTATE: String = "TransportState" {
allowed: ["STOPPED", "PLAYING", "TRANSITIONING", "PAUSED_PLAYBACK", "NO_MEDIA_PRESENT"],
evented: true,
}
}

View File

@@ -1,8 +0,0 @@
use crate::define_variable;
define_variable! {
pub static TRANSPORTSTATUS: String = "TransportStatus" {
allowed: ["OK", "ERROR_OCCURRED"],
evented: true,
}
}

View File

@@ -1,8 +0,0 @@
use crate::mediarenderer::connectionmanager::variables::CURRENTCONNECTIONIDS;
use crate::define_action;
define_action! {
pub static GETCURRENTCONNECTIONIDS = "GetCurrentConnectionIDs" {
out "ConnectionIDs" => CURRENTCONNECTIONIDS,
}
}

View File

@@ -1,18 +0,0 @@
use crate::mediarenderer::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;
define_action! {
pub static GETCURRENTCONNECTIONINFO = "GetCurrentConnectionInfo" {
in "ConnectionID" => A_ARG_TYPE_CONNECTIONID,
out "RcsID" => A_ARG_TYPE_RCSID,
out "AVTransportID" => A_ARG_TYPE_AVTRANSPORTID,
out "ProtocolInfo" => A_ARG_TYPE_PROTOCOLINFO,
out "PeerConnectionManager" => A_ARG_TYPE_PROTOCOLINFO,
out "PeerConnectionID" => A_ARG_TYPE_CONNECTIONID,
out "Direction" => A_ARG_TYPE_DIRECTION,
out "Status" => A_ARG_TYPE_CONNECTIONSTATUS,
}
}

View File

@@ -1,9 +0,0 @@
use crate::mediarenderer::connectionmanager::variables::{SOURCEPROTOCOLINFO, SINKPROTOCOLINFO};
use crate::define_action;
define_action! {
pub static GETPROTOCOLINFO = "GetProtocolInfo" {
out "Source" => SOURCEPROTOCOLINFO,
out "Sink" => SINKPROTOCOLINFO,
}
}

View File

@@ -1,7 +0,0 @@
mod getprotocolinfo;
mod getcurrentconnectionids;
mod getcurrentconnectioninfo;
pub use getprotocolinfo::GETPROTOCOLINFO;
pub use getcurrentconnectionids::GETCURRENTCONNECTIONIDS;
pub use getcurrentconnectioninfo::GETCURRENTCONNECTIONINFO;

View File

@@ -1,89 +0,0 @@
//! # ConnectionManager Service - Service de gestion des connexions UPnP
//!
//! Ce module implémente le service ConnectionManager:1 selon la spécification UPnP AV.
//! Le service ConnectionManager gère les connexions entre MediaServer et MediaRenderer,
//! et expose les protocoles et formats supportés.
//!
//! ## Fonctionnalités
//!
//! Le service ConnectionManager permet :
//! - **Énumération des protocoles** : GetProtocolInfo
//! - **Gestion des connexions** : GetCurrentConnectionIDs, GetCurrentConnectionInfo
//! - Support des formats audio (MP3, FLAC, WAV, etc.)
//!
//! ## Conformité UPnP
//!
//! Cette implémentation suit la spécification **UPnP ConnectionManager:1 Service Template**.
//! Toutes les actions obligatoires (Required) sont implémentées :
//!
//! - ✅ GetProtocolInfo
//! - ✅ GetCurrentConnectionIDs
//! - ✅ GetCurrentConnectionInfo
//!
//! ## Variables d'état
//!
//! Le service expose les variables d'état conformes à la spécification :
//!
//! ### Informations de protocole
//! - [`SOURCEPROTOCOLINFO`] : Protocoles source (vide pour un renderer)
//! - [`SINKPROTOCOLINFO`] : Protocoles sink supportés (http-get:*:audio/mpeg:*, etc.)
//! - [`CURRENTCONNECTIONIDS`] : IDs des connexions actives
//!
//! ### Arguments
//! - [`A_ARG_TYPE_CONNECTIONID`] : ID de connexion
//! - [`A_ARG_TYPE_CONNECTIONSTATUS`] : Statut de connexion
//! - [`A_ARG_TYPE_DIRECTION`] : Direction (Input/Output)
//! - [`A_ARG_TYPE_PROTOCOLINFO`] : Information de protocole
//! - [`A_ARG_TYPE_RCSID`] : ID RenderingControl
//! - [`A_ARG_TYPE_AVTRANSPORTID`] : ID AVTransport
//!
//! ## Examples
//!
//! ```rust
//! use pmoupnp::mediarenderer::connectionmanager::CONNECTIONMANAGER;
//!
//! // Accéder au service
//! let service = &*CONNECTIONMANAGER;
//! println!("Service: {}", service.name());
//! println!("Type: {}", service.service_type());
//! ```
//!
//! ## Références
//!
//! - [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;
pub mod variables;
pub mod actions;
use actions::{GETCURRENTCONNECTIONIDS, GETCURRENTCONNECTIONINFO, GETPROTOCOLINFO};
use variables::{
A_ARG_TYPE_AVTRANSPORTID, A_ARG_TYPE_CONNECTIONID, A_ARG_TYPE_CONNECTIONSTATUS,
A_ARG_TYPE_DIRECTION, A_ARG_TYPE_PROTOCOLINFO, A_ARG_TYPE_RCSID,
CURRENTCONNECTIONIDS, SINKPROTOCOLINFO, SOURCEPROTOCOLINFO
};
// Service ConnectionManager:1 conforme à la spécification UPnP AV pour MediaRenderer audio
// Voir la documentation du module pour plus de détails
define_service! {
pub static CONNECTIONMANAGER = "ConnectionManager" {
variables: [
A_ARG_TYPE_AVTRANSPORTID,
A_ARG_TYPE_CONNECTIONID,
A_ARG_TYPE_CONNECTIONSTATUS,
A_ARG_TYPE_DIRECTION,
A_ARG_TYPE_PROTOCOLINFO,
A_ARG_TYPE_RCSID,
CURRENTCONNECTIONIDS,
SINKPROTOCOLINFO,
SOURCEPROTOCOLINFO,
],
actions: [
GETCURRENTCONNECTIONIDS,
GETCURRENTCONNECTIONINFO,
GETPROTOCOLINFO,
]
}
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_AVTRANSPORTID: I4 = "A_ARG_TYPE_AVTransportID"
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_CONNECTIONID: I4 = "A_ARG_TYPE_ConnectionID"
}

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_CONNECTIONSTATUS: String = "A_ARG_TYPE_ConnectionStatus" {
allowed: ["OK", "ContentFormatMismatch", "InsufficientBandwidth", "UnreliableChannel", "Unknown"],
}
}

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_DIRECTION: String = "A_ARG_TYPE_Direction" {
allowed: ["Input", "Output"],
}
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_PROTOCOLINFO: String = "A_ARG_TYPE_ProtocolInfo"
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_RCSID: I4 = "A_ARG_TYPE_RcsID"
}

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static CURRENTCONNECTIONIDS: String = "CurrentConnectionIDs" {
evented: true,
}
}

View File

@@ -1,19 +0,0 @@
mod sourceprotocolinfo;
mod sinkprotocolinfo;
mod currentconnectionids;
mod a_arg_type_connectionid;
mod a_arg_type_connectionstatus;
mod a_arg_type_direction;
mod a_arg_type_protocolinfo;
mod a_arg_type_rcsid;
mod a_arg_type_avtransportid;
pub use sourceprotocolinfo::SOURCEPROTOCOLINFO;
pub use sinkprotocolinfo::SINKPROTOCOLINFO;
pub use currentconnectionids::CURRENTCONNECTIONIDS;
pub use a_arg_type_connectionid::A_ARG_TYPE_CONNECTIONID;
pub use a_arg_type_connectionstatus::A_ARG_TYPE_CONNECTIONSTATUS;
pub use a_arg_type_direction::A_ARG_TYPE_DIRECTION;
pub use a_arg_type_protocolinfo::A_ARG_TYPE_PROTOCOLINFO;
pub use a_arg_type_rcsid::A_ARG_TYPE_RCSID;
pub use a_arg_type_avtransportid::A_ARG_TYPE_AVTRANSPORTID;

View File

@@ -1,8 +0,0 @@
use crate::define_variable;
// Pour un MediaRenderer audio, liste les protocoles/formats audio supportés
define_variable! {
pub static SINKPROTOCOLINFO: String = "SinkProtocolInfo" {
evented: true,
}
}

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static SOURCEPROTOCOLINFO: String = "SourceProtocolInfo" {
evented: true,
}
}

View File

@@ -1,69 +0,0 @@
//! Définition du device MediaRenderer.
use once_cell::sync::Lazy;
use std::sync::Arc;
use crate::{
devices::Device,
mediarenderer::{
avtransport::AVTTRANSPORT,
renderingcontrol::RENDERINGCONTROL,
connectionmanager::CONNECTIONMANAGER,
},
};
/// Device MediaRenderer UPnP.
///
/// MediaRenderer audio-only conforme UPnP AV Architecture 1.0.
///
/// # Services inclus
///
/// - **AVTransport:1** : Contrôle de la lecture
/// - **RenderingControl:1** : Contrôle du volume et du mute
/// - **ConnectionManager:1** : Gestion des connexions
///
/// # Spécifications
///
/// - Device Type : `urn:schemas-upnp-org:device:MediaRenderer:1`
/// - Version : 1
/// - Manufacturer : PMOMusic
/// - Model : PMOMusic Audio Renderer
///
/// # Exemple
///
/// ```ignore
/// use pmoupnp::mediarenderer::MEDIA_RENDERER;
/// use pmoupnp::UpnpModel;
///
/// // Créer une instance du renderer
/// let renderer_instance = MEDIA_RENDERER.create_instance();
///
/// // Accéder aux services
/// if let Some(avtransport) = renderer_instance.get_service("AVTransport") {
/// // Contrôler la lecture...
/// }
/// ```
pub static MEDIA_RENDERER: Lazy<Arc<Device>> = Lazy::new(|| {
let mut device = Device::new(
"MediaRenderer".to_string(),
"MediaRenderer".to_string(),
"PMOMusic Audio Renderer".to_string(),
);
device.set_manufacturer("PMOMusic".to_string());
device.set_model_name("PMOMusic Audio Renderer".to_string());
device.set_model_description("UPnP AV MediaRenderer for audio streaming".to_string());
device.set_udn_prefix("pmomusic".to_string());
// Ajouter les trois services obligatoires
device.add_service(Arc::clone(&AVTTRANSPORT))
.expect("Failed to add AVTransport service");
device.add_service(Arc::clone(&RENDERINGCONTROL))
.expect("Failed to add RenderingControl service");
device.add_service(Arc::clone(&CONNECTIONMANAGER))
.expect("Failed to add ConnectionManager service");
Arc::new(device)
});

View File

@@ -1,35 +0,0 @@
//! Module MediaRenderer UPnP.
//!
//! Ce module implémente un MediaRenderer UPnP audio-only conforme à la spécification
//! UPnP AV Architecture. Un MediaRenderer permet de recevoir et lire du contenu audio
//! depuis un serveur UPnP (MediaServer).
//!
//! # Architecture
//!
//! Le MediaRenderer est composé de trois services obligatoires :
//!
//! - **AVTransport** : Contrôle de la lecture (play, pause, stop, seek, 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
//!
//! ```ignore
//! use pmoupnp::mediarenderer::MEDIA_RENDERER;
//!
//! // Le device est déjà configuré avec tous ses services
//! let renderer = MEDIA_RENDERER.clone();
//! let instance = renderer.create_instance();
//! ```
pub mod avtransport;
pub mod connectionmanager;
pub mod renderingcontrol;
pub mod device;
pub use device::MEDIA_RENDERER;

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, MUTE};
use crate::define_action;
define_action! {
pub static GETMUTE = "GetMute" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "Channel" => A_ARG_TYPE_CHANNEL,
out "CurrentMute" => MUTE,
}
}

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, VOLUME};
use crate::define_action;
define_action! {
pub static GETVOLUME = "GetVolume" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "Channel" => A_ARG_TYPE_CHANNEL,
out "CurrentVolume" => VOLUME,
}
}

View File

@@ -1,9 +0,0 @@
mod getvolume;
mod setvolume;
mod getmute;
mod setmute;
pub use getvolume::GETVOLUME;
pub use setvolume::SETVOLUME;
pub use getmute::GETMUTE;
pub use setmute::SETMUTE;

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, MUTE};
use crate::define_action;
define_action! {
pub static SETMUTE = "SetMute" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "Channel" => A_ARG_TYPE_CHANNEL,
in "DesiredMute" => MUTE,
}
}

View File

@@ -1,10 +0,0 @@
use crate::mediarenderer::renderingcontrol::variables::{A_ARG_TYPE_INSTANCE_ID, A_ARG_TYPE_CHANNEL, VOLUME};
use crate::define_action;
define_action! {
pub static SETVOLUME = "SetVolume" {
in "InstanceID" => A_ARG_TYPE_INSTANCE_ID,
in "Channel" => A_ARG_TYPE_CHANNEL,
in "DesiredVolume" => VOLUME,
}
}

View File

@@ -1,77 +0,0 @@
//! # RenderingControl Service - Service de contrôle du rendu audio UPnP
//!
//! Ce module implémente le service RenderingControl:1 selon la spécification UPnP AV.
//! Le service RenderingControl permet de contrôler les paramètres de rendu audio
//! (volume, mute, etc.) sur un MediaRenderer.
//!
//! ## Fonctionnalités
//!
//! Le service RenderingControl permet :
//! - **Contrôle du volume** : GetVolume, SetVolume
//! - **Contrôle du mute** : GetMute, SetMute
//! - Support multi-canal (Master, LF, RF)
//!
//! ## Conformité UPnP
//!
//! Cette implémentation suit la spécification **UPnP RenderingControl:1 Service Template**.
//! Toutes les actions obligatoires (Required) sont implémentées :
//!
//! - ✅ GetVolume
//! - ✅ SetVolume
//! - ✅ GetMute
//! - ✅ SetMute
//!
//! ## Variables d'état
//!
//! Le service expose les variables d'état conformes à la spécification :
//!
//! ### Contrôle audio
//! - [`VOLUME`] : Niveau de volume (0-100)
//! - [`MUTE`] : État mute (true/false)
//!
//! ### Arguments
//! - [`A_ARG_TYPE_INSTANCE_ID`] : ID d'instance
//! - [`A_ARG_TYPE_CHANNEL`] : Canal audio (Master, LF, RF)
//!
//! ## Examples
//!
//! ```rust
//! use pmoupnp::mediarenderer::renderingcontrol::RENDERINGCONTROL;
//!
//! // Accéder au service
//! let service = &*RENDERINGCONTROL;
//! println!("Service: {}", service.name());
//! println!("Type: {}", service.service_type());
//! ```
//!
//! ## Références
//!
//! - [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;
pub mod variables;
pub mod actions;
use actions::{GETMUTE, GETVOLUME, SETMUTE, SETVOLUME};
use variables::{A_ARG_TYPE_CHANNEL, A_ARG_TYPE_INSTANCE_ID, MUTE, VOLUME};
// Service RenderingControl:1 conforme à la spécification UPnP AV pour MediaRenderer audio
// Voir la documentation du module pour plus de détails
define_service! {
pub static RENDERINGCONTROL = "RenderingControl" {
variables: [
A_ARG_TYPE_CHANNEL,
A_ARG_TYPE_INSTANCE_ID,
MUTE,
VOLUME,
],
actions: [
GETMUTE,
GETVOLUME,
SETMUTE,
SETVOLUME,
]
}
}

View File

@@ -1,8 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_CHANNEL: String = "A_ARG_TYPE_Channel" {
allowed: ["Master", "LF", "RF"],
default: "Master",
}
}

View File

@@ -1,5 +0,0 @@
use crate::define_variable;
define_variable! {
pub static A_ARG_TYPE_INSTANCE_ID: UI4 = "A_ARG_TYPE_InstanceID"
}

View File

@@ -1,9 +0,0 @@
mod a_arg_type_instanceid;
mod a_arg_type_channel;
mod volume;
mod mute;
pub use a_arg_type_instanceid::A_ARG_TYPE_INSTANCE_ID;
pub use a_arg_type_channel::A_ARG_TYPE_CHANNEL;
pub use volume::VOLUME;
pub use mute::MUTE;

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static MUTE: Boolean = "Mute" {
evented: true,
}
}

View File

@@ -1,7 +0,0 @@
use crate::define_variable;
define_variable! {
pub static VOLUME: UI2 = "Volume" {
evented: true,
}
}