Implement BrowseMetadata

This commit is contained in:
Igor Katson 2024-08-31 18:50:55 +01:00
parent 206bcde06f
commit 2d4b467055
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
2 changed files with 48 additions and 12 deletions

View file

@ -246,26 +246,34 @@ impl UpnpServerSessionAdapter {
}) })
.collect_vec() .collect_vec()
} }
}
impl ContentDirectoryBrowseProvider for UpnpServerSessionAdapter { fn build_impl(
fn browse_direct_children(
&self, &self,
parent_id: usize, object_id: usize,
http_hostname: &str, http_hostname: &str,
metadata: bool,
) -> Vec<ItemOrContainer> { ) -> Vec<ItemOrContainer> {
if parent_id == 0 { if object_id == 0 {
return self.build_root(http_hostname); let root = self.build_root(http_hostname);
if metadata {
return vec![ItemOrContainer::Container(Container {
id: 0,
parent_id: None,
children_count: Some(root.len()),
title: "root".to_owned(),
})];
}
return root;
} }
let (node_id, torrent_id) = match decode_id(parent_id) { let (node_id, torrent_id) = match decode_id(object_id) {
Ok((node_id, torrent_id)) => (node_id, torrent_id), Ok((node_id, torrent_id)) => (node_id, torrent_id),
Err(_) => { Err(_) => {
debug!(id=?parent_id, "invalid id"); debug!(id=?object_id, "invalid id");
return vec![]; return vec![];
} }
}; };
trace!(parent_id, node_id, torrent_id); trace!(object_id, node_id, torrent_id);
let torrent = match self.session.get(torrent_id.into()) { let torrent = match self.session.get(torrent_id.into()) {
Some(t) => t, Some(t) => t,
@ -278,7 +286,7 @@ impl ContentDirectoryBrowseProvider for UpnpServerSessionAdapter {
let tree = match TorrentFileTree::build(torrent.id(), &torrent.shared().info) { let tree = match TorrentFileTree::build(torrent.id(), &torrent.shared().info) {
Ok(tree) => tree, Ok(tree) => tree,
Err(e) => { Err(e) => {
warn!(parent_id, error=?e, "error building torrent file tree"); warn!(object_id, error=?e, "error building torrent file tree");
return vec![]; return vec![];
} }
}; };
@ -295,7 +303,7 @@ impl ContentDirectoryBrowseProvider for UpnpServerSessionAdapter {
let mut result = Vec::new(); let mut result = Vec::new();
if node.real_torrent_file_id.is_some() { if node.real_torrent_file_id.is_some() || metadata {
result.push(node.as_item_or_container(node_id, http_hostname, &torrent, self)) result.push(node.as_item_or_container(node_id, http_hostname, &torrent, self))
} else { } else {
for (child_node_id, child_node) in node for (child_node_id, child_node) in node
@ -316,6 +324,20 @@ impl ContentDirectoryBrowseProvider for UpnpServerSessionAdapter {
} }
} }
impl ContentDirectoryBrowseProvider for UpnpServerSessionAdapter {
fn browse_direct_children(
&self,
object_id: usize,
http_hostname: &str,
) -> Vec<ItemOrContainer> {
self.build_impl(object_id, http_hostname, false)
}
fn browse_metadata(&self, object_id: usize, http_hostname: &str) -> Vec<ItemOrContainer> {
self.build_impl(object_id, http_hostname, true)
}
}
impl Session { impl Session {
pub async fn make_upnp_adapter( pub async fn make_upnp_adapter(
self: &Arc<Self>, self: &Arc<Self>,

View file

@ -293,7 +293,15 @@ pub(crate) async fn http_handler(
), ),
) )
.into_response(), .into_response(),
BrowseFlag::BrowseMetadata => StatusCode::NOT_IMPLEMENTED.into_response(), BrowseFlag::BrowseMetadata => (
[(CONTENT_TYPE, CONTENT_TYPE_XML_UTF8)],
browse::response::render(
state
.provider
.browse_metadata(request.object_id, http_hostname),
),
)
.into_response(),
} }
} }
SOAP_ACTION_GET_SYSTEM_UPDATE_ID => { SOAP_ACTION_GET_SYSTEM_UPDATE_ID => {
@ -314,12 +322,18 @@ pub(crate) async fn http_handler(
pub trait ContentDirectoryBrowseProvider: Send + Sync { pub trait ContentDirectoryBrowseProvider: Send + Sync {
fn browse_direct_children(&self, parent_id: usize, http_hostname: &str) fn browse_direct_children(&self, parent_id: usize, http_hostname: &str)
-> Vec<ItemOrContainer>; -> Vec<ItemOrContainer>;
fn browse_metadata(&self, object_id: usize, http_hostname: &str) -> Vec<ItemOrContainer>;
} }
impl ContentDirectoryBrowseProvider for Vec<ItemOrContainer> { impl ContentDirectoryBrowseProvider for Vec<ItemOrContainer> {
fn browse_direct_children(&self, _parent_id: usize, _http_host: &str) -> Vec<ItemOrContainer> { fn browse_direct_children(&self, _parent_id: usize, _http_host: &str) -> Vec<ItemOrContainer> {
self.clone() self.clone()
} }
fn browse_metadata(&self, _object_id: usize, _http_hostname: &str) -> Vec<ItemOrContainer> {
// TODO. Remove the vec provider from core code.
vec![]
}
} }
#[cfg(test)] #[cfg(test)]