Compare commits
5 commits
26a3381a25
...
dae598e15c
Author | SHA1 | Date | |
---|---|---|---|
dae598e15c | |||
9dfa38225f | |||
62651ea80b | |||
1cf1429753 | |||
05dddfde6d |
2 changed files with 41 additions and 34 deletions
10
src/main.rs
10
src/main.rs
|
@ -53,8 +53,14 @@ async fn get_player(_req: tide::Request<()>) -> tide::Result {
|
||||||
let song = mpd.command("currentsong").await?.into_hashmap();
|
let song = mpd.command("currentsong").await?.into_hashmap();
|
||||||
let status = mpd.command("status").await?.into_hashmap();
|
let status = mpd.command("status").await?.into_hashmap();
|
||||||
|
|
||||||
let elapsed = status["elapsed"].parse().unwrap_or(0.0);
|
let elapsed = status
|
||||||
let duration = status["duration"].parse().unwrap_or(1.0);
|
.get("elapsed")
|
||||||
|
.and_then(|e| e.parse().ok())
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
let duration = status
|
||||||
|
.get("duration")
|
||||||
|
.and_then(|e| e.parse().ok())
|
||||||
|
.unwrap_or(1.0);
|
||||||
|
|
||||||
let mut template = PlayerTemplate {
|
let mut template = PlayerTemplate {
|
||||||
song: if song.is_empty() { None } else { Some(&song) },
|
song: if song.is_empty() { None } else { Some(&song) },
|
||||||
|
|
65
src/mpd.rs
65
src/mpd.rs
|
@ -49,6 +49,20 @@ pub struct CommandResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandResult {
|
impl CommandResult {
|
||||||
|
pub fn new(properties: Vec<(String, String)>) -> Self {
|
||||||
|
Self {
|
||||||
|
properties,
|
||||||
|
binary: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_binary(properties: Vec<(String, String)>, binary: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
properties,
|
||||||
|
binary: Some(binary),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_hashmap(self) -> HashMap<String, String> {
|
pub fn into_hashmap(self) -> HashMap<String, String> {
|
||||||
self.properties.into_iter().collect()
|
self.properties.into_iter().collect()
|
||||||
}
|
}
|
||||||
|
@ -84,28 +98,24 @@ impl Mpd {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn connect() -> anyhow::Result<Self> {
|
pub async fn connect() -> anyhow::Result<Self> {
|
||||||
let mut stream = TcpStream::connect(host()).await?;
|
let stream = TcpStream::connect(host()).await?;
|
||||||
let mut reader = BufReader::new(stream.clone());
|
let reader = BufReader::new(stream.clone());
|
||||||
|
let mut this = Self { stream, reader };
|
||||||
|
|
||||||
// skip OK MPD line
|
// skip OK MPD line
|
||||||
// TODO check if it is indeed OK
|
// TODO check if it is indeed OK
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
reader.read_line(&mut buffer).await?;
|
this.reader.read_line(&mut buffer).await?;
|
||||||
|
|
||||||
let password = std::env::var("MPD_PASSWORD").unwrap_or(String::new());
|
let password = std::env::var("MPD_PASSWORD").unwrap_or(String::new());
|
||||||
if !password.is_empty() {
|
if !password.is_empty() {
|
||||||
let password = Self::escape_str(&password);
|
let password = Self::escape_str(&password);
|
||||||
let command = format!("password \"{password}\"\n");
|
this.command(&format!(r#"password "{password}""#)).await?;
|
||||||
stream.write_all(command.as_bytes()).await?;
|
|
||||||
|
|
||||||
reader.read_line(&mut buffer).await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.write_all(b"binarylimit 1048576\n").await?;
|
this.command("binarylimit 1048576").await?;
|
||||||
buffer.clear();
|
|
||||||
reader.read_line(&mut buffer).await?;
|
|
||||||
|
|
||||||
Ok(Self { stream, reader })
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_binary_data(&mut self, size: usize) -> anyhow::Result<Vec<u8>> {
|
async fn read_binary_data(&mut self, size: usize) -> anyhow::Result<Vec<u8>> {
|
||||||
|
@ -142,21 +152,15 @@ impl Mpd {
|
||||||
|
|
||||||
if key == "binary" {
|
if key == "binary" {
|
||||||
let binary = self.read_binary_data(value.parse()?).await?;
|
let binary = self.read_binary_data(value.parse()?).await?;
|
||||||
|
break Ok(CommandResult::new_binary(properties, binary));
|
||||||
break Ok(CommandResult {
|
|
||||||
properties,
|
|
||||||
binary: Some(binary),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if buffer.starts_with("OK") {
|
} else if buffer.starts_with("OK") {
|
||||||
break Ok(CommandResult {
|
break Ok(CommandResult::new(properties));
|
||||||
properties,
|
|
||||||
binary: None,
|
|
||||||
});
|
|
||||||
} else if buffer.starts_with("ACK") {
|
} else if buffer.starts_with("ACK") {
|
||||||
break Err(anyhow!(buffer));
|
break Err(anyhow!(buffer));
|
||||||
} else {
|
} else {
|
||||||
println!("Unexpected MPD response {buffer}");
|
println!("Unexpected MPD response {buffer}");
|
||||||
|
break Err(anyhow!(buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,16 +176,10 @@ impl Mpd {
|
||||||
if !binary.is_empty() {
|
if !binary.is_empty() {
|
||||||
buffer.append(&mut binary);
|
buffer.append(&mut binary);
|
||||||
} else {
|
} else {
|
||||||
return Ok(CommandResult {
|
return Ok(CommandResult::new_binary(result.properties, buffer));
|
||||||
properties: result.properties,
|
|
||||||
binary: Some(buffer),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(CommandResult {
|
return Ok(CommandResult::new(result.properties));
|
||||||
properties: result.properties,
|
|
||||||
binary: None,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +198,7 @@ impl Mpd {
|
||||||
pub async fn add_pos(&mut self, path: &str, pos: &str) -> anyhow::Result<()> {
|
pub async fn add_pos(&mut self, path: &str, pos: &str) -> anyhow::Result<()> {
|
||||||
let path = Self::escape_str(path);
|
let path = Self::escape_str(path);
|
||||||
let pos = Self::escape_str(pos);
|
let pos = Self::escape_str(pos);
|
||||||
self.command(&format!("add \"{path}\" \"{pos}\"")).await?;
|
self.command(&format!(r#"add "{path}" "{pos}""#)).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +221,9 @@ impl Mpd {
|
||||||
|
|
||||||
pub async fn albumart(&mut self, path: &str) -> anyhow::Result<Vec<u8>> {
|
pub async fn albumart(&mut self, path: &str) -> anyhow::Result<Vec<u8>> {
|
||||||
let path = Self::escape_str(path);
|
let path = Self::escape_str(path);
|
||||||
let result = self.command_binary(&format!("albumart \"{path}\"")).await?;
|
let result = self
|
||||||
|
.command_binary(&format!(r#"albumart "{path}""#))
|
||||||
|
.await?;
|
||||||
|
|
||||||
match result.binary {
|
match result.binary {
|
||||||
Some(binary) => Ok(binary),
|
Some(binary) => Ok(binary),
|
||||||
|
@ -234,7 +234,7 @@ impl Mpd {
|
||||||
pub async fn readpicture(&mut self, path: &str) -> anyhow::Result<Vec<u8>> {
|
pub async fn readpicture(&mut self, path: &str) -> anyhow::Result<Vec<u8>> {
|
||||||
let path = Self::escape_str(path);
|
let path = Self::escape_str(path);
|
||||||
let result = self
|
let result = self
|
||||||
.command_binary(&format!("readpicture \"{path}\""))
|
.command_binary(&format!(r#"readpicture "{path}""#))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match result.binary {
|
match result.binary {
|
||||||
|
@ -252,8 +252,9 @@ impl Mpd {
|
||||||
.unwrap_or("n/a".to_string())
|
.unwrap_or("n/a".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let path = Self::escape_str(path);
|
||||||
let result = self
|
let result = self
|
||||||
.command(&format!("lsinfo \"{}\"", Self::escape_str(path)))
|
.command(&format!(r#"lsinfo "{path}""#))
|
||||||
.await?
|
.await?
|
||||||
.into_hashmaps(&["file", "directory", "playlist"]);
|
.into_hashmaps(&["file", "directory", "playlist"]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue