tsk-50: Create functionality to extract song properties #52

Merged
phoenix merged 8 commits from tsk-50 into main 2025-11-06 17:31:37 +00:00
3 changed files with 70 additions and 50 deletions
Showing only changes of commit 7c1b3a437f - Show all commits

View File

@@ -19,10 +19,7 @@ pub mod test_util {
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
pub fn get_full_path( pub fn get_full_path(directory: &str, filename: &str) -> Result<String, std::io::Error> {
directory: &String,
filename: &String,
) -> Result<String, std::io::Error> {
match path_buf(directory, filename) { match path_buf(directory, filename) {
Ok(pf) => Ok(pf.display().to_string()), Ok(pf) => Ok(pf.display().to_string()),
Err(err) => Err(err), Err(err) => Err(err),
@@ -39,6 +36,12 @@ pub mod test_util {
std::fs::copy(src_path, dest_path) std::fs::copy(src_path, dest_path)
} }
pub fn remove_file(filepath: &str) -> Result<(), std::io::Error> {
let f_path = std::path::Path::new(filepath);
std::fs::remove_file(f_path)
}
pub fn get_data_from_file(source_path: &str) -> Result<Vec<u8>, std::io::Error> { pub fn get_data_from_file(source_path: &str) -> Result<Vec<u8>, std::io::Error> {
match std::fs::File::open(source_path) { match std::fs::File::open(source_path) {
Ok(mut file) => { Ok(mut file) => {
@@ -52,13 +55,23 @@ pub mod test_util {
} }
} }
pub fn file_exists(directory: &String, filename: &String) -> Result<bool, std::io::Error> { pub fn file_exists(directory: &str, filename: &str) -> Result<bool, std::io::Error> {
match path_buf(directory, filename) { match path_buf(directory, filename) {
Ok(pf) => Ok(pf.exists()), Ok(pf) => Ok(pf.exists()),
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
pub fn generate_newfilepath(directory: &str) -> Result<String, std::io::Error> {
match generate_filename() {
Ok(filename) => match get_full_path(directory, &filename) {
Ok(filepath) => Ok(filepath),
Err(err) => Err(err),
},
Err(err) => Err(err),
}
}
pub fn generate_filename() -> Result<String, std::io::Error> { pub fn generate_filename() -> Result<String, std::io::Error> {
let mut filename = String::from("track-"); let mut filename = String::from("track-");
let length = 20; let length = 20;
@@ -78,10 +91,7 @@ pub mod test_util {
Ok(format!("{filename}.flac")) Ok(format!("{filename}.flac"))
} }
fn path_buf( fn path_buf(directory: &str, filename: &str) -> Result<std::path::PathBuf, std::io::Error> {
directory: &String,
filename: &String,
) -> Result<std::path::PathBuf, std::io::Error> {
let dir_path = std::path::Path::new(&directory); let dir_path = std::path::Path::new(&directory);
Ok(dir_path.join(filename)) Ok(dir_path.join(filename))
} }

View File

@@ -5,9 +5,7 @@ pub fn get_properties(songpath: &str) -> Result<lofty::flac::FlacProperties, std
Ok(mut content) => { Ok(mut content) => {
match lofty::flac::FlacFile::read_from(&mut content, lofty::config::ParseOptions::new()) match lofty::flac::FlacFile::read_from(&mut content, lofty::config::ParseOptions::new())
{ {
Ok(flac_file) => { Ok(flac_file) => Ok(*flac_file.properties()),
Ok(*flac_file.properties())
}
Err(err) => Err(std::io::Error::other(err.to_string())), Err(err) => Err(std::io::Error::other(err.to_string())),
} }
} }

View File

@@ -1,6 +1,5 @@
pub mod audio; pub mod audio;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct SongProperties { pub struct SongProperties {
pub duration: std::time::Duration, pub duration: std::time::Duration,
@@ -11,33 +10,27 @@ pub struct SongProperties {
pub channels: u8, pub channels: u8,
} }
pub fn get_song_properties(song_path: &str) -> Result<SongProperties, std::io::Error> { pub fn get_song_properties(song_path: &str) -> Result<SongProperties, std::io::Error> {
match audio::get_properties(song_path) { match audio::get_properties(song_path) {
Ok(flac_properties) => { Ok(flac_properties) => Ok(SongProperties {
Ok(SongProperties {
duration: flac_properties.duration(), duration: flac_properties.duration(),
sample_rate: flac_properties.sample_rate(), sample_rate: flac_properties.sample_rate(),
bitrate: flac_properties.audio_bitrate(), bitrate: flac_properties.audio_bitrate(),
overall_bitrate: flac_properties.overall_bitrate(), overall_bitrate: flac_properties.overall_bitrate(),
bit_depth: flac_properties.bit_depth(), bit_depth: flac_properties.bit_depth(),
channels: flac_properties.channels(), channels: flac_properties.channels(),
}) }),
}
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
pub fn get_duration(song_path: &String) -> Result<std::time::Duration, std::io::Error> { pub fn get_duration(song_path: &str) -> Result<std::time::Duration, std::io::Error> {
match get_song_properties(song_path) { match get_song_properties(song_path) {
Ok(song_properties) => { Ok(song_properties) => Ok(song_properties.duration),
Ok(song_properties.duration)
}
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::test_util; use crate::test_util;
@@ -79,7 +72,10 @@ mod tests {
match test_util::util::file_exists(&dir, &filename) { match test_util::util::file_exists(&dir, &filename) {
Ok(_) => { Ok(_) => {
let filepath = test_util::util::get_full_path(&dir, &filename).unwrap(); let filepath = test_util::util::get_full_path(&dir, &filename).unwrap();
match super::get_song_properties(&filepath) { let new_filepath = test_util::util::generate_newfilepath(&dir).unwrap();
match test_util::util::copy_file(&filepath, &new_filepath) {
Ok(_) => match super::get_song_properties(&filepath) {
Ok(song_properties) => { Ok(song_properties) => {
let song_duration: u64 = 41; let song_duration: u64 = 41;
let bitrate: u32 = 1; let bitrate: u32 = 1;
@@ -98,14 +94,30 @@ mod tests {
"Durations should match, but they don't {song_duration} {fetched_song_duration} ({song_properties:?})" "Durations should match, but they don't {song_duration} {fetched_song_duration} ({song_properties:?})"
); );
assert_eq!(bitrate, fetched_bitrate, "Bitrates do not match {bitrate:?} {fetched_bitrate:?} {song_properties:?}"); assert_eq!(
assert_eq!(overall_bitrate, fetched_overall_bitrate, "Overall bitrates do not match {overall_bitrate:?} {fetched_overall_bitrate:?} {song_properties:?}"); bitrate, fetched_bitrate,
assert_eq!(bit_depth, fetched_bit_depth, "Bit depth do not match {bit_depth:?} {fetched_bit_depth:?} {song_properties:?}"); "Bitrates do not match {bitrate:?} {fetched_bitrate:?} {song_properties:?}"
assert_eq!(channels, fetched_channels, "Channels do not match {channels:?} {fetched_channels:?} {song_properties:?}"); );
assert_eq!(
overall_bitrate, fetched_overall_bitrate,
"Overall bitrates do not match {overall_bitrate:?} {fetched_overall_bitrate:?} {song_properties:?}"
);
assert_eq!(
bit_depth, fetched_bit_depth,
"Bit depth do not match {bit_depth:?} {fetched_bit_depth:?} {song_properties:?}"
);
assert_eq!(
channels, fetched_channels,
"Channels do not match {channels:?} {fetched_channels:?} {song_properties:?}"
);
} }
Err(err) => { Err(err) => {
assert!(false, "Error: {err:?}"); assert!(false, "Error: {err:?}");
} }
},
Err(err) => {
assert!(false, "Error: {err:?}");
}
} }
} }
Err(err) => { Err(err) => {