Reuse the same mpd connection

This commit is contained in:
Sijmen 2023-12-23 06:16:50 +01:00
parent b8416b29dd
commit ef43275561
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
6 changed files with 30 additions and 15 deletions

View file

@ -3,22 +3,26 @@ mod routes;
mod crate_version; mod crate_version;
async fn post_play(_req: tide::Request<()>) -> tide::Result { async fn post_play(_req: tide::Request<()>) -> tide::Result {
mpd::Mpd::connect().await?.command("play").await?; let mut mpd = mpd::get_instance().await;
mpd.command("play").await?;
Ok("".into()) Ok("".into())
} }
async fn post_pause(_req: tide::Request<()>) -> tide::Result { async fn post_pause(_req: tide::Request<()>) -> tide::Result {
mpd::Mpd::connect().await?.command("pause 1").await?; let mut mpd = mpd::get_instance().await;
mpd.command("pause 1").await?;
Ok("".into()) Ok("".into())
} }
async fn post_previous(_req: tide::Request<()>) -> tide::Result { async fn post_previous(_req: tide::Request<()>) -> tide::Result {
mpd::Mpd::connect().await?.command("previous").await?; let mut mpd = mpd::get_instance().await;
mpd.command("previous").await?;
Ok("".into()) Ok("".into())
} }
async fn post_next(_req: tide::Request<()>) -> tide::Result { async fn post_next(_req: tide::Request<()>) -> tide::Result {
mpd::Mpd::connect().await?.command("next").await?; let mut mpd = mpd::get_instance().await;
mpd.command("next").await?;
Ok("".into()) Ok("".into())
} }

View file

@ -1,9 +1,11 @@
use std::collections::HashMap; use std::{collections::HashMap, sync::OnceLock};
use anyhow::anyhow; use anyhow::anyhow;
use async_std::{ use async_std::{
io::{prelude::BufReadExt, BufReader, ReadExt, WriteExt}, io::{prelude::BufReadExt, BufReader, ReadExt, WriteExt},
net::TcpStream, net::TcpStream,
sync::{Mutex, MutexGuard},
task::block_on,
}; };
pub fn host() -> String { pub fn host() -> String {
@ -37,12 +39,19 @@ pub enum Entry {
}, },
} }
#[derive(Debug)]
pub struct Mpd { pub struct Mpd {
stream: TcpStream, stream: TcpStream,
reader: BufReader<TcpStream>, reader: BufReader<TcpStream>,
} }
#[derive(Debug)] pub static INSTANCE: OnceLock<Mutex<Mpd>> = OnceLock::new();
pub async fn get_instance() -> MutexGuard<'static, Mpd> {
let instance = INSTANCE.get_or_init(|| Mutex::from(block_on(Mpd::connect()).unwrap()));
instance.lock().await
}
pub struct CommandResult { pub struct CommandResult {
properties: Vec<(String, String)>, properties: Vec<(String, String)>,
binary: Option<Vec<u8>>, binary: Option<Vec<u8>>,
@ -107,7 +116,7 @@ impl Mpd {
let mut buffer = String::new(); let mut buffer = String::new();
this.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_default();
if !password.is_empty() { if !password.is_empty() {
let password = Self::escape_str(&password); let password = Self::escape_str(&password);
this.command(&format!(r#"password "{password}""#)).await?; this.command(&format!(r#"password "{password}""#)).await?;
@ -159,7 +168,7 @@ impl Mpd {
} 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)); break Err(anyhow!(buffer));
} }
} }

View file

@ -12,7 +12,7 @@ pub async fn get_art(req: tide::Request<()>) -> tide::Result {
let query: ArtQuery = req.query()?; let query: ArtQuery = req.query()?;
let path = percent_decode_str(&query.path).decode_utf8_lossy(); let path = percent_decode_str(&query.path).decode_utf8_lossy();
let mut mpd = mpd::Mpd::connect().await?; let mut mpd = mpd::get_instance().await;
let resp = if let Ok(art) = mpd.albumart(&path).await { let resp = if let Ok(art) = mpd.albumart(&path).await {
let mime = infer::get(&art) let mime = infer::get(&art)

View file

@ -20,7 +20,8 @@ struct BrowserQuery {
pub async fn get_browser(req: tide::Request<()>) -> tide::Result { pub async fn get_browser(req: tide::Request<()>) -> tide::Result {
let query: BrowserQuery = req.query()?; let query: BrowserQuery = req.query()?;
let path = percent_decode_str(&query.path).decode_utf8_lossy(); let path = percent_decode_str(&query.path).decode_utf8_lossy();
let entries = mpd::Mpd::connect().await?.ls(&path).await?; let mut mpd = mpd::get_instance().await;
let entries = mpd.ls(&path).await?;
let template = BrowserTemplate { let template = BrowserTemplate {
path: Path::new(&*path) path: Path::new(&*path)

View file

@ -13,7 +13,7 @@ struct PlayerTemplate<'a> {
} }
pub async fn get_player(_req: tide::Request<()>) -> tide::Result { pub async fn get_player(_req: tide::Request<()>) -> tide::Result {
let mut mpd = mpd::Mpd::connect().await?; let mut mpd = mpd::get_instance().await;
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();

View file

@ -10,7 +10,8 @@ struct QueueTemplate {
} }
pub async fn get_queue(_req: tide::Request<()>) -> tide::Result { pub async fn get_queue(_req: tide::Request<()>) -> tide::Result {
let queue = mpd::Mpd::connect().await?.playlist().await?; let mut mpd = mpd::get_instance().await;
let queue = mpd.playlist().await?;
let template = QueueTemplate { queue }; let template = QueueTemplate { queue };
Ok(template.into()) Ok(template.into())
} }
@ -29,7 +30,7 @@ struct PostQueueQuery {
pub async fn post_queue(req: tide::Request<()>) -> tide::Result { pub async fn post_queue(req: tide::Request<()>) -> tide::Result {
let query: PostQueueQuery = req.query()?; let query: PostQueueQuery = req.query()?;
let path = percent_decode_str(&query.path).decode_utf8_lossy(); let path = percent_decode_str(&query.path).decode_utf8_lossy();
let mut mpd = mpd::Mpd::connect().await?; let mut mpd = mpd::get_instance().await;
if query.replace { if query.replace {
mpd.clear().await?; mpd.clear().await?;
@ -57,7 +58,7 @@ struct DeleteQueueQuery {
pub async fn delete_queue(req: tide::Request<()>) -> tide::Result { pub async fn delete_queue(req: tide::Request<()>) -> tide::Result {
let query: DeleteQueueQuery = req.query()?; let query: DeleteQueueQuery = req.query()?;
let mut mpd = mpd::Mpd::connect().await?; let mut mpd = mpd::get_instance().await;
if let Some(id) = query.id { if let Some(id) = query.id {
mpd.command(&format!("deleteid {id}")).await?; mpd.command(&format!("deleteid {id}")).await?;
} else { } else {
@ -75,7 +76,7 @@ struct UpdateQueueBody {
pub async fn post_queue_move(mut req: tide::Request<()>) -> tide::Result { pub async fn post_queue_move(mut req: tide::Request<()>) -> tide::Result {
let body: UpdateQueueBody = req.body_json().await?; let body: UpdateQueueBody = req.body_json().await?;
let mut mpd = mpd::Mpd::connect().await?; let mut mpd = mpd::get_instance().await;
mpd.command(&format!("move {} {}", body.from, body.to)) mpd.command(&format!("move {} {}", body.from, body.to))
.await?; .await?;
Ok("".into()) Ok("".into())