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.
This commit is contained in:
Mark 2024-10-11 21:57:32 +02:00
parent 01e59249f5
commit 4bc3d0b147
5 changed files with 292 additions and 170 deletions

View File

@ -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<CheckError>)> {
if let Some(obj) = out
.get()
.as_any()
.downcast_ref::<musicdb_mers::mers_lib::data::object::Object>()
{
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<Updatable<Rectangle>>,
) -> 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, _| {

View File

@ -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);
}
}
}

View File

@ -34,10 +34,10 @@ impl Queue {
&mut self.content
}
pub fn add_to_end(&mut self, v: Vec<Self>) -> Option<usize> {
pub fn add_to_end(&mut self, v: Vec<Self>, skip_init: bool) -> Option<usize> {
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<Self>, index: usize) -> bool {
pub fn insert(&mut self, v: Vec<Self>, 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<usize>) {
pub fn set_index_inner(
&mut self,
index: &[usize],
depth: usize,
mut build_index: Vec<usize>,
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() {
if !keep_child_indices {
c.init();
c.set_index_inner(index, depth + 1, build_index);
}
c.set_index_inner(index, depth + 1, build_index, keep_child_indices);
}
}
QueueContent::Loop(_, _, inner) => {
if !keep_child_indices {
inner.init();
inner.set_index_inner(index, depth + 1, build_index)
}
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<Queue>) -> Option<usize> {
pub fn add_to_end(&mut self, v: Vec<Queue>, skip_init: bool) -> Option<usize> {
let add_len = v.len();
let len = self.content.len();
for mut v in v.into_iter() {
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<Queue>, index: usize) -> bool {
pub fn insert(&mut self, v: Vec<Queue>, 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| {
if !skip_init {
v.init();
}
v
};
if let Some(order) = &mut self.order {

View File

@ -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" }

View File

@ -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<Int>`.").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::<MusicDbId>().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::<MusicDbId>().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::<MusicDbId>().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>() {
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::<Self>()
}