Semantic indexing for composer/lyricist
This commit is contained in:
parent
0841c15f48
commit
a2232aa9f2
3 changed files with 75 additions and 23 deletions
|
@ -4,7 +4,7 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
use lasso2::{RodeoReader, Rodeo};
|
use lasso2::{Rodeo, RodeoReader};
|
||||||
use rand::{rngs::ThreadRng, seq::IteratorRandom};
|
use rand::{rngs::ThreadRng, seq::IteratorRandom};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -17,7 +17,9 @@ use super::storage::fetch_song;
|
||||||
pub struct Artist {
|
pub struct Artist {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub albums: Vec<Album>,
|
pub albums: Vec<Album>,
|
||||||
pub album_appearances: Vec<Album>,
|
pub song_credits: Vec<Album>, // Albums where this artist shows up as `artist` without being `album_artist`
|
||||||
|
pub composer_credits: Vec<Album>, // Albums where this artist shows up as `composer` without being `artist` or `album_artist`
|
||||||
|
pub lyricist_credits: Vec<Album>, // Albums where this artist shows up as `lyricist` without being `artist` or `album_artist`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
|
@ -72,24 +74,48 @@ impl Collection {
|
||||||
albums
|
albums
|
||||||
};
|
};
|
||||||
|
|
||||||
let album_appearances = {
|
let sort_albums = |a: &Album, b: &Album| {
|
||||||
let mut album_appearances = a
|
(&a.artists, a.year, &a.name)
|
||||||
.album_appearances
|
.partial_cmp(&(&b.artists, b.year, &b.name))
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let song_credits = {
|
||||||
|
let mut albums = a
|
||||||
|
.song_credits
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|key| self.get_album(strings, key.clone()))
|
.filter_map(|key| self.get_album(strings, key.clone()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
album_appearances.sort_by(|a, b| {
|
albums.sort_by(&sort_albums);
|
||||||
(&a.artists, a.year, &a.name)
|
albums
|
||||||
.partial_cmp(&(&b.artists, b.year, &b.name))
|
};
|
||||||
.unwrap()
|
|
||||||
});
|
let composer_credits = {
|
||||||
album_appearances
|
let mut albums = a
|
||||||
|
.composer_credits
|
||||||
|
.iter()
|
||||||
|
.filter_map(|key| self.get_album(strings, key.clone()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
albums.sort_by(&sort_albums);
|
||||||
|
albums
|
||||||
|
};
|
||||||
|
|
||||||
|
let lyricist_credits = {
|
||||||
|
let mut albums = a
|
||||||
|
.lyricist_credits
|
||||||
|
.iter()
|
||||||
|
.filter_map(|key| self.get_album(strings, key.clone()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
albums.sort_by(&sort_albums);
|
||||||
|
albums
|
||||||
};
|
};
|
||||||
|
|
||||||
Artist {
|
Artist {
|
||||||
name: a.name.map(|s| strings.resolve(&s).to_string()),
|
name: a.name.map(|s| strings.resolve(&s).to_string()),
|
||||||
albums,
|
albums,
|
||||||
album_appearances,
|
song_credits,
|
||||||
|
composer_credits,
|
||||||
|
lyricist_credits,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -196,17 +222,35 @@ impl Builder {
|
||||||
fn add_album_to_artists(&mut self, song: &storage::Song) {
|
fn add_album_to_artists(&mut self, song: &storage::Song) {
|
||||||
let album_key: AlbumKey = song.album_key();
|
let album_key: AlbumKey = song.album_key();
|
||||||
|
|
||||||
for artist_name in &song.album_artists {
|
for name in &song.album_artists {
|
||||||
let artist = self.get_or_create_artist(*artist_name);
|
let artist = self.get_or_create_artist(*name);
|
||||||
artist.albums.insert(album_key.clone());
|
artist.albums.insert(album_key.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
for artist_name in &song.artists {
|
for name in &song.artists {
|
||||||
let artist = self.get_or_create_artist(*artist_name);
|
let artist = self.get_or_create_artist(*name);
|
||||||
if song.album_artists.is_empty() {
|
if song.album_artists.is_empty() {
|
||||||
artist.albums.insert(album_key.clone());
|
artist.albums.insert(album_key.clone());
|
||||||
} else if !song.album_artists.contains(artist_name) {
|
} else if !song.album_artists.contains(name) {
|
||||||
artist.album_appearances.insert(album_key.clone());
|
artist.song_credits.insert(album_key.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name in &song.composers {
|
||||||
|
let is_also_artist = song.artists.contains(name);
|
||||||
|
let is_also_album_artist = song.artists.contains(name);
|
||||||
|
if !is_also_artist && !is_also_album_artist {
|
||||||
|
let artist = self.get_or_create_artist(*name);
|
||||||
|
artist.composer_credits.insert(album_key.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name in &song.lyricists {
|
||||||
|
let is_also_artist = song.artists.contains(name);
|
||||||
|
let is_also_album_artist = song.artists.contains(name);
|
||||||
|
if !is_also_artist && !is_also_album_artist {
|
||||||
|
let artist = self.get_or_create_artist(*name);
|
||||||
|
artist.lyricist_credits.insert(album_key.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +262,9 @@ impl Builder {
|
||||||
.or_insert_with(|| storage::Artist {
|
.or_insert_with(|| storage::Artist {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
albums: HashSet::new(),
|
albums: HashSet::new(),
|
||||||
album_appearances: HashSet::new(),
|
song_credits: HashSet::new(),
|
||||||
|
composer_credits: HashSet::new(),
|
||||||
|
lyricist_credits: HashSet::new(),
|
||||||
})
|
})
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use lasso2::{RodeoReader, Rodeo};
|
use lasso2::{Rodeo, RodeoReader};
|
||||||
use log::error;
|
use log::error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tinyvec::TinyVec;
|
use tinyvec::TinyVec;
|
||||||
|
@ -20,7 +20,9 @@ pub enum File {
|
||||||
pub struct Artist {
|
pub struct Artist {
|
||||||
pub name: Option<lasso2::Spur>,
|
pub name: Option<lasso2::Spur>,
|
||||||
pub albums: HashSet<AlbumKey>,
|
pub albums: HashSet<AlbumKey>,
|
||||||
pub album_appearances: HashSet<AlbumKey>,
|
pub song_credits: HashSet<AlbumKey>,
|
||||||
|
pub composer_credits: HashSet<AlbumKey>,
|
||||||
|
pub lyricist_credits: HashSet<AlbumKey>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
|
|
|
@ -310,7 +310,9 @@ impl From<index::File> for BrowserEntry {
|
||||||
pub struct Artist {
|
pub struct Artist {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub albums: Vec<AlbumHeader>,
|
pub albums: Vec<AlbumHeader>,
|
||||||
pub album_appearances: Vec<AlbumHeader>,
|
pub song_credits: Vec<AlbumHeader>,
|
||||||
|
pub composer_credits: Vec<AlbumHeader>,
|
||||||
|
pub lyricist_credits: Vec<AlbumHeader>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<index::Artist> for Artist {
|
impl From<index::Artist> for Artist {
|
||||||
|
@ -318,7 +320,9 @@ impl From<index::Artist> for Artist {
|
||||||
Self {
|
Self {
|
||||||
name: a.name,
|
name: a.name,
|
||||||
albums: a.albums.into_iter().map(|a| a.into()).collect(),
|
albums: a.albums.into_iter().map(|a| a.into()).collect(),
|
||||||
album_appearances: a.album_appearances.into_iter().map(|a| a.into()).collect(),
|
song_credits: a.song_credits.into_iter().map(|a| a.into()).collect(),
|
||||||
|
composer_credits: a.composer_credits.into_iter().map(|a| a.into()).collect(),
|
||||||
|
lyricist_credits: a.lyricist_credits.into_iter().map(|a| a.into()).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue