[READ-ONLY] Mirror of https://github.com/mrgnw/dlna-rs. Single-binary DLNA media server in Rust. Auto-discovered by VLC on Apple TV.
0

Configure Feed

Select the types of activity you want to include in your feed.

library: filter to media files only (audio/image/video by mime)

+54 -5
+2 -2
src/api.rs
··· 190 190 191 191 async fn api_status(State(state): State<AppState>) -> Json<serde_json::Value> { 192 192 let g = state.lib.read().await; 193 - let folders = snapshot(&*g); 193 + let folders = snapshot(&g); 194 194 Json(serde_json::json!({ "folders": folders })) 195 195 } 196 196 197 197 async fn status_text(State(state): State<AppState>) -> String { 198 198 let g = state.lib.read().await; 199 - let folders = snapshot(&*g); 199 + let folders = snapshot(&g); 200 200 let mut s = String::new(); 201 201 for f in folders { 202 202 s.push_str(&format!("{} {} files\n", f.path, f.file_count));
+13
src/library.rs
··· 121 121 .into_iter() 122 122 .filter_map(|e| e.ok()) 123 123 .filter(|e| e.file_type().is_file()) 124 + .filter(|e| is_media_file(e.path())) 124 125 .filter_map(|e| { 125 126 let rel = e.path().strip_prefix(root).ok()?.to_path_buf(); 126 127 let size = e.metadata().ok()?.len(); ··· 152 153 .collect() 153 154 } 154 155 } 156 + 157 + pub fn is_media_file(path: &Path) -> bool { 158 + match mime_guess::from_path(path).first() { 159 + Some(mime) => { 160 + let essence = mime.essence_str(); 161 + essence.starts_with("audio/") 162 + || essence.starts_with("image/") 163 + || essence.starts_with("video/") 164 + } 165 + None => false, 166 + } 167 + }
+2 -2
tests/config.rs
··· 11 11 assert_eq!(cfg.port, 9119); 12 12 assert_eq!(cfg.folders.len(), 2); 13 13 assert_eq!(cfg.folders[0].path, "/tmp/a"); 14 - assert_eq!(cfg.folders[0].recursive, true); 15 - assert_eq!(cfg.folders[1].recursive, false); 14 + assert!(cfg.folders[0].recursive); 15 + assert!(!cfg.folders[1].recursive); 16 16 17 17 let out = facet_styx::to_string(&cfg).unwrap(); 18 18 let cfg2: Config = facet_styx::from_str(&out).unwrap();
+37 -1
tests/library.rs
··· 1 - use dlna_rs::library::{Entry, FileMeta, Library}; 1 + use dlna_rs::library::{is_media_file, Entry, Library}; 2 2 use std::fs; 3 3 use tempfile::tempdir; 4 4 ··· 19 19 let f = lib.add_folder(dir.path().to_path_buf(), true).unwrap(); 20 20 assert_eq!(f.file_count, 3); 21 21 assert_eq!(lib.folders().len(), 1); 22 + } 23 + 24 + #[test] 25 + fn add_folder_counts_only_media_files() { 26 + let dir = tempdir().unwrap(); 27 + make_tree( 28 + dir.path(), 29 + &[ 30 + ".DS_Store", 31 + "a.mp4", 32 + "cover.jpg", 33 + "notes.strings", 34 + "sub/b.mkv", 35 + ], 36 + ); 37 + 38 + let mut lib = Library::new(); 39 + let f = lib.add_folder(dir.path().to_path_buf(), true).unwrap(); 40 + 41 + let rels: Vec<String> = f 42 + .files 43 + .iter() 44 + .map(|m| m.rel.to_string_lossy().into_owned()) 45 + .collect(); 46 + assert_eq!(f.file_count, 3); 47 + assert_eq!(rels, vec!["a.mp4", "cover.jpg", "sub/b.mkv"]); 48 + } 49 + 50 + #[test] 51 + fn media_file_detection_uses_media_mime_types() { 52 + assert!(is_media_file(std::path::Path::new("movie.mp4"))); 53 + assert!(is_media_file(std::path::Path::new("song.flac"))); 54 + assert!(is_media_file(std::path::Path::new("poster.webp"))); 55 + assert!(!is_media_file(std::path::Path::new(".DS_Store"))); 56 + assert!(!is_media_file(std::path::Path::new("Application.tvdb"))); 57 + assert!(!is_media_file(std::path::Path::new("ca.strings"))); 22 58 } 23 59 24 60 #[test]