Correction du média serveur.

This commit is contained in:
2025-11-28 19:03:27 +01:00
parent c972182b3b
commit 6589279bb3
7 changed files with 38 additions and 45 deletions

View File

@@ -224,7 +224,9 @@ impl AudioMetadata {
/// ```
pub fn to_didl_resource(&self, url: String) -> pmodidl::Resource {
pmodidl::Resource {
protocol_info: "http-get:*:audio/flac:*".to_string(),
// Aligne le protocolInfo sur ce que le renderer déclare dans Sink (audio/flac).
// PN explicite pour compatibilité DLNA, sinon fallback générique.
protocol_info: "http-get:*:audio/flac:DLNA.ORG_PN=FLAC".to_string(),
bits_per_sample: None,
sample_frequency: self.sample_rate.map(|sr| sr.to_string()),
nr_audio_channels: self.channels.map(|ch| ch.to_string()),

View File

@@ -117,7 +117,8 @@ impl TrackMetadataDidlExt for dyn TrackMetadata {
});
pmodidl::Resource {
protocol_info: "http-get:*:audio/flac:*".to_string(),
// Aligne sur Sink du renderer (audio/flac) avec PN explicite.
protocol_info: "http-get:*:audio/flac:DLNA.ORG_PN=FLAC".to_string(),
bits_per_sample: self.get_bits_per_sample().await.ok().flatten().map(|b| b.to_string()),
sample_frequency: self.get_sample_rate().await.ok().flatten().map(|sr| sr.to_string()),
nr_audio_channels: self.get_channels().await.ok().flatten().map(|ch| ch.to_string()),

View File

@@ -18,6 +18,7 @@ quick-xml = { version = "0.38.3", features = ["serialize"] }
thiserror = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
pmoutils = { path = "../pmoutils" }
# Optional dependencies
axum = { version = "0.8", optional = true }

View File

@@ -10,6 +10,7 @@
//! - **Search** : Recherche dans les sources qui le supportent
//! - **Update ID** : Suivi des changements pour les notifications UPnP
use pmoutils::ToXmlElement;
use pmodidl::{Container, DIDLLite};
use pmosource::api::{get_source as get_source_from_registry, list_all_sources};
use pmosource::{BrowseResult, MusicSource, MusicSourceError};
@@ -28,12 +29,9 @@ fn to_didl_lite(containers: &[Container], items: &[pmodidl::Item]) -> Result<Str
items: items.to_vec(),
};
let body = quick_xml::se::to_string(&didl)
.map_err(|e| format!("Failed to serialize DIDL-Lite: {}", e))?;
Ok(format!(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>{}",
body
))
// Retourne uniquement le corps DIDL, sans préfixer une seconde déclaration XML.
let body = didl.to_xml();
Ok(body)
}
/// Handler pour le service ContentDirectory

View File

@@ -1,7 +1,7 @@
use crate::UpnpModel;
use crate::actions::ArgInstanceSet;
use crate::{UpnpObject, actions::ArgumentSet};
use xmltree::Element;
use xmltree::{Element, XMLNode};
impl UpnpObject for ArgumentSet {
// Méthode pour convertir en XML (à implémenter avec une librairie XML)
@@ -9,11 +9,8 @@ impl UpnpObject for ArgumentSet {
let mut elem = Element::new("argumentList");
for arg in self.all() {
let arg_elem = arg.to_xml_element(); // toujours un <argumentList> contenant 1 ou 2 <argument>
// Pour InOut, on ajoute tous les enfants du <argumentList> généré
for child in arg_elem.children {
elem.children.push(child);
for arg_elem in arg.to_xml_elements() {
elem.children.push(XMLNode::Element(arg_elem));
}
}

View File

@@ -16,31 +16,8 @@ impl UpnpTyped for Argument {
impl UpnpObject for Argument {
fn to_xml_element(&self) -> Element {
let mut parent = Element::new("argumentList");
if self.is_in() && self.is_out() {
// InOut → deux arguments
parent.children.push(XMLNode::Element(make_argument_elem(
self.get_name(),
"in",
self.state_variable().get_name(),
)));
parent.children.push(XMLNode::Element(make_argument_elem(
self.get_name(),
"out",
self.state_variable().get_name(),
)));
} else {
// Cas simple
let direction = if self.is_in() { "in" } else { "out" };
parent.children.push(XMLNode::Element(make_argument_elem(
self.get_name(),
direction,
self.state_variable().get_name(),
)));
}
parent
// Compat: retourne le premier argument (utile si consommé isolément)
self.to_xml_elements().into_iter().next().unwrap_or_else(|| Element::new("argument"))
}
}
@@ -91,6 +68,23 @@ impl Argument {
pub fn is_out(&self) -> bool {
self.is_out
}
/// Retourne les éléments XML <argument> (1 ou 2 si InOut)
pub fn to_xml_elements(&self) -> Vec<Element> {
if self.is_in() && self.is_out() {
vec![
make_argument_elem(self.get_name(), "in", self.state_variable().get_name()),
make_argument_elem(self.get_name(), "out", self.state_variable().get_name()),
]
} else {
let direction = if self.is_in() { "in" } else { "out" };
vec![make_argument_elem(
self.get_name(),
direction,
self.state_variable().get_name(),
)]
}
}
}
/// Fabrique un <argument> complet avec ses sous-éléments

View File

@@ -626,16 +626,16 @@ impl ServiceInstance {
elem.children.push(XMLNode::Element(spec));
// actionList
if !self.actions.all().is_empty() {
// actionList (depuis le modèle)
if !self.model.actions.all().is_empty() {
elem.children
.push(XMLNode::Element(self.actions.to_xml_element()));
.push(XMLNode::Element(self.model.actions.to_xml_element()));
}
// serviceStateTable
if !self.statevariables.all().is_empty() {
// serviceStateTable (depuis le modèle)
if !self.model.state_table.all().is_empty() {
elem.children
.push(XMLNode::Element(self.statevariables.to_xml_element()));
.push(XMLNode::Element(self.model.state_table.to_xml_element()));
}
elem