Skip to content

Commit 8002061

Browse files
authored
Merge pull request #1020 from JasonLG1979/improve-pipe-backend
Improve pipe backend
2 parents 179ceda + 2532687 commit 8002061

1 file changed

Lines changed: 57 additions & 27 deletions

File tree

playback/src/audio_backend/pipe.rs

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,38 @@ use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult};
22
use crate::config::AudioFormat;
33
use crate::convert::Converter;
44
use crate::decoder::AudioPacket;
5+
56
use std::fs::OpenOptions;
67
use std::io::{self, Write};
78
use std::process::exit;
9+
use thiserror::Error;
10+
11+
#[derive(Debug, Error)]
12+
enum StdoutError {
13+
#[error("<StdoutSink> {0}")]
14+
OnWrite(std::io::Error),
15+
16+
#[error("<StdoutSink> File Path {file} Can Not be Opened and/or Created, {e}")]
17+
OpenFailure { file: String, e: std::io::Error },
18+
19+
#[error("<StdoutSink> Failed to Flush the Output Stream, {0}")]
20+
FlushFailure(std::io::Error),
21+
22+
#[error("<StdoutSink> The Output Stream is None")]
23+
NoOutput,
24+
}
25+
26+
impl From<StdoutError> for SinkError {
27+
fn from(e: StdoutError) -> SinkError {
28+
use StdoutError::*;
29+
let es = e.to_string();
30+
match e {
31+
FlushFailure(_) | OnWrite(_) => SinkError::OnWrite(es),
32+
OpenFailure { .. } => SinkError::ConnectionRefused(es),
33+
NoOutput => SinkError::NotConnected(es),
34+
}
35+
}
36+
}
837

938
pub struct StdoutSink {
1039
output: Option<Box<dyn Write>>,
@@ -15,13 +44,12 @@ pub struct StdoutSink {
1544
impl Open for StdoutSink {
1645
fn open(file: Option<String>, format: AudioFormat) -> Self {
1746
if let Some("?") = file.as_deref() {
18-
info!("Usage:");
19-
println!(" Output to stdout: --backend pipe");
20-
println!(" Output to file: --backend pipe --device {{filename}}");
47+
println!("\nUsage:\n\nOutput to stdout:\n\n\t--backend pipe\n\nOutput to file:\n\n\t--backend pipe --device {{filename}}\n");
2148
exit(0);
2249
}
2350

24-
info!("Using pipe sink with format: {:?}", format);
51+
info!("Using StdoutSink (pipe) with format: {:?}", format);
52+
2553
Self {
2654
output: None,
2755
file,
@@ -32,21 +60,31 @@ impl Open for StdoutSink {
3260

3361
impl Sink for StdoutSink {
3462
fn start(&mut self) -> SinkResult<()> {
35-
if self.output.is_none() {
36-
let output: Box<dyn Write> = match self.file.as_deref() {
37-
Some(file) => {
38-
let open_op = OpenOptions::new()
63+
self.output.get_or_insert({
64+
match self.file.as_deref() {
65+
Some(file) => Box::new(
66+
OpenOptions::new()
3967
.write(true)
4068
.create(true)
4169
.open(file)
42-
.map_err(|e| SinkError::ConnectionRefused(e.to_string()))?;
43-
Box::new(open_op)
44-
}
70+
.map_err(|e| StdoutError::OpenFailure {
71+
file: file.to_string(),
72+
e,
73+
})?,
74+
),
4575
None => Box::new(io::stdout()),
46-
};
76+
}
77+
});
4778

48-
self.output = Some(output);
49-
}
79+
Ok(())
80+
}
81+
82+
fn stop(&mut self) -> SinkResult<()> {
83+
self.output
84+
.take()
85+
.ok_or(StdoutError::NoOutput)?
86+
.flush()
87+
.map_err(StdoutError::FlushFailure)?;
5088

5189
Ok(())
5290
}
@@ -56,19 +94,11 @@ impl Sink for StdoutSink {
5694

5795
impl SinkAsBytes for StdoutSink {
5896
fn write_bytes(&mut self, data: &[u8]) -> SinkResult<()> {
59-
match self.output.as_deref_mut() {
60-
Some(output) => {
61-
output
62-
.write_all(data)
63-
.map_err(|e| SinkError::OnWrite(e.to_string()))?;
64-
output
65-
.flush()
66-
.map_err(|e| SinkError::OnWrite(e.to_string()))?;
67-
}
68-
None => {
69-
return Err(SinkError::NotConnected("Output is None".to_string()));
70-
}
71-
}
97+
self.output
98+
.as_deref_mut()
99+
.ok_or(StdoutError::NoOutput)?
100+
.write_all(data)
101+
.map_err(StdoutError::OnWrite)?;
72102

73103
Ok(())
74104
}

0 commit comments

Comments
 (0)