100 lines
2.4 KiB
Rust
100 lines
2.4 KiB
Rust
use crate::json_parsing;
|
|
use audiotags::Tag;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
use std::time::Duration;
|
|
use thiserror::Error;
|
|
|
|
#[derive(Debug)]
|
|
pub struct TrackInfo {
|
|
pub track_name: String,
|
|
pub artist_name: String,
|
|
pub album_name: String,
|
|
pub duration: Duration,
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum MusicError {
|
|
#[error("failed to read directory: {0}")]
|
|
ReadDir(#[from] std::io::Error),
|
|
|
|
#[error("failed to read audio tags from {0}")]
|
|
TagRead(String),
|
|
|
|
#[error("failed to get song duration for {0}")]
|
|
DurationRead(String),
|
|
}
|
|
|
|
fn is_mp3(path: &Path) -> bool {
|
|
path.extension()
|
|
.and_then(|ext| ext.to_str())
|
|
.map(|ext| ext.eq_ignore_ascii_case("mp3"))
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
pub fn get_song_file(path: &Path) -> Result<(), MusicError> {
|
|
if !is_mp3(path) {
|
|
return Ok(());
|
|
}
|
|
|
|
let info = get_song_info(path)?;
|
|
|
|
println!("Track: {}", info.track_name);
|
|
println!("Artist: {}", info.artist_name);
|
|
println!("Album: {}", info.album_name);
|
|
println!("Duration: {:?}\n", info.duration);
|
|
|
|
json_parsing::get_lyrics_text(
|
|
&info.artist_name,
|
|
&info.track_name,
|
|
&info.album_name,
|
|
info.duration,
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_all_music_files(directory: &Path) -> Result<(), MusicError> {
|
|
if !directory.is_dir() {
|
|
return Ok(());
|
|
}
|
|
|
|
for entry in fs::read_dir(directory)? {
|
|
let entry = entry?;
|
|
let path = entry.path();
|
|
|
|
if entry.file_type()?.is_dir() {
|
|
get_all_music_files(&path)?;
|
|
} else if let Err(e) = get_song_file(&path) {
|
|
eprintln!("Skipping file {}: {}", path.display(), e);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_song_info(path: &Path) -> Result<TrackInfo, MusicError> {
|
|
let tag = Tag::new()
|
|
.read_from_path(path)
|
|
.map_err(|_| MusicError::TagRead(path.display().to_string()))?;
|
|
|
|
let track_name = tag.title().unwrap_or("Unknown Track").to_string();
|
|
let artist_name = tag.artist().unwrap_or("Unknown Artist").to_string();
|
|
let album_name = tag
|
|
.album()
|
|
.map_or("Unknown Album".to_string(), |a| a.title.to_string());
|
|
|
|
let duration = get_song_length(path)?;
|
|
|
|
Ok(TrackInfo {
|
|
track_name,
|
|
artist_name,
|
|
album_name,
|
|
duration,
|
|
})
|
|
}
|
|
|
|
pub fn get_song_length(path: &Path) -> Result<Duration, MusicError> {
|
|
mp3_duration::from_path(path).map_err(|_| MusicError::DurationRead(path.display().to_string()))
|
|
}
|