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 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())
}

View file

@ -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<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 {
properties: Vec<(String, String)>,
binary: Option<Vec<u8>>,
@ -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));
}
}

View file

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

View file

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

View file

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

View file

@ -1,5 +1,5 @@
pub mod index;
pub mod queue;
pub mod player;
pub mod art;
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 askama::Template;
use std::collections::HashMap;
#[derive(Template)]
@ -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();

View file

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