From 45c0ab2051495677b296c0bc7c7ce000270aeb3e Mon Sep 17 00:00:00 2001 From: Polochon_street Date: Sun, 22 Sep 2024 16:13:21 +0200 Subject: [PATCH] Return failed songs from Library is now possible --- CHANGELOG.md | 3 ++ Cargo.lock | 2 +- Cargo.toml | 2 +- TODO.md | 3 ++ src/library.rs | 91 ++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 160a64a..177feb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## bliss 0.9.2 +* Add a way to retrieve failed analysis for a Library. + ## bliss 0.9.1 * Expose the Mahalanobis distance in the library feature, reading the learned matrix in metric learning. diff --git a/Cargo.lock b/Cargo.lock index 775cdc0..d2e78c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,7 +138,7 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bliss-audio" -version = "0.9.1" +version = "0.9.2" dependencies = [ "adler32", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 6a6da83..9d2b9c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bliss-audio" -version = "0.9.1" +version = "0.9.2" build = "build.rs" authors = ["Polochon-street "] edition = "2021" diff --git a/TODO.md b/TODO.md index ab896cf..fc90521 100644 --- a/TODO.md +++ b/TODO.md @@ -36,6 +36,9 @@ ask questions if you want to tackle an item. - Improve bliss-python somehow / use it in a small demo project maybe? A blissify in python? - Investigate what type SAMPLE_RATE is in Aubio - maybe u16 is enough +- Should library really use `indicatif`? And not leave it up to the CLI program itself? +- Library: the database should maybe have errored_songs in a separate column (and remove + the "analyzed" flag?) ## Done - Split out ffmpeg (see https://github.com/Polochon-street/bliss-rs/issues/63 and https://users.rust-lang.org/t/proper-way-to-abstract-a-third-party-provider/107076/8) diff --git a/src/library.rs b/src/library.rs index 050213a..dbc9be6 100644 --- a/src/library.rs +++ b/src/library.rs @@ -335,6 +335,17 @@ pub struct Library { decoder: PhantomData, } +/// Hold an error that happened while processing songs during analysis. +#[derive(Debug, Eq, PartialEq)] +pub struct ProcessingError { + /// The path of the song whose analysis was attempted. + pub song_path: PathBuf, + /// The actual error string. + pub error: String, + /// Features version the analysis was attempted with. + pub features_version: u16, +} + /// Struct holding both a Bliss song, as well as any extra info /// that a user would want to store in the database related to that /// song. @@ -1372,6 +1383,28 @@ impl Library { Ok(()) } + /// Return all the songs that failed the analysis. + pub fn get_failed_songs(&self) -> Result> { + let conn = self.sqlite_conn.lock().unwrap(); + let mut stmt = conn.prepare( + " + select path, error, version + from song where error is not null order by id + ", + )?; + let rows = stmt.query_map([], |row| { + Ok(ProcessingError { + song_path: row.get::<_, String>(0)?.into(), + error: row.get(1)?, + features_version: row.get(2)?, + }) + })?; + Ok(rows + .into_iter() + .map(|r| r.unwrap()) + .collect::>()) + } + /// Delete a song with path `song_path` from the database. /// /// Errors out if the song is not in the database. @@ -1777,52 +1810,52 @@ mod test { insert into song ( id, path, artist, title, album, album_artist, track_number, disc_number, genre, duration, analyzed, version, extra_info, - cue_path, audio_file_path + cue_path, audio_file_path, error ) values ( 1001, '/path/to/song1001', 'Artist1001', 'Title1001', 'An Album1001', 'An Album Artist1001', 3, 1, 'Electronica1001', 310, true, 1, '{\"ignore\": true, \"metadata_bliss_does_not_have\": - \"/path/to/charlie1001\"}', null, null + \"/path/to/charlie1001\"}', null, null, null ), ( 2001, '/path/to/song2001', 'Artist2001', 'Title2001', 'An Album2001', 'An Album Artist2001', 2, 1, 'Electronica2001', 410, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie2001\"}', null, null + \"/path/to/charlie2001\"}', null, null, null ), ( 2201, '/path/to/song2201', 'Artist2001', 'Title2001', 'An Album2001', 'An Album Artist2001', 1, 2, 'Electronica2001', 410, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie2201\"}', null, null + \"/path/to/charlie2201\"}', null, null, null ), ( 3001, '/path/to/song3001', null, null, null, - null, null, null, null, null, false, 1, '{}', null, null + null, null, null, null, null, false, 1, '{}', null, null, null ), ( 4001, '/path/to/song4001', 'Artist4001', 'Title4001', 'An Album4001', 'An Album Artist4001', 1, 1, 'Electronica4001', 510, true, 0, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie4001\"}', null, null + \"/path/to/charlie4001\"}', null, null, null ), ( 5001, '/path/to/song5001', 'Artist5001', 'Title5001', 'An Album1001', 'An Album Artist5001', 1, 1, 'Electronica5001', 610, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie5001\"}', null, null + \"/path/to/charlie5001\"}', null, null, null ), ( 6001, '/path/to/song6001', 'Artist6001', 'Title6001', 'An Album2001', 'An Album Artist6001', 1, 1, 'Electronica6001', 710, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie6001\"}', null, null + \"/path/to/charlie6001\"}', null, null, null ), ( 7001, '/path/to/song7001', 'Artist7001', 'Title7001', 'An Album7001', 'An Album Artist7001', 1, 1, 'Electronica7001', 810, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie7001\"}', null, null + \"/path/to/charlie7001\"}', null, null, null ), ( 7002, '/path/to/cuetrack.cue/CUE_TRACK001', 'CUE Artist', @@ -1830,7 +1863,7 @@ mod test { 'CUE Album Artist', 1, 1, null, 810, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": \"/path/to/charlie7001\"}', '/path/to/cuetrack.cue', - '/path/to/cuetrack.flac' + '/path/to/cuetrack.flac', null ), ( 7003, '/path/to/cuetrack.cue/CUE_TRACK002', 'CUE Artist', @@ -1838,19 +1871,29 @@ mod test { 'CUE Album Artist', 2, 1, null, 910, true, 1, '{\"ignore\": false, \"metadata_bliss_does_not_have\": \"/path/to/charlie7001\"}', '/path/to/cuetrack.cue', - '/path/to/cuetrack.flac' + '/path/to/cuetrack.flac', null ), ( 8001, '/path/to/song8001', 'Artist8001', 'Title8001', 'An Album1001', 'An Album Artist8001', 3, 1, 'Electronica8001', 910, true, 0, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie8001\"}', null, null + \"/path/to/charlie8001\"}', null, null, null ), ( 9001, './data/s16_stereo_22_5kHz.flac', 'Artist9001', 'Title9001', 'An Album9001', 'An Album Artist8001', 3, 1, 'Electronica8001', 1010, true, 0, '{\"ignore\": false, \"metadata_bliss_does_not_have\": - \"/path/to/charlie7001\"}', null, null + \"/path/to/charlie7001\"}', null, null, null + ), + ( + 404, './data/not-existing.m4a', null, null, + null, null, null, null, null, + null, false, 0, null, null, null, 'error finding the file' + ), + ( + 502, './data/invalid-file.m4a', null, null, + null, null, null, null, null, + null, false, 0, null, null, null, 'error decoding the file' ); ", [], @@ -3644,4 +3687,26 @@ mod test { .unwrap(); assert!(config_dir.is_dir()); } + + #[test] + #[cfg(feature = "ffmpeg")] + fn test_library_get_failed_songs() { + let (mut library, _temp_dir, _) = setup_test_library(); + let failed_songs = library.get_failed_songs().unwrap(); + assert_eq!( + failed_songs, + vec![ + ProcessingError { + song_path: PathBuf::from("./data/not-existing.m4a"), + error: String::from("error finding the file"), + features_version: 0, + }, + ProcessingError { + song_path: PathBuf::from("./data/invalid-file.m4a"), + error: String::from("error decoding the file"), + features_version: 0, + } + ] + ); + } }