|
|
|
@ -9,16 +9,66 @@ use crate::core::{
|
|
|
|
|
musichoard::{base::IMusicHoardBasePrivate, Error, MusicHoard, NoDatabase},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
impl<Library> MusicHoard<NoDatabase, Library> {
|
|
|
|
|
pub fn commit(&mut self) -> Result<(), Error> {
|
|
|
|
|
self.collection = self.pre_commit.clone();
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
pub trait IMusicHoardDatabase {
|
|
|
|
|
fn reload_database(&mut self) -> Result<(), Error>;
|
|
|
|
|
|
|
|
|
|
fn add_artist<IntoId: Into<ArtistId>>(&mut self, artist_id: IntoId) -> Result<(), Error>;
|
|
|
|
|
fn remove_artist<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
|
|
|
|
|
|
|
|
|
|
fn set_artist_sort<Id: AsRef<ArtistId>, IntoId: Into<ArtistId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
artist_sort: IntoId,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
|
|
|
|
|
|
|
|
|
|
fn set_artist_musicbrainz<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
url: S,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
fn clear_artist_musicbrainz<Id: AsRef<ArtistId>>(&mut self, artist_id: Id)
|
|
|
|
|
-> Result<(), Error>;
|
|
|
|
|
|
|
|
|
|
fn add_to_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
fn remove_from_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
fn set_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
fn clear_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
|
|
|
|
|
fn set_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: ArtistIdRef,
|
|
|
|
|
album_id: AlbumIdRef,
|
|
|
|
|
seq: u8,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
fn clear_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: ArtistIdRef,
|
|
|
|
|
album_id: AlbumIdRef,
|
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
|
|
|
|
/// Load the database and merge with the in-memory collection.
|
|
|
|
|
pub fn reload_database(&mut self) -> Result<(), Error> {
|
|
|
|
|
impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database, Library> {
|
|
|
|
|
fn reload_database(&mut self) -> Result<(), Error> {
|
|
|
|
|
self.database_cache = self.database.load()?;
|
|
|
|
|
Self::sort_albums_and_tracks(self.database_cache.iter_mut());
|
|
|
|
|
|
|
|
|
@ -28,7 +78,146 @@ impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn commit(&mut self) -> Result<(), Error> {
|
|
|
|
|
fn add_artist<IntoId: Into<ArtistId>>(&mut self, artist_id: IntoId) -> Result<(), Error> {
|
|
|
|
|
let artist_id: ArtistId = artist_id.into();
|
|
|
|
|
|
|
|
|
|
self.update_collection(|collection| {
|
|
|
|
|
if Self::get_artist(collection, &artist_id).is_none() {
|
|
|
|
|
collection.push(Artist::new(artist_id));
|
|
|
|
|
Self::sort_artists(collection);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn remove_artist<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
|
|
|
|
|
self.update_collection(|collection| {
|
|
|
|
|
let index_opt = collection.iter().position(|a| &a.id == artist_id.as_ref());
|
|
|
|
|
if let Some(index) = index_opt {
|
|
|
|
|
collection.remove(index);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_artist_sort<Id: AsRef<ArtistId>, IntoId: Into<ArtistId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
artist_sort: IntoId,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
|artist| artist.set_sort_key(artist_sort),
|
|
|
|
|
|collection| Self::sort_artists(collection),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
|
|
|
|
|
self.update_artist_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
|artist| artist.clear_sort_key(),
|
|
|
|
|
|collection| Self::sort_artists(collection),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_artist_musicbrainz<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
url: S,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
let mb = MusicBrainzUrl::artist_from_str(url)?;
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| artist.set_musicbrainz_url(mb))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_artist_musicbrainz<Id: AsRef<ArtistId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| artist.clear_musicbrainz_url())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add_to_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| {
|
|
|
|
|
artist.add_to_property(property, values)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn remove_from_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| {
|
|
|
|
|
artist.remove_from_property(property, values)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| {
|
|
|
|
|
artist.set_property(property, values)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| artist.clear_property(property))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: ArtistIdRef,
|
|
|
|
|
album_id: AlbumIdRef,
|
|
|
|
|
seq: u8,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_album_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
album_id.as_ref(),
|
|
|
|
|
|album| album.set_seq(AlbumSeq(seq)),
|
|
|
|
|
|artist| artist.albums.sort_unstable(),
|
|
|
|
|
|_| {},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: ArtistIdRef,
|
|
|
|
|
album_id: AlbumIdRef,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_album_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
album_id.as_ref(),
|
|
|
|
|
|album| album.clear_seq(),
|
|
|
|
|
|artist| artist.albums.sort_unstable(),
|
|
|
|
|
|_| {},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait IMusicHoardDatabasePrivate {
|
|
|
|
|
fn commit(&mut self) -> Result<(), Error>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<Library> IMusicHoardDatabasePrivate for MusicHoard<NoDatabase, Library> {
|
|
|
|
|
fn commit(&mut self) -> Result<(), Error> {
|
|
|
|
|
self.collection = self.pre_commit.clone();
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<Database: IDatabase, Library> IMusicHoardDatabasePrivate for MusicHoard<Database, Library> {
|
|
|
|
|
fn commit(&mut self) -> Result<(), Error> {
|
|
|
|
|
if self.collection != self.pre_commit {
|
|
|
|
|
if let Err(err) = self.database.save(&self.pre_commit) {
|
|
|
|
|
self.pre_commit = self.collection.clone();
|
|
|
|
@ -38,7 +227,9 @@ impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
|
|
|
|
fn update_collection<FnColl>(&mut self, fn_coll: FnColl) -> Result<(), Error>
|
|
|
|
|
where
|
|
|
|
|
FnColl: FnOnce(&mut Collection),
|
|
|
|
@ -92,132 +283,6 @@ impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
|
|
|
|
fn_artist(artist);
|
|
|
|
|
self.update_collection(fn_coll)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_artist<IntoId: Into<ArtistId>>(&mut self, artist_id: IntoId) -> Result<(), Error> {
|
|
|
|
|
let artist_id: ArtistId = artist_id.into();
|
|
|
|
|
|
|
|
|
|
self.update_collection(|collection| {
|
|
|
|
|
if Self::get_artist(collection, &artist_id).is_none() {
|
|
|
|
|
collection.push(Artist::new(artist_id));
|
|
|
|
|
Self::sort_artists(collection);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn remove_artist<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
|
|
|
|
|
self.update_collection(|collection| {
|
|
|
|
|
let index_opt = collection.iter().position(|a| &a.id == artist_id.as_ref());
|
|
|
|
|
if let Some(index) = index_opt {
|
|
|
|
|
collection.remove(index);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_artist_sort<Id: AsRef<ArtistId>, IntoId: Into<ArtistId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
artist_sort: IntoId,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
|artist| artist.set_sort_key(artist_sort),
|
|
|
|
|
|collection| Self::sort_artists(collection),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
|
|
|
|
|
self.update_artist_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
|artist| artist.clear_sort_key(),
|
|
|
|
|
|collection| Self::sort_artists(collection),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_artist_musicbrainz<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
url: S,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
let mb = MusicBrainzUrl::artist_from_str(url)?;
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| artist.set_musicbrainz_url(mb))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_artist_musicbrainz<Id: AsRef<ArtistId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| artist.clear_musicbrainz_url())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_to_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| {
|
|
|
|
|
artist.add_to_property(property, values)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn remove_from_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| {
|
|
|
|
|
artist.remove_from_property(property, values)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
values: Vec<S>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| {
|
|
|
|
|
artist.set_property(property, values)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: Id,
|
|
|
|
|
property: S,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_artist(artist_id.as_ref(), |artist| artist.clear_property(property))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: ArtistIdRef,
|
|
|
|
|
album_id: AlbumIdRef,
|
|
|
|
|
seq: u8,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_album_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
album_id.as_ref(),
|
|
|
|
|
|album| album.set_seq(AlbumSeq(seq)),
|
|
|
|
|
|artist| artist.albums.sort_unstable(),
|
|
|
|
|
|_| {},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
artist_id: ArtistIdRef,
|
|
|
|
|
album_id: AlbumIdRef,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
self.update_album_and(
|
|
|
|
|
artist_id.as_ref(),
|
|
|
|
|
album_id.as_ref(),
|
|
|
|
|
|album| album.clear_seq(),
|
|
|
|
|
|artist| artist.albums.sort_unstable(),
|
|
|
|
|
|_| {},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|