11extern crate anyhow;
2+ extern crate clap;
23extern crate cpal;
34
45use cpal:: traits:: { DeviceTrait , HostTrait , StreamTrait } ;
56
6- #[ cfg_attr( target_os = "android" , ndk_glue:: main( backtrace = "full" ) ) ]
7- fn main ( ) {
7+ #[ derive( Debug ) ]
8+ struct Opt {
9+ #[ cfg( all(
10+ any( target_os = "linux" , target_os = "dragonfly" , target_os = "freebsd" ) ,
11+ feature = "jack"
12+ ) ) ]
13+ jack : bool ,
14+
15+ device : String ,
16+ }
17+
18+ impl Opt {
19+ fn from_args ( ) -> Self {
20+ let app = clap:: App :: new ( "beep" ) . arg_from_usage ( "[DEVICE] 'The audio device to use'" ) ;
21+ #[ cfg( all(
22+ any( target_os = "linux" , target_os = "dragonfly" , target_os = "freebsd" ) ,
23+ feature = "jack"
24+ ) ) ]
25+ let app = app. arg_from_usage ( "-j, --jack 'Use the JACK host" ) ;
26+ let matches = app. get_matches ( ) ;
27+ let device = matches. value_of ( "DEVICE" ) . unwrap_or ( "default" ) . to_string ( ) ;
28+
29+ #[ cfg( all(
30+ any( target_os = "linux" , target_os = "dragonfly" , target_os = "freebsd" ) ,
31+ feature = "jack"
32+ ) ) ]
33+ return Opt {
34+ jack : matches. is_present ( "jack" ) ,
35+ device,
36+ } ;
37+
38+ #[ cfg( any(
39+ not( any( target_os = "linux" , target_os = "dragonfly" , target_os = "freebsd" ) ) ,
40+ not( feature = "jack" )
41+ ) ) ]
42+ Opt { device }
43+ }
44+ }
45+
46+ fn main ( ) -> anyhow:: Result < ( ) > {
47+ let opt = Opt :: from_args ( ) ;
48+
849 // Conditionally compile with jack if the feature is specified.
950 #[ cfg( all(
1051 any( target_os = "linux" , target_os = "dragonfly" , target_os = "freebsd" ) ,
1152 feature = "jack"
1253 ) ) ]
1354 // Manually check for flags. Can be passed through cargo with -- e.g.
1455 // cargo run --release --example beep --features jack -- --jack
15- let host = if std:: env:: args ( )
16- . collect :: < String > ( )
17- . contains ( & String :: from ( "--jack" ) )
18- {
56+ let host = if opt. jack {
1957 cpal:: host_from_id ( cpal:: available_hosts ( )
2058 . into_iter ( )
2159 . find ( |id| * id == cpal:: HostId :: Jack )
@@ -32,19 +70,26 @@ fn main() {
3270 ) ) ]
3371 let host = cpal:: default_host ( ) ;
3472
35- let device = host
36- . default_output_device ( )
37- . expect ( "failed to find a default output device" ) ;
73+ let device = if opt. device == "default" {
74+ host. default_output_device ( )
75+ } else {
76+ host. output_devices ( ) ?
77+ . find ( |x| x. name ( ) . map ( |y| y == opt. device ) . unwrap_or ( false ) )
78+ }
79+ . expect ( "failed to find output device" ) ;
80+ println ! ( "Output device: {}" , device. name( ) ?) ;
81+
3882 let config = device. default_output_config ( ) . unwrap ( ) ;
83+ println ! ( "Default output config: {:?}" , config) ;
3984
4085 match config. sample_format ( ) {
41- cpal:: SampleFormat :: F32 => run :: < f32 > ( & device, & config. into ( ) ) . unwrap ( ) ,
42- cpal:: SampleFormat :: I16 => run :: < i16 > ( & device, & config. into ( ) ) . unwrap ( ) ,
43- cpal:: SampleFormat :: U16 => run :: < u16 > ( & device, & config. into ( ) ) . unwrap ( ) ,
86+ cpal:: SampleFormat :: F32 => run :: < f32 > ( & device, & config. into ( ) ) ,
87+ cpal:: SampleFormat :: I16 => run :: < i16 > ( & device, & config. into ( ) ) ,
88+ cpal:: SampleFormat :: U16 => run :: < u16 > ( & device, & config. into ( ) ) ,
4489 }
4590}
4691
47- fn run < T > ( device : & cpal:: Device , config : & cpal:: StreamConfig ) -> Result < ( ) , anyhow:: Error >
92+ pub fn run < T > ( device : & cpal:: Device , config : & cpal:: StreamConfig ) -> Result < ( ) , anyhow:: Error >
4893where
4994 T : cpal:: Sample ,
5095{
55100 let mut sample_clock = 0f32 ;
56101 let mut next_value = move || {
57102 sample_clock = ( sample_clock + 1.0 ) % sample_rate;
58- ( sample_clock * 440.0 * 2.0 * 3.141592 / sample_rate) . sin ( )
103+ ( sample_clock * 440.0 * 2.0 * std :: f32 :: consts :: PI / sample_rate) . sin ( )
59104 } ;
60105
61106 let err_fn = |err| eprintln ! ( "an error occurred on stream: {}" , err) ;
0 commit comments