Skip to content

Commit

Permalink
Add albumart support.
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonTeixidor committed Mar 14, 2021
1 parent 2235a4c commit 8642c72
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
50 changes: 45 additions & 5 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use bufstream::BufStream;

use crate::convert::*;
use crate::error::{Error, ProtoError, Result};
use crate::error::{Error, ParseError, ProtoError, Result};
use crate::message::{Channel, Message};
use crate::mount::{Mount, Neighbor};
use crate::output::Output;
Expand Down Expand Up @@ -384,6 +384,29 @@ impl<S: Read + Write> Client<S> {
self.find_generic("find", query, window.into())
}

/// Find album art for file
pub fn albumart<P: ToSongPath>(&mut self, path: &P) -> Result<Vec<u8>> {
let mut buf = vec![];
loop {
self.run_command("albumart", (path, &*format!("{}", buf.len())))?;
let (_, size) = self.read_pair()?;
let (_, bytes) = self.read_pair()?;
let mut chunk = self.read_bytes(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(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 Down Expand Up @@ -615,19 +638,36 @@ impl<S: Read + Write> Client<S> {
impl<S: Read + Write> Proto for Client<S> {
type Stream = S;

fn read_bytes(&mut self, bytes: usize) -> Result<Vec<u8>> {
let mut buf = Vec::with_capacity(bytes);
let mut chunk = (&mut self.socket).take(bytes as u64);
chunk.read_to_end(&mut buf)?;
Ok(buf)
}

fn read_line(&mut self) -> Result<String> {
let mut buf = String::new();
self.socket.read_line(&mut buf)?;
if buf.ends_with('\n') {
let mut buf = Vec::new();
self.socket.read_until(b'\n', &mut buf)?;
if buf.ends_with(&[b'\n']) {
buf.pop();
}
Ok(buf)
let str = String::from_utf8(buf)
.map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "stream did not contain valid UTF-8"))?;
Ok(str)
}

fn read_pairs(&mut self) -> Pairs<Lines<&mut BufStream<S>>> {
Pairs((&mut self.socket).lines())
}

fn read_pair(&mut self) -> Result<(String, String)> {
let line = self.read_line()?;
let mut split = line.split(": ");
let key = split.next().ok_or(ParseError::BadPair)?;
let val = split.next().ok_or(ParseError::BadPair)?;
Ok((key.to_string(), val.to_string()))
}

fn run_command<I>(&mut self, command: &str, arguments: I) -> Result<()>
where I: ToArguments
{
Expand Down
1 change: 1 addition & 0 deletions src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl<I> Pairs<I>
pub trait Proto {
type Stream: Read + Write;

fn read_bytes(&mut self, bytes: usize) -> Result<Vec<u8>>;
fn read_line(&mut self) -> Result<String>;
fn read_pairs(&mut self) -> Pairs<Lines<&mut BufStream<Self::Stream>>>;

Expand Down

0 comments on commit 8642c72

Please sign in to comment.