Remove default regex match for files() but keep tag populating without regex pattern

This commit is contained in:
NGnius (Graham) 2022-01-26 17:50:06 -05:00
parent 1af24ba899
commit 0c3f0fee9c
2 changed files with 95 additions and 38 deletions

View file

@ -16,7 +16,8 @@ const DEFAULT_VEC_CACHE_SIZE: usize = 4;
#[derive(Debug)] #[derive(Debug)]
pub struct FileIter { pub struct FileIter {
root: PathBuf, root: PathBuf,
pattern: Regex, pattern: Option<Regex>,
tags_pattern: Regex,
recursive: bool, recursive: bool,
dir_iters: Vec<SortedReadDir>, dir_iters: Vec<SortedReadDir>,
is_complete: bool, is_complete: bool,
@ -67,7 +68,7 @@ impl Display for FileIter {
f, f,
"root=`{}`, pattern={}, recursive={}", "root=`{}`, pattern={}, recursive={}",
self.root.to_str().unwrap_or(""), self.root.to_str().unwrap_or(""),
self.pattern, self.pattern.as_ref().map(|re| re.to_string()).unwrap_or("[none]".to_string()),
self.recursive self.recursive
) )
} }
@ -100,15 +101,22 @@ impl FileIter {
} else { } else {
Vec::with_capacity(DEFAULT_VEC_CACHE_SIZE) Vec::with_capacity(DEFAULT_VEC_CACHE_SIZE)
}; };
let pattern_re = let pattern_re = if let Some(pattern) = pattern {
Regex::new(pattern.unwrap_or(DEFAULT_REGEX)).map_err(|e| RuntimeError { Some(Regex::new(pattern).map_err(|e| RuntimeError {
line: 0, line: 0,
op: op(), op: op(),
msg: format!("Regex compile error: {}", e), msg: format!("Regex compile error: {}", e),
})?; })?)
} else {None};
let tags_re = Regex::new(DEFAULT_REGEX).map_err(|e| RuntimeError {
line: 0,
op: op(),
msg: format!("Regex compile error: {}", e),
})?;
Ok(Self { Ok(Self {
root: root_path, root: root_path,
pattern: pattern_re, pattern: pattern_re,
tags_pattern: tags_re,
recursive: recurse, recursive: recurse,
dir_iters: dir_vec, dir_iters: dir_vec,
is_complete: false, is_complete: false,
@ -122,7 +130,8 @@ impl FileIter {
dir_vec.push(read_dir.into()); dir_vec.push(read_dir.into());
Self { Self {
root: root_path, root: root_path,
pattern: Regex::new(DEFAULT_REGEX).unwrap(), pattern: None,
tags_pattern: Regex::new(DEFAULT_REGEX).unwrap(),
recursive: recurse, recursive: recurse,
dir_iters: dir_vec, dir_iters: dir_vec,
is_complete: false, is_complete: false,
@ -136,10 +145,17 @@ impl FileIter {
if !path.is_file() { if !path.is_file() {
panic!("Got non-file path `{}` when building music item", path_str) panic!("Got non-file path `{}` when building music item", path_str)
} }
let captures = self.pattern.captures(path_str)?; if let Some(pattern) = &self.pattern {
let capture_names = self.pattern.capture_names(); let captures = pattern.captures(path_str)?;
// populate fields let capture_names = pattern.capture_names();
self.populate_item_impl(path, path_str, captures, capture_names) // populate fields
self.populate_item_impl(path, path_str, Some(captures), capture_names)
} else {
let captures = self.tags_pattern.captures(path_str);
let capture_names = self.tags_pattern.capture_names();
self.populate_item_impl(path, path_str, captures, capture_names)
}
} }
#[cfg(feature = "music_library")] #[cfg(feature = "music_library")]
@ -147,7 +163,7 @@ impl FileIter {
&self, &self,
path: &Path, path: &Path,
path_str: &str, path_str: &str,
captures: regex::Captures, captures: Option<regex::Captures>,
capture_names: regex::CaptureNames, capture_names: regex::CaptureNames,
) -> Option<MpsItem> { ) -> Option<MpsItem> {
match crate::music::MpsLibrary::read_media_tags(path) { match crate::music::MpsLibrary::read_media_tags(path) {
@ -196,7 +212,7 @@ impl FileIter {
fn populate_item_impl( fn populate_item_impl(
&self, &self,
path_str: &str, path_str: &str,
captures: regex::Captures, captures: Option<regex::Captures>,
capture_names: regex::CaptureNames, capture_names: regex::CaptureNames,
) -> Option<MpsItem> { ) -> Option<MpsItem> {
let mut item = MpsItem::new(); let mut item = MpsItem::new();
@ -209,17 +225,19 @@ impl FileIter {
&self, &self,
item: &mut MpsItem, item: &mut MpsItem,
path_str: &str, path_str: &str,
captures: regex::Captures, captures: Option<regex::Captures>,
mut capture_names: regex::CaptureNames, mut capture_names: regex::CaptureNames,
) { ) {
// populates fields from named capture groups // populates fields from named capture groups
while let Some(name_maybe) = capture_names.next() { if let Some(captures) = captures {
if let Some(name) = name_maybe { while let Some(name_maybe) = capture_names.next() {
if let Some(value) = captures if let Some(name) = name_maybe {
.name(name) if let Some(value) = captures
.and_then(|m| Some(m.as_str().to_string())) .name(name)
{ .and_then(|m| Some(m.as_str().to_string()))
item.set_field(name, MpsTypePrimitive::parse(value)); {
item.set_field(name, MpsTypePrimitive::parse(value));
}
} }
} }
} }
@ -238,6 +256,7 @@ impl FileIter {
impl Iterator for FileIter { impl Iterator for FileIter {
type Item = Result<MpsItem, String>; type Item = Result<MpsItem, String>;
//#[recursion_limit = "1024"]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.is_complete { if self.is_complete {
None None
@ -262,7 +281,7 @@ impl Iterator for FileIter {
} else { } else {
while !self.dir_iters.is_empty() { while !self.dir_iters.is_empty() {
let mut dir_iter = self.dir_iters.pop().unwrap(); let mut dir_iter = self.dir_iters.pop().unwrap();
while let Some(path_result) = dir_iter.next() { 'inner: while let Some(path_result) = dir_iter.next() {
match path_result { match path_result {
Ok(dir_entry) => { Ok(dir_entry) => {
if dir_entry.path().is_dir() { if dir_entry.path().is_dir() {
@ -277,7 +296,8 @@ impl Iterator for FileIter {
))) )))
} }
}); });
return self.next(); //return self.next();
break 'inner;
} }
} else { } else {
if let Some(item) = self.build_item(dir_entry.path()) { if let Some(item) = self.build_item(dir_entry.path()) {
@ -285,7 +305,7 @@ impl Iterator for FileIter {
return Some(Ok(item)); return Some(Ok(item));
} }
} }
} },
Err(e) => { Err(e) => {
self.dir_iters.push(dir_iter); self.dir_iters.push(dir_iter);
return Some(Err(format!("Path read error: {}", e))); return Some(Err(format!("Path read error: {}", e)));

View file

@ -1,5 +1,6 @@
use std::fs; use std::fs;
use std::io; use std::io;
use std::path::PathBuf;
use rodio::{decoder::Decoder, OutputStream, OutputStreamHandle, Sink}; use rodio::{decoder::Decoder, OutputStream, OutputStreamHandle, Sink};
@ -39,17 +40,29 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
if let Some(filename) = if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str()) music.field("filename").and_then(|x| x.to_owned().to_str())
{ {
let file = fs::File::open(filename).map_err(PlaybackError::from_err)?; let path: PathBuf = filename.into();
let stream = io::BufReader::new(file); if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?; match ext {
self.sink.append(source); "mp3"
| "wav"
| "flac"
| "aac"
| "ogg" => {
let file = fs::File::open(path).map_err(PlaybackError::from_err)?;
let stream = io::BufReader::new(file);
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?;
self.sink.append(source);
},
_ => {}
}
}
Ok(()) Ok(())
} else { } else {
Err(PlaybackError::from_err( Err(PlaybackError::from_err(
"Field `filename` does not exist on item", "Field `filename` does not exist on item",
)) ))
} }
} },
Err(e) => Err(PlaybackError::from_err(e)), Err(e) => Err(PlaybackError::from_err(e)),
}?; }?;
} }
@ -66,10 +79,22 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
if let Some(filename) = if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str()) music.field("filename").and_then(|x| x.to_owned().to_str())
{ {
let file = fs::File::open(filename).map_err(PlaybackError::from_err)?; let path: PathBuf = filename.into();
let stream = io::BufReader::new(file); if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?; match ext {
self.sink.append(source); "mp3"
| "wav"
| "flac"
| "aac"
| "ogg" => {
let file = fs::File::open(path).map_err(PlaybackError::from_err)?;
let stream = io::BufReader::new(file);
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?;
self.sink.append(source);
},
_ => {}
}
}
Ok(()) Ok(())
} else { } else {
Err(PlaybackError::from_err( Err(PlaybackError::from_err(
@ -92,14 +117,27 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
for item in &mut self.runner { for item in &mut self.runner {
match item { match item {
Ok(music) => { Ok(music) => {
enqueued.push(music.clone());
if let Some(filename) = if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str()) music.field("filename").and_then(|x| x.to_owned().to_str())
{ {
let file = fs::File::open(filename).map_err(PlaybackError::from_err)?; let path: PathBuf = filename.into();
let stream = io::BufReader::new(file); if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?; match ext {
self.sink.append(source); "mp3"
| "wav"
| "flac"
| "aac"
| "ogg" => {
enqueued.push(music.clone());
let file = fs::File::open(path).map_err(PlaybackError::from_err)?;
let stream = io::BufReader::new(file);
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?;
self.sink.append(source);
items_left -= 1;
},
_ => {}
}
}
Ok(()) Ok(())
} else { } else {
Err(PlaybackError::from_err( Err(PlaybackError::from_err(
@ -109,7 +147,6 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
} }
Err(e) => Err(PlaybackError::from_err(e)), Err(e) => Err(PlaybackError::from_err(e)),
}?; }?;
items_left -= 1;
if items_left == 0 { if items_left == 0 {
break; break;
} }