feat(lib): carry audio attributes in browse and folder listings
A browse listed each file as a name and a size, so a searcher who saw a bitrate in a search reply lost it the moment they opened the sharer's files. Listings (codes 5 and 37) now carry each file's attributes the way Nicotine+ sends them, as a SharedFileEntry with name, size and attributes in place of the (name, size) pair; the CLI's browse record gains bitrate and duration, and the daemon protocol moves to version 2 for the new listing shape.
This commit is contained in:
@@ -12,7 +12,8 @@ use soulseek_rs::types::{
|
||||
};
|
||||
use soulseek_rs::{
|
||||
DownloadStatus, File, RoomEvent, RoomInfo, SearchResult, SessionLoss,
|
||||
SharedDirectory, UploadInfo, UploadStatus, UserInfo, UserMessage,
|
||||
SharedDirectory, SharedFileEntry, UploadInfo, UploadStatus, UserInfo,
|
||||
UserMessage,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -553,15 +554,32 @@ impl From<UserInfoDto> for UserInfo {
|
||||
#[cfg_attr(test, derive(schemars::JsonSchema))]
|
||||
pub struct SharedDirectoryDto {
|
||||
pub name: String,
|
||||
/// Basename and size; join with the directory to get a downloadable path.
|
||||
pub files: Vec<(String, u64)>,
|
||||
pub files: Vec<SharedFileEntryDto>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[cfg_attr(test, derive(schemars::JsonSchema))]
|
||||
pub struct SharedFileEntryDto {
|
||||
/// Basename; join with the directory to get a downloadable path.
|
||||
pub name: String,
|
||||
pub size: u64,
|
||||
/// `(code, value)` audio attributes the owner advertises.
|
||||
pub attributes: Vec<(u32, u32)>,
|
||||
}
|
||||
|
||||
impl From<&SharedDirectory> for SharedDirectoryDto {
|
||||
fn from(directory: &SharedDirectory) -> Self {
|
||||
Self {
|
||||
name: directory.name.clone(),
|
||||
files: directory.files.clone(),
|
||||
files: directory
|
||||
.files
|
||||
.iter()
|
||||
.map(|file| SharedFileEntryDto {
|
||||
name: file.name.clone(),
|
||||
size: file.size,
|
||||
attributes: file.attributes.clone(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -570,7 +588,15 @@ impl From<SharedDirectoryDto> for SharedDirectory {
|
||||
fn from(dto: SharedDirectoryDto) -> Self {
|
||||
Self {
|
||||
name: dto.name,
|
||||
files: dto.files,
|
||||
files: dto
|
||||
.files
|
||||
.into_iter()
|
||||
.map(|file| SharedFileEntry {
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
attributes: file.attributes,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/// Bumped when a change would break a client written against the old shape.
|
||||
/// Sent in the `auth` reply so a mismatch is caught at connect time rather
|
||||
/// than as a confusing failure three calls later.
|
||||
pub const PROTOCOL_VERSION: u32 = 1;
|
||||
pub const PROTOCOL_VERSION: u32 = 2;
|
||||
|
||||
/// The OpenRPC document, served by `rpc.discover` so a generator can point at
|
||||
/// a running daemon instead of needing this repository.
|
||||
@@ -322,7 +322,11 @@ mod tests {
|
||||
fn a_shared_listing_survives_the_round_trip() {
|
||||
let directory = SharedDirectory {
|
||||
name: "@@x\\Music".into(),
|
||||
files: vec![("a.mp3".into(), 4096)],
|
||||
files: vec![soulseek_rs::SharedFileEntry {
|
||||
name: "a.mp3".into(),
|
||||
size: 4096,
|
||||
attributes: vec![(0, 320)],
|
||||
}],
|
||||
};
|
||||
let json = serde_json::to_string(&SharedDirectoryDto::from(&directory))
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user