Bon, à nouveau ça marche plus dans bubble UPNP.

This commit is contained in:
2025-11-28 23:13:59 +01:00
parent 128fa823a9
commit 7562801989
9 changed files with 877 additions and 4 deletions

BIN
bubble_upmpdcli.pcap Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -123,12 +123,20 @@ impl ContentHandler {
container.child_count = None; // compatibilité CP container.child_count = None; // compatibilité CP
let didl = to_didl_lite(&[container], &[])?; let didl = to_didl_lite(&[container], &[])?;
let update_id = source.update_id().await.max(1); let update_id = source.update_id().await.max(1);
tracing::debug!(
"BrowseMetadata root (flatten) didl_len={}B",
didl.len()
);
return Ok((didl, 1, 1, update_id)); return Ok((didl, 1, 1, update_id));
} }
// Sinon retourner le container racine agrégé // Sinon retourner le container racine agrégé
let root = self.build_root_container().await; let root = self.build_root_container().await;
let didl = to_didl_lite(&[root], &[])?; let didl = to_didl_lite(&[root], &[])?;
tracing::debug!(
"BrowseMetadata root (aggregate) didl_len={}B",
didl.len()
);
Ok((didl, 1, 1, 1)) Ok((didl, 1, 1, 1))
} else { } else {
// Essayer de trouver l'objet dans les sources // Essayer de trouver l'objet dans les sources
@@ -140,6 +148,11 @@ impl ContentHandler {
.map_err(|e| format!("Failed to get root container: {}", e))?; .map_err(|e| format!("Failed to get root container: {}", e))?;
let didl = to_didl_lite(&[container], &[])?; let didl = to_didl_lite(&[container], &[])?;
let update_id = source.update_id().await.max(1); let update_id = source.update_id().await.max(1);
tracing::debug!(
"BrowseMetadata source_root id={} didl_len={}B",
object_id,
didl.len()
);
return Ok((didl, 1, 1, update_id)); return Ok((didl, 1, 1, update_id));
} }
@@ -149,6 +162,11 @@ impl ContentHandler {
Ok(item) => { Ok(item) => {
let didl = to_didl_lite(&[], &[item])?; let didl = to_didl_lite(&[], &[item])?;
let update_id = source.update_id().await.max(1); let update_id = source.update_id().await.max(1);
tracing::debug!(
"BrowseMetadata item id={} didl_len={}B",
object_id,
didl.len()
);
return Ok((didl, 1, 1, update_id)); return Ok((didl, 1, 1, update_id));
} }
Err(MusicSourceError::ObjectNotFound(_)) Err(MusicSourceError::ObjectNotFound(_))

View File

@@ -188,7 +188,7 @@ impl RadioParadiseSource {
parent_id: "radio-paradise".to_string(), parent_id: "radio-paradise".to_string(),
restricted: Some("1".to_string()), restricted: Some("1".to_string()),
child_count: None, child_count: None,
searchable: Some("0".to_string()), searchable: Some("1".to_string()),
title: descriptor.display_name.to_string(), title: descriptor.display_name.to_string(),
class: "object.container".to_string(), class: "object.container".to_string(),
containers: vec![], containers: vec![],
@@ -357,7 +357,7 @@ impl MusicSource for RadioParadiseSource {
restricted: Some("1".to_string()), restricted: Some("1".to_string()),
// childCount retiré pour éviter les soucis de compatibilité côté CP // childCount retiré pour éviter les soucis de compatibilité côté CP
child_count: None, child_count: None,
searchable: Some("0".to_string()), searchable: Some("1".to_string()),
title: "Radio Paradise".to_string(), title: "Radio Paradise".to_string(),
class: "object.container".to_string(), class: "object.container".to_string(),
containers: vec![], containers: vec![],

View File

@@ -29,6 +29,7 @@ impl UpnpInstance for ArgInstanceSet {
fn new(_: &ArgumentSet) -> Self { fn new(_: &ArgumentSet) -> Self {
Self { Self {
objects: RwLock::new(HashMap::new()), objects: RwLock::new(HashMap::new()),
order: RwLock::new(Vec::new()),
} }
} }
} }

View File

@@ -259,6 +259,7 @@ impl UpnpInstance for ActionInstanceSet {
fn new(_: &ActionSet) -> Self { fn new(_: &ActionSet) -> Self {
Self { Self {
objects: RwLock::new(HashMap::new()), objects: RwLock::new(HashMap::new()),
order: RwLock::new(Vec::new()),
} }
} }
} }

View File

@@ -32,6 +32,7 @@ pub struct UpnpObjectType {
#[derive(Debug)] #[derive(Debug)]
pub struct UpnpObjectSet<T: UpnpTypedObject> { pub struct UpnpObjectSet<T: UpnpTypedObject> {
objects: RwLock<HashMap<String, Arc<T>>>, objects: RwLock<HashMap<String, Arc<T>>>,
order: RwLock<Vec<String>>,
} }
#[derive(Debug)] #[derive(Debug)]

View File

@@ -12,6 +12,7 @@ use crate::{UpnpDeepClone, UpnpObjectSet, UpnpObjectSetError, UpnpTypedObject};
impl<T: UpnpTypedObject> UpnpDeepClone for UpnpObjectSet<T> { impl<T: UpnpTypedObject> UpnpDeepClone for UpnpObjectSet<T> {
fn deep_clone(&self) -> Self { fn deep_clone(&self) -> Self {
let guard = self.objects.read().unwrap(); let guard = self.objects.read().unwrap();
let order_guard = self.order.read().unwrap();
let cloned_map: HashMap<String, Arc<T>> = guard let cloned_map: HashMap<String, Arc<T>> = guard
.iter() .iter()
@@ -20,6 +21,7 @@ impl<T: UpnpTypedObject> UpnpDeepClone for UpnpObjectSet<T> {
Self { Self {
objects: RwLock::new(cloned_map), objects: RwLock::new(cloned_map),
order: RwLock::new(order_guard.clone()),
} }
} }
} }
@@ -39,9 +41,11 @@ impl<T: UpnpTypedObject> UpnpDeepClone for UpnpObjectSet<T> {
impl<T: UpnpTypedObject> Clone for UpnpObjectSet<T> { impl<T: UpnpTypedObject> Clone for UpnpObjectSet<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let guard = self.objects.read().unwrap(); let guard = self.objects.read().unwrap();
let order_guard = self.order.read().unwrap();
Self { Self {
objects: RwLock::new(guard.clone()), objects: RwLock::new(guard.clone()),
order: RwLock::new(order_guard.clone()),
} }
} }
} }
@@ -57,6 +61,7 @@ impl<T: UpnpTypedObject> UpnpObjectSet<T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
objects: RwLock::new(HashMap::new()), objects: RwLock::new(HashMap::new()),
order: RwLock::new(Vec::new()),
} }
} }
@@ -80,13 +85,15 @@ impl<T: UpnpTypedObject> UpnpObjectSet<T> {
/// ``` /// ```
pub fn insert(&mut self, object: Arc<T>) -> Result<(), UpnpObjectSetError> { pub fn insert(&mut self, object: Arc<T>) -> Result<(), UpnpObjectSetError> {
let mut guard = self.objects.write().unwrap(); let mut guard = self.objects.write().unwrap();
let mut order_guard = self.order.write().unwrap();
let key = object.get_name().to_string(); let key = object.get_name().to_string();
if guard.contains_key(&key) { if guard.contains_key(&key) {
return Err(UpnpObjectSetError::AlreadyExists(key)); return Err(UpnpObjectSetError::AlreadyExists(key));
} }
guard.insert(key, object); guard.insert(key.clone(), object);
order_guard.push(key);
Ok(()) Ok(())
} }
@@ -110,8 +117,13 @@ impl<T: UpnpTypedObject> UpnpObjectSet<T> {
/// ``` /// ```
pub fn insert_or_replace(&mut self, object: Arc<T>) { pub fn insert_or_replace(&mut self, object: Arc<T>) {
let mut guard = self.objects.write().unwrap(); let mut guard = self.objects.write().unwrap();
let mut order_guard = self.order.write().unwrap();
let key: String = object.get_name().to_string(); let key: String = object.get_name().to_string();
if !guard.contains_key(&key) {
order_guard.push(key.clone());
}
guard.insert(key, object); guard.insert(key, object);
} }
@@ -192,6 +204,11 @@ impl<T: UpnpTypedObject> UpnpObjectSet<T> {
/// appeler cette méthode simultanément sans blocage. /// appeler cette méthode simultanément sans blocage.
pub fn all(&self) -> Vec<Arc<T>> { pub fn all(&self) -> Vec<Arc<T>> {
let guard = self.objects.read().unwrap(); let guard = self.objects.read().unwrap();
guard.values().cloned().collect() let order_guard = self.order.read().unwrap();
order_guard
.iter()
.filter_map(|k| guard.get(k).cloned())
.collect()
} }
} }

View File

@@ -29,6 +29,7 @@ impl UpnpInstance for StateVarInstanceSet {
fn new(_: &StateVariableSet) -> Self { fn new(_: &StateVariableSet) -> Self {
Self { Self {
objects: RwLock::new(HashMap::new()), objects: RwLock::new(HashMap::new()),
order: RwLock::new(Vec::new()),
} }
} }
} }