mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Merge pull request #1020 from JasonLG1979/improve-pipe-backend
Improve pipe backend
This commit is contained in:
commit
80020616fc
1 changed files with 57 additions and 27 deletions
|
@ -2,9 +2,38 @@ use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult};
|
||||||
use crate::config::AudioFormat;
|
use crate::config::AudioFormat;
|
||||||
use crate::convert::Converter;
|
use crate::convert::Converter;
|
||||||
use crate::decoder::AudioPacket;
|
use crate::decoder::AudioPacket;
|
||||||
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
enum StdoutError {
|
||||||
|
#[error("<StdoutSink> {0}")]
|
||||||
|
OnWrite(std::io::Error),
|
||||||
|
|
||||||
|
#[error("<StdoutSink> File Path {file} Can Not be Opened and/or Created, {e}")]
|
||||||
|
OpenFailure { file: String, e: std::io::Error },
|
||||||
|
|
||||||
|
#[error("<StdoutSink> Failed to Flush the Output Stream, {0}")]
|
||||||
|
FlushFailure(std::io::Error),
|
||||||
|
|
||||||
|
#[error("<StdoutSink> The Output Stream is None")]
|
||||||
|
NoOutput,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<StdoutError> for SinkError {
|
||||||
|
fn from(e: StdoutError) -> SinkError {
|
||||||
|
use StdoutError::*;
|
||||||
|
let es = e.to_string();
|
||||||
|
match e {
|
||||||
|
FlushFailure(_) | OnWrite(_) => SinkError::OnWrite(es),
|
||||||
|
OpenFailure { .. } => SinkError::ConnectionRefused(es),
|
||||||
|
NoOutput => SinkError::NotConnected(es),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct StdoutSink {
|
pub struct StdoutSink {
|
||||||
output: Option<Box<dyn Write>>,
|
output: Option<Box<dyn Write>>,
|
||||||
|
@ -15,13 +44,12 @@ pub struct StdoutSink {
|
||||||
impl Open for StdoutSink {
|
impl Open for StdoutSink {
|
||||||
fn open(file: Option<String>, format: AudioFormat) -> Self {
|
fn open(file: Option<String>, format: AudioFormat) -> Self {
|
||||||
if let Some("?") = file.as_deref() {
|
if let Some("?") = file.as_deref() {
|
||||||
info!("Usage:");
|
println!("\nUsage:\n\nOutput to stdout:\n\n\t--backend pipe\n\nOutput to file:\n\n\t--backend pipe --device {{filename}}\n");
|
||||||
println!(" Output to stdout: --backend pipe");
|
|
||||||
println!(" Output to file: --backend pipe --device {{filename}}");
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Using pipe sink with format: {:?}", format);
|
info!("Using StdoutSink (pipe) with format: {:?}", format);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
output: None,
|
output: None,
|
||||||
file,
|
file,
|
||||||
|
@ -32,21 +60,31 @@ impl Open for StdoutSink {
|
||||||
|
|
||||||
impl Sink for StdoutSink {
|
impl Sink for StdoutSink {
|
||||||
fn start(&mut self) -> SinkResult<()> {
|
fn start(&mut self) -> SinkResult<()> {
|
||||||
if self.output.is_none() {
|
self.output.get_or_insert({
|
||||||
let output: Box<dyn Write> = match self.file.as_deref() {
|
match self.file.as_deref() {
|
||||||
Some(file) => {
|
Some(file) => Box::new(
|
||||||
let open_op = OpenOptions::new()
|
OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(file)
|
.open(file)
|
||||||
.map_err(|e| SinkError::ConnectionRefused(e.to_string()))?;
|
.map_err(|e| StdoutError::OpenFailure {
|
||||||
Box::new(open_op)
|
file: file.to_string(),
|
||||||
}
|
e,
|
||||||
|
})?,
|
||||||
|
),
|
||||||
None => Box::new(io::stdout()),
|
None => Box::new(io::stdout()),
|
||||||
};
|
}
|
||||||
|
});
|
||||||
|
|
||||||
self.output = Some(output);
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stop(&mut self) -> SinkResult<()> {
|
||||||
|
self.output
|
||||||
|
.take()
|
||||||
|
.ok_or(StdoutError::NoOutput)?
|
||||||
|
.flush()
|
||||||
|
.map_err(StdoutError::FlushFailure)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -56,19 +94,11 @@ impl Sink for StdoutSink {
|
||||||
|
|
||||||
impl SinkAsBytes for StdoutSink {
|
impl SinkAsBytes for StdoutSink {
|
||||||
fn write_bytes(&mut self, data: &[u8]) -> SinkResult<()> {
|
fn write_bytes(&mut self, data: &[u8]) -> SinkResult<()> {
|
||||||
match self.output.as_deref_mut() {
|
self.output
|
||||||
Some(output) => {
|
.as_deref_mut()
|
||||||
output
|
.ok_or(StdoutError::NoOutput)?
|
||||||
.write_all(data)
|
.write_all(data)
|
||||||
.map_err(|e| SinkError::OnWrite(e.to_string()))?;
|
.map_err(StdoutError::OnWrite)?;
|
||||||
output
|
|
||||||
.flush()
|
|
||||||
.map_err(|e| SinkError::OnWrite(e.to_string()))?;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(SinkError::NotConnected("Output is None".to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue