A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1use std::{fs, thread};
2
3use anyhow::Error;
4use rockbox_settings::get_music_dir;
5
6use crate::{consts::AUDIO_EXTENSIONS, Context};
7
8pub fn read_dir(
9 ctx: Context,
10 path: String,
11 recursive: bool,
12 with_metadata: bool,
13) -> Result<String, Error> {
14 let music_dir = get_music_dir()?;
15 let mut files = String::new();
16
17 fn read_dir_recursive(
18 ctx: &Context,
19 path: String,
20 music_dir: &str,
21 recursive: bool,
22 files: &mut String,
23 with_metadata: bool,
24 ) -> Result<(), Error> {
25 for entry in fs::read_dir(path)? {
26 let entry = entry?;
27 let path = entry.path();
28 let path_str = path.to_str().unwrap().to_string();
29
30 if path.is_dir() {
31 if recursive {
32 read_dir_recursive(
33 ctx,
34 path_str.clone(),
35 music_dir,
36 recursive,
37 files,
38 with_metadata,
39 )?;
40 }
41 }
42
43 if AUDIO_EXTENSIONS.iter().any(|ext| path_str.ends_with(ext)) || path.is_dir() {
44 let last_modified = entry.metadata()?.modified()?;
45 let last_modified = chrono::DateTime::from_timestamp(
46 last_modified
47 .duration_since(std::time::UNIX_EPOCH)?
48 .as_secs() as i64,
49 0,
50 )
51 .unwrap();
52
53 let last_modified = last_modified.format("%Y-%m-%dT%H:%M:%SZ").to_string();
54 let entry_str = path_str.replace(music_dir, "");
55 let entry_str = if entry_str.starts_with('/') {
56 &entry_str[1..]
57 } else {
58 &entry_str
59 };
60
61 let mut metadata = format!(
62 "{}: {}\nLast-Modified: {}\n",
63 if path.is_dir() { "directory" } else { "file" },
64 entry_str,
65 last_modified
66 );
67
68 if !with_metadata {
69 files.push_str(&metadata);
70 continue;
71 }
72
73 let kv = ctx.kv.clone();
74 let track = thread::spawn(move || {
75 let rt = tokio::runtime::Runtime::new().unwrap();
76 let kv_clone = kv.clone();
77 let kv = rt.block_on(kv_clone.lock());
78 let track = kv.get(&path_str);
79 track.map(|x| x.clone())
80 })
81 .join()
82 .unwrap();
83
84 if let Some(track) = track {
85 metadata.push_str(&format!(
86 "Title: {}\nArtist: {}\nAlbum: {}\nTime: {}\nDuration: {}\n",
87 track.title,
88 track.artist,
89 track.album,
90 (track.length / 1000) as u32,
91 track.length / 1000
92 ));
93 if let Some(track_number) = track.track_number {
94 metadata.push_str(&format!("Track: {}\n", track_number));
95 }
96
97 if let Some(year) = track.year {
98 metadata.push_str(&format!("Date: {}\n", year));
99 }
100 }
101 files.push_str(&metadata);
102 }
103 }
104 Ok(())
105 }
106
107 read_dir_recursive(&ctx, path, &music_dir, recursive, &mut files, with_metadata)?;
108 Ok(files)
109}