lib_dir is no longer saved in dbfile

This commit is contained in:
Mark 2023-10-04 13:57:55 +02:00
parent 4a729c596c
commit 3093ec1a25
8 changed files with 108 additions and 364 deletions

View File

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
clap = { version = "4.4.6", features = ["derive"] }
directories = "5.0.1" directories = "5.0.1"
musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" } musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" }
regex = "1.9.3" regex = "1.9.3"

View File

@ -198,7 +198,7 @@ impl Gui {
| Command::Pause | Command::Pause
| Command::Stop | Command::Stop
| Command::Save | Command::Save
| Command::SetLibraryDirectory(..) => {} | Command::InitComplete => {}
Command::NextSong Command::NextSong
| Command::QueueUpdate(..) | Command::QueueUpdate(..)
| Command::QueueAdd(..) | Command::QueueAdd(..)

View File

@ -1,5 +1,4 @@
use std::{ use std::{
eprintln, fs,
io::{BufReader, Write}, io::{BufReader, Write},
net::{SocketAddr, TcpStream}, net::{SocketAddr, TcpStream},
path::PathBuf, path::PathBuf,
@ -8,15 +7,12 @@ use std::{
time::Duration, time::Duration,
}; };
use clap::{Parser, Subcommand};
use gui::GuiEvent; use gui::GuiEvent;
use musicdb_lib::{ use musicdb_lib::{
data::{ data::{
album::Album, database::{ClientIo, Database},
artist::Artist, CoverId, SongId,
database::{ClientIo, Cover, Database},
queue::QueueContent,
song::Song,
CoverId, DatabaseLocation, GeneralData, SongId,
}, },
load::ToFromBytes, load::ToFromBytes,
player::Player, player::Player,
@ -44,12 +40,24 @@ mod gui_text;
mod gui_wrappers; mod gui_wrappers;
mod textcfg; mod textcfg;
#[derive(Clone, Copy)] #[derive(Parser, Debug)]
struct Args {
/// the address to be used for the tcp connection to the server
addr: SocketAddr,
/// what to do
#[command(subcommand)]
mode: Mode,
}
#[derive(Subcommand, Debug, Clone)]
enum Mode { enum Mode {
Cli, #[cfg(feature = "speedy2d")]
/// graphical user interface
Gui, Gui,
SyncPlayer, /// play in sync with the server, but load the songs from a local copy of the lib-dir
SyncPlayerWithoutData, SyncplayerLocal { lib_dir: PathBuf },
/// play in sync with the server, and fetch the songs from it too. slower than the local variant for obvious reasons
SyncplayerNetwork,
} }
fn get_config_file_path() -> PathBuf { fn get_config_file_path() -> PathBuf {
@ -57,36 +65,15 @@ fn get_config_file_path() -> PathBuf {
.unwrap() .unwrap()
.config_dir() .config_dir()
.to_path_buf() .to_path_buf()
// if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") {
// let mut config_home: PathBuf = config_home.into();
// config_home.push("musicdb-client");
// config_home
// } else if let Ok(home) = std::env::var("HOME") {
// let mut config_home: PathBuf = home.into();
// config_home.push(".config");
// config_home.push("musicdb-client");
// config_home
// } else {
// eprintln!("No config directory!");
// std::process::exit(24);
// }
} }
fn main() { fn main() {
let mut args = std::env::args().skip(1); // parse args
let mode = match args.next().as_ref().map(|v| v.trim()) { let args = Args::parse();
Some("cli") => Mode::Cli, // start
Some("gui") => Mode::Gui, let addr = args.addr;
Some("syncplayer") => Mode::SyncPlayer,
Some("syncplayernd") => Mode::SyncPlayerWithoutData,
_ => {
println!("Run with argument <cli/gui/syncplayer/syncplayernd>!");
return;
}
};
let addr = args.next().unwrap_or("127.0.0.1:26314".to_string());
let addr = addr.parse::<SocketAddr>().unwrap();
let mut con = TcpStream::connect(addr).unwrap(); let mut con = TcpStream::connect(addr).unwrap();
let mode = args.mode;
writeln!(con, "main").unwrap(); writeln!(con, "main").unwrap();
let database = Arc::new(Mutex::new(Database::new_clientside())); let database = Arc::new(Mutex::new(Database::new_clientside()));
#[cfg(feature = "speedy2d")] #[cfg(feature = "speedy2d")]
@ -95,16 +82,21 @@ fn main() {
#[cfg(feature = "speedy2d")] #[cfg(feature = "speedy2d")]
let sender = Arc::clone(&update_gui_sender); let sender = Arc::clone(&update_gui_sender);
let con_thread = { let con_thread = {
let mode = mode.clone();
let database = Arc::clone(&database); let database = Arc::clone(&database);
let mut con = con.try_clone().unwrap(); let mut con = con.try_clone().unwrap();
// this is all you need to keep the db in sync // this is all you need to keep the db in sync
thread::spawn(move || { thread::spawn(move || {
let mut player = if matches!(mode, Mode::SyncPlayer | Mode::SyncPlayerWithoutData) { let mut player =
Some(Player::new().unwrap()) if matches!(mode, Mode::SyncplayerLocal { .. } | Mode::SyncplayerNetwork) {
Some(Player::new().unwrap())
} else {
None
};
if let Mode::SyncplayerLocal { lib_dir } = mode {
let mut db = database.lock().unwrap();
db.lib_directory = lib_dir;
} else { } else {
None
};
if matches!(mode, Mode::SyncPlayerWithoutData) {
let mut db = database.lock().unwrap(); let mut db = database.lock().unwrap();
let client_con: Box<dyn ClientIo> = Box::new(TcpStream::connect(addr).unwrap()); let client_con: Box<dyn ClientIo> = Box::new(TcpStream::connect(addr).unwrap());
db.remote_server_as_song_file_source = Some(Arc::new(Mutex::new( db.remote_server_as_song_file_source = Some(Arc::new(Mutex::new(
@ -114,7 +106,7 @@ fn main() {
loop { loop {
if let Some(player) = &mut player { if let Some(player) = &mut player {
let mut db = database.lock().unwrap(); let mut db = database.lock().unwrap();
if !db.lib_directory.as_os_str().is_empty() { if db.is_client_init() {
player.update(&mut db); player.update(&mut db);
} }
} }
@ -131,15 +123,8 @@ fn main() {
}) })
}; };
match mode { match mode {
Mode::Cli => { #[cfg(feature = "speedy2d")]
Looper {
con: &mut con,
database: &database,
}
.cmd_loop();
}
Mode::Gui => { Mode::Gui => {
#[cfg(feature = "speedy2d")]
{ {
let occasional_refresh_sender = Arc::clone(&sender); let occasional_refresh_sender = Arc::clone(&sender);
thread::spawn(move || loop { thread::spawn(move || loop {
@ -159,162 +144,12 @@ fn main() {
) )
}; };
} }
Mode::SyncPlayer | Mode::SyncPlayerWithoutData => { Mode::SyncplayerLocal { .. } | Mode::SyncplayerNetwork => {
con_thread.join().unwrap(); con_thread.join().unwrap();
} }
} }
} }
struct Looper<'a> {
pub con: &'a mut TcpStream,
pub database: &'a Arc<Mutex<Database>>,
}
impl<'a> Looper<'a> {
pub fn cmd_loop(&mut self) {
loop {
println!();
let line = self.read_line(" > enter a command (help for help)");
let line = line.trim();
match line {
"resume" => Command::Resume,
"pause" => Command::Pause,
"stop" => Command::Stop,
"next" => Command::NextSong,
"set-lib-dir" => {
let line = self.read_line("Enter the new (absolute) library directory, or leave empty to abort");
if !line.is_empty() {
Command::SetLibraryDirectory(line.into())
} else {
continue;
}
},
"add-song" => {
let song = Song {
id: 0,
location: self.read_line("The songs file is located, relative to the library root, at...").into(),
title: self.read_line("The songs title is..."),
album: self.read_line_ido("The song is part of the album with the id... (empty for None)"),
artist: self.read_line_id("The song is made by the artist with the id..."),
more_artists: accumulate(|| self.read_line_ido("The song is made with support by other artist, one of which has the id... (will ask repeatedly; leave empty once done)")),
cover: self.read_line_ido("The song should use the cover with the id... (empty for None - will default to album or artist cover, if available)"),
general: GeneralData::default(),
cached_data: Arc::new(Mutex::new(None)),
};
println!("You are about to add the following song to the database:");
println!(" + {song}");
if self.read_line("Are you sure? (type 'yes' to continue)").to_lowercase().trim() == "yes" {
Command::AddSong(song)
} else {
println!("[-] Aborted - no event will be sent to the database.");
continue;
}
},
"update-song" => {
let song_id = self.read_line_id("The ID of the song is...");
if let Some(mut song) = self.database.lock().unwrap().get_song(&song_id).cloned() {
println!("You are now editing the song {song}.");
loop {
match self.read_line("What do you want to edit? (title/album/artist/location or done)").to_lowercase().trim() {
"done" => break,
"title" => {
println!("prev: '{}'", song.title);
song.title = self.read_line("");
}
"album" => {
println!("prev: '{}'", song.album.map_or(String::new(), |v| v.to_string()));
song.album = self.read_line_ido("");
}
"artist" => {
println!("prev: '{}'", song.artist);
song.artist = self.read_line_id("");
}
"location" => {
println!("prev: '{:?}'", song.location);
song.location = self.read_line("").into();
}
_ => println!("[-] must be title/album/artist/location or done"),
}
}
println!("You are about to update the song:");
println!(" + {song}");
if self.read_line("Are you sure? (type 'yes' to continue)").to_lowercase().trim() == "yes" {
Command::ModifySong(song)
} else {
println!("[-] Aborted - no event will be sent to the database.");
continue;
}
} else {
println!("[-] No song with that ID found, aborting.");
continue;
}
}
"queue-clear" => Command::QueueUpdate(vec![], QueueContent::Folder(0, vec![], String::new()).into()),
"queue-add-to-end" => Command::QueueAdd(vec![], QueueContent::Song(self.read_line_id("The ID of the song that should be added to the end of the queue is...")).into()),
"save" => Command::Save,
"status" => {
let db = self.database.lock().unwrap();
println!("DB contains {} songs:", db.songs().len());
for song in db.songs().values() {
println!("> [{}]: {}", song.id, song);
}
println!("Queue: {:?}, then {:?}", db.queue.get_current(), db.queue.get_next());
continue;
}
"exit" => {
println!("<< goodbye");
break;
}
_ => {
println!("Type 'exit' to exit, 'status' to see the db, 'resume', 'pause', 'stop', 'next', 'queue-clear', 'queue-add-to-end', 'add-song', 'add-album', 'add-artist', 'update-song', 'update-album', 'update-artist', 'set-lib-dir', or 'save' to control playback or update the db.");
continue;
}
}
.to_bytes(self.con)
.unwrap();
}
}
pub fn read_line(&mut self, q: &str) -> String {
loop {
if !q.is_empty() {
println!("{q}");
}
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
while line.ends_with('\n') || line.ends_with('\r') {
line.pop();
}
if line.trim() == "#" {
self.cmd_loop();
} else {
return line;
}
}
}
pub fn read_line_id(&mut self, q: &str) -> u64 {
loop {
if let Ok(v) = self.read_line(q).trim().parse() {
return v;
} else {
println!("[-] Must be a positive integer.");
}
}
}
pub fn read_line_ido(&mut self, q: &str) -> Option<u64> {
loop {
let line = self.read_line(q);
let line = line.trim();
if line.is_empty() {
return None;
}
if let Ok(v) = line.parse() {
return Some(v);
} else {
println!("[-] Must be a positive integer or nothing for None.");
}
}
}
}
pub fn accumulate<F: FnMut() -> Option<T>, T>(mut f: F) -> Vec<T> { pub fn accumulate<F: FnMut() -> Option<T>, T>(mut f: F) -> Vec<T> {
let mut o = vec![]; let mut o = vec![];
loop { loop {

View File

@ -38,6 +38,8 @@ pub struct Database {
pub command_sender: Option<mpsc::Sender<Command>>, pub command_sender: Option<mpsc::Sender<Command>>,
pub remote_server_as_song_file_source: pub remote_server_as_song_file_source:
Option<Arc<Mutex<crate::server::get::Client<Box<dyn ClientIo>>>>>, Option<Arc<Mutex<crate::server::get::Client<Box<dyn ClientIo>>>>>,
/// only relevant for clients. true if init is done
client_is_init: bool,
} }
pub trait ClientIo: Read + Write + Send {} pub trait ClientIo: Read + Write + Send {}
impl<T: Read + Write + Send> ClientIo for T {} impl<T: Read + Write + Send> ClientIo for T {}
@ -60,6 +62,9 @@ impl Database {
pub fn is_client(&self) -> bool { pub fn is_client(&self) -> bool {
self.db_file.as_os_str().is_empty() self.db_file.as_os_str().is_empty()
} }
pub fn is_client_init(&self) -> bool {
self.client_is_init
}
pub fn get_path(&self, location: &DatabaseLocation) -> PathBuf { pub fn get_path(&self, location: &DatabaseLocation) -> PathBuf {
self.lib_directory.join(&location.rel_path) self.lib_directory.join(&location.rel_path)
} }
@ -220,7 +225,7 @@ impl Database {
} }
// since this is so easy to check for, it comes last. // since this is so easy to check for, it comes last.
// this allows clients to find out when init_connection is done. // this allows clients to find out when init_connection is done.
Command::SetLibraryDirectory(self.lib_directory.clone()).to_bytes(con)?; Command::InitComplete.to_bytes(con)?;
// is initialized now - client can receive updates after this point. // is initialized now - client can receive updates after this point.
// NOTE: Don't write to connection anymore - the db will dispatch updates on its own. // NOTE: Don't write to connection anymore - the db will dispatch updates on its own.
// we just need to handle commands (receive from the connection). // we just need to handle commands (receive from the connection).
@ -341,8 +346,8 @@ impl Database {
Command::RemoveArtist(artist) => { Command::RemoveArtist(artist) => {
_ = self.remove_artist(artist); _ = self.remove_artist(artist);
} }
Command::SetLibraryDirectory(new_dir) => { Command::InitComplete => {
self.lib_directory = new_dir; self.client_is_init = true;
} }
} }
} }
@ -368,6 +373,7 @@ impl Database {
playing: false, playing: false,
command_sender: None, command_sender: None,
remote_server_as_song_file_source: None, remote_server_as_song_file_source: None,
client_is_init: false,
} }
} }
pub fn new_empty(path: PathBuf, lib_dir: PathBuf) -> Self { pub fn new_empty(path: PathBuf, lib_dir: PathBuf) -> Self {
@ -385,13 +391,12 @@ impl Database {
playing: false, playing: false,
command_sender: None, command_sender: None,
remote_server_as_song_file_source: None, remote_server_as_song_file_source: None,
client_is_init: false,
} }
} }
pub fn load_database(path: PathBuf) -> Result<Self, std::io::Error> { pub fn load_database(path: PathBuf, lib_directory: PathBuf) -> Result<Self, std::io::Error> {
let mut file = BufReader::new(File::open(&path)?); let mut file = BufReader::new(File::open(&path)?);
eprintln!("[info] loading library from {file:?}"); eprintln!("[info] loading library from {file:?}");
let lib_directory = ToFromBytes::from_bytes(&mut file)?;
eprintln!("[info] library directory is {lib_directory:?}");
Ok(Self { Ok(Self {
db_file: path, db_file: path,
lib_directory, lib_directory,
@ -406,6 +411,7 @@ impl Database {
playing: false, playing: false,
command_sender: None, command_sender: None,
remote_server_as_song_file_source: None, remote_server_as_song_file_source: None,
client_is_init: false,
}) })
} }
/// saves the database's contents. save path can be overridden /// saves the database's contents. save path can be overridden
@ -425,7 +431,6 @@ impl Database {
.truncate(true) .truncate(true)
.create(true) .create(true)
.open(&path)?; .open(&path)?;
self.lib_directory.to_bytes(&mut file)?;
self.artists.to_bytes(&mut file)?; self.artists.to_bytes(&mut file)?;
self.albums.to_bytes(&mut file)?; self.albums.to_bytes(&mut file)?;
self.songs.to_bytes(&mut file)?; self.songs.to_bytes(&mut file)?;
@ -433,6 +438,10 @@ impl Database {
Ok(path) Ok(path)
} }
pub fn broadcast_update(&mut self, update: &Command) { pub fn broadcast_update(&mut self, update: &Command) {
match update {
Command::InitComplete => return,
_ => {}
}
let mut remove = vec![]; let mut remove = vec![];
let mut bytes = None; let mut bytes = None;
let mut arc = None; let mut arc = None;

View File

@ -4,7 +4,6 @@ use std::{
eprintln, eprintln,
io::{BufRead, BufReader, Read, Write}, io::{BufRead, BufReader, Read, Write},
net::{SocketAddr, TcpListener}, net::{SocketAddr, TcpListener},
path::PathBuf,
sync::{mpsc, Arc, Mutex}, sync::{mpsc, Arc, Mutex},
thread, thread,
time::Duration, time::Duration,
@ -51,7 +50,7 @@ pub enum Command {
RemoveAlbum(AlbumId), RemoveAlbum(AlbumId),
RemoveArtist(ArtistId), RemoveArtist(ArtistId),
ModifyArtist(Artist), ModifyArtist(Artist),
SetLibraryDirectory(PathBuf), InitComplete,
} }
impl Command { impl Command {
pub fn send_to_server(self, db: &Database) -> Result<(), Self> { pub fn send_to_server(self, db: &Database) -> Result<(), Self> {
@ -277,9 +276,8 @@ impl ToFromBytes for Command {
s.write_all(&[0b11011100])?; s.write_all(&[0b11011100])?;
artist.to_bytes(s)?; artist.to_bytes(s)?;
} }
Self::SetLibraryDirectory(path) => { Self::InitComplete => {
s.write_all(&[0b00110001])?; s.write_all(&[0b00110001])?;
path.to_bytes(s)?;
} }
} }
Ok(()) Ok(())
@ -325,7 +323,7 @@ impl ToFromBytes for Command {
0b11010011 => Self::RemoveAlbum(ToFromBytes::from_bytes(s)?), 0b11010011 => Self::RemoveAlbum(ToFromBytes::from_bytes(s)?),
0b11011100 => Self::RemoveArtist(ToFromBytes::from_bytes(s)?), 0b11011100 => Self::RemoveArtist(ToFromBytes::from_bytes(s)?),
0b01011101 => Self::AddCover(ToFromBytes::from_bytes(s)?), 0b01011101 => Self::AddCover(ToFromBytes::from_bytes(s)?),
0b00110001 => Self::SetLibraryDirectory(ToFromBytes::from_bytes(s)?), 0b00110001 => Self::InitComplete,
_ => { _ => {
eprintln!("unexpected byte when reading command; stopping playback."); eprintln!("unexpected byte when reading command; stopping playback.");
Self::Stop Self::Stop

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
axum = { version = "0.6.19", features = ["headers"] } axum = { version = "0.6.19", features = ["headers"] }
clap = { version = "4.4.6", features = ["derive"] }
futures = "0.3.28" futures = "0.3.28"
headers = "0.3.8" headers = "0.3.8"
musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" } musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" }

View File

@ -1,166 +1,68 @@
mod web; mod web;
use std::{ use std::{
net::SocketAddr,
path::PathBuf, path::PathBuf,
process::exit, process::exit,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
thread, thread,
}; };
use clap::Parser;
use musicdb_lib::server::run_server; use musicdb_lib::server::run_server;
use musicdb_lib::data::database::Database; use musicdb_lib::data::database::Database;
/* #[derive(Parser, Debug)]
struct Args {
# Exit codes /// The file which contains information about the songs in your library
#[arg()]
0 => exited as requested by the user dbfile: PathBuf,
1 => exit after printing help message /// The path containing your actual library.
3 => error parsing cli arguments #[arg()]
10 => tried to start with a path that caused some io::Error lib_dir: PathBuf,
11 => tried to start with a path that does not exist (--init prevents this) /// skip reading the `dbfile` (because it doesn't exist yet)
#[arg(long)]
*/ init: bool,
/// optional address for tcp connections to the server
#[arg(long)]
tcp: Option<SocketAddr>,
/// optional address on which to start a website which can be used on devices without `musicdb-client` to control playback.
/// requires the `assets/` folder to be present!
#[arg(long)]
web: Option<SocketAddr>,
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
// parse args // parse args
let mut args = std::env::args().skip(1); let args = Args::parse();
let mut tcp_addr = None; let database = if args.init {
let mut web_addr = None; Database::new_empty(args.dbfile, args.lib_dir)
let mut lib_dir_for_init = None;
let database = if let Some(path_s) = args.next() {
loop {
if let Some(arg) = args.next() {
if arg.starts_with("--") {
match &arg[2..] {
"init" => {
if let Some(lib_dir) = args.next() {
lib_dir_for_init = Some(lib_dir);
} else {
eprintln!(
"[EXIT]
missing argument: --init <lib path>"
);
exit(3);
}
}
"tcp" => {
if let Some(addr) = args.next() {
if let Ok(addr) = addr.parse() {
tcp_addr = Some(addr)
} else {
eprintln!(
"[EXIT]
bad argument: --tcp <addr:port>: couldn't parse <addr:port>"
);
exit(3);
}
} else {
eprintln!(
"[EXIT]
missing argument: --tcp <addr:port>"
);
exit(3);
}
}
"web" => {
if let Some(addr) = args.next() {
if let Ok(addr) = addr.parse() {
web_addr = Some(addr)
} else {
eprintln!(
"[EXIT]
bad argument: --web <addr:port>: couldn't parse <addr:port>"
);
exit(3);
}
} else {
eprintln!(
"[EXIT]
missing argument: --web <addr:port>"
);
exit(3);
}
}
o => {
eprintln!(
"[EXIT]
Unknown long argument --{o}"
);
exit(3);
}
}
} else if arg.starts_with("-") {
match &arg[1..] {
o => {
eprintln!(
"[EXIT]
Unknown short argument -{o}"
);
exit(3);
}
}
} else {
eprintln!(
"[EXIT]
Argument didn't start with - or -- ({arg})."
);
exit(3);
}
} else {
break;
}
}
let path = PathBuf::from(&path_s);
match path.try_exists() {
Ok(exists) => {
if let Some(lib_directory) = lib_dir_for_init {
Database::new_empty(path, lib_directory.into())
} else if exists {
Database::load_database(path).unwrap()
} else {
eprintln!(
"[EXIT]
The provided path does not exist."
);
exit(11);
}
}
Err(e) => {
eprintln!(
"[EXIT]
Error getting information about the provided path '{path_s}': {e}"
);
exit(10);
}
}
} else { } else {
eprintln!( match Database::load_database(args.dbfile.clone(), args.lib_dir.clone()) {
"[EXIT] Ok(db) => db,
musicdb-server - help Err(e) => {
musicdb-server <path to database file> <options> <options> <...> eprintln!("Couldn't load database!");
options: eprintln!(" dbfile: {:?}", args.dbfile);
--init <lib directory> eprintln!(" libdir: {:?}", args.lib_dir);
--tcp <addr:port> eprintln!(" err: {}", e);
--web <addr:port> exit(1);
this help was shown because no arguments were provided." }
); }
exit(1);
}; };
// database can be shared by multiple threads using Arc<Mutex<_>> // database can be shared by multiple threads using Arc<Mutex<_>>
let database = Arc::new(Mutex::new(database)); let database = Arc::new(Mutex::new(database));
if tcp_addr.is_some() || web_addr.is_some() { if args.tcp.is_some() || args.web.is_some() {
if let Some(addr) = web_addr { if let Some(addr) = &args.web {
let (s, mut r) = tokio::sync::mpsc::channel(2); let (s, mut r) = tokio::sync::mpsc::channel(2);
let db = Arc::clone(&database); let db = Arc::clone(&database);
thread::spawn(move || run_server(database, tcp_addr, Some(s))); thread::spawn(move || run_server(database, args.tcp, Some(s)));
if let Some(sender) = r.recv().await { if let Some(sender) = r.recv().await {
web::main(db, sender, addr).await; web::main(db, sender, *addr).await;
} }
} else { } else {
run_server(database, tcp_addr, None); run_server(database, args.tcp, None);
} }
} else { } else {
eprintln!("nothing to do, not starting the server."); eprintln!("nothing to do, not starting the server.");

View File

@ -438,7 +438,7 @@ async fn sse_handler(
.collect::<String>(), .collect::<String>(),
) )
} }
Command::Save | Command::SetLibraryDirectory(_) => return Poll::Pending, Command::Save | Command::InitComplete => return Poll::Pending,
})) }))
} else { } else {
return Poll::Pending; return Poll::Pending;
@ -673,17 +673,15 @@ fn build_queue_content_build(
HtmlPart::Plain(v) => html.push_str(v), HtmlPart::Plain(v) => html.push_str(v),
HtmlPart::Insert(key) => match key.as_str() { HtmlPart::Insert(key) => match key.as_str() {
"path" => html.push_str(&path), "path" => html.push_str(&path),
"content" => { "content" => build_queue_content_build(
build_queue_content_build( db,
db, state,
state, html,
html, &inner,
&inner, format!("{path}-0"),
format!("{path}-0"), current,
current, true,
true, ),
)
}
_ => {} _ => {}
}, },
} }