Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
authors = ["Konstantin Stepanov <me@kstep.me>"]
description = "A client library for MPD (music player daemon), like libmpdclient but in Rust"
authors = ["Konstantin Stepanov <me@kstep.me>", "Ari Rios <me@aririos.com>"]
description = "NOT meant to be a maintained fork of rust-mpd, just for use in my own projects"
documentation = "http://kstep.me/rust-mpd/mpd/index.html"
homepage = "https://github.com/kstep/rust-mpd"
homepage = "https://github.com/ariririos/rust-mpd"
license = "MIT/Apache-2.0"
name = "mpd"
repository = "https://github.com/kstep/rust-mpd.git"
name = "mpd-aririos"
repository = "https://github.com/ariririos/rust-mpd.git"
version = "0.1.0"
edition = "2018"

Expand Down
71 changes: 71 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ impl<S: Read + Write> Client<S> {
self.find_generic("find", query, window.into())
}

/// Ask MPD to send larger chunks
pub fn binary_limit(&mut self, bytes: usize) -> Result<()> {
self.run_command("binarylimit", bytes).and_then(|_| self.expect_ok())
}

/// Find album art for file
pub fn albumart<P: ToSongPath>(&mut self, path: &P) -> Result<Vec<u8>> {
let mut buf = vec![];
Expand All @@ -422,6 +427,42 @@ impl<S: Read + Write> Client<S> {
Ok(buf)
}

/// Find embedded album art for file. Returns a tuple of an optional mimetype and the artwork binary data. If the song was recognized but there is no picture, the response is successful but otherwise empty.
pub fn readpicture<P: ToSongPath>(&mut self, path: &P) -> Result<(Option<String>, Vec<u8>)> {
let mut buf = vec![];
let mut mime_type;

loop {
self.run_command("readpicture", (path, &*format!("{}", buf.len())))?;
let (_, size) = self.read_pair()?;
let (type_or_binary, mut mime_type_or_bytes) = self.read_pair()?;
match type_or_binary.as_str() {
"type" => {
mime_type = Some(mime_type_or_bytes);
mime_type_or_bytes = self.read_pair()?.1; // type field is optional so read one more pair to get bytes
}
"binary" => {
mime_type = None;
}
_ => return Err(ProtoError::NoField("Expected 'type' or 'binary'").into()),
}
let mut chunk = self.read_bytes(mime_type_or_bytes.parse()?)?;
buf.append(&mut chunk);

// Read empty newline
let _ = self.read_line()?;
let result = self.read_line()?;
if result != "OK" {
return Err(ProtoError::NotOk)?;
}

if size.parse::<usize>()? == buf.len() {
break;
}
}
Ok((mime_type, buf))
}

/// Case-insensitively search for songs matching Query conditions.
pub fn search<W>(&mut self, query: &Query, window: W) -> Result<Vec<Song>>
where W: Into<Window> {
Expand All @@ -432,6 +473,36 @@ impl<S: Read + Write> Client<S> {
self.run_command(cmd, (query, window)).and_then(|_| self.read_structs("file"))
}

/// Find several files by full path, batching requests
pub fn find_paths<I, P>(&mut self, paths: I) -> Result<Vec<Vec<Song>>>
where
I: IntoIterator<Item = P>,
P: AsRef<str>,
{
let mut queries: Vec<Query> = Vec::new();
for path in paths {
let mut query = Query::new();
query.and(Term::File, path.as_ref().to_owned());
queries.push(query);
}
if queries.is_empty() {
return Ok(Vec::new());
}

self.run_command("command_list_ok_begin", ())?;
for query in &queries {
self.run_command("find", (query, Window::from(None)))?;
}
self.run_command("command_list_end", ())?;

let mut songs = Vec::with_capacity(queries.len());
for _ in &queries {
songs.push(self.read_structs("file")?);
}
self.expect_ok()?;
Ok(songs)
}

/// Lists unique tags values of the specified type for songs matching the given query.
// TODO: list type [filtertype] [filterwhat] [...] [group] [grouptype] [...]
// It isn't clear if or how `group` works
Expand Down