Compare commits
No commits in common. "5abac79414cd62e1a899cfa3dd8e1c4d3c35a6d0" and "f7e215eedfe0de641dc874390d3706046b221e0b" have entirely different histories.
5abac79414
...
f7e215eedf
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
pub mod album;
|
pub mod album;
|
||||||
pub mod artist;
|
pub mod artist;
|
||||||
pub mod merge;
|
|
||||||
pub mod musicbrainz;
|
pub mod musicbrainz;
|
||||||
pub mod track;
|
pub mod track;
|
||||||
|
|
||||||
|
mod merge;
|
||||||
|
pub use merge::MergeCollections;
|
||||||
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
/// The [`Collection`] alias type for convenience.
|
/// The [`Collection`] alias type for convenience.
|
||||||
|
@ -2,8 +2,7 @@ use crate::core::{
|
|||||||
collection::{
|
collection::{
|
||||||
album::{Album, AlbumId},
|
album::{Album, AlbumId},
|
||||||
artist::{Artist, ArtistId},
|
artist::{Artist, ArtistId},
|
||||||
merge::MergeCollections,
|
Collection, MergeCollections,
|
||||||
Collection,
|
|
||||||
},
|
},
|
||||||
musichoard::{Error, MusicHoard},
|
musichoard::{Error, MusicHoard},
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use std::mem;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
collection::{album::AlbumInfo, artist::ArtistInfo, merge::Merge},
|
collection::{album::AlbumInfo, artist::ArtistInfo},
|
||||||
core::{
|
core::{
|
||||||
collection::{
|
collection::{
|
||||||
album::{Album, AlbumId, AlbumSeq},
|
album::{Album, AlbumId, AlbumSeq},
|
||||||
@ -26,7 +24,7 @@ pub trait IMusicHoardDatabase {
|
|||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
|
fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
|
||||||
|
|
||||||
fn merge_artist_info<Id: AsRef<ArtistId>>(
|
fn set_artist_info<Id: AsRef<ArtistId>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
artist_id: Id,
|
artist_id: Id,
|
||||||
info: ArtistInfo,
|
info: ArtistInfo,
|
||||||
@ -68,7 +66,7 @@ pub trait IMusicHoardDatabase {
|
|||||||
artist_id: ArtistIdRef,
|
artist_id: ArtistIdRef,
|
||||||
album_id: AlbumIdRef,
|
album_id: AlbumIdRef,
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
fn merge_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
fn set_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
artist_id: Id,
|
artist_id: Id,
|
||||||
album_id: AlbumIdRef,
|
album_id: AlbumIdRef,
|
||||||
@ -134,15 +132,12 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_artist_info<Id: AsRef<ArtistId>>(
|
fn set_artist_info<Id: AsRef<ArtistId>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
artist_id: Id,
|
artist_id: Id,
|
||||||
mut info: ArtistInfo,
|
info: ArtistInfo,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.update_artist(artist_id.as_ref(), |artist| {
|
self.update_artist(artist_id.as_ref(), |artist| artist.meta.info = info)
|
||||||
mem::swap(&mut artist.meta.info, &mut info);
|
|
||||||
artist.meta.info.merge_in_place(info);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_artist_info<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
|
fn clear_artist_info<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
|
||||||
@ -221,15 +216,14 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
fn set_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
artist_id: Id,
|
artist_id: Id,
|
||||||
album_id: AlbumIdRef,
|
album_id: AlbumIdRef,
|
||||||
mut info: AlbumInfo,
|
info: AlbumInfo,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
|
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
|
||||||
mem::swap(&mut album.meta.info, &mut info);
|
album.meta.info = info
|
||||||
album.meta.info.merge_in_place(info);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +457,7 @@ mod tests {
|
|||||||
|
|
||||||
let artist_id = ArtistId::new("an artist");
|
let artist_id = ArtistId::new("an artist");
|
||||||
let actual_err = music_hoard
|
let actual_err = music_hoard
|
||||||
.merge_artist_info(&artist_id, ArtistInfo::default())
|
.set_artist_info(&artist_id, ArtistInfo::default())
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
let expected_err =
|
let expected_err =
|
||||||
Error::CollectionError(format!("artist '{artist_id}' is not in the collection"));
|
Error::CollectionError(format!("artist '{artist_id}' is not in the collection"));
|
||||||
@ -490,13 +484,13 @@ mod tests {
|
|||||||
|
|
||||||
// Setting a URL on an artist not in the collection is an error.
|
// Setting a URL on an artist not in the collection is an error.
|
||||||
assert!(music_hoard
|
assert!(music_hoard
|
||||||
.merge_artist_info(&artist_id_2, info.clone())
|
.set_artist_info(&artist_id_2, info.clone())
|
||||||
.is_err());
|
.is_err());
|
||||||
assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
|
assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
|
||||||
|
|
||||||
// Setting a URL on an artist.
|
// Setting a URL on an artist.
|
||||||
assert!(music_hoard
|
assert!(music_hoard
|
||||||
.merge_artist_info(&artist_id, info.clone())
|
.set_artist_info(&artist_id, info.clone())
|
||||||
.is_ok());
|
.is_ok());
|
||||||
expected.replace(MbArtistRef::from_uuid_str(MBID).unwrap());
|
expected.replace(MbArtistRef::from_uuid_str(MBID).unwrap());
|
||||||
assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
|
assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
|
||||||
@ -685,14 +679,14 @@ mod tests {
|
|||||||
|
|
||||||
// Seting info on an album not belonging to the artist is an error.
|
// Seting info on an album not belonging to the artist is an error.
|
||||||
assert!(music_hoard
|
assert!(music_hoard
|
||||||
.merge_album_info(&artist_id, &album_id_2, info.clone())
|
.set_album_info(&artist_id, &album_id_2, info.clone())
|
||||||
.is_err());
|
.is_err());
|
||||||
let meta = &music_hoard.collection[0].albums[0].meta;
|
let meta = &music_hoard.collection[0].albums[0].meta;
|
||||||
assert_eq!(meta.info, AlbumInfo::default());
|
assert_eq!(meta.info, AlbumInfo::default());
|
||||||
|
|
||||||
// Set info.
|
// Set info.
|
||||||
assert!(music_hoard
|
assert!(music_hoard
|
||||||
.merge_album_info(&artist_id, &album_id, info.clone())
|
.set_album_info(&artist_id, &album_id, info.clone())
|
||||||
.is_ok());
|
.is_ok());
|
||||||
let meta = &music_hoard.collection[0].albums[0].meta;
|
let meta = &music_hoard.collection[0].albums[0].meta;
|
||||||
assert_eq!(meta.info, info);
|
assert_eq!(meta.info, info);
|
||||||
|
@ -5,7 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{Album, AlbumId},
|
album::{Album, AlbumMeta},
|
||||||
artist::{Artist, ArtistId, ArtistMeta},
|
artist::{Artist, ArtistId, ArtistMeta},
|
||||||
musicbrainz::{IMusicBrainzRef, MbArtistRef, MbRefOption, Mbid},
|
musicbrainz::{IMusicBrainzRef, MbArtistRef, MbRefOption, Mbid},
|
||||||
};
|
};
|
||||||
@ -151,13 +151,13 @@ impl AppMachine<FetchState> {
|
|||||||
inner: AppInner,
|
inner: AppInner,
|
||||||
fetch: FetchState,
|
fetch: FetchState,
|
||||||
artist_id: &ArtistId,
|
artist_id: &ArtistId,
|
||||||
album_id: &AlbumId,
|
album: &AlbumMeta,
|
||||||
mbid: Mbid,
|
mbid: Mbid,
|
||||||
) -> App {
|
) -> App {
|
||||||
let f = |mb: &dyn IMbJobSender, rs, album, mbid| {
|
let f = |mb: &dyn IMbJobSender, rs, album, mbid| {
|
||||||
Self::submit_lookup_release_group_job(mb, rs, artist_id, album, mbid)
|
Self::submit_lookup_release_group_job(mb, rs, artist_id, album, mbid)
|
||||||
};
|
};
|
||||||
Self::app_lookup(f, inner, fetch, album_id, mbid)
|
Self::app_lookup(f, inner, fetch, album, mbid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_lookup<F, Meta>(
|
fn app_lookup<F, Meta>(
|
||||||
@ -243,12 +243,12 @@ impl AppMachine<FetchState> {
|
|||||||
musicbrainz: &dyn IMbJobSender,
|
musicbrainz: &dyn IMbJobSender,
|
||||||
result_sender: ResultSender,
|
result_sender: ResultSender,
|
||||||
artist_id: &ArtistId,
|
artist_id: &ArtistId,
|
||||||
album_id: &AlbumId,
|
album: &AlbumMeta,
|
||||||
mbid: Mbid,
|
mbid: Mbid,
|
||||||
) -> Result<(), DaemonError> {
|
) -> Result<(), DaemonError> {
|
||||||
let requests = VecDeque::from([MbParams::lookup_release_group(
|
let requests = VecDeque::from([MbParams::lookup_release_group(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album_id.clone(),
|
album.clone(),
|
||||||
mbid,
|
mbid,
|
||||||
)]);
|
)]);
|
||||||
musicbrainz.submit_foreground_job(result_sender, requests)
|
musicbrainz.submit_foreground_job(result_sender, requests)
|
||||||
@ -468,11 +468,11 @@ mod tests {
|
|||||||
fn lookup_album_expectation(
|
fn lookup_album_expectation(
|
||||||
job_sender: &mut MockIMbJobSender,
|
job_sender: &mut MockIMbJobSender,
|
||||||
artist_id: &ArtistId,
|
artist_id: &ArtistId,
|
||||||
album_id: &AlbumId,
|
album: &AlbumMeta,
|
||||||
) {
|
) {
|
||||||
let requests = VecDeque::from([MbParams::lookup_release_group(
|
let requests = VecDeque::from([MbParams::lookup_release_group(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album_id.clone(),
|
album.clone(),
|
||||||
mbid(),
|
mbid(),
|
||||||
)]);
|
)]);
|
||||||
job_sender
|
job_sender
|
||||||
@ -487,8 +487,8 @@ mod tests {
|
|||||||
let mut mb_job_sender = MockIMbJobSender::new();
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
|
||||||
let artist_id = COLLECTION[1].meta.id.clone();
|
let artist_id = COLLECTION[1].meta.id.clone();
|
||||||
let album_id = COLLECTION[1].albums[0].meta.id.clone();
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
lookup_album_expectation(&mut mb_job_sender, &artist_id, &album_id);
|
lookup_album_expectation(&mut mb_job_sender, &artist_id, &album);
|
||||||
|
|
||||||
let music_hoard = music_hoard(COLLECTION.to_owned());
|
let music_hoard = music_hoard(COLLECTION.to_owned());
|
||||||
let inner = AppInner::new(music_hoard, mb_job_sender);
|
let inner = AppInner::new(music_hoard, mb_job_sender);
|
||||||
@ -496,7 +496,7 @@ mod tests {
|
|||||||
let (_fetch_tx, fetch_rx) = mpsc::channel();
|
let (_fetch_tx, fetch_rx) = mpsc::channel();
|
||||||
let fetch = FetchState::new(fetch_rx);
|
let fetch = FetchState::new(fetch_rx);
|
||||||
|
|
||||||
AppMachine::app_lookup_album(inner, fetch, &artist_id, &album_id, mbid());
|
AppMachine::app_lookup_album(inner, fetch, &artist_id, &album, mbid());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_artist_expectation(job_sender: &mut MockIMbJobSender, artist: &ArtistMeta) {
|
fn search_artist_expectation(job_sender: &mut MockIMbJobSender, artist: &ArtistMeta) {
|
||||||
|
@ -24,7 +24,7 @@ impl GetInfoMeta for AlbumMeta {
|
|||||||
|
|
||||||
trait GetInfo {
|
trait GetInfo {
|
||||||
type InfoType;
|
type InfoType;
|
||||||
fn get_info(&self) -> InfoOption<Self::InfoType>;
|
fn into_info(&self, info: Self::InfoType) -> InfoOption<Self::InfoType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InfoOption<T> {
|
enum InfoOption<T> {
|
||||||
@ -35,8 +35,7 @@ enum InfoOption<T> {
|
|||||||
impl GetInfo for MatchOption<ArtistMeta> {
|
impl GetInfo for MatchOption<ArtistMeta> {
|
||||||
type InfoType = ArtistInfo;
|
type InfoType = ArtistInfo;
|
||||||
|
|
||||||
fn get_info(&self) -> InfoOption<Self::InfoType> {
|
fn into_info(&self, mut info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
||||||
let mut info = ArtistInfo::default();
|
|
||||||
match self {
|
match self {
|
||||||
MatchOption::Some(option) => info.musicbrainz = option.entity.info.musicbrainz.clone(),
|
MatchOption::Some(option) => info.musicbrainz = option.entity.info.musicbrainz.clone(),
|
||||||
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
||||||
@ -49,8 +48,7 @@ impl GetInfo for MatchOption<ArtistMeta> {
|
|||||||
impl GetInfo for MatchOption<AlbumMeta> {
|
impl GetInfo for MatchOption<AlbumMeta> {
|
||||||
type InfoType = AlbumInfo;
|
type InfoType = AlbumInfo;
|
||||||
|
|
||||||
fn get_info(&self) -> InfoOption<Self::InfoType> {
|
fn into_info(&self, mut info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
||||||
let mut info = AlbumInfo::default();
|
|
||||||
match self {
|
match self {
|
||||||
MatchOption::Some(option) => info = option.entity.info.clone(),
|
MatchOption::Some(option) => info = option.entity.info.clone(),
|
||||||
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
MatchOption::CannotHaveMbid => info.musicbrainz = MbRefOption::CannotHaveMbid,
|
||||||
@ -62,7 +60,7 @@ impl GetInfo for MatchOption<AlbumMeta> {
|
|||||||
|
|
||||||
trait ExtractInfo {
|
trait ExtractInfo {
|
||||||
type InfoType;
|
type InfoType;
|
||||||
fn extract_info(&self, index: usize) -> InfoOption<Self::InfoType>;
|
fn extract_info(&self, index: usize, info: Self::InfoType) -> InfoOption<Self::InfoType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: GetInfoMeta> ExtractInfo for Vec<MatchOption<T>>
|
impl<T: GetInfoMeta> ExtractInfo for Vec<MatchOption<T>>
|
||||||
@ -72,8 +70,8 @@ where
|
|||||||
{
|
{
|
||||||
type InfoType = T::InfoType;
|
type InfoType = T::InfoType;
|
||||||
|
|
||||||
fn extract_info(&self, index: usize) -> InfoOption<Self::InfoType> {
|
fn extract_info(&self, index: usize, info: Self::InfoType) -> InfoOption<Self::InfoType> {
|
||||||
self.get(index).unwrap().get_info()
|
self.get(index).unwrap().into_info(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,16 +225,22 @@ impl IAppInteractMatch for AppMachine<MatchState> {
|
|||||||
|
|
||||||
let mh = &mut self.inner.music_hoard;
|
let mh = &mut self.inner.music_hoard;
|
||||||
let result = match self.state.current {
|
let result = match self.state.current {
|
||||||
EntityMatches::Artist(ref mut matches) => match matches.list.extract_info(index) {
|
EntityMatches::Artist(ref mut matches) => {
|
||||||
InfoOption::Info(info) => mh.merge_artist_info(&matches.matching.id, info),
|
let info: ArtistInfo = matches.matching.info.clone();
|
||||||
InfoOption::NeedInput => return self.get_input(),
|
match matches.list.extract_info(index, info) {
|
||||||
},
|
InfoOption::Info(info) => mh.set_artist_info(&matches.matching.id, info),
|
||||||
EntityMatches::Album(ref mut matches) => match matches.list.extract_info(index) {
|
InfoOption::NeedInput => return self.get_input(),
|
||||||
InfoOption::Info(info) => {
|
|
||||||
mh.merge_album_info(&matches.artist, &matches.matching, info)
|
|
||||||
}
|
}
|
||||||
InfoOption::NeedInput => return self.get_input(),
|
}
|
||||||
},
|
EntityMatches::Album(ref mut matches) => {
|
||||||
|
let info: AlbumInfo = matches.matching.info.clone();
|
||||||
|
match matches.list.extract_info(index, info) {
|
||||||
|
InfoOption::Info(info) => {
|
||||||
|
mh.set_album_info(&matches.artist, &matches.matching.id, info)
|
||||||
|
}
|
||||||
|
InfoOption::NeedInput => return self.get_input(),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
@ -314,13 +318,9 @@ mod tests {
|
|||||||
EntityMatches::artist_lookup(artist, lookup)
|
EntityMatches::artist_lookup(artist, lookup)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_id() -> AlbumId {
|
fn album_meta() -> AlbumMeta {
|
||||||
AlbumId::new("Album")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn album_meta(id: AlbumId) -> AlbumMeta {
|
|
||||||
AlbumMeta::new(
|
AlbumMeta::new(
|
||||||
id,
|
AlbumId::new("Album"),
|
||||||
AlbumDate::new(Some(1990), Some(5), None),
|
AlbumDate::new(Some(1990), Some(5), None),
|
||||||
AlbumInfo::new(
|
AlbumInfo::new(
|
||||||
MbRefOption::Some(mbid().into()),
|
MbRefOption::Some(mbid().into()),
|
||||||
@ -332,27 +332,25 @@ mod tests {
|
|||||||
|
|
||||||
fn album_match() -> EntityMatches {
|
fn album_match() -> EntityMatches {
|
||||||
let artist_id = ArtistId::new("Artist");
|
let artist_id = ArtistId::new("Artist");
|
||||||
let album_id = album_id();
|
let album = album_meta();
|
||||||
let album_meta = album_meta(album_id.clone());
|
|
||||||
|
|
||||||
let album_1 = album_meta.clone();
|
let album_1 = album.clone();
|
||||||
let album_match_1 = Entity::with_score(album_1, 100);
|
let album_match_1 = Entity::with_score(album_1, 100);
|
||||||
|
|
||||||
let mut album_2 = album_meta.clone();
|
let mut album_2 = album.clone();
|
||||||
album_2.id.title.push_str(" extra title part");
|
album_2.id.title.push_str(" extra title part");
|
||||||
album_2.info.secondary_types.pop();
|
album_2.info.secondary_types.pop();
|
||||||
let album_match_2 = Entity::with_score(album_2, 100);
|
let album_match_2 = Entity::with_score(album_2, 100);
|
||||||
|
|
||||||
let list = vec![album_match_1.clone(), album_match_2.clone()];
|
let list = vec![album_match_1.clone(), album_match_2.clone()];
|
||||||
EntityMatches::album_search(artist_id, album_id, list)
|
EntityMatches::album_search(artist_id, album, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_lookup() -> EntityMatches {
|
fn album_lookup() -> EntityMatches {
|
||||||
let artist_id = ArtistId::new("Artist");
|
let artist_id = ArtistId::new("Artist");
|
||||||
let album_id = album_id();
|
let album = album_meta();
|
||||||
let album_meta = album_meta(album_id.clone());
|
let lookup = Entity::new(album.clone());
|
||||||
let lookup = Entity::new(album_meta.clone());
|
EntityMatches::album_lookup(artist_id, album, lookup)
|
||||||
EntityMatches::album_lookup(artist_id, album_id, lookup)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_state() -> FetchState {
|
fn fetch_state() -> FetchState {
|
||||||
@ -395,10 +393,10 @@ mod tests {
|
|||||||
match matches_info {
|
match matches_info {
|
||||||
EntityMatches::Album(_) => {
|
EntityMatches::Album(_) => {
|
||||||
let album_id = AlbumId::new("Album");
|
let album_id = AlbumId::new("Album");
|
||||||
let mut info = album_meta(album_id.clone()).info;
|
let mut info = album_meta().info;
|
||||||
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_merge_album_info()
|
.expect_set_album_info()
|
||||||
.with(eq(artist_id.clone()), eq(album_id.clone()), eq(info))
|
.with(eq(artist_id.clone()), eq(album_id.clone()), eq(info))
|
||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_, _, _| Ok(()));
|
.return_once(|_, _, _| Ok(()));
|
||||||
@ -407,7 +405,7 @@ mod tests {
|
|||||||
let mut info = artist_meta().info;
|
let mut info = artist_meta().info;
|
||||||
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
info.musicbrainz = MbRefOption::CannotHaveMbid;
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_merge_artist_info()
|
.expect_set_artist_info()
|
||||||
.with(eq(artist_id.clone()), eq(info))
|
.with(eq(artist_id.clone()), eq(info))
|
||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_, _| Ok(()));
|
.return_once(|_, _| Ok(()));
|
||||||
@ -491,7 +489,7 @@ mod tests {
|
|||||||
EntityMatches::Artist(_) => {
|
EntityMatches::Artist(_) => {
|
||||||
let meta = artist_meta();
|
let meta = artist_meta();
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_merge_artist_info()
|
.expect_set_artist_info()
|
||||||
.with(eq(meta.id), eq(meta.info))
|
.with(eq(meta.id), eq(meta.info))
|
||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_, _| Ok(()));
|
.return_once(|_, _| Ok(()));
|
||||||
@ -513,9 +511,9 @@ mod tests {
|
|||||||
match matches_info {
|
match matches_info {
|
||||||
EntityMatches::Artist(_) => panic!(),
|
EntityMatches::Artist(_) => panic!(),
|
||||||
EntityMatches::Album(matches) => {
|
EntityMatches::Album(matches) => {
|
||||||
let meta = album_meta(album_id());
|
let meta = album_meta();
|
||||||
music_hoard
|
music_hoard
|
||||||
.expect_merge_album_info()
|
.expect_set_album_info()
|
||||||
.with(eq(matches.artist), eq(meta.id), eq(meta.info))
|
.with(eq(matches.artist), eq(meta.id), eq(meta.info))
|
||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_, _, _| Ok(()));
|
.return_once(|_, _, _| Ok(()));
|
||||||
@ -537,7 +535,7 @@ mod tests {
|
|||||||
match matches_info {
|
match matches_info {
|
||||||
EntityMatches::Album(_) => panic!(),
|
EntityMatches::Album(_) => panic!(),
|
||||||
EntityMatches::Artist(_) => {
|
EntityMatches::Artist(_) => {
|
||||||
music_hoard.expect_merge_artist_info().return_once(|_, _| {
|
music_hoard.expect_set_artist_info().return_once(|_, _| {
|
||||||
Err(musichoard::Error::DatabaseError(String::from("error")))
|
Err(musichoard::Error::DatabaseError(String::from("error")))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -624,7 +622,7 @@ mod tests {
|
|||||||
let album = AlbumMeta::new("Album", 1990, AlbumInfo::default());
|
let album = AlbumMeta::new("Album", 1990, AlbumInfo::default());
|
||||||
let requests = VecDeque::from([MbParams::lookup_release_group(
|
let requests = VecDeque::from([MbParams::lookup_release_group(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album.id.clone(),
|
album.clone(),
|
||||||
mbid(),
|
mbid(),
|
||||||
)]);
|
)]);
|
||||||
mb_job_sender
|
mb_job_sender
|
||||||
@ -634,7 +632,7 @@ mod tests {
|
|||||||
|
|
||||||
let matches_vec: Vec<Entity<AlbumMeta>> = vec![];
|
let matches_vec: Vec<Entity<AlbumMeta>> = vec![];
|
||||||
let album_match =
|
let album_match =
|
||||||
EntityMatches::album_search(artist_id.clone(), album.id.clone(), matches_vec);
|
EntityMatches::album_search(artist_id.clone(), album.clone(), matches_vec);
|
||||||
let matches = AppMachine::match_state(
|
let matches = AppMachine::match_state(
|
||||||
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
||||||
match_state(album_match),
|
match_state(album_match),
|
||||||
|
@ -6,7 +6,7 @@ use ratatui::widgets::ListState;
|
|||||||
pub use selection::{Category, Selection};
|
pub use selection::{Category, Selection};
|
||||||
|
|
||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{AlbumId, AlbumMeta},
|
album::AlbumMeta,
|
||||||
artist::{ArtistId, ArtistMeta},
|
artist::{ArtistId, ArtistMeta},
|
||||||
Collection,
|
Collection,
|
||||||
};
|
};
|
||||||
@ -235,7 +235,7 @@ pub struct ArtistMatches {
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct AlbumMatches {
|
pub struct AlbumMatches {
|
||||||
pub artist: ArtistId,
|
pub artist: ArtistId,
|
||||||
pub matching: AlbumId,
|
pub matching: AlbumMeta,
|
||||||
pub list: Vec<MatchOption<AlbumMeta>>,
|
pub list: Vec<MatchOption<AlbumMeta>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ impl EntityMatches {
|
|||||||
|
|
||||||
pub fn album_search<M: Into<MatchOption<AlbumMeta>>>(
|
pub fn album_search<M: Into<MatchOption<AlbumMeta>>>(
|
||||||
artist: ArtistId,
|
artist: ArtistId,
|
||||||
matching: AlbumId,
|
matching: AlbumMeta,
|
||||||
list: Vec<M>,
|
list: Vec<M>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = list.into_iter().map(Into::into).collect();
|
let list = list.into_iter().map(Into::into).collect();
|
||||||
@ -274,7 +274,7 @@ impl EntityMatches {
|
|||||||
|
|
||||||
pub fn album_lookup<M: Into<MatchOption<AlbumMeta>>>(
|
pub fn album_lookup<M: Into<MatchOption<AlbumMeta>>>(
|
||||||
artist: ArtistId,
|
artist: ArtistId,
|
||||||
matching: AlbumId,
|
matching: AlbumMeta,
|
||||||
item: M,
|
item: M,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let list = vec![item.into()];
|
let list = vec![item.into()];
|
||||||
|
21
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
21
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
@ -231,7 +231,7 @@ impl JobInstance {
|
|||||||
if let Some(params) = self.requests.front() {
|
if let Some(params) = self.requests.front() {
|
||||||
let result_sender = &mut self.result_sender;
|
let result_sender = &mut self.result_sender;
|
||||||
let paging = &mut self.paging;
|
let paging = &mut self.paging;
|
||||||
Self::execute(musicbrainz, result_sender, event_sender, params, paging)?;
|
Self::execute(musicbrainz, result_sender, event_sender, ¶ms, paging)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.paging.is_none() {
|
if self.paging.is_none() {
|
||||||
@ -263,7 +263,7 @@ impl JobInstance {
|
|||||||
.map(|rv| EntityMatches::artist_lookup(p.artist.clone(), rv)),
|
.map(|rv| EntityMatches::artist_lookup(p.artist.clone(), rv)),
|
||||||
LookupParams::ReleaseGroup(p) => {
|
LookupParams::ReleaseGroup(p) => {
|
||||||
musicbrainz.lookup_release_group(&p.mbid).map(|rv| {
|
musicbrainz.lookup_release_group(&p.mbid).map(|rv| {
|
||||||
EntityMatches::album_lookup(p.artist_id.clone(), p.album_id.clone(), rv)
|
EntityMatches::album_lookup(p.artist_id.clone(), p.album.clone(), rv)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +275,7 @@ impl JobInstance {
|
|||||||
SearchParams::ReleaseGroup(p) => musicbrainz
|
SearchParams::ReleaseGroup(p) => musicbrainz
|
||||||
.search_release_group(&p.artist_mbid, &p.album)
|
.search_release_group(&p.artist_mbid, &p.album)
|
||||||
.map(|rv| {
|
.map(|rv| {
|
||||||
EntityMatches::album_search(p.artist_id.clone(), p.album.id.clone(), rv)
|
EntityMatches::album_search(p.artist_id.clone(), p.album.clone(), rv)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
.map(MbReturn::Match),
|
.map(MbReturn::Match),
|
||||||
@ -428,9 +428,9 @@ mod tests {
|
|||||||
|
|
||||||
fn lookup_release_group_requests() -> VecDeque<MbParams> {
|
fn lookup_release_group_requests() -> VecDeque<MbParams> {
|
||||||
let artist_id = COLLECTION[1].meta.id.clone();
|
let artist_id = COLLECTION[1].meta.id.clone();
|
||||||
let album_id = COLLECTION[1].albums[0].meta.id.clone();
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
let mbid = mbid();
|
let mbid = mbid();
|
||||||
VecDeque::from([MbParams::lookup_release_group(artist_id, album_id, mbid)])
|
VecDeque::from([MbParams::lookup_release_group(artist_id, album, mbid)])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_artist_requests() -> VecDeque<MbParams> {
|
fn search_artist_requests() -> VecDeque<MbParams> {
|
||||||
@ -630,9 +630,8 @@ mod tests {
|
|||||||
fn execute_lookup_release_group() {
|
fn execute_lookup_release_group() {
|
||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let mbid = mbid();
|
let mbid = mbid();
|
||||||
let album_id = COLLECTION[1].albums[0].meta.id.clone();
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
let album_meta = COLLECTION[1].albums[0].meta.clone();
|
let lookup = Entity::new(album.clone());
|
||||||
let lookup = Entity::new(album_meta.clone());
|
|
||||||
lookup_release_group_expectation(&mut musicbrainz, &mbid, &lookup);
|
lookup_release_group_expectation(&mut musicbrainz, &mbid, &lookup);
|
||||||
|
|
||||||
let mut event_sender = event_sender();
|
let mut event_sender = event_sender();
|
||||||
@ -657,7 +656,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Ok(MbReturn::Match(EntityMatches::album_lookup(
|
Ok(MbReturn::Match(EntityMatches::album_lookup(
|
||||||
artist_id, album_id, lookup
|
artist_id, album, lookup
|
||||||
)))
|
)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -761,7 +760,7 @@ mod tests {
|
|||||||
result,
|
result,
|
||||||
Ok(MbReturn::Match(EntityMatches::album_search(
|
Ok(MbReturn::Match(EntityMatches::album_search(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album_1.id,
|
album_1,
|
||||||
matches_1
|
matches_1
|
||||||
)))
|
)))
|
||||||
);
|
);
|
||||||
@ -771,7 +770,7 @@ mod tests {
|
|||||||
result,
|
result,
|
||||||
Ok(MbReturn::Match(EntityMatches::album_search(
|
Ok(MbReturn::Match(EntityMatches::album_search(
|
||||||
artist_id.clone(),
|
artist_id.clone(),
|
||||||
album_4.id,
|
album_4,
|
||||||
matches_4
|
matches_4
|
||||||
)))
|
)))
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{collections::VecDeque, fmt, sync::mpsc};
|
use std::{collections::VecDeque, fmt, sync::mpsc};
|
||||||
|
|
||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{AlbumId, AlbumMeta},
|
album::AlbumMeta,
|
||||||
artist::{ArtistId, ArtistMeta},
|
artist::{ArtistId, ArtistMeta},
|
||||||
musicbrainz::Mbid,
|
musicbrainz::Mbid,
|
||||||
};
|
};
|
||||||
@ -59,7 +59,6 @@ pub trait IMbJobSender {
|
|||||||
pub enum MbParams {
|
pub enum MbParams {
|
||||||
Lookup(LookupParams),
|
Lookup(LookupParams),
|
||||||
Search(SearchParams),
|
Search(SearchParams),
|
||||||
#[allow(dead_code)] // TODO: remove with completion of #160
|
|
||||||
Browse(BrowseParams),
|
Browse(BrowseParams),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +77,7 @@ pub struct LookupArtistParams {
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct LookupReleaseGroupParams {
|
pub struct LookupReleaseGroupParams {
|
||||||
pub artist_id: ArtistId,
|
pub artist_id: ArtistId,
|
||||||
pub album_id: AlbumId,
|
pub album: AlbumMeta,
|
||||||
pub mbid: Mbid,
|
pub mbid: Mbid,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +101,6 @@ pub struct SearchReleaseGroupParams {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum BrowseParams {
|
pub enum BrowseParams {
|
||||||
#[allow(dead_code)] // TODO: remove with completion of #160
|
|
||||||
ReleaseGroup(BrowseReleaseGroupParams),
|
ReleaseGroup(BrowseReleaseGroupParams),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +114,10 @@ impl MbParams {
|
|||||||
MbParams::Lookup(LookupParams::Artist(LookupArtistParams { artist, mbid }))
|
MbParams::Lookup(LookupParams::Artist(LookupArtistParams { artist, mbid }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_release_group(artist_id: ArtistId, album_id: AlbumId, mbid: Mbid) -> Self {
|
pub fn lookup_release_group(artist_id: ArtistId, album: AlbumMeta, mbid: Mbid) -> Self {
|
||||||
MbParams::Lookup(LookupParams::ReleaseGroup(LookupReleaseGroupParams {
|
MbParams::Lookup(LookupParams::ReleaseGroup(LookupReleaseGroupParams {
|
||||||
artist_id,
|
artist_id,
|
||||||
album_id,
|
album,
|
||||||
mbid,
|
mbid,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,9 @@ pub trait IMusicHoard {
|
|||||||
fn reload_database(&mut self) -> Result<(), musichoard::Error>;
|
fn reload_database(&mut self) -> Result<(), musichoard::Error>;
|
||||||
fn get_collection(&self) -> &Collection;
|
fn get_collection(&self) -> &Collection;
|
||||||
|
|
||||||
fn merge_artist_info(
|
fn set_artist_info(&mut self, id: &ArtistId, info: ArtistInfo)
|
||||||
&mut self,
|
-> Result<(), musichoard::Error>;
|
||||||
id: &ArtistId,
|
fn set_album_info(
|
||||||
info: ArtistInfo,
|
|
||||||
) -> Result<(), musichoard::Error>;
|
|
||||||
fn merge_album_info(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
artist_id: &ArtistId,
|
artist_id: &ArtistId,
|
||||||
album_id: &AlbumId,
|
album_id: &AlbumId,
|
||||||
@ -47,21 +44,21 @@ impl<Database: IDatabase, Library: ILibrary> IMusicHoard for MusicHoard<Database
|
|||||||
<Self as IMusicHoardBase>::get_collection(self)
|
<Self as IMusicHoardBase>::get_collection(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_artist_info(
|
fn set_artist_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: &ArtistId,
|
id: &ArtistId,
|
||||||
info: ArtistInfo,
|
info: ArtistInfo,
|
||||||
) -> Result<(), musichoard::Error> {
|
) -> Result<(), musichoard::Error> {
|
||||||
<Self as IMusicHoardDatabase>::merge_artist_info(self, id, info)
|
<Self as IMusicHoardDatabase>::set_artist_info(self, id, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_album_info(
|
fn set_album_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
artist_id: &ArtistId,
|
artist_id: &ArtistId,
|
||||||
album_id: &AlbumId,
|
album_id: &AlbumId,
|
||||||
info: AlbumInfo,
|
info: AlbumInfo,
|
||||||
) -> Result<(), musichoard::Error> {
|
) -> Result<(), musichoard::Error> {
|
||||||
<Self as IMusicHoardDatabase>::merge_album_info(self, artist_id, album_id, info)
|
<Self as IMusicHoardDatabase>::set_album_info(self, artist_id, album_id, info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// GRCOV_EXCL_STOP
|
// GRCOV_EXCL_STOP
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{
|
album::{AlbumDate, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus},
|
||||||
AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus,
|
|
||||||
},
|
|
||||||
artist::ArtistMeta,
|
artist::ArtistMeta,
|
||||||
musicbrainz::{IMusicBrainzRef, MbRefOption},
|
musicbrainz::{IMusicBrainzRef, MbRefOption},
|
||||||
track::{TrackFormat, TrackQuality},
|
track::{TrackFormat, TrackQuality},
|
||||||
@ -113,8 +111,12 @@ impl UiDisplay {
|
|||||||
format!("Matching artist: {}", &artist.id.name)
|
format!("Matching artist: {}", &artist.id.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_album_matching(album: &AlbumId) -> String {
|
pub fn display_album_matching(album: &AlbumMeta) -> String {
|
||||||
format!("Matching album: {}", &album.title)
|
format!(
|
||||||
|
"Matching album: {} | {}",
|
||||||
|
UiDisplay::display_album_date(&album.date),
|
||||||
|
&album.id.title
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_matching_info(info: &EntityMatches) -> String {
|
pub fn display_matching_info(info: &EntityMatches) -> String {
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{album::AlbumMeta, artist::ArtistMeta};
|
||||||
album::{AlbumId, AlbumMeta},
|
|
||||||
artist::ArtistMeta,
|
|
||||||
};
|
|
||||||
use ratatui::widgets::{List, ListItem};
|
use ratatui::widgets::{List, ListItem};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
@ -40,7 +37,7 @@ impl<'a, 'b> MatchOverlay<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn albums(
|
fn albums(
|
||||||
matching: &AlbumId,
|
matching: &AlbumMeta,
|
||||||
matches: &'a [MatchOption<AlbumMeta>],
|
matches: &'a [MatchOption<AlbumMeta>],
|
||||||
state: &'b mut WidgetState,
|
state: &'b mut WidgetState,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -356,13 +356,9 @@ mod tests {
|
|||||||
ArtistId::new("Artist")
|
ArtistId::new("Artist")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_id() -> AlbumId {
|
fn album_meta() -> AlbumMeta {
|
||||||
AlbumId::new("An Album")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn album_meta(id: AlbumId) -> AlbumMeta {
|
|
||||||
AlbumMeta::new(
|
AlbumMeta::new(
|
||||||
id,
|
AlbumId::new("An Album"),
|
||||||
AlbumDate::new(Some(1990), Some(5), None),
|
AlbumDate::new(Some(1990), Some(5), None),
|
||||||
AlbumInfo::new(
|
AlbumInfo::new(
|
||||||
MbRefOption::None,
|
MbRefOption::None,
|
||||||
@ -374,12 +370,11 @@ mod tests {
|
|||||||
|
|
||||||
fn album_matches() -> EntityMatches {
|
fn album_matches() -> EntityMatches {
|
||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
let album_id = album_id();
|
let album = album_meta();
|
||||||
let album_meta = album_meta(album_id.clone());
|
let album_match = Entity::with_score(album.clone(), 80);
|
||||||
let album_match = Entity::with_score(album_meta.clone(), 80);
|
|
||||||
let list = vec![album_match.clone(), album_match.clone()];
|
let list = vec![album_match.clone(), album_match.clone()];
|
||||||
|
|
||||||
let mut info = EntityMatches::album_search(artist_id, album_id, list);
|
let mut info = EntityMatches::album_search(artist_id, album, list);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
info.push_manual_input_mbid();
|
info.push_manual_input_mbid();
|
||||||
info
|
info
|
||||||
@ -387,11 +382,10 @@ mod tests {
|
|||||||
|
|
||||||
fn album_lookup() -> EntityMatches {
|
fn album_lookup() -> EntityMatches {
|
||||||
let artist_id = album_artist_id();
|
let artist_id = album_artist_id();
|
||||||
let album_id = album_id();
|
let album = album_meta();
|
||||||
let album_meta = album_meta(album_id.clone());
|
let album_lookup = Entity::new(album.clone());
|
||||||
let album_lookup = Entity::new(album_meta.clone());
|
|
||||||
|
|
||||||
let mut info = EntityMatches::album_lookup(artist_id, album_id, album_lookup);
|
let mut info = EntityMatches::album_lookup(artist_id, album, album_lookup);
|
||||||
info.push_cannot_have_mbid();
|
info.push_cannot_have_mbid();
|
||||||
info.push_manual_input_mbid();
|
info.push_manual_input_mbid();
|
||||||
info
|
info
|
||||||
|
Loading…
Reference in New Issue
Block a user