Compare commits

...

2 commits

Author SHA1 Message Date
4119956810
Run rustfmt 2023-12-23 06:16:59 +01:00
ef43275561
Reuse the same mpd connection 2023-12-23 06:16:50 +01:00
8 changed files with 42 additions and 27 deletions

View file

@ -1,24 +1,28 @@
mod crate_version;
mod mpd; mod mpd;
mod routes; mod routes;
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

@ -1,6 +1,6 @@
use serde::Deserialize;
use crate::mpd; use crate::mpd;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use serde::Deserialize;
#[derive(Deserialize, Default)] #[derive(Deserialize, Default)]
#[serde(default)] #[serde(default)]
@ -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

@ -1,7 +1,7 @@
use askama::Template;
use serde::Deserialize;
use crate::mpd; use crate::mpd;
use askama::Template;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use serde::Deserialize;
use std::path::Path; use std::path::Path;
#[derive(Template)] #[derive(Template)]
@ -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

@ -1,6 +1,6 @@
use crate::crate_version;
use askama::Template; use askama::Template;
use serde::Deserialize; use serde::Deserialize;
use crate::crate_version;
#[derive(Template)] #[derive(Template)]
#[template(path = "index.html")] #[template(path = "index.html")]

View file

@ -1,5 +1,5 @@
pub mod index; pub mod art;
pub mod queue;
pub mod player;
pub mod browser; pub mod browser;
pub mod art; pub mod index;
pub mod player;
pub mod queue;

View file

@ -1,5 +1,5 @@
use askama::Template;
use crate::mpd; use crate::mpd;
use askama::Template;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Template)] #[derive(Template)]
@ -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

@ -1,7 +1,7 @@
use askama::Template;
use crate::mpd; use crate::mpd;
use serde::Deserialize; use askama::Template;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use serde::Deserialize;
#[derive(Template)] #[derive(Template)]
#[template(path = "queue.html")] #[template(path = "queue.html")]
@ -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())