diff --git a/musicdb-server/src/web.rs b/musicdb-server/src/web.rs index 3604cbb..3fde47b 100755 --- a/musicdb-server/src/web.rs +++ b/musicdb-server/src/web.rs @@ -4,7 +4,7 @@ use std::sync::{mpsc, Arc, Mutex}; use musicdb_lib::data::album::Album; use musicdb_lib::data::artist::Artist; use musicdb_lib::data::database::Database; -use musicdb_lib::data::queue::{QueueContent, QueueFolder}; +use musicdb_lib::data::queue::{Queue, QueueContent, QueueFolder}; use musicdb_lib::data::song::Song; use musicdb_lib::data::SongId; use musicdb_lib::server::Command; @@ -34,7 +34,7 @@ use rocket::{get, routes, Config, State}; */ const HTML_START: &'static str = - ""; + ""; const HTML_SEP: &'static str = ""; const HTML_END: &'static str = ""; @@ -44,8 +44,10 @@ struct Data { } #[get("/")] -async fn index(data: &State) -> RawHtml { +fn index(data: &State) -> RawHtml { + dbg!(()); let script = r#""#; - let buttons = ""; + let script2 = r#""#; + let buttons = ""; let search = "
"; let db = data.db.lock().unwrap(); - let now_playing = - if let Some(current_song) = db.queue.get_current_song().and_then(|id| db.get_song(id)) { - format!( - "

Now Playing

{}

", - html_escape::encode_safe(¤t_song.title), - ) - } else { - format!("

Now Playing

nothing

",) - }; + let now_playing = gen_now_playing(&db); + let mut queue = String::new(); + gen_queue_html(&db.queue, &mut queue, &db); + dbg!(&queue); drop(db); RawHtml(format!( - "{HTML_START}MusicDb{script}{HTML_SEP}{now_playing}
{buttons}
{search}
{HTML_END}", + "{HTML_START}MusicDb{script}{HTML_SEP}
no javascript? reload to see updated information.
{now_playing}
{buttons}
{search}
{queue}
{script2}{HTML_END}", )) } +#[get("/now-playing-html")] +fn now_playing_html(data: &State) -> RawHtml { + RawHtml(gen_now_playing(&*data.db.lock().unwrap())) +} +#[get("/queue-html")] +fn queue_html(data: &State) -> RawHtml { + let mut str = String::new(); + let db = data.db.lock().unwrap(); + gen_queue_html(&db.queue, &mut str, &db); + RawHtml(str) +} +fn gen_now_playing(db: &Database) -> String { + if let Some(current_song) = db.queue.get_current_song().and_then(|id| db.get_song(id)) { + format!( + "

Now Playing

{}

", + html_escape::encode_safe(¤t_song.title), + ) + } else { + format!("

Now Playing

nothing

",) + } +} +fn gen_queue_html(queue: &Queue, str: &mut String, db: &Database) { + gen_queue_html_impl(queue, str, db, true, &mut "".to_owned()); +} +fn gen_queue_html_impl( + queue: &Queue, + str: &mut String, + db: &Database, + active_highlight: bool, + path: &mut String, +) { + match queue.content() { + QueueContent::Song(id) => { + if let Some(song) = db.songs().get(id) { + str.push_str("
"); + if active_highlight { + str.push_str(""); + } + str.push_str(&format!(""); + if active_highlight { + str.push_str(""); + } + str.push_str(""); + if let Some(artist) = db.artists().get(&song.artist) { + str.push_str(" by "); + str.push_str(&html_escape::encode_text(&artist.name)); + } + if let Some(album) = song.album.as_ref().and_then(|id| db.albums().get(id)) { + str.push_str(" on "); + str.push_str(&html_escape::encode_text(&album.name)); + } + str.push_str(&format!( + "" + )); + str.push_str("
"); + } else { + str.push_str("
unknown song
"); + } + } + QueueContent::Folder(f) => { + let html_shuf: &'static str = " shuffled"; + if f.content.is_empty() { + str.push_str("[0/0] "); + if active_highlight { + str.push_str(""); + } + str.push_str(&html_escape::encode_text(&f.name)); + if active_highlight { + str.push_str(""); + } + if f.order.is_some() { + str.push_str(html_shuf); + } + } else { + str.push_str(&format!("[{}/{}] ", f.index + 1, f.content.len(),)); + if active_highlight { + str.push_str(""); + } + str.push_str(&html_escape::encode_text(&f.name)); + if active_highlight { + str.push_str(""); + } + if f.order.is_some() { + str.push_str(html_shuf); + } + str.push_str("
    "); + for (i, v) in f.iter().enumerate() { + str.push_str("
  1. "); + if !path.is_empty() { + path.push('_'); + } + path.push_str(&format!("{i}")); + gen_queue_html_impl(v, str, db, active_highlight && i == f.index, path); + while !(path.is_empty() || path.ends_with('_')) { + path.pop(); + } + path.pop(); + str.push_str("
  2. "); + } + str.push_str("
"); + } + } + QueueContent::Loop(d, t, i) => { + if active_highlight { + str.push_str(""); + } + if *t == 0 { + str.push_str(&format!("[{}/∞]", d + 1)); + } else { + str.push_str(&format!("[{}/{}]", d + 1, t)); + } + if active_highlight { + str.push_str(""); + } + if !path.is_empty() { + path.push('_'); + } + path.push('0'); + gen_queue_html_impl(i, str, db, active_highlight, path); + while !(path.is_empty() || path.ends_with('_')) { + path.pop(); + } + path.pop(); + } + } +} + +#[get("/queue-remove/")] +fn queue_remove(data: &State, path: &str) { + if let Some(path) = path.split('_').map(|v| v.parse().ok()).collect() { + data.command_sender + .send(Command::QueueRemove(path)) + .unwrap(); + } +} +#[get("/queue-goto/")] +fn queue_goto(data: &State, path: &str) { + if let Some(path) = path.split('_').map(|v| v.parse().ok()).collect() { + data.command_sender.send(Command::QueueGoto(path)).unwrap(); + } +} #[get("/play")] -async fn play(data: &State) { +fn play(data: &State) { data.command_sender.send(Command::Resume).unwrap(); } #[get("/pause")] -async fn pause(data: &State) { +fn pause(data: &State) { data.command_sender.send(Command::Pause).unwrap(); } #[get("/skip")] -async fn skip(data: &State) { +fn skip(data: &State) { data.command_sender.send(Command::NextSong).unwrap(); } #[get("/clear-queue")] -async fn clear_queue(data: &State) { +fn clear_queue(data: &State) { data.command_sender .send(Command::QueueUpdate( vec![], @@ -129,7 +298,7 @@ async fn clear_queue(data: &State) { } #[get("/add-song/")] -async fn add_song(data: &State, id: SongId) { +fn add_song(data: &State, id: SongId) { data.command_sender .send(Command::QueueAdd( vec![], @@ -139,7 +308,7 @@ async fn add_song(data: &State, id: SongId) { } #[get("/search?&&&<artist_tags>&<album_tags>&<song_tags>")] -async fn search( +fn search( data: &State<Data>, artist: Option<&str>, album: Option<&str>, @@ -371,7 +540,19 @@ pub async fn main( .manage(Data { db, command_sender }) .mount( "/", - routes![index, play, pause, skip, clear_queue, add_song, search], + routes![ + index, + play, + pause, + skip, + clear_queue, + queue_goto, + queue_remove, + add_song, + search, + now_playing_html, + queue_html + ], ) .launch() .await