From 4bc3d0b1477c268a99e36890db93983145d5ad3b Mon Sep 17 00:00:00 2001 From: Mark <> Date: Fri, 11 Oct 2024 21:57:32 +0200 Subject: [PATCH] fix playback position being lost when moving when moving a folder, loop, or any other queue element containing the currently playing song (unless the song was the first song in the element), the player would reset the element and jump to playing its first song again. this is now fixed. --- musicdb-client/src/merscfg.rs | 65 +++--- musicdb-lib/src/data/database.rs | 12 +- musicdb-lib/src/data/queue.rs | 42 ++-- musicdb-mers/Cargo.toml | 2 +- musicdb-mers/src/lib.rs | 341 ++++++++++++++++++++----------- 5 files changed, 292 insertions(+), 170 deletions(-) diff --git a/musicdb-client/src/merscfg.rs b/musicdb-client/src/merscfg.rs index 74d914b..de3f41b 100644 --- a/musicdb-client/src/merscfg.rs +++ b/musicdb-client/src/merscfg.rs @@ -12,6 +12,7 @@ use musicdb_lib::{data::database::Database, server::Command}; use musicdb_mers::mers_lib::{ data::{Data, Type}, errors::CheckError, + info::DisplayInfo, }; use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle, window::UserEventSender}; @@ -165,11 +166,11 @@ impl MersCfg { let es = event_sender.clone(); let v = Arc::clone(&self.updated_playing_status); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_zero_tuple() { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `playback_resume` with argument of type `{a}` (must be `()`).").into()) + Err(format!("Can't call `playback_resume` with argument of type `{}` (must be `()`).", a.with_info(i)).into()) } }, move |_, _| { @@ -183,11 +184,11 @@ impl MersCfg { let es = event_sender.clone(); let v = Arc::clone(&self.updated_playing_status); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_zero_tuple() { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `playback_pause` with argument of type `{a}` (must be `()`).").into()) + Err(format!("Can't call `playback_pause` with argument of type `{}` (must be `()`).", a.with_info(i)).into()) } }, move |_, _| { @@ -201,11 +202,11 @@ impl MersCfg { let es = event_sender.clone(); let v = Arc::clone(&self.updated_playing_status); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a,i| { if a.is_zero_tuple() { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `playback_stop` with argument of type `{a}` (must be `()`).").into()) + Err(format!("Can't call `playback_stop` with argument of type `{}` (must be `()`).", a.with_info(i)).into()) } }, move |_, _| { @@ -219,11 +220,11 @@ impl MersCfg { let es = event_sender.clone(); let v = Arc::clone(&self.updated_idle_status); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_zero_tuple() { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `idle_start` with argument of type `{a}` (must be `()`).").into()) + Err(format!("Can't call `idle_start` with argument of type `{}` (must be `()`).",a.with_info(i)).into()) } }, move |_, _| { @@ -237,11 +238,11 @@ impl MersCfg { let es = event_sender.clone(); let v = Arc::clone(&self.updated_idle_status); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a,i| { if a.is_zero_tuple() { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `idle_stop` with argument of type `{a}` (must be `()`).").into()) + Err(format!("Can't call `idle_stop` with argument of type `{}` (must be `()`).", a.with_info(i)).into()) } }, move |_, _| { @@ -255,11 +256,11 @@ impl MersCfg { let es = event_sender.clone(); let v = Arc::clone(&self.updated_idle_status); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a | { + |a, i| { if a.is_zero_tuple() { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `idle_prevent` with argument of type `{a}` (must be `()`).").into()) + Err(format!("Can't call `idle_prevent` with argument of type `{}` (must be `()`).", a.with_info(i)).into()) } }, move |_, _| { @@ -272,18 +273,18 @@ impl MersCfg { .add_var("send_notification".to_owned(),{ let es = event_sender.clone(); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&musicdb_mers::mers_lib::data::tuple::TupleT(vec![ musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::string::StringT), musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::string::StringT), musicdb_mers::mers_lib::data::Type::newm(vec![ - Arc::new(musicdb_mers::mers_lib::data::int::IntT), + Arc::new(musicdb_mers::mers_lib::data::int::IntT(musicdb_mers::mers_lib::data::int::INT_MIN,musicdb_mers::mers_lib::data::int::INT_MAX)), Arc::new(musicdb_mers::mers_lib::data::float::FloatT) ]), ])) { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `send_notification` with argument of type `{a}` (must be `String`).").into()) + Err(format!("Can't call `send_notification` with argument of type `{}` (must be `String`).", a.with_info(i)).into()) } }, move |a, _| { @@ -335,7 +336,7 @@ impl MersCfg { let es = event_sender.clone(); let update = Arc::clone(&self.updated_idle_screen_cover_pos); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in(&musicdb_mers::mers_lib::data::Type::newm(vec![ Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])), Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![ @@ -347,7 +348,7 @@ impl MersCfg { ])) { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `set_idle_screen_cover_pos` with argument of type `{a}` (must be `()` or `(Float, Float, Float, Float)`).").into()) + Err(format!("Can't call `set_idle_screen_cover_pos` with argument of type `{}` (must be `()` or `(Float, Float, Float, Float)`).", a.with_info(i)).into()) } }, move |a, _| { @@ -365,7 +366,7 @@ impl MersCfg { let es = event_sender.clone(); let update = Arc::clone(&self.updated_idle_screen_artist_image_pos); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in(&musicdb_mers::mers_lib::data::Type::newm(vec![ Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])), Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![ @@ -377,7 +378,7 @@ impl MersCfg { ])) { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `set_idle_screen_artist_image_pos` with argument of type `{a}` (must be `()` or `(Float, Float, Float, Float)`).").into()) + Err(format!("Can't call `set_idle_screen_artist_image_pos` with argument of type `{}` (must be `()` or `(Float, Float, Float, Float)`).", a.with_info(i)).into()) } }, move |a, _| { @@ -401,14 +402,14 @@ impl MersCfg { let es = event_sender.clone(); let update = Arc::clone(&self.updated_statusbar_text_format); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) { Ok(Type::newm(vec![ Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])), Arc::new(musicdb_mers::mers_lib::data::string::StringT), ])) } else { - Err(format!("Can't call `set_statusbar_text_format` with argument of type `{a}` (must be `String`).").into()) + Err(format!("Can't call `set_statusbar_text_format` with argument of type `{}` (must be `String`).", a.with_info(i)).into()) } }, move |a, _| { @@ -429,14 +430,14 @@ impl MersCfg { let es = event_sender.clone(); let update = Arc::clone(&self.updated_idle_screen_top_text_format); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) { Ok(Type::newm(vec![ Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])), Arc::new(musicdb_mers::mers_lib::data::string::StringT), ])) } else { - Err(format!("Can't call `set_idle_screen_top_text_format` with argument of type `{a}` (must be `String`).").into()) + Err(format!("Can't call `set_idle_screen_top_text_format` with argument of type `{}` (must be `String`).", a.with_info(i)).into()) } }, move |a, _| { @@ -456,14 +457,14 @@ impl MersCfg { let es = event_sender.clone(); let update = Arc::clone(&self.updated_idle_screen_side_text_1_format); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) { Ok(Type::newm(vec![ Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])), Arc::new(musicdb_mers::mers_lib::data::string::StringT), ])) } else { - Err(format!("Can't call `set_idle_screen_side_text_1_format` with argument of type `{a}` (must be `String`).").into()) + Err(format!("Can't call `set_idle_screen_side_text_1_format` with argument of type `{}` (must be `String`).", a.with_info(i)).into()) } }, move |a, _| { @@ -483,14 +484,14 @@ impl MersCfg { let es = event_sender.clone(); let update = Arc::clone(&self.updated_idle_screen_side_text_2_format); musicdb_mers::mers_lib::data::function::Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) { Ok(Type::newm(vec![ Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])), Arc::new(musicdb_mers::mers_lib::data::string::StringT), ])) } else { - Err(format!("Can't call `set_idle_screen_side_text_2_format` with argument of type `{a}` (must be `String`).").into()) + Err(format!("Can't call `set_idle_screen_side_text_2_format` with argument of type `{}` (must be `String`).", a.with_info(i)).into()) } }, move |a, _| { @@ -691,18 +692,20 @@ impl MersCfg { .compile(&mut i1, Default::default())?; let _ = compiled.check(&mut i3, None)?; let out = compiled.run(&mut i2)?; - Ok(self.load3(out)) + Ok(self.load3(out, i2.display_info())) } fn load3( &mut self, out: musicdb_mers::mers_lib::data::Data, + i: DisplayInfo, ) -> Result<(), (String, Option)> { if let Some(obj) = out .get() .as_any() .downcast_ref::() { - for (name, val) in obj.0.iter() { + for (name, val) in obj.iter() { + let name = i.get_object_field_name(*name).to_string(); let name = name.as_str(); match name { "before_draw" => { @@ -750,7 +753,7 @@ fn gen_set_pos_func( update: Arc>, ) -> musicdb_mers::mers_lib::data::function::Function { musicdb_mers::mers_lib::data::function::Function::new_generic( - move |a| { + move |a, i| { if a.is_included_in(&musicdb_mers::mers_lib::data::Type::newm(vec![Arc::new( musicdb_mers::mers_lib::data::tuple::TupleT(vec![ musicdb_mers::mers_lib::data::Type::new( @@ -769,7 +772,7 @@ fn gen_set_pos_func( )])) { Ok(Type::empty_tuple()) } else { - Err(format!("Can't call `{name}` with argument of type `{a}` (must be `(Float, Float, Float, Float)`).").into()) + Err(format!("Can't call `{name}` with argument of type `{}` (must be `(Float, Float, Float, Float)`).", a.with_info(i)).into()) } }, move |a, _| { diff --git a/musicdb-lib/src/data/database.rs b/musicdb-lib/src/data/database.rs index 2d2d15d..299d499 100755 --- a/musicdb-lib/src/data/database.rs +++ b/musicdb-lib/src/data/database.rs @@ -552,12 +552,12 @@ impl Database { } Command::QueueAdd(index, new_data) => { if let Some(v) = self.queue.get_item_at_index_mut(&index, 0) { - v.add_to_end(new_data); + v.add_to_end(new_data, false); } } Command::QueueInsert(index, pos, new_data) => { if let Some(v) = self.queue.get_item_at_index_mut(&index, 0) { - v.insert(new_data, pos); + v.insert(new_data, pos, false); } } Command::QueueRemove(index) => { @@ -598,9 +598,9 @@ impl Database { .queue .get_item_at_index_mut(&index_to[0..index_to.len() - 1], 0) { - parent.insert(vec![elem], index_to[index_to.len() - 1]); + parent.insert(vec![elem], index_to[index_to.len() - 1], true); if was_current { - self.queue.set_index_inner(&index_to, 0, vec![]); + self.queue.set_index_inner(&index_to, 0, vec![], true); } } } @@ -619,10 +619,10 @@ impl Database { parent_to[index_from.len() - 1] -= 1; } if let Some(parent) = self.queue.get_item_at_index_mut(&parent_to, 0) { - if let Some(i) = parent.add_to_end(vec![elem]) { + if let Some(i) = parent.add_to_end(vec![elem], true) { if was_current { parent_to.push(i); - self.queue.set_index_inner(&parent_to, 0, vec![]); + self.queue.set_index_inner(&parent_to, 0, vec![], true); } } } diff --git a/musicdb-lib/src/data/queue.rs b/musicdb-lib/src/data/queue.rs index c162003..2ac0624 100755 --- a/musicdb-lib/src/data/queue.rs +++ b/musicdb-lib/src/data/queue.rs @@ -34,10 +34,10 @@ impl Queue { &mut self.content } - pub fn add_to_end(&mut self, v: Vec) -> Option { + pub fn add_to_end(&mut self, v: Vec, skip_init: bool) -> Option { match &mut self.content { QueueContent::Song(_) => None, - QueueContent::Folder(folder) => folder.add_to_end(v), + QueueContent::Folder(folder) => folder.add_to_end(v, skip_init), QueueContent::Loop(..) => None, } } @@ -56,10 +56,10 @@ impl Queue { QueueContent::Loop(_, _, inner) => index[0] == 0 && inner.is_current(&index[1..]), } } - pub fn insert(&mut self, v: Vec, index: usize) -> bool { + pub fn insert(&mut self, v: Vec, index: usize, skip_init: bool) -> bool { match &mut self.content { QueueContent::Song(_) => false, - QueueContent::Folder(folder) => folder.insert(v, index), + QueueContent::Folder(folder) => folder.insert(v, index, skip_init), QueueContent::Loop(..) => false, } } @@ -215,9 +215,15 @@ impl Queue { pub fn set_index_db(db: &mut Database, index: &[usize]) { db.queue.reset_index(); - db.queue.set_index_inner(index, 0, vec![]); + db.queue.set_index_inner(index, 0, vec![], false); } - pub fn set_index_inner(&mut self, index: &[usize], depth: usize, mut build_index: Vec) { + pub fn set_index_inner( + &mut self, + index: &[usize], + depth: usize, + mut build_index: Vec, + keep_child_indices: bool, + ) { let i = if let Some(i) = index.get(depth) { *i } else { @@ -229,13 +235,17 @@ impl Queue { QueueContent::Folder(folder) => { folder.index = i; if let Some(c) = folder.get_current_mut() { - c.init(); - c.set_index_inner(index, depth + 1, build_index); + if !keep_child_indices { + c.init(); + } + c.set_index_inner(index, depth + 1, build_index, keep_child_indices); } } QueueContent::Loop(_, _, inner) => { - inner.init(); - inner.set_index_inner(index, depth + 1, build_index) + if !keep_child_indices { + inner.init(); + } + inner.set_index_inner(index, depth + 1, build_index, keep_child_indices) } } } @@ -347,11 +357,13 @@ impl QueueFolder { index: 0, } } - pub fn add_to_end(&mut self, v: Vec) -> Option { + pub fn add_to_end(&mut self, v: Vec, skip_init: bool) -> Option { let add_len = v.len(); let len = self.content.len(); for mut v in v.into_iter() { - v.init(); + if !skip_init { + v.init(); + } self.content.push(v); } if let Some(order) = &mut self.order { @@ -361,7 +373,7 @@ impl QueueFolder { } Some(len) } - pub fn insert(&mut self, v: Vec, index: usize) -> bool { + pub fn insert(&mut self, v: Vec, index: usize, skip_init: bool) -> bool { if index <= self.content.len() { if self.index >= index { self.index += v.len(); @@ -377,7 +389,9 @@ impl QueueFolder { vec.extend(end); } let mapfunc = |mut v: Queue| { - v.init(); + if !skip_init { + v.init(); + } v }; if let Some(order) = &mut self.order { diff --git a/musicdb-mers/Cargo.toml b/musicdb-mers/Cargo.toml index f14ab45..4d40069 100644 --- a/musicdb-mers/Cargo.toml +++ b/musicdb-mers/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -mers_lib = { version = "0.9.1", features = ["ecolor-term"] } +mers_lib = { version = "0.9.6", features = ["ecolor-term"] } musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" } diff --git a/musicdb-mers/src/lib.rs b/musicdb-mers/src/lib.rs index d4a810e..efc90f3 100644 --- a/musicdb-mers/src/lib.rs +++ b/musicdb-mers/src/lib.rs @@ -6,7 +6,8 @@ use std::{ pub use mers_lib; use mers_lib::{ - data::{self, function::Function, Data, MersData, MersType, Type}, + data::{self, function::Function, object::ObjectFieldsMap, Data, MersData, MersType, Type}, + info::DisplayInfo, prelude_extend_config::Config, }; use musicdb_lib::{ @@ -157,7 +158,7 @@ pub fn add( cfg = cfg.add_var( format!("handle_event_{name}"), Function::new_generic( - move |a| { + move |a, i| { if a.types.iter().all(|a| { Type::newm(vec![Arc::clone(a)]).is_zero_tuple() || a.as_any() @@ -166,7 +167,10 @@ pub fn add( }) { Ok(Type::empty_tuple()) } else { - Err(format!("Handler function must be `{in_type} -> ()`").into()) + Err( + format!("Handler function must be `{} -> ()`", in_type.with_info(i)) + .into(), + ) } }, move |a, _| { @@ -180,7 +184,7 @@ pub fn add( cfg.add_var( "send_server_notification".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in_single(&data::string::StringT) { Ok(Type::empty_tuple()) } else { @@ -207,7 +211,7 @@ pub fn add( .add_var( "resume".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::empty_tuple()) } else { @@ -226,7 +230,7 @@ pub fn add( .add_var( "pause".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::empty_tuple()) } else { @@ -245,7 +249,7 @@ pub fn add( .add_var( "stop".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::empty_tuple()) } else { @@ -264,7 +268,7 @@ pub fn add( .add_var( "next_song".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::empty_tuple()) } else { @@ -283,7 +287,7 @@ pub fn add( .add_var( "get_playing".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(data::bool::bool_type()) } else { @@ -299,7 +303,7 @@ pub fn add( .add_var( "queue_get_current_song".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::newm(vec![ Arc::new(MusicDbIdT), @@ -323,7 +327,7 @@ pub fn add( .add_var( "queue_get_next_song".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::newm(vec![ Arc::new(MusicDbIdT), @@ -347,22 +351,22 @@ pub fn add( .add_var( "queue_get_elem".to_owned(), Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&mers_lib::program::configs::with_list::ListT( - Type::new(data::int::IntT), + Type::new(data::int::IntT(data::int::INT_MIN, data::int::INT_MAX)), )) { - Ok(gen_queue_elem_type_or_empty_tuple()) + Ok(gen_queue_elem_type_or_empty_tuple(i.display_info())) } else { Err(format!("Function argument must be `List`.").into()) } }, { let db = Arc::clone(db); - move |a, _| { + move |a, i| { let a = int_list_to_usize_vec(&a); Ok( if let Some(elem) = db.lock().unwrap().queue.get_item_at_index(&a, 0) { - gen_queue_elem(elem) + gen_queue_elem(elem, i.display_info()) } else { Data::empty_tuple() }, @@ -374,9 +378,9 @@ pub fn add( .add_var( "queue_goto".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in_single(&mers_lib::program::configs::with_list::ListT( - Type::new(data::int::IntT), + Type::new(data::int::IntT(data::int::INT_MIN, data::int::INT_MAX)), )) { Ok(Type::empty_tuple()) } else { @@ -395,7 +399,7 @@ pub fn add( .add_var( "queue_clear".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in(&Type::empty_tuple()) { Ok(Type::empty_tuple()) } else { @@ -533,10 +537,10 @@ pub fn add( .add_var( "all_songs".to_owned(), Function::new_generic( - |a| { + |a, i| { if a.is_zero_tuple() { Ok(Type::new(mers_lib::program::configs::with_list::ListT( - Type::new(gen_song_type()), + Type::new(gen_song_type(i.display_info())), ))) } else { Err(format!("Function argument must be `()`.").into()) @@ -544,13 +548,13 @@ pub fn add( }, { let db = Arc::clone(db); - move |_, _| { + move |_, i| { Ok(Data::new(mers_lib::program::configs::with_list::List( db.lock() .unwrap() .songs() .values() - .map(|s| Arc::new(RwLock::new(gen_song(s)))) + .map(|s| Arc::new(RwLock::new(gen_song(s, i.display_info())))) .collect(), ))) } @@ -560,10 +564,10 @@ pub fn add( .add_var( "get_song".to_owned(), Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&MusicDbIdT) { Ok(Type::newm(vec![ - Arc::new(gen_song_type()), + Arc::new(gen_song_type(i.display_info())), Arc::new(data::tuple::TupleT(vec![])), ])) } else { @@ -572,10 +576,10 @@ pub fn add( }, { let db = Arc::clone(db); - move |a, _| { + move |a, i| { let id = a.get().as_any().downcast_ref::().unwrap().0; Ok(match db.lock().unwrap().get_song(&id) { - Some(song) => gen_song(song), + Some(song) => gen_song(song, i.display_info()), None => Data::empty_tuple(), }) } @@ -585,10 +589,10 @@ pub fn add( .add_var( "get_album".to_owned(), Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&MusicDbIdT) { Ok(Type::newm(vec![ - Arc::new(gen_album_type()), + Arc::new(gen_album_type(i.display_info())), Arc::new(data::tuple::TupleT(vec![])), ])) } else { @@ -597,10 +601,10 @@ pub fn add( }, { let db = Arc::clone(db); - move |a, _| { + move |a, i| { let id = a.get().as_any().downcast_ref::().unwrap().0; Ok(match db.lock().unwrap().albums().get(&id) { - Some(album) => gen_album(album), + Some(album) => gen_album(album, i.display_info()), None => Data::empty_tuple(), }) } @@ -610,10 +614,10 @@ pub fn add( .add_var( "get_artist".to_owned(), Function::new_generic( - |a| { + |a, i| { if a.is_included_in_single(&MusicDbIdT) { Ok(Type::newm(vec![ - Arc::new(gen_artist_type()), + Arc::new(gen_artist_type(i.display_info())), Arc::new(data::tuple::TupleT(vec![])), ])) } else { @@ -622,10 +626,10 @@ pub fn add( }, { let db = Arc::clone(db); - move |a, _| { + move |a, i| { let id = a.get().as_any().downcast_ref::().unwrap().0; Ok(match db.lock().unwrap().artists().get(&id) { - Some(artist) => gen_artist(artist), + Some(artist) => gen_artist(artist, i.display_info()), None => Data::empty_tuple(), }) } @@ -635,7 +639,7 @@ pub fn add( .add_var( "get_song_tags".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in_single(&MusicDbIdT) { Ok(Type::newm(vec![ Arc::new(mers_lib::program::configs::with_list::ListT(Type::new( @@ -672,7 +676,7 @@ pub fn add( .add_var( "get_album_tags".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in_single(&MusicDbIdT) { Ok(Type::newm(vec![ Arc::new(mers_lib::program::configs::with_list::ListT(Type::new( @@ -710,7 +714,7 @@ pub fn add( .add_var( "get_artist_tags".to_owned(), Function::new_generic( - |a| { + |a, _| { if a.is_included_in_single(&MusicDbIdT) { Ok(Type::newm(vec![ Arc::new(mers_lib::program::configs::with_list::ListT(Type::new( @@ -747,20 +751,29 @@ pub fn add( ) } -fn gen_song_type() -> data::object::ObjectT { - data::object::ObjectT(vec![ - ("id".to_owned(), Type::new(MusicDbIdT)), - ("title".to_owned(), Type::new(data::string::StringT)), +fn gen_song_type(i: DisplayInfo) -> data::object::ObjectT { + data::object::ObjectT::new(vec![ ( - "album".to_owned(), + i.object_fields.get_or_add_field("id"), + Type::new(MusicDbIdT), + ), + ( + i.object_fields.get_or_add_field("title"), + Type::new(data::string::StringT), + ), + ( + i.object_fields.get_or_add_field("album"), Type::newm(vec![ Arc::new(MusicDbIdT), Arc::new(data::tuple::TupleT(vec![])), ]), ), - ("artist".to_owned(), Type::new(MusicDbIdT)), ( - "cover".to_owned(), + i.object_fields.get_or_add_field("artist"), + Type::new(MusicDbIdT), + ), + ( + i.object_fields.get_or_add_field("cover"), Type::newm(vec![ Arc::new(MusicDbIdT), Arc::new(data::tuple::TupleT(vec![])), @@ -768,24 +781,30 @@ fn gen_song_type() -> data::object::ObjectT { ), ]) } -fn gen_song(song: &Song) -> Data { - Data::new(data::object::Object(vec![ - ("id".to_owned(), Data::new(MusicDbId(song.id))), +fn gen_song(song: &Song, i: DisplayInfo) -> Data { + Data::new(data::object::Object::new(vec![ ( - "title".to_owned(), + i.object_fields.get_or_add_field("id"), + Data::new(MusicDbId(song.id)), + ), + ( + i.object_fields.get_or_add_field("title"), Data::new(data::string::String(song.title.clone())), ), ( - "album".to_owned(), + i.object_fields.get_or_add_field("album"), if let Some(album) = song.album { Data::new(MusicDbId(album)) } else { Data::empty_tuple() }, ), - ("artist".to_owned(), Data::new(MusicDbId(song.artist))), ( - "cover".to_owned(), + i.object_fields.get_or_add_field("artist"), + Data::new(MusicDbId(song.artist)), + ), + ( + i.object_fields.get_or_add_field("cover"), if let Some(cover) = song.cover { Data::new(MusicDbId(cover)) } else { @@ -794,36 +813,51 @@ fn gen_song(song: &Song) -> Data { ), ])) } -fn gen_album_type() -> data::object::ObjectT { - data::object::ObjectT(vec![ - ("id".to_owned(), Type::new(MusicDbIdT)), - ("name".to_owned(), Type::new(data::string::StringT)), - ("artist".to_owned(), Type::new(MusicDbIdT)), +fn gen_album_type(i: DisplayInfo) -> data::object::ObjectT { + data::object::ObjectT::new(vec![ ( - "cover".to_owned(), + i.object_fields.get_or_add_field("id"), + Type::new(MusicDbIdT), + ), + ( + i.object_fields.get_or_add_field("name"), + Type::new(data::string::StringT), + ), + ( + i.object_fields.get_or_add_field("artist"), + Type::new(MusicDbIdT), + ), + ( + i.object_fields.get_or_add_field("cover"), Type::newm(vec![ Arc::new(MusicDbIdT), Arc::new(data::tuple::TupleT(vec![])), ]), ), ( - "songs".to_owned(), + i.object_fields.get_or_add_field("songs"), Type::new(mers_lib::program::configs::with_list::ListT(Type::new( MusicDbIdT, ))), ), ]) } -fn gen_album(album: &Album) -> Data { - Data::new(data::object::Object(vec![ - ("id".to_owned(), Data::new(MusicDbId(album.id))), +fn gen_album(album: &Album, i: DisplayInfo) -> Data { + Data::new(data::object::Object::new(vec![ ( - "name".to_owned(), + i.object_fields.get_or_add_field("id"), + Data::new(MusicDbId(album.id)), + ), + ( + i.object_fields.get_or_add_field("name"), Data::new(data::string::String(album.name.clone())), ), - ("artist".to_owned(), Data::new(MusicDbId(album.artist))), ( - "cover".to_owned(), + i.object_fields.get_or_add_field("artist"), + Data::new(MusicDbId(album.artist)), + ), + ( + i.object_fields.get_or_add_field("cover"), if let Some(cover) = album.cover { Data::new(MusicDbId(cover)) } else { @@ -831,7 +865,7 @@ fn gen_album(album: &Album) -> Data { }, ), ( - "songs".to_owned(), + i.object_fields.get_or_add_field("songs"), Data::new(mers_lib::program::configs::with_list::List( album .songs @@ -842,40 +876,49 @@ fn gen_album(album: &Album) -> Data { ), ])) } -fn gen_artist_type() -> data::object::ObjectT { - data::object::ObjectT(vec![ - ("id".to_owned(), Type::new(MusicDbIdT)), - ("name".to_owned(), Type::new(data::string::StringT)), +fn gen_artist_type(i: DisplayInfo) -> data::object::ObjectT { + data::object::ObjectT::new(vec![ ( - "cover".to_owned(), + i.object_fields.get_or_add_field("id"), + Type::new(MusicDbIdT), + ), + ( + i.object_fields.get_or_add_field("name"), + Type::new(data::string::StringT), + ), + ( + i.object_fields.get_or_add_field("cover"), Type::newm(vec![ Arc::new(MusicDbIdT), Arc::new(data::tuple::TupleT(vec![])), ]), ), ( - "albums".to_owned(), + i.object_fields.get_or_add_field("albums"), Type::new(mers_lib::program::configs::with_list::ListT(Type::new( MusicDbIdT, ))), ), ( - "singles".to_owned(), + i.object_fields.get_or_add_field("singles"), Type::new(mers_lib::program::configs::with_list::ListT(Type::new( MusicDbIdT, ))), ), ]) } -fn gen_artist(artist: &Artist) -> Data { - Data::new(data::object::Object(vec![ - ("id".to_owned(), Data::new(MusicDbId(artist.id))), +fn gen_artist(artist: &Artist, i: DisplayInfo) -> Data { + Data::new(data::object::Object::new(vec![ ( - "name".to_owned(), + i.object_fields.get_or_add_field("id"), + Data::new(MusicDbId(artist.id)), + ), + ( + i.object_fields.get_or_add_field("name"), Data::new(data::string::String(artist.name.clone())), ), ( - "cover".to_owned(), + i.object_fields.get_or_add_field("cover"), if let Some(cover) = artist.cover { Data::new(MusicDbId(cover)) } else { @@ -883,7 +926,7 @@ fn gen_artist(artist: &Artist) -> Data { }, ), ( - "albums".to_owned(), + i.object_fields.get_or_add_field("albums"), Data::new(mers_lib::program::configs::with_list::List( artist .albums @@ -893,7 +936,7 @@ fn gen_artist(artist: &Artist) -> Data { )), ), ( - "singles".to_owned(), + i.object_fields.get_or_add_field("singles"), Data::new(mers_lib::program::configs::with_list::List( artist .singles @@ -905,72 +948,120 @@ fn gen_artist(artist: &Artist) -> Data { ])) } -fn gen_queue_elem_type_or_empty_tuple() -> Type { +fn gen_queue_elem_type_or_empty_tuple(i: DisplayInfo) -> Type { Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![])), - Arc::new(data::object::ObjectT(vec![ - ("enabled".to_owned(), data::bool::bool_type()), - ("song".to_owned(), Type::new(MusicDbIdT)), - ])), - Arc::new(data::object::ObjectT(vec![ - ("enabled".to_owned(), data::bool::bool_type()), + Arc::new(data::object::ObjectT::new(vec![ ( - "loop".to_owned(), - Type::new(data::object::ObjectT(vec![ - ("total".to_owned(), Type::new(data::int::IntT)), - ("done".to_owned(), Type::new(data::int::IntT)), + i.object_fields.get_or_add_field("enabled"), + data::bool::bool_type(), + ), + ( + i.object_fields.get_or_add_field("song"), + Type::new(MusicDbIdT), + ), + ])), + Arc::new(data::object::ObjectT::new(vec![ + ( + i.object_fields.get_or_add_field("enabled"), + data::bool::bool_type(), + ), + ( + i.object_fields.get_or_add_field("loop"), + Type::new(data::object::ObjectT::new(vec![ + ( + i.object_fields.get_or_add_field("total"), + Type::new(data::int::IntT(data::int::INT_MIN, data::int::INT_MAX)), + ), + ( + i.object_fields.get_or_add_field("done"), + Type::new(data::int::IntT(data::int::INT_MIN, data::int::INT_MAX)), + ), ])), ), ])), - Arc::new(data::object::ObjectT(vec![ - ("enabled".to_owned(), data::bool::bool_type()), - ("random".to_owned(), Type::empty_tuple()), - ])), - Arc::new(data::object::ObjectT(vec![ - ("enabled".to_owned(), data::bool::bool_type()), + Arc::new(data::object::ObjectT::new(vec![ ( - "folder".to_owned(), - Type::new(data::object::ObjectT(vec![ - ("index".to_owned(), Type::new(data::int::IntT)), - ("length".to_owned(), Type::new(data::int::IntT)), - ("name".to_owned(), Type::new(data::string::StringT)), + i.object_fields.get_or_add_field("enabled"), + data::bool::bool_type(), + ), + ( + i.object_fields.get_or_add_field("random"), + Type::empty_tuple(), + ), + ])), + Arc::new(data::object::ObjectT::new(vec![ + ( + i.object_fields.get_or_add_field("enabled"), + data::bool::bool_type(), + ), + ( + i.object_fields.get_or_add_field("folder"), + Type::new(data::object::ObjectT::new(vec![ + ( + i.object_fields.get_or_add_field("index"), + Type::new(data::int::IntT(data::int::INT_MIN, data::int::INT_MAX)), + ), + ( + i.object_fields.get_or_add_field("length"), + Type::new(data::int::IntT(data::int::INT_MIN, data::int::INT_MAX)), + ), + ( + i.object_fields.get_or_add_field("name"), + Type::new(data::string::StringT), + ), ])), ), ])), - Arc::new(data::object::ObjectT(vec![ - ("enabled".to_owned(), data::bool::bool_type()), - ("shuffle".to_owned(), Type::empty_tuple()), + Arc::new(data::object::ObjectT::new(vec![ + ( + i.object_fields.get_or_add_field("enabled"), + data::bool::bool_type(), + ), + ( + i.object_fields.get_or_add_field("shuffle"), + Type::empty_tuple(), + ), ])), ]) } -fn gen_queue_elem(queue_elem: &Queue) -> Data { - Data::new(data::object::Object(vec![ +fn gen_queue_elem(queue_elem: &Queue, i: DisplayInfo) -> Data { + Data::new(data::object::Object::new(vec![ ( - "enabled".to_owned(), + i.object_fields.get_or_add_field("enabled"), Data::new(data::bool::Bool(queue_elem.enabled())), ), match queue_elem.content() { - QueueContent::Song(id) => ("song".to_owned(), Data::new(MusicDbId(*id))), + QueueContent::Song(id) => ( + i.object_fields.get_or_add_field("song"), + Data::new(MusicDbId(*id)), + ), QueueContent::Loop(total, done, _inner) => ( - "loop".to_owned(), - Data::new(data::object::Object(vec![ - ("total".to_owned(), Data::new(data::int::Int(*total as _))), - ("done".to_owned(), Data::new(data::int::Int(*done as _))), + i.object_fields.get_or_add_field("loop"), + Data::new(data::object::Object::new(vec![ + ( + i.object_fields.get_or_add_field("total"), + Data::new(data::int::Int(*total as _)), + ), + ( + i.object_fields.get_or_add_field("done"), + Data::new(data::int::Int(*done as _)), + ), ])), ), QueueContent::Folder(folder) => ( - "folder".to_owned(), - Data::new(data::object::Object(vec![ + i.object_fields.get_or_add_field("folder"), + Data::new(data::object::Object::new(vec![ ( - "index".to_owned(), + i.object_fields.get_or_add_field("index"), Data::new(data::int::Int(folder.index as _)), ), ( - "length".to_owned(), + i.object_fields.get_or_add_field("length"), Data::new(data::int::Int(folder.content.len() as _)), ), ( - "name".to_owned(), + i.object_fields.get_or_add_field("name"), Data::new(data::string::String(folder.name.clone())), ), ])), @@ -1009,6 +1100,13 @@ impl MersData for MusicDbId { fn as_type(&self) -> Type { Type::new(MusicDbIdT) } + fn display( + &self, + _info: &mers_lib::info::DisplayInfo<'_>, + f: &mut std::fmt::Formatter, + ) -> std::fmt::Result { + write!(f, "{}", self) + } fn is_eq(&self, other: &dyn MersData) -> bool { if let Some(other) = other.as_any().downcast_ref::() { self.0 == other.0 @@ -1030,6 +1128,13 @@ impl MersData for MusicDbId { } } impl MersType for MusicDbIdT { + fn display( + &self, + _info: &mers_lib::info::DisplayInfo<'_>, + f: &mut std::fmt::Formatter, + ) -> std::fmt::Result { + write!(f, "{}", self) + } fn is_same_type_as(&self, other: &dyn MersType) -> bool { other.as_any().is::() }