@@ -2,9 +2,38 @@ use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult};
22use crate :: config:: AudioFormat ;
33use crate :: convert:: Converter ;
44use crate :: decoder:: AudioPacket ;
5+
56use std:: fs:: OpenOptions ;
67use std:: io:: { self , Write } ;
78use 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
938pub struct StdoutSink {
1039 output : Option < Box < dyn Write > > ,
@@ -15,13 +44,12 @@ pub struct StdoutSink {
1544impl 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 ! ( "\n Usage:\n \n Output to stdout:\n \n \t --backend pipe\n \n Output 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
3361impl 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
5795impl 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