Bon, à nouveau ça marche plus dans bubble UPNP.
This commit is contained in:
BIN
bubble_upmpdcli.pcap
Normal file
BIN
bubble_upmpdcli.pcap
Normal file
Binary file not shown.
834
com.bubblesoft.android.bubbleupnp_log.txt
Normal file
834
com.bubblesoft.android.bubbleupnp_log.txt
Normal file
File diff suppressed because one or more lines are too long
@@ -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(_))
|
||||||
|
|||||||
@@ -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![],
|
||||||
|
|||||||
@@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user