1use std::{
2 fs,
3 path::{Path, PathBuf},
4};
5
6use crate::error::{MtagError, MtagResult};
7
8pub fn scan_audio_files(root: &Path) -> MtagResult<Vec<PathBuf>> {
17 let mut files = Vec::new();
18 visit_folder(root, &mut files)?;
19 files.sort();
20 Ok(files)
21}
22
23fn visit_folder(folder: &Path, files: &mut Vec<PathBuf>) -> MtagResult<()> {
24 let entries = fs::read_dir(folder).map_err(|source| MtagError::ReadDirectory {
25 path: folder.to_path_buf(),
26 source,
27 })?;
28
29 for entry in entries {
30 let entry = entry.map_err(|source| MtagError::ReadDirectory {
31 path: folder.to_path_buf(),
32 source,
33 })?;
34 let path = entry.path();
35 if path.is_dir() {
36 visit_folder(&path, files)?;
37 } else if path.is_file() && is_audio_file(&path)? {
38 files.push(path);
39 }
40 }
41
42 Ok(())
43}
44
45fn is_audio_file(path: &Path) -> MtagResult<bool> {
46 let kind = infer::get_from_path(path).map_err(|source| MtagError::InspectFileType {
47 path: path.to_path_buf(),
48 source,
49 })?;
50
51 Ok(kind.is_some_and(|kind| kind.mime_type().starts_with("audio/")))
52}