cargo fmt
This commit is contained in:
parent
b521d22513
commit
46459c7da1
25 changed files with 142 additions and 109 deletions
|
@ -90,7 +90,8 @@ where
|
|||
if next_item.is_none() {
|
||||
is_stmt_done = true;
|
||||
}
|
||||
next_item.map(|item| item.map_err(|e| box_error_with_ctx(e, self.tokenizer.current_line())))
|
||||
next_item
|
||||
.map(|item| item.map_err(|e| box_error_with_ctx(e, self.tokenizer.current_line())))
|
||||
} else {
|
||||
/*if self.tokenizer.end_of_file() {
|
||||
return None;
|
||||
|
@ -121,7 +122,9 @@ where
|
|||
if next_item.is_none() {
|
||||
is_stmt_done = true;
|
||||
}
|
||||
next_item.map(|item| item.map_err(|e| box_error_with_ctx(e, self.tokenizer.current_line())))
|
||||
next_item.map(|item| {
|
||||
item.map_err(|e| box_error_with_ctx(e, self.tokenizer.current_line()))
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
Some(Err(e).map_err(|e| box_error_with_ctx(e, self.tokenizer.current_line())))
|
||||
|
|
|
@ -366,14 +366,17 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
|
|||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match &self.iterable {
|
||||
VariableOrOp::Variable(s) => self.context.as_ref()
|
||||
VariableOrOp::Variable(s) => self
|
||||
.context
|
||||
.as_ref()
|
||||
.and_then(|x| x.variables.get_opt(s))
|
||||
.and_then(|x| match x {
|
||||
MpsType::Op(op) => Some(op.size_hint()),
|
||||
_ => None
|
||||
}),
|
||||
VariableOrOp::Op(op) => op.try_real_ref().map(|x| x.size_hint()).ok()
|
||||
}.unwrap_or((0, None))
|
||||
MpsType::Op(op) => Some(op.size_hint()),
|
||||
_ => None,
|
||||
}),
|
||||
VariableOrOp::Op(op) => op.try_real_ref().map(|x| x.size_hint()).ok(),
|
||||
}
|
||||
.unwrap_or((0, None))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -555,7 +558,7 @@ fn last_open_bracket_is_after_dot(tokens: &VecDeque<MpsToken>) -> bool {
|
|||
inside_brackets -= 1;
|
||||
}
|
||||
} else if open_bracket_found {
|
||||
return tokens[i].is_dot()
|
||||
return tokens[i].is_dot();
|
||||
}
|
||||
}
|
||||
false
|
||||
|
|
|
@ -313,14 +313,17 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
|
|||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match &self.iterable {
|
||||
VariableOrOp::Variable(s) => self.context.as_ref()
|
||||
VariableOrOp::Variable(s) => self
|
||||
.context
|
||||
.as_ref()
|
||||
.and_then(|x| x.variables.get_opt(s))
|
||||
.and_then(|x| match x {
|
||||
MpsType::Op(op) => Some(op.size_hint()),
|
||||
_ => None
|
||||
}),
|
||||
VariableOrOp::Op(op) => op.try_real_ref().map(|x| x.size_hint()).ok()
|
||||
}.unwrap_or((0, None))
|
||||
MpsType::Op(op) => Some(op.size_hint()),
|
||||
_ => None,
|
||||
}),
|
||||
VariableOrOp::Op(op) => op.try_real_ref().map(|x| x.size_hint()).ok(),
|
||||
}
|
||||
.unwrap_or((0, None))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ use std::collections::VecDeque;
|
|||
//use std::fmt::{Debug, Display, Error, Formatter};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::lang::utility::{assert_token, assert_token_raw, assert_token_raw_back};
|
||||
#[cfg(debug_assertions)]
|
||||
use crate::lang::utility::assert_empty;
|
||||
use crate::lang::utility::{assert_token, assert_token_raw, assert_token_raw_back};
|
||||
use crate::lang::MpsLanguageDictionary;
|
||||
use crate::lang::SyntaxError;
|
||||
use crate::lang::{BoxedMpsOpFactory, MpsOp};
|
||||
|
|
|
@ -35,10 +35,7 @@ impl PseudoOp {
|
|||
|
||||
pub fn unwrap_real(self) -> Result<Box<dyn MpsOp>, RuntimeError> {
|
||||
match self {
|
||||
Self::Real(op) => {
|
||||
|
||||
Ok(op)
|
||||
}
|
||||
Self::Real(op) => Ok(op),
|
||||
Self::Fake(_) => Err(RuntimeError {
|
||||
line: 0,
|
||||
op: self.clone(),
|
||||
|
|
|
@ -103,7 +103,10 @@ impl<S: MpsSorter + 'static> Iterator for MpsSortStatement<S> {
|
|||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iterable.try_real_ref().map(|x| x.size_hint()).unwrap_or((0, None))
|
||||
self.iterable
|
||||
.try_real_ref()
|
||||
.map(|x| x.size_hint())
|
||||
.unwrap_or((0, None))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,7 @@ impl Display for EmptyStatement {
|
|||
|
||||
impl std::clone::Clone for EmptyStatement {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
context: None,
|
||||
}
|
||||
Self { context: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,16 +68,13 @@ impl MpsFunctionFactory<EmptyStatement> for EmptyFunctionFactory {
|
|||
fn build_function_params(
|
||||
&self,
|
||||
_name: String,
|
||||
#[allow(unused_variables)]
|
||||
tokens: &mut VecDeque<MpsToken>,
|
||||
#[allow(unused_variables)] tokens: &mut VecDeque<MpsToken>,
|
||||
_dict: &MpsLanguageDictionary,
|
||||
) -> Result<EmptyStatement, SyntaxError> {
|
||||
// empty()
|
||||
#[cfg(debug_assertions)]
|
||||
assert_empty(tokens)?;
|
||||
Ok(EmptyStatement {
|
||||
context: None,
|
||||
})
|
||||
Ok(EmptyStatement { context: None })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,4 +84,3 @@ pub type EmptyStatementFactory = MpsFunctionStatementFactory<EmptyStatement, Emp
|
|||
pub fn empty_function_factory() -> EmptyStatementFactory {
|
||||
EmptyStatementFactory::new(EmptyFunctionFactory)
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,10 @@ impl Iterator for FilesStatement {
|
|||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.file_iter.as_ref().map(|x| x.size_hint()).unwrap_or((0, None))
|
||||
self.file_iter
|
||||
.as_ref()
|
||||
.map(|x| x.size_hint())
|
||||
.unwrap_or((0, None))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,9 +197,8 @@ impl MpsOp for RepeatStatement {
|
|||
return Err(RuntimeError {
|
||||
line: 0,
|
||||
op: PseudoOp::from_printable(self),
|
||||
msg:
|
||||
"Cannot reset part way through repeat when inner statement is not resetable"
|
||||
.to_string(),
|
||||
msg: "Cannot reset part way through repeat when inner statement is not resetable"
|
||||
.to_string(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -45,7 +45,7 @@ impl Iterator for ResetStatement {
|
|||
Err(e) => return Some(Err(e)),
|
||||
};
|
||||
match inner.reset() {
|
||||
Ok(_) => {},
|
||||
Ok(_) => {}
|
||||
Err(e) => return Some(Err(e)),
|
||||
};
|
||||
}
|
||||
|
@ -86,8 +86,7 @@ impl MpsFunctionFactory<ResetStatement> for ResetFunctionFactory {
|
|||
fn build_function_params(
|
||||
&self,
|
||||
_name: String,
|
||||
#[allow(unused_variables)]
|
||||
tokens: &mut VecDeque<MpsToken>,
|
||||
#[allow(unused_variables)] tokens: &mut VecDeque<MpsToken>,
|
||||
dict: &MpsLanguageDictionary,
|
||||
) -> Result<ResetStatement, SyntaxError> {
|
||||
// reset(var)
|
||||
|
@ -106,4 +105,3 @@ pub type ResetStatementFactory = MpsFunctionStatementFactory<ResetStatement, Res
|
|||
pub fn reset_function_factory() -> ResetStatementFactory {
|
||||
ResetStatementFactory::new(ResetFunctionFactory)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,14 +39,19 @@ impl BlissNextSorter {
|
|||
}
|
||||
}
|
||||
|
||||
fn algorithm(mut items: VecDeque<MpsItem>, results: Sender<Option<Result<MpsItem, bliss_audio::BlissError>>>) {
|
||||
fn algorithm(
|
||||
mut items: VecDeque<MpsItem>,
|
||||
results: Sender<Option<Result<MpsItem, bliss_audio::BlissError>>>,
|
||||
) {
|
||||
let mut song_cache: Option<(Song, String)> = None;
|
||||
let items_len = items.len();
|
||||
for i in 0..items_len {
|
||||
let item = items.pop_front().unwrap();
|
||||
if let Some(MpsTypePrimitive::String(path)) = item.field("filename") {
|
||||
if let Err(_) = results.send(Some(Ok(item.clone()))) {break;}
|
||||
if i+2 < items_len {
|
||||
if let Err(_) = results.send(Some(Ok(item.clone()))) {
|
||||
break;
|
||||
}
|
||||
if i + 2 < items_len {
|
||||
let target_song = if let Some((_, ref cached_filename)) = song_cache {
|
||||
if cached_filename == path {
|
||||
Ok(song_cache.take().unwrap().0)
|
||||
|
@ -67,14 +72,16 @@ impl BlissNextSorter {
|
|||
Err(e) => {
|
||||
results.send(Some(Err(e))).unwrap_or(());
|
||||
break;
|
||||
},
|
||||
}
|
||||
Ok((next_song, index)) => {
|
||||
if let Some(next_song) = next_song {
|
||||
if index != 0 {
|
||||
items.swap(0, index);
|
||||
}
|
||||
song_cache = Some((next_song, path.to_owned()));
|
||||
} else {break;}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +90,10 @@ impl BlissNextSorter {
|
|||
results.send(None).unwrap_or(());
|
||||
}
|
||||
|
||||
fn find_best(items: &VecDeque<MpsItem>, target: Song) -> Result<(Option<Song>, usize), bliss_audio::BlissError> {
|
||||
fn find_best(
|
||||
items: &VecDeque<MpsItem>,
|
||||
target: Song,
|
||||
) -> Result<(Option<Song>, usize), bliss_audio::BlissError> {
|
||||
let mut best = None;
|
||||
let mut best_index = 0;
|
||||
let mut best_distance = f32::MAX;
|
||||
|
@ -94,15 +104,11 @@ impl BlissNextSorter {
|
|||
let result_chann = tx.clone();
|
||||
let target_clone = target.clone();
|
||||
let path_clone = path.to_owned();
|
||||
std::thread::spawn(move || {
|
||||
match Song::new(path_clone) {
|
||||
Err(e) => result_chann
|
||||
.send(Err(e))
|
||||
.unwrap_or(()),
|
||||
Ok(song) => result_chann
|
||||
.send(Ok((i, target_clone.distance(&song), song)))
|
||||
.unwrap_or(()),
|
||||
}
|
||||
std::thread::spawn(move || match Song::new(path_clone) {
|
||||
Err(e) => result_chann.send(Err(e)).unwrap_or(()),
|
||||
Ok(song) => result_chann
|
||||
.send(Ok((i, target_clone.distance(&song), song)))
|
||||
.unwrap_or(()),
|
||||
});
|
||||
threads_spawned += 1;
|
||||
}
|
||||
|
@ -115,7 +121,9 @@ impl BlissNextSorter {
|
|||
best_index = index;
|
||||
best_distance = distance;
|
||||
}
|
||||
} else {break;}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok((best, best_index))
|
||||
}
|
||||
|
@ -203,7 +211,9 @@ pub struct BlissNextSorterFactory;
|
|||
|
||||
impl MpsSorterFactory<BlissNextSorter> for BlissNextSorterFactory {
|
||||
fn is_sorter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||
tokens.len() == 2 && check_name("advanced", tokens[0]) && check_name("bliss_next", tokens[1])
|
||||
tokens.len() == 2
|
||||
&& check_name("advanced", tokens[0])
|
||||
&& check_name("bliss_next", tokens[1])
|
||||
}
|
||||
|
||||
fn build_sorter(
|
||||
|
@ -217,7 +227,8 @@ impl MpsSorterFactory<BlissNextSorter> for BlissNextSorterFactory {
|
|||
}
|
||||
}
|
||||
|
||||
pub type BlissNextSorterStatementFactory = MpsSortStatementFactory<BlissNextSorter, BlissNextSorterFactory>;
|
||||
pub type BlissNextSorterStatementFactory =
|
||||
MpsSortStatementFactory<BlissNextSorter, BlissNextSorterFactory>;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn bliss_next_sort() -> BlissNextSorterStatementFactory {
|
||||
|
|
|
@ -210,7 +210,9 @@ pub struct BlissSorterFactory;
|
|||
|
||||
impl MpsSorterFactory<BlissSorter> for BlissSorterFactory {
|
||||
fn is_sorter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||
tokens.len() == 2 && check_name("advanced", tokens[0]) && check_name("bliss_first", tokens[1])
|
||||
tokens.len() == 2
|
||||
&& check_name("advanced", tokens[0])
|
||||
&& check_name("bliss_first", tokens[1])
|
||||
}
|
||||
|
||||
fn build_sorter(
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
mod bliss_sorter;
|
||||
mod bliss_next_sorter;
|
||||
mod bliss_sorter;
|
||||
mod empty_sorter;
|
||||
mod field_sorter;
|
||||
mod shuffle;
|
||||
|
||||
pub use bliss_next_sorter::{
|
||||
bliss_next_sort, BlissNextSorter, BlissNextSorterFactory, BlissNextSorterStatementFactory,
|
||||
};
|
||||
pub use bliss_sorter::{bliss_sort, BlissSorter, BlissSorterFactory, BlissSorterStatementFactory};
|
||||
pub use bliss_next_sorter::{bliss_next_sort, BlissNextSorter, BlissNextSorterFactory, BlissNextSorterStatementFactory};
|
||||
pub use empty_sorter::{empty_sort, EmptySorter, EmptySorterFactory, EmptySorterStatementFactory};
|
||||
pub use field_sorter::{field_sort, FieldSorter, FieldSorterFactory, FieldSorterStatementFactory};
|
||||
pub use shuffle::{shuffle_sort, ShuffleSorter, ShuffleSorterFactory, ShuffleSorterStatementFactory};
|
||||
pub use shuffle::{
|
||||
shuffle_sort, ShuffleSorter, ShuffleSorterFactory, ShuffleSorterStatementFactory,
|
||||
};
|
||||
|
|
|
@ -3,16 +3,16 @@ use std::fmt::{Debug, Display, Error, Formatter};
|
|||
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::lang::utility::{assert_name, check_name};
|
||||
use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp};
|
||||
use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory};
|
||||
use crate::lang::{RuntimeError, SyntaxError};
|
||||
use crate::lang::utility::{check_name, assert_name};
|
||||
use crate::processing::OpGetter;
|
||||
use crate::tokens::MpsToken;
|
||||
|
||||
const RNG_LIMIT_BITMASK: usize = 0xffff; // bits to preserve in RNG
|
||||
// imposes an upper limit in the name of optimisation which reduces randomness past this point
|
||||
// this is also an effective item_buf size limit, 2^16 - 1 seems reasonable
|
||||
// imposes an upper limit in the name of optimisation which reduces randomness past this point
|
||||
// this is also an effective item_buf size limit, 2^16 - 1 seems reasonable
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShuffleSorter;
|
||||
|
@ -74,8 +74,9 @@ pub struct ShuffleSorterFactory;
|
|||
impl MpsSorterFactory<ShuffleSorter> for ShuffleSorterFactory {
|
||||
fn is_sorter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||
(tokens.len() == 1 && check_name("shuffle", &tokens[0]))
|
||||
||
|
||||
(tokens.len() == 2 && check_name("random", &tokens[0]) && check_name("shuffle", &tokens[1]))
|
||||
|| (tokens.len() == 2
|
||||
&& check_name("random", &tokens[0])
|
||||
&& check_name("shuffle", &tokens[1]))
|
||||
}
|
||||
|
||||
fn build_sorter(
|
||||
|
@ -91,7 +92,8 @@ impl MpsSorterFactory<ShuffleSorter> for ShuffleSorterFactory {
|
|||
}
|
||||
}
|
||||
|
||||
pub type ShuffleSorterStatementFactory = MpsSortStatementFactory<ShuffleSorter, ShuffleSorterFactory>;
|
||||
pub type ShuffleSorterStatementFactory =
|
||||
MpsSortStatementFactory<ShuffleSorter, ShuffleSorterFactory>;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn shuffle_sort() -> ShuffleSorterStatementFactory {
|
||||
|
|
|
@ -33,7 +33,8 @@ impl Tags {
|
|||
self.data
|
||||
.get("TITLE")
|
||||
.unwrap_or(&TagType::Unknown)
|
||||
.str().map(|s| s.to_string())
|
||||
.str()
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| self.default_title())
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,8 @@ impl Tags {
|
|||
.unwrap_or("");
|
||||
self.filename
|
||||
.file_name()
|
||||
.and_then(|file| file.to_str()).map(|file| file.replacen(&format!(".{}", extension), "", 1))
|
||||
.and_then(|file| file.to_str())
|
||||
.map(|file| file.replacen(&format!(".{}", extension), "", 1))
|
||||
.unwrap_or("Unknown Title".into())
|
||||
}
|
||||
|
||||
|
@ -55,7 +57,8 @@ impl Tags {
|
|||
self.data
|
||||
.get("ARTIST")
|
||||
.unwrap_or(&TagType::Unknown)
|
||||
.str().map(|s| s.to_string())
|
||||
.str()
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -63,7 +66,8 @@ impl Tags {
|
|||
self.data
|
||||
.get("ALBUM")
|
||||
.unwrap_or(&TagType::Unknown)
|
||||
.str().map(|s| s.to_string())
|
||||
.str()
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -71,7 +75,8 @@ impl Tags {
|
|||
self.data
|
||||
.get("GENRE")
|
||||
.unwrap_or(&TagType::Unknown)
|
||||
.str().map(|s| s.to_string())
|
||||
.str()
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -68,7 +68,10 @@ impl Display for FileIter {
|
|||
f,
|
||||
"root=`{}`, pattern={}, recursive={}",
|
||||
self.root.to_str().unwrap_or(""),
|
||||
self.pattern.as_ref().map(|re| re.to_string()).unwrap_or("[none]".to_string()),
|
||||
self.pattern
|
||||
.as_ref()
|
||||
.map(|re| re.to_string())
|
||||
.unwrap_or("[none]".to_string()),
|
||||
self.recursive
|
||||
)
|
||||
}
|
||||
|
@ -107,7 +110,9 @@ impl FileIter {
|
|||
op: op(),
|
||||
msg: format!("Regex compile error: {}", e),
|
||||
})?)
|
||||
} else {None};
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let tags_re = Regex::new(DEFAULT_REGEX).map_err(|e| RuntimeError {
|
||||
line: 0,
|
||||
op: op(),
|
||||
|
@ -155,7 +160,6 @@ impl FileIter {
|
|||
let capture_names = self.tags_pattern.capture_names();
|
||||
self.populate_item_impl(path, path_str, captures, capture_names)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(feature = "music_library")]
|
||||
|
@ -232,9 +236,7 @@ impl FileIter {
|
|||
if let Some(captures) = captures {
|
||||
for name_maybe in capture_names {
|
||||
if let Some(name) = name_maybe {
|
||||
if let Some(value) = captures
|
||||
.name(name).map(|m| m.as_str().to_string())
|
||||
{
|
||||
if let Some(value) = captures.name(name).map(|m| m.as_str().to_string()) {
|
||||
item.set_field(name, MpsTypePrimitive::parse(value));
|
||||
}
|
||||
}
|
||||
|
@ -298,7 +300,7 @@ impl Iterator for FileIter {
|
|||
self.dir_iters.push(dir_iter);
|
||||
return Some(Ok(item));
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
self.dir_iters.push(dir_iter);
|
||||
return Some(Err(format!("Path read error: {}", e)));
|
||||
|
|
|
@ -248,7 +248,8 @@ impl std::convert::TryInto<rusqlite::Connection> for SqliteSettings {
|
|||
|
||||
fn try_into(self) -> Result<rusqlite::Connection, Self::Error> {
|
||||
let music_path = self
|
||||
.music_path.map(std::path::PathBuf::from)
|
||||
.music_path
|
||||
.map(std::path::PathBuf::from)
|
||||
.unwrap_or_else(crate::lang::utility::music_folder);
|
||||
let sqlite_path = self
|
||||
.db_path
|
||||
|
|
|
@ -379,20 +379,12 @@ fn execute_blissnextsort_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|||
|
||||
#[test]
|
||||
fn execute_emptyfn_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
||||
execute_single_line(
|
||||
"empty()",
|
||||
true,
|
||||
true,
|
||||
)
|
||||
execute_single_line("empty()", true, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn execute_resetfn_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
||||
execute_single_line(
|
||||
"reset(empty())",
|
||||
true,
|
||||
true,
|
||||
)
|
||||
execute_single_line("reset(empty())", true, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -407,9 +399,5 @@ fn execute_shufflesort_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|||
false,
|
||||
true,
|
||||
)?;
|
||||
execute_single_line(
|
||||
"empty()~(shuffle)",
|
||||
true,
|
||||
true,
|
||||
)
|
||||
execute_single_line("empty()~(shuffle)", true, true)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ pub struct CliArgs {
|
|||
|
||||
/// Parse input as MPS instead of as filename
|
||||
#[clap(long)]
|
||||
pub raw: bool
|
||||
pub raw: bool,
|
||||
}
|
||||
|
||||
pub fn parse() -> CliArgs {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
mod cli;
|
||||
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::io::{BufReader, BufWriter, Cursor};
|
||||
use std::path::Path;
|
||||
|
||||
use m3u8_rs::{MediaPlaylist, MediaSegment};
|
||||
|
||||
|
@ -34,7 +34,7 @@ fn main() {
|
|||
match item {
|
||||
Ok(music) => {
|
||||
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())
|
||||
{
|
||||
playlist.segments.push(MediaSegment {
|
||||
uri: filename,
|
||||
|
@ -44,7 +44,7 @@ fn main() {
|
|||
} else {
|
||||
skipped_count += 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => eprintln!("{}", e),
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ fn main() {
|
|||
match item {
|
||||
Ok(music) => {
|
||||
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())
|
||||
{
|
||||
playlist.segments.push(MediaSegment {
|
||||
uri: filename,
|
||||
|
@ -67,13 +67,16 @@ fn main() {
|
|||
} else {
|
||||
skipped_count += 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => eprintln!("{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
if skipped_count != 0 {
|
||||
eprintln!("Skipped {} items due to missing `filename` field", skipped_count);
|
||||
eprintln!(
|
||||
"Skipped {} items due to missing `filename` field",
|
||||
skipped_count
|
||||
);
|
||||
}
|
||||
if let Err(e) = playlist.write_to(&mut out_file) {
|
||||
eprintln!("Playlist save error: {}", e);
|
||||
|
|
|
@ -25,7 +25,10 @@ pub struct SystemControlWrapper {
|
|||
|
||||
/// OS-specific APIs for media controls.
|
||||
/// Currently only Linux (dbus) is supported.
|
||||
#[cfg(any(not(feature = "os-controls"), not(all(target_os = "linux", feature = "os-controls", feature = "mpris-player"))))]
|
||||
#[cfg(any(
|
||||
not(feature = "os-controls"),
|
||||
not(all(target_os = "linux", feature = "os-controls", feature = "mpris-player"))
|
||||
))]
|
||||
pub struct SystemControlWrapper {
|
||||
#[allow(dead_code)]
|
||||
control: Sender<ControlAction>,
|
||||
|
@ -221,7 +224,10 @@ impl SystemControlWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(not(feature = "os-controls"), not(all(target_os = "linux", feature = "os-controls", feature = "mpris-player"))))]
|
||||
#[cfg(any(
|
||||
not(feature = "os-controls"),
|
||||
not(all(target_os = "linux", feature = "os-controls", feature = "mpris-player"))
|
||||
))]
|
||||
impl SystemControlWrapper {
|
||||
pub fn new(control: Sender<ControlAction>) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -50,7 +50,7 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
|
|||
"Field `filename` does not exist on item",
|
||||
))
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => Err(PlaybackError::from_err(e)),
|
||||
}?;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ impl<T: MpsTokenReader> MpsPlayerServer<T> {
|
|||
match self.player.enqueue(count) {
|
||||
Err(e) => {
|
||||
self.event.send(PlayerAction::Exception(e)).unwrap();
|
||||
},
|
||||
}
|
||||
Ok(items) => {
|
||||
for item in items {
|
||||
// notify of new items that have been enqueued
|
||||
|
|
|
@ -64,13 +64,16 @@ fn main() {
|
|||
.unwrap_or_else(|_| panic!("Abort: Cannot open file `{}`", &script_file2)),
|
||||
);
|
||||
let runner = MpsRunner::with_stream(script_reader);
|
||||
|
||||
|
||||
MpsPlayer::new(runner).unwrap()
|
||||
};
|
||||
if let Some(playlist_file) = &args.playlist {
|
||||
// generate playlist
|
||||
let mut player = player_builder();
|
||||
let mut writer = io::BufWriter::new(std::fs::File::create(playlist_file).unwrap_or_else(|_| panic!("Abort: Cannot create writeable file `{}`", playlist_file)));
|
||||
let mut writer =
|
||||
io::BufWriter::new(std::fs::File::create(playlist_file).unwrap_or_else(|_| {
|
||||
panic!("Abort: Cannot create writeable file `{}`", playlist_file)
|
||||
}));
|
||||
match player.save_m3u8(&mut writer) {
|
||||
Ok(_) => println!(
|
||||
"Succes: Finished playlist `{}` from script `{}`",
|
||||
|
|
|
@ -37,14 +37,17 @@ pub fn repl(args: CliArgs) {
|
|||
let (writer, reader) = channel_io();
|
||||
let player_builder = move || {
|
||||
let runner = MpsRunner::with_stream(reader);
|
||||
|
||||
|
||||
MpsPlayer::new(runner).unwrap()
|
||||
};
|
||||
let mut state = ReplState::new(writer);
|
||||
if let Some(playlist_file) = &args.playlist {
|
||||
println!("Playlist mode (output: `{}`)", playlist_file);
|
||||
let mut player = player_builder();
|
||||
let mut playlist_writer = io::BufWriter::new(std::fs::File::create(playlist_file).unwrap_or_else(|_| panic!("Abort: Cannot create writeable file `{}`", playlist_file)));
|
||||
let mut playlist_writer =
|
||||
io::BufWriter::new(std::fs::File::create(playlist_file).unwrap_or_else(|_| {
|
||||
panic!("Abort: Cannot create writeable file `{}`", playlist_file)
|
||||
}));
|
||||
read_loop(&args, &mut state, || {
|
||||
match player.save_m3u8(&mut playlist_writer) {
|
||||
Ok(_) => {}
|
||||
|
|
Loading…
Reference in a new issue