diff --git a/Cargo.toml b/Cargo.toml index abbe833f..637b4b56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] -authors = ["Konstantin Stepanov "] -description = "A client library for MPD (music player daemon), like libmpdclient but in Rust" +authors = ["Konstantin Stepanov ", "Ari Rios "] +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" diff --git a/src/client.rs b/src/client.rs index 19452bf0..14b74faa 100644 --- a/src/client.rs +++ b/src/client.rs @@ -399,6 +399,11 @@ impl Client { 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(&mut self, path: &P) -> Result> { let mut buf = vec![]; @@ -422,6 +427,42 @@ impl Client { 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(&mut self, path: &P) -> Result<(Option, Vec)> { + 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::()? == buf.len() { + break; + } + } + Ok((mime_type, buf)) + } + /// Case-insensitively search for songs matching Query conditions. pub fn search(&mut self, query: &Query, window: W) -> Result> where W: Into { @@ -432,6 +473,36 @@ impl Client { self.run_command(cmd, (query, window)).and_then(|_| self.read_structs("file")) } + /// Find several files by full path, batching requests + pub fn find_paths(&mut self, paths: I) -> Result>> + where + I: IntoIterator, + P: AsRef, + { + let mut queries: Vec = 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