Remove default regex match for files() but keep tag populating without regex pattern
This commit is contained in:
parent
1af24ba899
commit
0c3f0fee9c
2 changed files with 95 additions and 38 deletions
|
@ -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)));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue