Fix some REPL playback issues, including upgrading rodio to use more robust symphonia decoding
This commit is contained in:
parent
0c3f0fee9c
commit
d3bb52d354
5 changed files with 35 additions and 61 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -1807,15 +1807,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rodio"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9"
|
||||
checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e"
|
||||
dependencies = [
|
||||
"claxon",
|
||||
"cpal",
|
||||
"hound",
|
||||
"lewton",
|
||||
"minimp3",
|
||||
"symphonia",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -6,7 +6,7 @@ license = "LGPL-2.1-only OR GPL-2.0-or-later"
|
|||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
rodio = { version = "^0.14"}
|
||||
rodio = { version = "^0.15", features = ["symphonia"]}
|
||||
m3u8-rs = { version = "^3.0.0" }
|
||||
|
||||
# local
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rodio::{decoder::Decoder, OutputStream, OutputStreamHandle, Sink};
|
||||
|
||||
|
@ -40,22 +39,11 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
|
|||
if let Some(filename) =
|
||||
music.field("filename").and_then(|x| x.to_owned().to_str())
|
||||
{
|
||||
let path: PathBuf = filename.into();
|
||||
if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
|
||||
match ext {
|
||||
"mp3"
|
||||
| "wav"
|
||||
| "flac"
|
||||
| "aac"
|
||||
| "ogg" => {
|
||||
let file = fs::File::open(path).map_err(PlaybackError::from_err)?;
|
||||
// NOTE: Default rodio::Decoder hangs here when decoding large files, but symphonia does not
|
||||
let file = fs::File::open(filename).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(())
|
||||
} else {
|
||||
Err(PlaybackError::from_err(
|
||||
|
@ -79,22 +67,11 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
|
|||
if let Some(filename) =
|
||||
music.field("filename").and_then(|x| x.to_owned().to_str())
|
||||
{
|
||||
let path: PathBuf = filename.into();
|
||||
if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
|
||||
match ext {
|
||||
"mp3"
|
||||
| "wav"
|
||||
| "flac"
|
||||
| "aac"
|
||||
| "ogg" => {
|
||||
let file = fs::File::open(path).map_err(PlaybackError::from_err)?;
|
||||
// NOTE: Default rodio::Decoder hangs here when decoding large files, but symphonia does not
|
||||
let file = fs::File::open(filename).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(())
|
||||
} else {
|
||||
Err(PlaybackError::from_err(
|
||||
|
@ -120,24 +97,13 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
|
|||
if let Some(filename) =
|
||||
music.field("filename").and_then(|x| x.to_owned().to_str())
|
||||
{
|
||||
let path: PathBuf = filename.into();
|
||||
if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
|
||||
match ext {
|
||||
"mp3"
|
||||
| "wav"
|
||||
| "flac"
|
||||
| "aac"
|
||||
| "ogg" => {
|
||||
enqueued.push(music.clone());
|
||||
let file = fs::File::open(path).map_err(PlaybackError::from_err)?;
|
||||
// NOTE: Default rodio::Decoder hangs here when decoding large files, but symphonia does not
|
||||
let file = fs::File::open(filename).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(())
|
||||
} else {
|
||||
Err(PlaybackError::from_err(
|
||||
|
|
|
@ -39,7 +39,9 @@ impl<T: MpsTokenReader> MpsPlayerServer<T> {
|
|||
fn enqeue_some(&mut self, count: usize) {
|
||||
//println!("Enqueuing up to {} items", count);
|
||||
match self.player.enqueue(count) {
|
||||
Err(e) => self.event.send(PlayerAction::Exception(e)).unwrap(),
|
||||
Err(e) => {
|
||||
self.event.send(PlayerAction::Exception(e)).unwrap();
|
||||
},
|
||||
Ok(items) => {
|
||||
for item in items {
|
||||
// notify of new items that have been enqueued
|
||||
|
@ -152,7 +154,7 @@ impl<T: MpsTokenReader> MpsPlayerServer<T> {
|
|||
playback: Sender<PlaybackAction>,
|
||||
keep_alive: bool,
|
||||
) -> JoinHandle<()> {
|
||||
thread::spawn(move || Self::unblocking_timer_loop(ctrl_tx, 50));
|
||||
thread::spawn(move || Self::unblocking_timer_loop(ctrl_tx, 100));
|
||||
thread::spawn(move || {
|
||||
let player = factory();
|
||||
let mut server_obj = Self::new(player, ctrl_rx, event, playback, keep_alive);
|
||||
|
|
15
src/repl.rs
15
src/repl.rs
|
@ -51,10 +51,10 @@ pub fn repl(args: CliArgs) {
|
|||
match player.save_m3u8(&mut playlist_writer) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
eprintln!("{}", e.message());
|
||||
error_prompt(e, &args);
|
||||
// consume any further errors (this shouldn't actually write anything)
|
||||
while let Err(e) = player.save_m3u8(&mut playlist_writer) {
|
||||
eprintln!("{}", e.message());
|
||||
error_prompt(e, &args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ pub fn repl(args: CliArgs) {
|
|||
if args.wait {
|
||||
match ctrl.wait_for_empty() {
|
||||
Ok(_) => {}
|
||||
Err(e) => eprintln!("{}", e.message()),
|
||||
Err(e) => error_prompt(e, &args),
|
||||
}
|
||||
} else {
|
||||
// consume all incoming errors
|
||||
|
@ -77,7 +77,7 @@ pub fn repl(args: CliArgs) {
|
|||
while had_err {
|
||||
let mut new_had_err = false;
|
||||
for e in ctrl.check_ack() {
|
||||
eprintln!("{}", e.message());
|
||||
error_prompt(e, &args);
|
||||
new_had_err = true;
|
||||
}
|
||||
had_err = new_had_err;
|
||||
|
@ -127,7 +127,7 @@ fn read_loop<F: FnMut()>(args: &CliArgs, state: &mut ReplState, mut execute: F)
|
|||
'\n' => {
|
||||
let statement_result = std::str::from_utf8(state.statement_buf.as_slice());
|
||||
if statement_result.is_ok() && statement_result.unwrap().trim().starts_with("?") {
|
||||
println!("Got {}", statement_result.unwrap());
|
||||
//println!("Got {}", statement_result.unwrap());
|
||||
repl_commands(statement_result.unwrap().trim());
|
||||
state.statement_buf.clear();
|
||||
} else if state.bracket_depth == 0 && state.in_literal.is_none() {
|
||||
|
@ -153,6 +153,11 @@ fn prompt(line: &mut usize, args: &CliArgs) {
|
|||
std::io::stdout().flush().expect("Failed to flush stdout");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn error_prompt(error: mps_player::PlaybackError, args: &CliArgs) {
|
||||
eprintln!("E{}{}", args.prompt, error.message());
|
||||
}
|
||||
|
||||
fn repl_commands(command_str: &str) {
|
||||
let words: Vec<&str> = command_str.split(" ").map(|s| s.trim()).collect();
|
||||
match words[0] {
|
||||
|
|
Loading…
Reference in a new issue