Add a library identifier to disambiguate clashes in the library #238
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
src/external/** linguist-vendored=false
|
@ -4,7 +4,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::core::collection::{
|
||||
merge::{Merge, MergeSorted, WithId},
|
||||
merge::{Merge, MergeSorted},
|
||||
musicbrainz::{MbAlbumRef, MbRefOption},
|
||||
track::{Track, TrackFormat},
|
||||
};
|
||||
@ -33,18 +33,34 @@ pub struct AlbumInfo {
|
||||
pub secondary_types: Vec<AlbumSecondaryType>,
|
||||
}
|
||||
|
||||
impl WithId for Album {
|
||||
type Id = AlbumId;
|
||||
|
||||
fn id(&self) -> &Self::Id {
|
||||
&self.meta.id
|
||||
}
|
||||
}
|
||||
|
||||
/// The album identifier.
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||
pub struct AlbumId {
|
||||
pub title: String,
|
||||
pub lib_id: AlbumLibId,
|
||||
}
|
||||
|
||||
impl AlbumId {
|
||||
pub fn compatible(&self, other: &AlbumId) -> bool {
|
||||
let titles_compatible = self.title == other.title;
|
||||
let lib_id_compatible =
|
||||
self.lib_id.is_none() || other.lib_id.is_none() || (self.lib_id == other.lib_id);
|
||||
titles_compatible && lib_id_compatible
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique library identifier.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||
pub enum AlbumLibId {
|
||||
Value(u32),
|
||||
Singleton,
|
||||
None,
|
||||
}
|
||||
|
||||
impl AlbumLibId {
|
||||
pub fn is_none(&self) -> bool {
|
||||
matches!(self, AlbumLibId::None)
|
||||
}
|
||||
}
|
||||
|
||||
// There are crates for handling dates, but we don't need much complexity beyond year-month-day.
|
||||
@ -252,9 +268,8 @@ impl Ord for AlbumMeta {
|
||||
|
||||
impl Merge for AlbumMeta {
|
||||
fn merge_in_place(&mut self, other: Self) {
|
||||
assert_eq!(self.id, other.id);
|
||||
assert!(self.id.compatible(&other.id));
|
||||
self.seq = std::cmp::max(self.seq, other.seq);
|
||||
|
||||
self.info.merge_in_place(other.info);
|
||||
}
|
||||
}
|
||||
@ -283,7 +298,10 @@ impl AsRef<AlbumId> for AlbumId {
|
||||
|
||||
impl AlbumId {
|
||||
pub fn new<S: Into<String>>(name: S) -> AlbumId {
|
||||
AlbumId { title: name.into() }
|
||||
AlbumId {
|
||||
title: name.into(),
|
||||
lib_id: AlbumLibId::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,15 +333,11 @@ mod tests {
|
||||
fn same_date_seq_cmp() {
|
||||
let date: AlbumDate = (2024, 3, 2).into();
|
||||
|
||||
let album_id_1 = AlbumId {
|
||||
title: String::from("album z"),
|
||||
};
|
||||
let album_id_1 = AlbumId::new("album z");
|
||||
let mut album_1 = Album::new(album_id_1).with_date(date.clone());
|
||||
album_1.meta.set_seq(AlbumSeq(1));
|
||||
|
||||
let album_id_2 = AlbumId {
|
||||
title: String::from("album a"),
|
||||
};
|
||||
let album_id_2 = AlbumId::new("album a");
|
||||
let mut album_2 = Album::new(album_id_2).with_date(date.clone());
|
||||
album_2.meta.set_seq(AlbumSeq(2));
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::{self, Debug, Display},
|
||||
mem,
|
||||
};
|
||||
|
||||
use crate::core::collection::{
|
||||
album::Album,
|
||||
merge::{Merge, MergeCollections, WithId},
|
||||
album::{Album, AlbumLibId},
|
||||
merge::{Merge, MergeId},
|
||||
musicbrainz::{MbArtistRef, MbRefOption},
|
||||
};
|
||||
|
||||
@ -32,7 +31,7 @@ pub struct ArtistInfo {
|
||||
pub properties: HashMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
impl WithId for Artist {
|
||||
impl MergeId for Artist {
|
||||
type Id = ArtistId;
|
||||
|
||||
fn id(&self) -> &Self::Id {
|
||||
@ -54,6 +53,56 @@ impl Artist {
|
||||
albums: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_album_by_lib_id(
|
||||
primary_albums: &mut [Album],
|
||||
mut secondary_album: Album,
|
||||
) -> Option<Album> {
|
||||
let id_opt = secondary_album.meta.id.lib_id;
|
||||
if let id @ AlbumLibId::Value(_) | id @ AlbumLibId::Singleton = id_opt {
|
||||
let mut iter = primary_albums.iter_mut();
|
||||
if let Some(ref mut primary_album) = iter.find(|a| a.meta.id.lib_id == id) {
|
||||
primary_album.merge_in_place(secondary_album);
|
||||
return None;
|
||||
}
|
||||
secondary_album.meta.id.lib_id = AlbumLibId::None;
|
||||
}
|
||||
Some(secondary_album)
|
||||
}
|
||||
|
||||
fn merge_albums_by_lib_id(
|
||||
primary_albums: &mut [Album],
|
||||
secondary_albums: Vec<Album>,
|
||||
) -> HashMap<String, Vec<Album>> {
|
||||
let mut secondary_without_id = HashMap::<String, Vec<Album>>::new();
|
||||
for secondary_album in secondary_albums.into_iter() {
|
||||
let unmerged = Artist::merge_album_by_lib_id(primary_albums, secondary_album);
|
||||
if let Some(secondary_album) = unmerged {
|
||||
secondary_without_id
|
||||
.entry(secondary_album.meta.id.title.clone())
|
||||
.or_default()
|
||||
.push(secondary_album);
|
||||
}
|
||||
}
|
||||
secondary_without_id
|
||||
}
|
||||
|
||||
fn merge_albums_by_title(
|
||||
primary_albums: &mut Vec<Album>,
|
||||
secondary_without_id: HashMap<String, Vec<Album>>,
|
||||
) {
|
||||
for (title, mut secondary_albums) in secondary_without_id.into_iter() {
|
||||
let mut iter = primary_albums.iter_mut();
|
||||
match iter.find(|album| album.meta.id.title == title) {
|
||||
Some(ref mut primary_album) => {
|
||||
// We do not support merging multiple DB albums with same title yet.
|
||||
assert_eq!(secondary_albums.len(), 1);
|
||||
primary_album.merge_in_place(secondary_albums.pop().unwrap())
|
||||
}
|
||||
None => primary_albums.append(&mut secondary_albums),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Artist {
|
||||
@ -71,8 +120,10 @@ impl Ord for Artist {
|
||||
impl Merge for Artist {
|
||||
fn merge_in_place(&mut self, other: Self) {
|
||||
self.meta.merge_in_place(other.meta);
|
||||
let albums = mem::take(&mut self.albums);
|
||||
self.albums = MergeCollections::merge_iter(albums, other.albums);
|
||||
|
||||
let other_without_id = Artist::merge_albums_by_lib_id(&mut self.albums, other.albums);
|
||||
Artist::merge_albums_by_title(&mut self.albums, other_without_id);
|
||||
self.albums.sort_unstable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,6 +461,12 @@ mod tests {
|
||||
assert!(info.properties.is_empty());
|
||||
}
|
||||
|
||||
fn reset_lib_id(albums: &mut [Album]) {
|
||||
for album in albums.iter_mut() {
|
||||
album.meta.id.lib_id = AlbumLibId::None;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_artist_no_overlap() {
|
||||
let left = FULL_COLLECTION[0].to_owned();
|
||||
@ -424,13 +481,25 @@ mod tests {
|
||||
.info
|
||||
.properties
|
||||
.merge(right.clone().meta.info.properties);
|
||||
expected.albums.append(&mut right.albums.clone());
|
||||
|
||||
// If an album in the secondary (right) collection has a lib id but there is no match in the
|
||||
// primary (left) collection then it is removed.
|
||||
let mut right_albums_without_lib_id = right.albums.clone();
|
||||
reset_lib_id(&mut right_albums_without_lib_id);
|
||||
expected.albums.extend(right_albums_without_lib_id);
|
||||
expected.albums.sort_unstable();
|
||||
|
||||
let merged = left.clone().merge(right.clone());
|
||||
assert_eq!(expected, merged);
|
||||
|
||||
// Non-overlapping merge should be commutative.
|
||||
// Non-overlapping merge should be commutative. Except for lib id which will be erased from
|
||||
// the albums in the secondary collection.
|
||||
expected.albums = right.albums.clone();
|
||||
let mut left_albums_without_lib_id = left.albums.clone();
|
||||
reset_lib_id(&mut left_albums_without_lib_id);
|
||||
expected.albums.extend(left_albums_without_lib_id);
|
||||
expected.albums.sort_unstable();
|
||||
|
||||
let merged = right.clone().merge(left.clone());
|
||||
assert_eq!(expected, merged);
|
||||
}
|
||||
@ -440,8 +509,20 @@ mod tests {
|
||||
let mut left = FULL_COLLECTION[0].to_owned();
|
||||
let mut right = FULL_COLLECTION[1].to_owned();
|
||||
right.meta.id = left.meta.id.clone();
|
||||
|
||||
// The right collection needs more albums than we modify to make sure some do not overlap.
|
||||
assert!(right.albums.len() > 2);
|
||||
|
||||
// This album will have a lib_id and will match based on lib_id.
|
||||
left.albums.push(right.albums[0].clone());
|
||||
left.albums.sort_unstable();
|
||||
|
||||
// This album will not have a lib_id and will match based on title.
|
||||
left.albums.push(right.albums[1].clone());
|
||||
right.albums[1].meta.id.lib_id = AlbumLibId::None;
|
||||
|
||||
// Albums on right without a match on the left will lose their lib id.
|
||||
let mut newly_added = right.albums[2..].to_vec();
|
||||
reset_lib_id(&mut newly_added);
|
||||
|
||||
let mut expected = left.clone();
|
||||
expected.meta.info.properties = expected
|
||||
@ -449,9 +530,12 @@ mod tests {
|
||||
.info
|
||||
.properties
|
||||
.merge(right.clone().meta.info.properties);
|
||||
expected.albums.append(&mut right.albums.clone());
|
||||
expected.albums.extend(newly_added);
|
||||
expected.albums.sort_unstable();
|
||||
expected.albums.dedup();
|
||||
|
||||
// Albums are expected to be sorted.
|
||||
left.albums.sort_unstable();
|
||||
right.albums.sort_unstable();
|
||||
|
||||
let merged = left.clone().merge(right);
|
||||
assert_eq!(expected, merged);
|
||||
|
@ -23,8 +23,8 @@ impl<T: Ord> Merge for Vec<T> {
|
||||
}
|
||||
|
||||
impl<K: Hash + PartialEq + Eq, T: Ord> Merge for HashMap<K, Vec<T>> {
|
||||
fn merge_in_place(&mut self, mut other: Self) {
|
||||
for (other_key, other_value) in other.drain() {
|
||||
fn merge_in_place(&mut self, other: Self) {
|
||||
for (other_key, other_value) in other.into_iter() {
|
||||
if let Some(ref mut value) = self.get_mut(&other_key) {
|
||||
value.merge_in_place(other_value)
|
||||
} else {
|
||||
@ -80,7 +80,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WithId {
|
||||
pub trait MergeId {
|
||||
type Id;
|
||||
|
||||
fn id(&self) -> &Self::Id;
|
||||
@ -95,17 +95,9 @@ pub struct MergeCollections<ID, T, IT> {
|
||||
impl<ID, T, IT> MergeCollections<ID, T, IT>
|
||||
where
|
||||
ID: Eq + Hash + Clone,
|
||||
T: WithId<Id = ID> + Merge + Ord,
|
||||
T: MergeId<Id = ID> + Merge + Ord,
|
||||
IT: IntoIterator<Item = T>,
|
||||
{
|
||||
pub fn merge_iter(primary: IT, secondary: IT) -> Vec<T> {
|
||||
let primary = primary
|
||||
.into_iter()
|
||||
.map(|item| (item.id().clone(), item))
|
||||
.collect();
|
||||
Self::merge(primary, secondary)
|
||||
}
|
||||
|
||||
pub fn merge(mut primary: HashMap<ID, T>, secondary: IT) -> Vec<T> {
|
||||
for secondary_item in secondary {
|
||||
if let Some(ref mut primary_item) = primary.get_mut(secondary_item.id()) {
|
||||
|
@ -1,11 +1,16 @@
|
||||
//! Module for interacting with the music library.
|
||||
|
||||
use std::{collections::HashSet, fmt, num::ParseIntError, str::Utf8Error};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fmt,
|
||||
num::ParseIntError,
|
||||
str::{ParseBoolError, Utf8Error},
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
use mockall::automock;
|
||||
|
||||
use crate::core::collection::track::TrackFormat;
|
||||
use crate::{collection::album::AlbumLibId, core::collection::track::TrackFormat};
|
||||
|
||||
/// Trait for interacting with the music library.
|
||||
#[cfg_attr(test, automock)]
|
||||
@ -32,6 +37,7 @@ pub struct Item {
|
||||
pub album_month: u8,
|
||||
pub album_day: u8,
|
||||
pub album_title: String,
|
||||
pub album_lib_id: AlbumLibId,
|
||||
pub track_number: u32,
|
||||
pub track_title: String,
|
||||
pub track_artist: Vec<String>,
|
||||
@ -90,6 +96,8 @@ pub enum Error {
|
||||
Io(String),
|
||||
/// The library received invalid data.
|
||||
Invalid(String),
|
||||
/// The library failed to parse a boolean.
|
||||
ParseBool(String),
|
||||
/// The library failed to parse an integer.
|
||||
ParseInt(String),
|
||||
/// The library failed to parse a UTF-8 string.
|
||||
@ -102,6 +110,7 @@ impl fmt::Display for Error {
|
||||
Self::Executor(ref s) => write!(f, "the library's executor failed: {s}"),
|
||||
Self::Io(ref s) => write!(f, "the library experienced an I/O error: {s}"),
|
||||
Self::Invalid(ref s) => write!(f, "the library received invalid data: {s}"),
|
||||
Self::ParseBool(ref s) => write!(f, "the library failed to parse a boolean: {s}"),
|
||||
Self::ParseInt(ref s) => write!(f, "the library failed to parse an integer: {s}"),
|
||||
Self::Utf8(ref s) => write!(f, "the library failed to parse a UTF-8 string: {s}"),
|
||||
}
|
||||
@ -114,6 +123,12 @@ impl From<std::io::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseBoolError> for Error {
|
||||
fn from(err: ParseBoolError) -> Error {
|
||||
Error::ParseBool(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for Error {
|
||||
fn from(err: ParseIntError) -> Error {
|
||||
Error::ParseInt(err.to_string())
|
||||
@ -162,6 +177,7 @@ mod tests {
|
||||
let exe_err = Error::Executor(String::from("Executor"));
|
||||
let io_err: Error = io::Error::new(io::ErrorKind::Interrupted, "Interrupted").into();
|
||||
let inv_err = Error::Invalid(String::from("Invalid"));
|
||||
let bool_err: Error = "f".parse::<bool>().unwrap_err().into();
|
||||
let int_err: Error = "five".parse::<u32>().unwrap_err().into();
|
||||
#[allow(invalid_from_utf8)]
|
||||
let utf_err: Error = std::str::from_utf8(b"\xe2\x28\xa1").unwrap_err().into();
|
||||
@ -169,12 +185,14 @@ mod tests {
|
||||
assert!(!exe_err.to_string().is_empty());
|
||||
assert!(!io_err.to_string().is_empty());
|
||||
assert!(!inv_err.to_string().is_empty());
|
||||
assert!(!bool_err.to_string().is_empty());
|
||||
assert!(!int_err.to_string().is_empty());
|
||||
assert!(!utf_err.to_string().is_empty());
|
||||
|
||||
assert!(!format!("{:?}", exe_err).is_empty());
|
||||
assert!(!format!("{:?}", io_err).is_empty());
|
||||
assert!(!format!("{:?}", inv_err).is_empty());
|
||||
assert!(!format!("{:?}", bool_err).is_empty());
|
||||
assert!(!format!("{:?}", int_err).is_empty());
|
||||
assert!(!format!("{:?}", utf_err).is_empty());
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::core::{collection::track::TrackFormat, interface::library::Item};
|
||||
use crate::{
|
||||
collection::album::AlbumLibId,
|
||||
core::{collection::track::TrackFormat, interface::library::Item},
|
||||
};
|
||||
|
||||
pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
vec![
|
||||
@ -11,6 +14,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title a.a"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 1,
|
||||
track_title: String::from("track a.a.1"),
|
||||
track_artist: vec![String::from("artist a.a.1")],
|
||||
@ -24,6 +28,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title a.a"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 2,
|
||||
track_title: String::from("track a.a.2"),
|
||||
track_artist: vec![
|
||||
@ -40,6 +45,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title a.a"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 3,
|
||||
track_title: String::from("track a.a.3"),
|
||||
track_artist: vec![String::from("artist a.a.3")],
|
||||
@ -53,6 +59,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title a.a"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 4,
|
||||
track_title: String::from("track a.a.4"),
|
||||
track_artist: vec![String::from("artist a.a.4")],
|
||||
@ -66,6 +73,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 4,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title a.b"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 1,
|
||||
track_title: String::from("track a.b.1"),
|
||||
track_artist: vec![String::from("artist a.b.1")],
|
||||
@ -79,6 +87,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 4,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title a.b"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 2,
|
||||
track_title: String::from("track a.b.2"),
|
||||
track_artist: vec![String::from("artist a.b.2")],
|
||||
@ -92,6 +101,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 6,
|
||||
album_day: 6,
|
||||
album_title: String::from("album_title b.a"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 1,
|
||||
track_title: String::from("track b.a.1"),
|
||||
track_artist: vec![String::from("artist b.a.1")],
|
||||
@ -105,6 +115,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 6,
|
||||
album_day: 6,
|
||||
album_title: String::from("album_title b.a"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 2,
|
||||
track_title: String::from("track b.a.2"),
|
||||
track_artist: vec![
|
||||
@ -121,6 +132,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title b.b"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 1,
|
||||
track_title: String::from("track b.b.1"),
|
||||
track_artist: vec![String::from("artist b.b.1")],
|
||||
@ -134,6 +146,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title b.b"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 2,
|
||||
track_title: String::from("track b.b.2"),
|
||||
track_artist: vec![
|
||||
@ -150,6 +163,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title b.c"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 1,
|
||||
track_title: String::from("track b.c.1"),
|
||||
track_artist: vec![String::from("artist b.c.1")],
|
||||
@ -163,6 +177,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title b.c"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 2,
|
||||
track_title: String::from("track b.c.2"),
|
||||
track_artist: vec![
|
||||
@ -179,6 +194,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title b.d"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 1,
|
||||
track_title: String::from("track b.d.1"),
|
||||
track_artist: vec![String::from("artist b.d.1")],
|
||||
@ -192,6 +208,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title b.d"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 2,
|
||||
track_title: String::from("track b.d.2"),
|
||||
track_artist: vec![
|
||||
@ -208,6 +225,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title c.a"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 1,
|
||||
track_title: String::from("track c.a.1"),
|
||||
track_artist: vec![String::from("artist c.a.1")],
|
||||
@ -221,6 +239,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title c.a"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 2,
|
||||
track_title: String::from("track c.a.2"),
|
||||
track_artist: vec![
|
||||
@ -237,6 +256,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title c.b"),
|
||||
album_lib_id: AlbumLibId::Value(8),
|
||||
track_number: 1,
|
||||
track_title: String::from("track c.b.1"),
|
||||
track_artist: vec![String::from("artist c.b.1")],
|
||||
@ -250,6 +270,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title c.b"),
|
||||
album_lib_id: AlbumLibId::Value(8),
|
||||
track_number: 2,
|
||||
track_title: String::from("track c.b.2"),
|
||||
track_artist: vec![
|
||||
@ -266,6 +287,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title d.a"),
|
||||
album_lib_id: AlbumLibId::Value(9),
|
||||
track_number: 1,
|
||||
track_title: String::from("track d.a.1"),
|
||||
track_artist: vec![String::from("artist d.a.1")],
|
||||
@ -279,6 +301,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title d.a"),
|
||||
album_lib_id: AlbumLibId::Value(9),
|
||||
track_number: 2,
|
||||
track_title: String::from("track d.a.2"),
|
||||
track_artist: vec![
|
||||
@ -295,6 +318,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title d.b"),
|
||||
album_lib_id: AlbumLibId::Value(10),
|
||||
track_number: 1,
|
||||
track_title: String::from("track d.b.1"),
|
||||
track_artist: vec![String::from("artist d.b.1")],
|
||||
@ -308,6 +332,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("album_title d.b"),
|
||||
album_lib_id: AlbumLibId::Value(10),
|
||||
track_number: 2,
|
||||
track_title: String::from("track d.b.2"),
|
||||
track_artist: vec![
|
||||
|
@ -56,6 +56,7 @@ impl<Database, Library: ILibrary> MusicHoard<Database, Library> {
|
||||
|
||||
let album_id = AlbumId {
|
||||
title: item.album_title,
|
||||
lib_id: item.album_lib_id,
|
||||
};
|
||||
|
||||
let album_date = AlbumDate {
|
||||
@ -230,7 +231,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rescan_library_album_id_clash() {
|
||||
fn rescan_library_different_artist_album_title_clash() {
|
||||
let mut library = MockILibrary::new();
|
||||
|
||||
let mut expected = LIBRARY_COLLECTION.to_owned();
|
||||
@ -245,7 +246,7 @@ mod tests {
|
||||
item.album_title = clashed_album_id.title.clone();
|
||||
}
|
||||
|
||||
expected[0].albums[0].meta.id = clashed_album_id.clone();
|
||||
expected[0].albums[0].meta.id.title = clashed_album_id.title.clone();
|
||||
|
||||
let library_input = Query::new();
|
||||
let library_result = Ok(items);
|
||||
|
@ -2,7 +2,7 @@ use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::core::collection::{
|
||||
album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
||||
album::{Album, AlbumId, AlbumInfo, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
||||
artist::{Artist, ArtistId, ArtistInfo, ArtistMeta},
|
||||
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
|
||||
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub static DATABASE_JSON: &str = "{\
|
||||
\"V20240924\":\
|
||||
\"V20250101\":\
|
||||
[\
|
||||
{\
|
||||
\"name\":\"Album_Artist ‘A’\",\
|
||||
@ -11,12 +11,12 @@ pub static DATABASE_JSON: &str = "{\
|
||||
},\
|
||||
\"albums\":[\
|
||||
{\
|
||||
\"title\":\"album_title a.a\",\"seq\":1,\
|
||||
\"title\":\"album_title a.a\",\"lib_id\":{\"Value\":1},\"seq\":1,\
|
||||
\"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
},\
|
||||
{\
|
||||
\"title\":\"album_title a.b\",\"seq\":1,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title a.b\",\"lib_id\":{\"Value\":2},\"seq\":1,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
}\
|
||||
]\
|
||||
@ -35,21 +35,21 @@ pub static DATABASE_JSON: &str = "{\
|
||||
},\
|
||||
\"albums\":[\
|
||||
{\
|
||||
\"title\":\"album_title b.a\",\"seq\":1,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title b.a\",\"lib_id\":{\"Value\":3},\"seq\":1,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
},\
|
||||
{\
|
||||
\"title\":\"album_title b.b\",\"seq\":3,\
|
||||
\"title\":\"album_title b.b\",\"lib_id\":{\"Value\":4},\"seq\":3,\
|
||||
\"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
},\
|
||||
{\
|
||||
\"title\":\"album_title b.c\",\"seq\":2,\
|
||||
\"title\":\"album_title b.c\",\"lib_id\":{\"Value\":5},\"seq\":2,\
|
||||
\"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111112\"},\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
},\
|
||||
{\
|
||||
\"title\":\"album_title b.d\",\"seq\":4,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title b.d\",\"lib_id\":{\"Value\":6},\"seq\":4,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
}\
|
||||
]\
|
||||
@ -61,11 +61,11 @@ pub static DATABASE_JSON: &str = "{\
|
||||
\"properties\":{},\
|
||||
\"albums\":[\
|
||||
{\
|
||||
\"title\":\"album_title c.a\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title c.a\",\"lib_id\":{\"Value\":7},\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
},\
|
||||
{\
|
||||
\"title\":\"album_title c.b\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title c.b\",\"lib_id\":{\"Value\":8},\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
}\
|
||||
]\
|
||||
@ -77,11 +77,11 @@ pub static DATABASE_JSON: &str = "{\
|
||||
\"properties\":{},\
|
||||
\"albums\":[\
|
||||
{\
|
||||
\"title\":\"album_title d.a\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title d.a\",\"lib_id\":{\"Value\":9},\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
},\
|
||||
{\
|
||||
\"title\":\"album_title d.b\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"title\":\"album_title d.b\",\"lib_id\":{\"Value\":10},\"seq\":0,\"musicbrainz\":\"None\",\
|
||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||
}\
|
||||
]\
|
||||
|
@ -2,9 +2,17 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
collection::musicbrainz::MbRefOption,
|
||||
core::collection::album::{AlbumPrimaryType, AlbumSecondaryType},
|
||||
core::collection::album::{AlbumLibId, AlbumPrimaryType, AlbumSecondaryType},
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(remote = "AlbumLibId")]
|
||||
pub enum AlbumLibIdDef {
|
||||
Value(u32),
|
||||
Singleton,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(remote = "MbRefOption")]
|
||||
pub enum MbRefOptionDef<T> {
|
||||
|
@ -4,7 +4,7 @@ use serde::{de::Visitor, Deserialize, Deserializer};
|
||||
|
||||
use crate::{
|
||||
collection::{
|
||||
album::{AlbumInfo, AlbumMeta},
|
||||
album::{AlbumInfo, AlbumLibId, AlbumMeta},
|
||||
artist::{ArtistInfo, ArtistMeta},
|
||||
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid},
|
||||
},
|
||||
@ -13,20 +13,20 @@ use crate::{
|
||||
artist::{Artist, ArtistId},
|
||||
Collection, Error as CollectionError,
|
||||
},
|
||||
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
||||
external::database::serde::common::{
|
||||
AlbumLibIdDef, MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType,
|
||||
},
|
||||
};
|
||||
|
||||
use super::common::MbRefOptionDef;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub enum DeserializeDatabase {
|
||||
V20240924(Vec<DeserializeArtist>),
|
||||
V20250101(Vec<DeserializeArtist>),
|
||||
}
|
||||
|
||||
impl From<DeserializeDatabase> for Collection {
|
||||
fn from(database: DeserializeDatabase) -> Self {
|
||||
match database {
|
||||
DeserializeDatabase::V20240924(collection) => {
|
||||
DeserializeDatabase::V20250101(collection) => {
|
||||
collection.into_iter().map(Into::into).collect()
|
||||
}
|
||||
}
|
||||
@ -45,12 +45,22 @@ pub struct DeserializeArtist {
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct DeserializeAlbum {
|
||||
title: String,
|
||||
lib_id: DeserializeAlbumLibId,
|
||||
seq: u8,
|
||||
musicbrainz: DeserializeMbRefOption,
|
||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct DeserializeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId);
|
||||
|
||||
impl From<DeserializeAlbumLibId> for AlbumLibId {
|
||||
fn from(value: DeserializeAlbumLibId) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct DeserializeMbRefOption(#[serde(with = "MbRefOptionDef")] MbRefOption<DeserializeMbid>);
|
||||
|
||||
@ -129,7 +139,10 @@ impl From<DeserializeAlbum> for Album {
|
||||
fn from(album: DeserializeAlbum) -> Self {
|
||||
Album {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId { title: album.title },
|
||||
id: AlbumId {
|
||||
title: album.title,
|
||||
lib_id: album.lib_id.into(),
|
||||
},
|
||||
date: AlbumDate::default(),
|
||||
seq: AlbumSeq(album.seq),
|
||||
info: AlbumInfo {
|
||||
|
@ -3,21 +3,24 @@ use std::collections::BTreeMap;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
collection::musicbrainz::{MbRefOption, Mbid},
|
||||
collection::{
|
||||
album::AlbumLibId,
|
||||
musicbrainz::{MbRefOption, Mbid},
|
||||
},
|
||||
core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection},
|
||||
external::database::serde::common::{
|
||||
MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType,
|
||||
AlbumLibIdDef, MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum SerializeDatabase<'a> {
|
||||
V20240924(Vec<SerializeArtist<'a>>),
|
||||
V20250101(Vec<SerializeArtist<'a>>),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
||||
fn from(collection: &'a Collection) -> Self {
|
||||
SerializeDatabase::V20240924(collection.iter().map(Into::into).collect())
|
||||
SerializeDatabase::V20250101(collection.iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,12 +36,22 @@ pub struct SerializeArtist<'a> {
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SerializeAlbum<'a> {
|
||||
title: &'a str,
|
||||
lib_id: SerializeAlbumLibId,
|
||||
seq: u8,
|
||||
musicbrainz: SerializeMbRefOption<'a>,
|
||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SerializeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId);
|
||||
|
||||
impl From<AlbumLibId> for SerializeAlbumLibId {
|
||||
fn from(value: AlbumLibId) -> Self {
|
||||
SerializeAlbumLibId(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SerializeMbRefOption<'a>(
|
||||
#[serde(with = "MbRefOptionDef")] MbRefOption<SerializeMbid<'a>>,
|
||||
@ -90,6 +103,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> {
|
||||
fn from(album: &'a Album) -> Self {
|
||||
SerializeAlbum {
|
||||
title: &album.meta.id.title,
|
||||
lib_id: album.meta.id.lib_id.into(),
|
||||
seq: album.meta.seq.0,
|
||||
musicbrainz: (&album.meta.info.musicbrainz).into(),
|
||||
primary_type: album.meta.info.primary_type.map(Into::into),
|
||||
|
@ -6,9 +6,12 @@ pub mod executor;
|
||||
#[cfg(test)]
|
||||
use mockall::automock;
|
||||
|
||||
use crate::core::{
|
||||
collection::track::TrackFormat,
|
||||
interface::library::{Error, Field, ILibrary, Item, Query},
|
||||
use crate::{
|
||||
collection::album::AlbumLibId,
|
||||
core::{
|
||||
collection::track::TrackFormat,
|
||||
interface::library::{Error, Field, ILibrary, Item, Query},
|
||||
},
|
||||
};
|
||||
|
||||
macro_rules! list_format_separator {
|
||||
@ -31,8 +34,12 @@ const LIST_FORMAT_ARG: &str = concat!(
|
||||
list_format_separator!(),
|
||||
"$day",
|
||||
list_format_separator!(),
|
||||
"$singleton",
|
||||
list_format_separator!(),
|
||||
"$album",
|
||||
list_format_separator!(),
|
||||
"$album_id",
|
||||
list_format_separator!(),
|
||||
"$track",
|
||||
list_format_separator!(),
|
||||
"$title",
|
||||
@ -144,7 +151,7 @@ impl<BLE: IBeetsLibraryExecutor> BeetsLibrary<BLE> {
|
||||
}
|
||||
|
||||
let split: Vec<&str> = line.split(LIST_FORMAT_SEPARATOR).collect();
|
||||
if split.len() != 11 {
|
||||
if split.len() != 13 {
|
||||
return Err(Error::Invalid(line.to_string()));
|
||||
}
|
||||
|
||||
@ -156,15 +163,20 @@ impl<BLE: IBeetsLibraryExecutor> BeetsLibrary<BLE> {
|
||||
let album_year = split[2].parse::<u32>()?;
|
||||
let album_month = split[3].parse::<u8>()?;
|
||||
let album_day = split[4].parse::<u8>()?;
|
||||
let album_title = split[5].to_string();
|
||||
let track_number = split[6].parse::<u32>()?;
|
||||
let track_title = split[7].to_string();
|
||||
let track_artist = split[8].split("; ").map(|s| s.to_owned()).collect();
|
||||
let track_format = match str_to_format(split[9].to_string().as_str()) {
|
||||
let singleton = split[5].to_lowercase().parse::<bool>()?;
|
||||
let album_title = split[6].to_string();
|
||||
let album_lib_id = match singleton {
|
||||
true => AlbumLibId::Singleton,
|
||||
false => AlbumLibId::Value(split[7].parse::<u32>()?),
|
||||
};
|
||||
let track_number = split[8].parse::<u32>()?;
|
||||
let track_title = split[9].to_string();
|
||||
let track_artist = split[10].split("; ").map(|s| s.to_owned()).collect();
|
||||
let track_format = match str_to_format(split[11].to_string().as_str()) {
|
||||
Some(format) => format,
|
||||
None => return Err(Error::Invalid(line.to_string())),
|
||||
};
|
||||
let track_bitrate = split[10].trim_end_matches("kbps").parse::<u32>()?;
|
||||
let track_bitrate = split[12].trim_end_matches("kbps").parse::<u32>()?;
|
||||
|
||||
items.push(Item {
|
||||
album_artist,
|
||||
@ -173,6 +185,7 @@ impl<BLE: IBeetsLibraryExecutor> BeetsLibrary<BLE> {
|
||||
album_month,
|
||||
album_day,
|
||||
album_title,
|
||||
album_lib_id,
|
||||
track_number,
|
||||
track_title,
|
||||
track_artist,
|
||||
@ -358,8 +371,8 @@ mod tests {
|
||||
.split(LIST_FORMAT_SEPARATOR)
|
||||
.map(|s| s.to_owned())
|
||||
.collect::<Vec<String>>();
|
||||
invalid_string[9].clear();
|
||||
invalid_string[9].push_str("invalid format");
|
||||
invalid_string[11].clear();
|
||||
invalid_string[11].push_str("invalid format");
|
||||
let invalid_string = invalid_string.join(LIST_FORMAT_SEPARATOR);
|
||||
output[2] = invalid_string.clone();
|
||||
let result = Ok(output);
|
||||
|
@ -4,112 +4,112 @@ pub static LIBRARY_BEETS: Lazy<Vec<String>> = Lazy::new(|| -> Vec<String> {
|
||||
vec![
|
||||
String::from(
|
||||
"Album_Artist ‘A’ -*^- -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \
|
||||
1 -*^- track a.a.1 -*^- artist a.a.1 -*^- FLAC -*^- 992",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘A’ -*^- -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \
|
||||
2 -*^- track a.a.2 -*^- artist a.a.2.1; artist a.a.2.2 -*^- MP3 -*^- 320",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘A’ -*^- -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \
|
||||
3 -*^- track a.a.3 -*^- artist a.a.3 -*^- FLAC -*^- 1061",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘A’ -*^- -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \
|
||||
1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \
|
||||
4 -*^- track a.a.4 -*^- artist a.a.4 -*^- FLAC -*^- 1042",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘A’ -*^- -*^- \
|
||||
2015 -*^- 04 -*^- 00 -*^- album_title a.b -*^- \
|
||||
2015 -*^- 04 -*^- 00 -*^- False -*^- album_title a.b -*^- 2 -*^- \
|
||||
1 -*^- track a.b.1 -*^- artist a.b.1 -*^- FLAC -*^- 1004",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘A’ -*^- -*^- \
|
||||
2015 -*^- 04 -*^- 00 -*^- album_title a.b -*^- \
|
||||
2015 -*^- 04 -*^- 00 -*^- False -*^- album_title a.b -*^- 2 -*^- \
|
||||
2 -*^- track a.b.2 -*^- artist a.b.2 -*^- FLAC -*^- 1077",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2003 -*^- 06 -*^- 06 -*^- album_title b.a -*^- \
|
||||
2003 -*^- 06 -*^- 06 -*^- False -*^- album_title b.a -*^- 3 -*^- \
|
||||
1 -*^- track b.a.1 -*^- artist b.a.1 -*^- MP3 -*^- 190",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2003 -*^- 06 -*^- 06 -*^- album_title b.a -*^- \
|
||||
2003 -*^- 06 -*^- 06 -*^- False -*^- album_title b.a -*^- 3 -*^- \
|
||||
2 -*^- track b.a.2 -*^- artist b.a.2.1; artist b.a.2.2 -*^- MP3 -*^- 120",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2008 -*^- 00 -*^- 00 -*^- album_title b.b -*^- \
|
||||
2008 -*^- 00 -*^- 00 -*^- False -*^- album_title b.b -*^- 4 -*^- \
|
||||
1 -*^- track b.b.1 -*^- artist b.b.1 -*^- FLAC -*^- 1077",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2008 -*^- 00 -*^- 00 -*^- album_title b.b -*^- \
|
||||
2008 -*^- 00 -*^- 00 -*^- False -*^- album_title b.b -*^- 4 -*^- \
|
||||
2 -*^- track b.b.2 -*^- artist b.b.2.1; artist b.b.2.2 -*^- MP3 -*^- 320",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2009 -*^- 00 -*^- 00 -*^- album_title b.c -*^- \
|
||||
2009 -*^- 00 -*^- 00 -*^- False -*^- album_title b.c -*^- 5 -*^- \
|
||||
1 -*^- track b.c.1 -*^- artist b.c.1 -*^- MP3 -*^- 190",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2009 -*^- 00 -*^- 00 -*^- album_title b.c -*^- \
|
||||
2009 -*^- 00 -*^- 00 -*^- False -*^- album_title b.c -*^- 5 -*^- \
|
||||
2 -*^- track b.c.2 -*^- artist b.c.2.1; artist b.c.2.2 -*^- MP3 -*^- 120",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2015 -*^- 00 -*^- 00 -*^- album_title b.d -*^- \
|
||||
2015 -*^- 00 -*^- 00 -*^- False -*^- album_title b.d -*^- 6 -*^- \
|
||||
1 -*^- track b.d.1 -*^- artist b.d.1 -*^- MP3 -*^- 190",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘B’ -*^- -*^- \
|
||||
2015 -*^- 00 -*^- 00 -*^- album_title b.d -*^- \
|
||||
2015 -*^- 00 -*^- 00 -*^- False -*^- album_title b.d -*^- 6 -*^- \
|
||||
2 -*^- track b.d.2 -*^- artist b.d.2.1; artist b.d.2.2 -*^- MP3 -*^- 120",
|
||||
),
|
||||
String::from(
|
||||
"The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \
|
||||
1985 -*^- 00 -*^- 00 -*^- album_title c.a -*^- \
|
||||
1985 -*^- 00 -*^- 00 -*^- False -*^- album_title c.a -*^- 7 -*^- \
|
||||
1 -*^- track c.a.1 -*^- artist c.a.1 -*^- MP3 -*^- 320",
|
||||
),
|
||||
String::from(
|
||||
"The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \
|
||||
1985 -*^- 00 -*^- 00 -*^- album_title c.a -*^- \
|
||||
1985 -*^- 00 -*^- 00 -*^- False -*^- album_title c.a -*^- 7 -*^- \
|
||||
2 -*^- track c.a.2 -*^- artist c.a.2.1; artist c.a.2.2 -*^- MP3 -*^- 120",
|
||||
),
|
||||
String::from(
|
||||
"The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \
|
||||
2018 -*^- 00 -*^- 00 -*^- album_title c.b -*^- \
|
||||
2018 -*^- 00 -*^- 00 -*^- False -*^- album_title c.b -*^- 8 -*^- \
|
||||
1 -*^- track c.b.1 -*^- artist c.b.1 -*^- FLAC -*^- 1041",
|
||||
),
|
||||
String::from(
|
||||
"The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \
|
||||
2018 -*^- 00 -*^- 00 -*^- album_title c.b -*^- \
|
||||
2018 -*^- 00 -*^- 00 -*^- False -*^- album_title c.b -*^- 8 -*^- \
|
||||
2 -*^- track c.b.2 -*^- artist c.b.2.1; artist c.b.2.2 -*^- FLAC -*^- 756",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘D’ -*^- -*^- \
|
||||
1995 -*^- 00 -*^- 00 -*^- album_title d.a -*^- \
|
||||
1995 -*^- 00 -*^- 00 -*^- False -*^- album_title d.a -*^- 9 -*^- \
|
||||
1 -*^- track d.a.1 -*^- artist d.a.1 -*^- MP3 -*^- 120",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘D’ -*^- -*^- \
|
||||
1995 -*^- 00 -*^- 00 -*^- album_title d.a -*^- \
|
||||
1995 -*^- 00 -*^- 00 -*^- False -*^- album_title d.a -*^- 9 -*^- \
|
||||
2 -*^- track d.a.2 -*^- artist d.a.2.1; artist d.a.2.2 -*^- MP3 -*^- 120",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘D’ -*^- -*^- \
|
||||
2028 -*^- 00 -*^- 00 -*^- album_title d.b -*^- \
|
||||
2028 -*^- 00 -*^- 00 -*^- False -*^- album_title d.b -*^- 10 -*^- \
|
||||
1 -*^- track d.b.1 -*^- artist d.b.1 -*^- FLAC -*^- 841",
|
||||
),
|
||||
String::from(
|
||||
"Album_Artist ‘D’ -*^- -*^- \
|
||||
2028 -*^- 00 -*^- 00 -*^- album_title d.b -*^- \
|
||||
2028 -*^- 00 -*^- 00 -*^- False -*^- album_title d.b -*^- 10 -*^- \
|
||||
2 -*^- track d.b.2 -*^- artist d.b.2.1; artist d.b.2.2 -*^- FLAC -*^- 756",
|
||||
),
|
||||
]
|
||||
|
@ -4,13 +4,14 @@ use url::form_urlencoded;
|
||||
use crate::{
|
||||
collection::musicbrainz::Mbid,
|
||||
external::musicbrainz::{
|
||||
api::{Error, MusicBrainzClient, MB_BASE_URL},
|
||||
api::{
|
||||
Error, MbArtistMeta, MbReleaseGroupMeta, MusicBrainzClient, SerdeMbArtistMeta,
|
||||
SerdeMbReleaseGroupMeta, MB_BASE_URL,
|
||||
},
|
||||
IMusicBrainzHttp,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{MbArtistMeta, MbReleaseGroupMeta, SerdeMbArtistMeta, SerdeMbReleaseGroupMeta};
|
||||
|
||||
impl<Http: IMusicBrainzHttp> MusicBrainzClient<Http> {
|
||||
pub fn lookup_artist(
|
||||
&mut self,
|
||||
|
@ -28,6 +28,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title a.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(1),
|
||||
},
|
||||
date: 1998.into(),
|
||||
seq: AlbumSeq(1),
|
||||
@ -93,6 +94,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title a.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(2),
|
||||
},
|
||||
date: (2015, 4).into(),
|
||||
seq: AlbumSeq(1),
|
||||
@ -160,6 +162,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(3),
|
||||
},
|
||||
date: (2003, 6, 6).into(),
|
||||
seq: AlbumSeq(1),
|
||||
@ -201,6 +204,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(4),
|
||||
},
|
||||
date: 2008.into(),
|
||||
seq: AlbumSeq(3),
|
||||
@ -244,6 +248,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.c".to_string(),
|
||||
lib_id: AlbumLibId::Value(5),
|
||||
},
|
||||
date: 2009.into(),
|
||||
seq: AlbumSeq(2),
|
||||
@ -287,6 +292,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.d".to_string(),
|
||||
lib_id: AlbumLibId::Value(6),
|
||||
},
|
||||
date: 2015.into(),
|
||||
seq: AlbumSeq(4),
|
||||
@ -342,6 +348,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title c.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(7),
|
||||
},
|
||||
date: 1985.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -383,6 +390,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title c.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(8),
|
||||
},
|
||||
date: 2018.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -438,6 +446,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title d.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(9),
|
||||
},
|
||||
date: 1995.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -479,6 +488,7 @@ macro_rules! full_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title d.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(10),
|
||||
},
|
||||
date: 2028.into(),
|
||||
seq: AlbumSeq(0),
|
||||
|
@ -18,6 +18,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title a.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(1),
|
||||
},
|
||||
date: 1998.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -77,6 +78,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title a.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(2),
|
||||
},
|
||||
date: (2015, 4).into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -125,6 +127,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(3),
|
||||
},
|
||||
date: (2003, 6, 6).into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -162,6 +165,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(4),
|
||||
},
|
||||
date: 2008.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -199,6 +203,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.c".to_string(),
|
||||
lib_id: AlbumLibId::Value(5),
|
||||
},
|
||||
date: 2009.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -236,6 +241,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title b.d".to_string(),
|
||||
lib_id: AlbumLibId::Value(6),
|
||||
},
|
||||
date: 2015.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -287,6 +293,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title c.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(7),
|
||||
},
|
||||
date: 1985.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -324,6 +331,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title c.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(8),
|
||||
},
|
||||
date: 2018.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -375,6 +383,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title d.a".to_string(),
|
||||
lib_id: AlbumLibId::Value(9),
|
||||
},
|
||||
date: 1995.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -412,6 +421,7 @@ macro_rules! library_collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: "album_title d.b".to_string(),
|
||||
lib_id: AlbumLibId::Value(10),
|
||||
},
|
||||
date: 2028.into(),
|
||||
seq: AlbumSeq(0),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use musichoard::collection::{
|
||||
album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
||||
album::{Album, AlbumId, AlbumInfo, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
||||
artist::{Artist, ArtistId, ArtistInfo, ArtistMeta},
|
||||
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
|
||||
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
||||
|
@ -1,6 +1,7 @@
|
||||
use musichoard::collection::{
|
||||
album::{
|
||||
AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus,
|
||||
AlbumDate, AlbumId, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq,
|
||||
AlbumStatus,
|
||||
},
|
||||
artist::ArtistMeta,
|
||||
musicbrainz::{IMusicBrainzRef, MbRefOption},
|
||||
@ -20,6 +21,14 @@ impl UiDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_album_lib_id(lib_id: &AlbumLibId) -> String {
|
||||
match lib_id {
|
||||
AlbumLibId::Value(val) => val.to_string(),
|
||||
AlbumLibId::Singleton => "Singleton".to_string(),
|
||||
AlbumLibId::None => "None".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_album_date(date: &AlbumDate) -> String {
|
||||
match date.year {
|
||||
Some(year) => match date.month {
|
||||
@ -196,6 +205,16 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_album_lib_id() {
|
||||
assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::Value(5)), "5");
|
||||
assert_eq!(
|
||||
UiDisplay::display_album_lib_id(&AlbumLibId::Singleton),
|
||||
"Singleton"
|
||||
);
|
||||
assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::None), "None");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_date() {
|
||||
let date: AlbumDate = 1990.into();
|
||||
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use musichoard::collection::{album::Album, artist::Artist};
|
||||
use ratatui::widgets::{ListState, Paragraph};
|
||||
|
||||
use super::display::UiDisplay;
|
||||
use crate::tui::ui::display::UiDisplay;
|
||||
|
||||
struct InfoOverlay;
|
||||
|
||||
@ -101,8 +101,12 @@ impl<'a> AlbumOverlay<'a> {
|
||||
|
||||
let properties = Paragraph::new(format!(
|
||||
"Album: {}\n\n{item_indent}\
|
||||
Library ID: {}\n{item_indent}\
|
||||
MusicBrainz: {}",
|
||||
album.map(|a| a.meta.id.title.as_str()).unwrap_or(""),
|
||||
album
|
||||
.map(|a| UiDisplay::display_album_lib_id(&a.meta.id.lib_id))
|
||||
.unwrap_or_default(),
|
||||
album
|
||||
.map(|a| UiDisplay::display_mb_ref_option_as_url(&a.meta.info.musicbrainz))
|
||||
.unwrap_or_default(),
|
||||
|
@ -1 +1 @@
|
||||
{"V20240924":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"baad262d-55ef-427a-83c7-f7530964f212"},"properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"8000598a-5edb-401c-8e6d-36b167feaf38"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"3a901353-fccd-4afd-ad01-9c03f451b490"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]}
|
||||
{"V20250101":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"baad262d-55ef-427a-83c7-f7530964f212"},"properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","lib_id":{"Value":7},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"8000598a-5edb-401c-8e6d-36b167feaf38"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","lib_id":{"Value":1},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Value":2},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"3a901353-fccd-4afd-ad01-9c03f451b490"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","lib_id":{"Value":3},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","lib_id":"Singleton","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Value":4},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","lib_id":{"Value":5},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Value":6},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]}
|
@ -1,6 +1,9 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use musichoard::{collection::track::TrackFormat, interface::library::Item};
|
||||
use musichoard::{
|
||||
collection::{album::AlbumLibId, track::TrackFormat},
|
||||
interface::library::Item,
|
||||
};
|
||||
|
||||
pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
vec![
|
||||
@ -11,6 +14,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 1,
|
||||
track_title: String::from("Az’"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -24,6 +28,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 2,
|
||||
track_title: String::from("Arkaim"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -37,6 +42,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 3,
|
||||
track_title: String::from("Bol’no mne"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -50,6 +56,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 4,
|
||||
track_title: String::from("Leshiy"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -63,6 +70,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 5,
|
||||
track_title: String::from("Zakliatie"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -76,6 +84,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 6,
|
||||
track_title: String::from("Predok"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -89,6 +98,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 7,
|
||||
track_title: String::from("Nikogda"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -102,6 +112,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 8,
|
||||
track_title: String::from("Tam za tumanami"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -115,6 +126,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 9,
|
||||
track_title: String::from("Potomok"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -128,6 +140,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 10,
|
||||
track_title: String::from("Slovo"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -141,6 +154,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 11,
|
||||
track_title: String::from("Odna"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -154,6 +168,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 12,
|
||||
track_title: String::from("Vo moiom sadochke…"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -167,6 +182,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 13,
|
||||
track_title: String::from("Stenka na stenku"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -180,6 +196,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slovo"),
|
||||
album_lib_id: AlbumLibId::Value(7),
|
||||
track_number: 14,
|
||||
track_title: String::from("Zimushka"),
|
||||
track_artist: vec![String::from("Аркона")],
|
||||
@ -193,6 +210,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Vên [re‐recorded]"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 1,
|
||||
track_title: String::from("Verja Urit an Bitus"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -206,6 +224,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Vên [re‐recorded]"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 2,
|
||||
track_title: String::from("Uis Elveti"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -219,6 +238,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Vên [re‐recorded]"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 3,
|
||||
track_title: String::from("Ôrô"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -232,6 +252,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Vên [re‐recorded]"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 4,
|
||||
track_title: String::from("Lament"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -245,6 +266,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Vên [re‐recorded]"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 5,
|
||||
track_title: String::from("Druid"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -258,6 +280,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Vên [re‐recorded]"),
|
||||
album_lib_id: AlbumLibId::Value(1),
|
||||
track_number: 6,
|
||||
track_title: String::from("Jêzaïg"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -271,6 +294,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 1,
|
||||
track_title: String::from("Samon"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -284,6 +308,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 2,
|
||||
track_title: String::from("Primordial Breath"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -297,6 +322,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 3,
|
||||
track_title: String::from("Inis Mona"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -310,6 +336,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 4,
|
||||
track_title: String::from("Gray Sublime Archon"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -323,6 +350,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 5,
|
||||
track_title: String::from("Anagantios"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -336,6 +364,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 6,
|
||||
track_title: String::from("Bloodstained Ground"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -349,6 +378,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 7,
|
||||
track_title: String::from("The Somber Lay"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -362,6 +392,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 8,
|
||||
track_title: String::from("Slanias Song"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -375,6 +406,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 9,
|
||||
track_title: String::from("Giamonios"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -388,6 +420,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 10,
|
||||
track_title: String::from("Tarvos"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -401,6 +434,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 11,
|
||||
track_title: String::from("Calling the Rain"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -414,6 +448,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Slania"),
|
||||
album_lib_id: AlbumLibId::Value(2),
|
||||
track_number: 12,
|
||||
track_title: String::from("Elembivos"),
|
||||
track_artist: vec![String::from("Eluveitie")],
|
||||
@ -427,6 +462,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 1,
|
||||
track_title: String::from("Intro = Chaos"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -440,6 +476,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 2,
|
||||
track_title: String::from("Modlitwa"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -453,6 +490,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 3,
|
||||
track_title: String::from("Długa droga z piekła"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -466,6 +504,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 4,
|
||||
track_title: String::from("Synowie ognia"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -479,6 +518,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 5,
|
||||
track_title: String::from("1902"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -492,6 +532,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 6,
|
||||
track_title: String::from("Krew za krew"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -505,6 +546,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 7,
|
||||
track_title: String::from("Kulminacja"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -518,6 +560,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 8,
|
||||
track_title: String::from("Judasz"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -531,6 +574,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 9,
|
||||
track_title: String::from("Więzy"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -544,6 +588,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 10,
|
||||
track_title: String::from("Zagubione dusze"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -557,6 +602,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
album_lib_id: AlbumLibId::Value(3),
|
||||
track_number: 11,
|
||||
track_title: String::from("Linia życia"),
|
||||
track_artist: vec![String::from("Frontside")],
|
||||
@ -570,6 +616,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Paper Plague"),
|
||||
album_lib_id: AlbumLibId::Singleton,
|
||||
track_number: 0,
|
||||
track_title: String::from("Paper Plague"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -583,6 +630,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 1,
|
||||
track_title: String::from("Unbreakable"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -596,6 +644,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 2,
|
||||
track_title: String::from("Guilt Trips and Sins"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -609,6 +658,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 3,
|
||||
track_title: String::from("The Long Goodbye"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -622,6 +672,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 4,
|
||||
track_title: String::from("Close Encounters"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -635,6 +686,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 5,
|
||||
track_title: String::from("Paranoia"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -648,6 +700,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 6,
|
||||
track_title: String::from("Let Me Out of Here"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -661,6 +714,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Unbreakable"),
|
||||
album_lib_id: AlbumLibId::Value(4),
|
||||
track_number: 7,
|
||||
track_title: String::from("Leeches"),
|
||||
track_artist: vec![String::from("Heaven’s Basement")],
|
||||
@ -674,6 +728,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 1,
|
||||
track_title: String::from("Fight Fire with Fire"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -687,6 +742,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 2,
|
||||
track_title: String::from("Ride the Lightning"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -700,6 +756,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 3,
|
||||
track_title: String::from("For Whom the Bell Tolls"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -713,6 +770,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 4,
|
||||
track_title: String::from("Fade to Black"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -726,6 +784,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 5,
|
||||
track_title: String::from("Trapped under Ice"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -739,6 +798,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 6,
|
||||
track_title: String::from("Escape"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -752,6 +812,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 7,
|
||||
track_title: String::from("Creeping Death"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -765,6 +826,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("Ride the Lightning"),
|
||||
album_lib_id: AlbumLibId::Value(5),
|
||||
track_number: 8,
|
||||
track_title: String::from("The Call of Ktulu"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -778,6 +840,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 1,
|
||||
track_title: String::from("The Ecstasy of Gold"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -791,6 +854,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 2,
|
||||
track_title: String::from("The Call of Ktulu"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -804,6 +868,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 3,
|
||||
track_title: String::from("Master of Puppets"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -817,6 +882,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 4,
|
||||
track_title: String::from("Of Wolf and Man"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -830,6 +896,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 5,
|
||||
track_title: String::from("The Thing That Should Not Be"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -843,6 +910,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 6,
|
||||
track_title: String::from("Fuel"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -856,6 +924,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 7,
|
||||
track_title: String::from("The Memory Remains"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -869,6 +938,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 8,
|
||||
track_title: String::from("No Leaf Clover"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -882,6 +952,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 9,
|
||||
track_title: String::from("Hero of the Day"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -895,6 +966,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 10,
|
||||
track_title: String::from("Devil’s Dance"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -908,6 +980,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 11,
|
||||
track_title: String::from("Bleeding Me"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -921,6 +994,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 12,
|
||||
track_title: String::from("Nothing Else Matters"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -934,6 +1008,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 13,
|
||||
track_title: String::from("Until It Sleeps"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -947,6 +1022,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 14,
|
||||
track_title: String::from("For Whom the Bell Tolls"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -960,6 +1036,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 15,
|
||||
track_title: String::from("−Human"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -973,6 +1050,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 16,
|
||||
track_title: String::from("Wherever I May Roam"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -986,6 +1064,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 17,
|
||||
track_title: String::from("Outlaw Torn"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -999,6 +1078,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 18,
|
||||
track_title: String::from("Sad but True"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -1012,6 +1092,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 19,
|
||||
track_title: String::from("One"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -1025,6 +1106,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 20,
|
||||
track_title: String::from("Enter Sandman"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
@ -1038,6 +1120,7 @@ pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||
album_month: 0,
|
||||
album_day: 0,
|
||||
album_title: String::from("S&M"),
|
||||
album_lib_id: AlbumLibId::Value(6),
|
||||
track_number: 21,
|
||||
track_title: String::from("Battery"),
|
||||
track_artist: vec![String::from("Metallica")],
|
||||
|
@ -2,7 +2,10 @@ use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use musichoard::collection::{
|
||||
album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq},
|
||||
album::{
|
||||
Album, AlbumId, AlbumInfo, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType,
|
||||
AlbumSeq,
|
||||
},
|
||||
artist::{Artist, ArtistId, ArtistInfo, ArtistMeta},
|
||||
musicbrainz::{MbArtistRef, MbRefOption},
|
||||
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
||||
@ -38,6 +41,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("Slovo"),
|
||||
lib_id: AlbumLibId::Value(7),
|
||||
},
|
||||
date: 2011.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -230,6 +234,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("Vên [re‐recorded]"),
|
||||
lib_id: AlbumLibId::Value(1),
|
||||
},
|
||||
date: 2004.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -312,6 +317,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("Slania"),
|
||||
lib_id: AlbumLibId::Value(2),
|
||||
},
|
||||
date: 2008.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -482,6 +488,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||
lib_id: AlbumLibId::Value(3),
|
||||
},
|
||||
date: 2001.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -640,6 +647,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("Paper Plague"),
|
||||
lib_id: AlbumLibId::Singleton,
|
||||
},
|
||||
date: 2011.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -662,6 +670,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("Unbreakable"),
|
||||
lib_id: AlbumLibId::Value(4),
|
||||
},
|
||||
date: 2011.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -777,6 +786,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("Ride the Lightning"),
|
||||
lib_id: AlbumLibId::Value(5),
|
||||
},
|
||||
date: 1984.into(),
|
||||
seq: AlbumSeq(0),
|
||||
@ -881,6 +891,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||
meta: AlbumMeta {
|
||||
id: AlbumId {
|
||||
title: String::from("S&M"),
|
||||
lib_id: AlbumLibId::Value(6),
|
||||
},
|
||||
date: 1999.into(),
|
||||
seq: AlbumSeq(0),
|
||||
|
Loading…
x
Reference in New Issue
Block a user