kopuz-utils 0.9.0

A modern, lightweight music player built with Rust and Dioxus.
Documentation
use super::{Lyrics, has_usable_line_timing, lrc::parse_lrc, lrc_has_usable_timing};

pub(super) async fn fetch_local_lrc(audio_path: &str) -> Option<Lyrics> {
    let content = read_local_lrc(audio_path).or_else(|| read_embedded_lyrics(audio_path))?;
    if content.trim().is_empty() {
        return None;
    }
    let lines = if lrc_has_usable_timing(&content) {
        parse_lrc(&content)
    } else {
        Vec::new()
    };
    if has_usable_line_timing(&lines) {
        Some(Lyrics::Synced(lines))
    } else {
        Some(Lyrics::Plain(content))
    }
}

fn read_embedded_lyrics(audio_path: &str) -> Option<String> {
    use lofty::file::TaggedFileExt;
    use lofty::probe::Probe;
    use lofty::tag::ItemKey;

    let tagged = Probe::open(audio_path).ok()?.read().ok()?;
    let tag = tagged.primary_tag().or_else(|| tagged.first_tag())?;
    tag.get_string(ItemKey::Lyrics)
        .filter(|s| !s.trim().is_empty())
        .map(|s| s.to_string())
}

fn read_local_lrc(audio_path: &str) -> Option<String> {
    use std::path::Path;

    let audio = Path::new(audio_path);

    let stem_lrc = audio.with_extension("lrc");
    if let Ok(content) = std::fs::read_to_string(&stem_lrc) {
        return Some(content);
    }

    let appended = format!("{audio_path}.lrc");
    if let Ok(content) = std::fs::read_to_string(&appended) {
        return Some(content);
    }

    let parent = audio.parent()?;
    let file_name = audio.file_name()?.to_string_lossy().to_lowercase();
    let stem = audio
        .file_stem()
        .map(|s| s.to_string_lossy().to_lowercase());

    for entry in std::fs::read_dir(parent).ok()?.flatten() {
        let path = entry.path();
        if path
            .extension()
            .map(|e| !e.eq_ignore_ascii_case("lrc"))
            .unwrap_or(true)
        {
            continue;
        }
        let Some(cand_name) = path.file_name().map(|n| n.to_string_lossy().to_lowercase()) else {
            continue;
        };
        let matches_appended = cand_name == format!("{file_name}.lrc");
        let matches_stem = stem
            .as_ref()
            .map(|s| cand_name == format!("{s}.lrc"))
            .unwrap_or(false);
        if (matches_appended || matches_stem)
            && let Ok(content) = std::fs::read_to_string(&path)
        {
            return Some(content);
        }
    }

    None
}