From ef43275561508e6d3f8f6137f5cee3c7c13b653c Mon Sep 17 00:00:00 2001 From: Sijmen Date: Sat, 23 Dec 2023 06:16:50 +0100 Subject: [PATCH] Reuse the same mpd connection --- src/main.rs | 12 ++++++++---- src/mpd.rs | 17 +++++++++++++---- src/routes/art.rs | 2 +- src/routes/browser.rs | 3 ++- src/routes/player.rs | 2 +- src/routes/queue.rs | 9 +++++---- 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index e9d74af..7598eb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,22 +3,26 @@ mod routes; mod crate_version; 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()) } 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()) } 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()) } 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()) } diff --git a/src/mpd.rs b/src/mpd.rs index 92deabb..6f0d3d4 100644 --- a/src/mpd.rs +++ b/src/mpd.rs @@ -1,9 +1,11 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::OnceLock}; use anyhow::anyhow; use async_std::{ io::{prelude::BufReadExt, BufReader, ReadExt, WriteExt}, net::TcpStream, + sync::{Mutex, MutexGuard}, + task::block_on, }; pub fn host() -> String { @@ -37,12 +39,19 @@ pub enum Entry { }, } +#[derive(Debug)] pub struct Mpd { stream: TcpStream, reader: BufReader, } -#[derive(Debug)] +pub static INSTANCE: OnceLock> = 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 { properties: Vec<(String, String)>, binary: Option>, @@ -107,7 +116,7 @@ impl Mpd { let mut buffer = String::new(); 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() { let password = Self::escape_str(&password); this.command(&format!(r#"password "{password}""#)).await?; @@ -159,7 +168,7 @@ impl Mpd { } else if buffer.starts_with("ACK") { break Err(anyhow!(buffer)); } else { - println!("Unexpected MPD response {buffer}"); + println!("Unexpected MPD response '{buffer}'"); break Err(anyhow!(buffer)); } } diff --git a/src/routes/art.rs b/src/routes/art.rs index 0cbfb62..388cb22 100644 --- a/src/routes/art.rs +++ b/src/routes/art.rs @@ -12,7 +12,7 @@ pub async fn get_art(req: tide::Request<()>) -> tide::Result { let query: ArtQuery = req.query()?; 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 mime = infer::get(&art) diff --git a/src/routes/browser.rs b/src/routes/browser.rs index 1316a96..5341e65 100644 --- a/src/routes/browser.rs +++ b/src/routes/browser.rs @@ -20,7 +20,8 @@ struct BrowserQuery { pub async fn get_browser(req: tide::Request<()>) -> tide::Result { let query: BrowserQuery = req.query()?; 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 { path: Path::new(&*path) diff --git a/src/routes/player.rs b/src/routes/player.rs index 0b1ac74..812887d 100644 --- a/src/routes/player.rs +++ b/src/routes/player.rs @@ -13,7 +13,7 @@ struct PlayerTemplate<'a> { } 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 status = mpd.command("status").await?.into_hashmap(); diff --git a/src/routes/queue.rs b/src/routes/queue.rs index 26dcc5d..b0d224a 100644 --- a/src/routes/queue.rs +++ b/src/routes/queue.rs @@ -10,7 +10,8 @@ struct QueueTemplate { } 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 }; Ok(template.into()) } @@ -29,7 +30,7 @@ struct PostQueueQuery { pub async fn post_queue(req: tide::Request<()>) -> tide::Result { let query: PostQueueQuery = req.query()?; 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 { mpd.clear().await?; @@ -57,7 +58,7 @@ struct DeleteQueueQuery { pub async fn delete_queue(req: tide::Request<()>) -> tide::Result { 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 { mpd.command(&format!("deleteid {id}")).await?; } else { @@ -75,7 +76,7 @@ struct UpdateQueueBody { pub async fn post_queue_move(mut req: tide::Request<()>) -> tide::Result { 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)) .await?; Ok("".into())