implemente le squelette de pmomediaserver

This commit is contained in:
2025-10-17 08:55:29 +02:00
parent bd61fdba81
commit d657ea2315
41 changed files with 720 additions and 1 deletions

View File

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

View File

@@ -0,0 +1,18 @@
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 pmoupnp::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_CONNECTIONID,
out "PeerConnectionID" => A_ARG_TYPE_CONNECTIONID,
out "Direction" => A_ARG_TYPE_DIRECTION,
out "Status" => A_ARG_TYPE_CONNECTIONSTATUS,
}
}

View File

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

View File

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

View File

@@ -0,0 +1,99 @@
//! # 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 supportés (http-get:*:audio/mpeg:*, etc.)
//! - [`SINKPROTOCOLINFO`] : Protocoles sink (vide pour un server)
//! - [`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
//!
//! ## Différences avec MediaRenderer
//!
//! Pour un MediaServer :
//! - **SourceProtocolInfo** : Liste des protocoles que le server peut **fournir** (Output)
//! - **SinkProtocolInfo** : Vide (le server ne **consomme** pas de contenu)
//!
//! Pour un MediaRenderer (inverse) :
//! - **SourceProtocolInfo** : Vide (le renderer ne fournit pas de contenu)
//! - **SinkProtocolInfo** : Liste des protocoles que le renderer peut **consommer** (Input)
//!
//! ## Examples
//!
//! ```rust
//! use pmomediaserver::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 pmoupnp::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 MediaServer
// 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

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_AVTRANSPORTID: I4 = "A_ARG_TYPE_AVTransportID" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_CONNECTIONID: I4 = "A_ARG_TYPE_ConnectionID" {
evented: false,
}
}

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_PROTOCOLINFO: String = "A_ARG_TYPE_ProtocolInfo" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_RCSID: I4 = "A_ARG_TYPE_RcsID" {
evented: false,
}
}

View File

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

View File

@@ -0,0 +1,19 @@
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;
mod currentconnectionids;
mod sourceprotocolinfo;
mod sinkprotocolinfo;
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;
pub use currentconnectionids::CURRENTCONNECTIONIDS;
pub use sourceprotocolinfo::SOURCEPROTOCOLINFO;
pub use sinkprotocolinfo::SINKPROTOCOLINFO;

View File

@@ -0,0 +1,8 @@
use pmoupnp::define_variable;
// Pour un MediaServer, SinkProtocolInfo est vide (le server ne consomme pas de contenu)
define_variable! {
pub static SINKPROTOCOLINFO: String = "SinkProtocolInfo" {
evented: true,
}
}

View File

@@ -0,0 +1,8 @@
use pmoupnp::define_variable;
// Pour un MediaServer, SourceProtocolInfo liste les protocoles qu'il peut servir
define_variable! {
pub static SOURCEPROTOCOLINFO: String = "SourceProtocolInfo" {
evented: true,
}
}

View File

@@ -0,0 +1,21 @@
use crate::contentdirectory::variables::{
A_ARG_TYPE_OBJECTID, A_ARG_TYPE_BROWSEFLAG, A_ARG_TYPE_FILTER,
A_ARG_TYPE_SORTCRITERIA, A_ARG_TYPE_INDEX, A_ARG_TYPE_COUNT,
A_ARG_TYPE_RESULT, A_ARG_TYPE_UPDATEID,
};
use pmoupnp::define_action;
define_action! {
pub static BROWSE = "Browse" {
in "ObjectID" => A_ARG_TYPE_OBJECTID,
in "BrowseFlag" => A_ARG_TYPE_BROWSEFLAG,
in "Filter" => A_ARG_TYPE_FILTER,
in "StartingIndex" => A_ARG_TYPE_INDEX,
in "RequestedCount" => A_ARG_TYPE_COUNT,
in "SortCriteria" => A_ARG_TYPE_SORTCRITERIA,
out "Result" => A_ARG_TYPE_RESULT,
out "NumberReturned" => A_ARG_TYPE_COUNT,
out "TotalMatches" => A_ARG_TYPE_COUNT,
out "UpdateID" => A_ARG_TYPE_UPDATEID,
}
}

View File

@@ -0,0 +1,8 @@
use crate::contentdirectory::variables::SEARCHCAPABILITIES;
use pmoupnp::define_action;
define_action! {
pub static GETSEARCHCAPABILITIES = "GetSearchCapabilities" {
out "SearchCaps" => SEARCHCAPABILITIES,
}
}

View File

@@ -0,0 +1,8 @@
use crate::contentdirectory::variables::SORTCAPABILITIES;
use pmoupnp::define_action;
define_action! {
pub static GETSORTCAPABILITIES = "GetSortCapabilities" {
out "SortCaps" => SORTCAPABILITIES,
}
}

View File

@@ -0,0 +1,8 @@
use crate::contentdirectory::variables::SYSTEMUPDATEID;
use pmoupnp::define_action;
define_action! {
pub static GETSYSTEMUPDATEID = "GetSystemUpdateID" {
out "Id" => SYSTEMUPDATEID,
}
}

View File

@@ -0,0 +1,11 @@
mod browse;
mod search;
mod getsearchcapabilities;
mod getsortcapabilities;
mod getsystemupdateid;
pub use browse::BROWSE;
pub use search::SEARCH;
pub use getsearchcapabilities::GETSEARCHCAPABILITIES;
pub use getsortcapabilities::GETSORTCAPABILITIES;
pub use getsystemupdateid::GETSYSTEMUPDATEID;

View File

@@ -0,0 +1,21 @@
use crate::contentdirectory::variables::{
A_ARG_TYPE_OBJECTID, A_ARG_TYPE_SEARCHCRITERIA, A_ARG_TYPE_FILTER,
A_ARG_TYPE_SORTCRITERIA, A_ARG_TYPE_INDEX, A_ARG_TYPE_COUNT,
A_ARG_TYPE_RESULT, A_ARG_TYPE_UPDATEID,
};
use pmoupnp::define_action;
define_action! {
pub static SEARCH = "Search" {
in "ContainerID" => A_ARG_TYPE_OBJECTID,
in "SearchCriteria" => A_ARG_TYPE_SEARCHCRITERIA,
in "Filter" => A_ARG_TYPE_FILTER,
in "StartingIndex" => A_ARG_TYPE_INDEX,
in "RequestedCount" => A_ARG_TYPE_COUNT,
in "SortCriteria" => A_ARG_TYPE_SORTCRITERIA,
out "Result" => A_ARG_TYPE_RESULT,
out "NumberReturned" => A_ARG_TYPE_COUNT,
out "TotalMatches" => A_ARG_TYPE_COUNT,
out "UpdateID" => A_ARG_TYPE_UPDATEID,
}
}

View File

@@ -0,0 +1,116 @@
//! # ContentDirectory Service - Service de gestion du contenu UPnP
//!
//! Ce module implémente le service ContentDirectory:1 selon la spécification UPnP AV.
//! Le service ContentDirectory permet de naviguer et rechercher dans une bibliothèque
//! de contenu musical.
//!
//! ## Fonctionnalités
//!
//! Le service ContentDirectory permet :
//! - **Navigation** : Browse pour parcourir la hiérarchie de contenu
//! - **Recherche** : Search pour rechercher du contenu selon des critères
//! - **Capacités** : GetSearchCapabilities, GetSortCapabilities
//! - **Synchronisation** : GetSystemUpdateID pour détecter les changements
//!
//! ## Conformité UPnP
//!
//! Cette implémentation suit la spécification **UPnP ContentDirectory:1 Service Template**.
//! Toutes les actions obligatoires (Required) sont implémentées :
//!
//! - ✅ Browse
//! - ✅ GetSearchCapabilities
//! - ✅ GetSortCapabilities
//! - ✅ GetSystemUpdateID
//!
//! Et certaines actions optionnelles :
//! - ✅ Search
//!
//! ## Variables d'état
//!
//! Le service expose les variables d'état conformes à la spécification :
//!
//! ### Variables principales
//! - [`SYSTEMUPDATEID`] : ID de mise à jour du système (évènementiel)
//! - [`SEARCHCAPABILITIES`] : Capacités de recherche supportées
//! - [`SORTCAPABILITIES`] : Capacités de tri supportées
//!
//! ### Arguments d'action
//! - [`A_ARG_TYPE_OBJECTID`] : ID d'un objet (container ou item)
//! - [`A_ARG_TYPE_BROWSEFLAG`] : Type de browsing (Metadata ou DirectChildren)
//! - [`A_ARG_TYPE_FILTER`] : Filtre de propriétés à retourner
//! - [`A_ARG_TYPE_SORTCRITERIA`] : Critères de tri
//! - [`A_ARG_TYPE_SEARCHCRITERIA`] : Critères de recherche
//! - [`A_ARG_TYPE_INDEX`] : Index de départ
//! - [`A_ARG_TYPE_COUNT`] : Nombre d'éléments
//! - [`A_ARG_TYPE_UPDATEID`] : ID de mise à jour
//! - [`A_ARG_TYPE_RESULT`] : Résultat au format DIDL-Lite
//!
//! ## Examples
//!
//! ```rust
//! use pmomediaserver::contentdirectory::CONTENTDIRECTORY;
//! use pmoupnp::UpnpTyped;
//!
//! // Accéder au service
//! let service = &*CONTENTDIRECTORY;
//! 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 ContentDirectory:1 Service Template](https://upnp.org/specs/av/UPnP-av-ContentDirectory-v1-Service.pdf)
//! - [UPnP AV Architecture](https://upnp.org/specs/av/)
use pmoupnp::define_service;
pub mod variables;
pub mod actions;
use actions::{
BROWSE, SEARCH, GETSEARCHCAPABILITIES, GETSORTCAPABILITIES, GETSYSTEMUPDATEID
};
use variables::{
A_ARG_TYPE_OBJECTID, A_ARG_TYPE_BROWSEFLAG, A_ARG_TYPE_FILTER,
A_ARG_TYPE_SORTCRITERIA, A_ARG_TYPE_INDEX, A_ARG_TYPE_COUNT,
A_ARG_TYPE_UPDATEID, A_ARG_TYPE_RESULT, A_ARG_TYPE_SEARCHCRITERIA,
SEARCHCAPABILITIES, SORTCAPABILITIES, SYSTEMUPDATEID
};
// Service ContentDirectory:1 conforme à la spécification UPnP AV pour MediaServer
// Voir la documentation du module pour plus de détails
define_service! {
pub static CONTENTDIRECTORY = "ContentDirectory" {
variables: [
A_ARG_TYPE_OBJECTID,
A_ARG_TYPE_BROWSEFLAG,
A_ARG_TYPE_FILTER,
A_ARG_TYPE_SORTCRITERIA,
A_ARG_TYPE_INDEX,
A_ARG_TYPE_COUNT,
A_ARG_TYPE_UPDATEID,
A_ARG_TYPE_RESULT,
A_ARG_TYPE_SEARCHCRITERIA,
SEARCHCAPABILITIES,
SORTCAPABILITIES,
SYSTEMUPDATEID,
],
actions: [
BROWSE,
SEARCH,
GETSEARCHCAPABILITIES,
GETSORTCAPABILITIES,
GETSYSTEMUPDATEID,
]
}
}

View File

@@ -0,0 +1,8 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_BROWSEFLAG: String = "A_ARG_TYPE_BrowseFlag" {
allowed: ["BrowseMetadata", "BrowseDirectChildren"],
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_COUNT: UI4 = "A_ARG_TYPE_Count" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_FILTER: String = "A_ARG_TYPE_Filter" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_INDEX: UI4 = "A_ARG_TYPE_Index" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_OBJECTID: String = "A_ARG_TYPE_ObjectID" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_RESULT: String = "A_ARG_TYPE_Result" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_SEARCHCRITERIA: String = "A_ARG_TYPE_SearchCriteria" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_SORTCRITERIA: String = "A_ARG_TYPE_SortCriteria" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static A_ARG_TYPE_UPDATEID: UI4 = "A_ARG_TYPE_UpdateID" {
evented: false,
}
}

View File

@@ -0,0 +1,25 @@
mod a_arg_type_objectid;
mod a_arg_type_browseflag;
mod a_arg_type_filter;
mod a_arg_type_sortcriteria;
mod a_arg_type_index;
mod a_arg_type_count;
mod a_arg_type_updateid;
mod a_arg_type_result;
mod a_arg_type_searchcriteria;
mod searchcapabilities;
mod sortcapabilities;
mod systemupdateid;
pub use a_arg_type_objectid::A_ARG_TYPE_OBJECTID;
pub use a_arg_type_browseflag::A_ARG_TYPE_BROWSEFLAG;
pub use a_arg_type_filter::A_ARG_TYPE_FILTER;
pub use a_arg_type_sortcriteria::A_ARG_TYPE_SORTCRITERIA;
pub use a_arg_type_index::A_ARG_TYPE_INDEX;
pub use a_arg_type_count::A_ARG_TYPE_COUNT;
pub use a_arg_type_updateid::A_ARG_TYPE_UPDATEID;
pub use a_arg_type_result::A_ARG_TYPE_RESULT;
pub use a_arg_type_searchcriteria::A_ARG_TYPE_SEARCHCRITERIA;
pub use searchcapabilities::SEARCHCAPABILITIES;
pub use sortcapabilities::SORTCAPABILITIES;
pub use systemupdateid::SYSTEMUPDATEID;

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static SEARCHCAPABILITIES: String = "SearchCapabilities" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static SORTCAPABILITIES: String = "SortCapabilities" {
evented: false,
}
}

View File

@@ -0,0 +1,7 @@
use pmoupnp::define_variable;
define_variable! {
pub static SYSTEMUPDATEID: UI4 = "SystemUpdateID" {
evented: true,
}
}

View File

@@ -0,0 +1,62 @@
//! Définition du device MediaServer.
use once_cell::sync::Lazy;
use std::sync::Arc;
use pmoupnp::devices::Device;
use crate::{
contentdirectory::CONTENTDIRECTORY,
connectionmanager::CONNECTIONMANAGER,
};
/// Device MediaServer UPnP.
///
/// MediaServer conforme UPnP AV Architecture 1.0.
///
/// # Services inclus
///
/// - **ContentDirectory:1** : Gestion du contenu et navigation
/// - **ConnectionManager:1** : Gestion des connexions
///
/// # Spécifications
///
/// - Device Type : `urn:schemas-upnp-org:device:MediaServer:1`
/// - Version : 1
/// - Manufacturer : PMOMusic
/// - Model : PMOMusic Media Server
///
/// # Exemple
///
/// ```ignore
/// use pmomediaserver::MEDIA_SERVER;
/// use pmoupnp::UpnpModel;
///
/// // Créer une instance du server
/// let server_instance = MEDIA_SERVER.create_instance();
///
/// // Accéder aux services
/// if let Some(content_directory) = server_instance.get_service("ContentDirectory") {
/// // Gérer le contenu...
/// }
/// ```
pub static MEDIA_SERVER: Lazy<Arc<Device>> = Lazy::new(|| {
let mut device = Device::new(
"MediaServer".to_string(),
"MediaServer".to_string(),
"PMOMusic Media Server".to_string(),
);
device.set_manufacturer("PMOMusic".to_string());
device.set_model_name("PMOMusic Media Server".to_string());
device.set_model_description("UPnP AV MediaServer for audio streaming".to_string());
device.set_udn_prefix("pmomusic".to_string());
// Ajouter les deux services obligatoires
device.add_service(Arc::clone(&CONTENTDIRECTORY))
.expect("Failed to add ContentDirectory service");
device.add_service(Arc::clone(&CONNECTIONMANAGER))
.expect("Failed to add ConnectionManager service");
Arc::new(device)
});

33
pmomediaserver/src/lib.rs Normal file
View File

@@ -0,0 +1,33 @@
//! Module MediaServer UPnP.
//!
//! Ce module implémente un MediaServer UPnP conforme à la spécification
//! UPnP AV Architecture. Un MediaServer permet d'exposer et de servir du contenu audio
//! à des clients UPnP (MediaRenderer).
//!
//! # Architecture
//!
//! Le MediaServer est composé de deux services obligatoires :
//!
//! - **ContentDirectory** : Gestion du contenu et navigation dans la bibliothèque musicale
//! - **ConnectionManager** : Gestion des connexions et des protocoles supportés
//!
//! # Device UPnP
//!
//! - Type : `urn:schemas-upnp-org:device:MediaServer:1`
//! - Services : ContentDirectory:1, ConnectionManager:1
//!
//! # Utilisation
//!
//! ```ignore
//! use pmomediaserver::MEDIA_SERVER;
//!
//! // Le device est déjà configuré avec tous ses services
//! let server = MEDIA_SERVER.clone();
//! let instance = server.create_instance();
//! ```
pub mod contentdirectory;
pub mod connectionmanager;
pub mod device;
pub use device::MEDIA_SERVER;