1 //! Takes 2 audio inputs and outputs them to 2 audio outputs.
2 //! All JACK notifications are also printed out.
3 extern crate jack;
4 use jack::prelude as j;
5 use std::io;
6 
7 struct Notifications;
8 
9 impl j::NotificationHandler for Notifications {
thread_init(&self, _: &j::Client)10     fn thread_init(&self, _: &j::Client) {
11         println!("JACK: thread init");
12     }
13 
shutdown(&mut self, status: j::ClientStatus, reason: &str)14     fn shutdown(&mut self, status: j::ClientStatus, reason: &str) {
15         println!(
16             "JACK: shutdown with status {:?} because \"{}\"",
17             status,
18             reason
19         );
20     }
21 
freewheel(&mut self, _: &j::Client, is_enabled: bool)22     fn freewheel(&mut self, _: &j::Client, is_enabled: bool) {
23         println!(
24             "JACK: freewheel mode is {}",
25             if is_enabled { "on" } else { "off" }
26         );
27     }
28 
buffer_size(&mut self, _: &j::Client, sz: j::JackFrames) -> j::JackControl29     fn buffer_size(&mut self, _: &j::Client, sz: j::JackFrames) -> j::JackControl {
30         println!("JACK: buffer size changed to {}", sz);
31         j::JackControl::Continue
32     }
33 
sample_rate(&mut self, _: &j::Client, srate: j::JackFrames) -> j::JackControl34     fn sample_rate(&mut self, _: &j::Client, srate: j::JackFrames) -> j::JackControl {
35         println!("JACK: sample rate changed to {}", srate);
36         j::JackControl::Continue
37     }
38 
client_registration(&mut self, _: &j::Client, name: &str, is_reg: bool)39     fn client_registration(&mut self, _: &j::Client, name: &str, is_reg: bool) {
40         println!(
41             "JACK: {} client with name \"{}\"",
42             if is_reg { "registered" } else { "unregistered" },
43             name
44         );
45     }
46 
port_registration(&mut self, _: &j::Client, port_id: j::JackPortId, is_reg: bool)47     fn port_registration(&mut self, _: &j::Client, port_id: j::JackPortId, is_reg: bool) {
48         println!(
49             "JACK: {} port with id {}",
50             if is_reg { "registered" } else { "unregistered" },
51             port_id
52         );
53     }
54 
port_rename( &mut self, _: &j::Client, port_id: j::JackPortId, old_name: &str, new_name: &str, ) -> j::JackControl55     fn port_rename(
56         &mut self,
57         _: &j::Client,
58         port_id: j::JackPortId,
59         old_name: &str,
60         new_name: &str,
61     ) -> j::JackControl {
62         println!(
63             "JACK: port with id {} renamed from {} to {}",
64             port_id,
65             old_name,
66             new_name
67         );
68         j::JackControl::Continue
69     }
70 
ports_connected( &mut self, _: &j::Client, port_id_a: j::JackPortId, port_id_b: j::JackPortId, are_connected: bool, )71     fn ports_connected(
72         &mut self,
73         _: &j::Client,
74         port_id_a: j::JackPortId,
75         port_id_b: j::JackPortId,
76         are_connected: bool,
77     ) {
78         println!(
79             "JACK: ports with id {} and {} are {}",
80             port_id_a,
81             port_id_b,
82             if are_connected {
83                 "connected"
84             } else {
85                 "disconnected"
86             }
87         );
88     }
89 
graph_reorder(&mut self, _: &j::Client) -> j::JackControl90     fn graph_reorder(&mut self, _: &j::Client) -> j::JackControl {
91         println!("JACK: graph reordered");
92         j::JackControl::Continue
93     }
94 
xrun(&mut self, _: &j::Client) -> j::JackControl95     fn xrun(&mut self, _: &j::Client) -> j::JackControl {
96         println!("JACK: xrun occurred");
97         j::JackControl::Continue
98     }
99 
latency(&mut self, _: &j::Client, mode: j::LatencyType)100     fn latency(&mut self, _: &j::Client, mode: j::LatencyType) {
101         println!(
102             "JACK: {} latency has changed",
103             match mode {
104                 j::LatencyType::Capture => "capture",
105                 j::LatencyType::Playback => "playback",
106             }
107         );
108     }
109 }
110 
main()111 fn main() {
112     // Create client
113     let (client, _status) = j::Client::new("rust_jack_simple", j::client_options::NO_START_SERVER)
114         .unwrap();
115 
116     // Register ports. They will be used in a callback that will be
117     // called when new data is available.
118     let in_a = client
119         .register_port("rust_in_l", j::AudioInSpec::default())
120         .unwrap();
121     let in_b = client
122         .register_port("rust_in_r", j::AudioInSpec::default())
123         .unwrap();
124     let mut out_a = client
125         .register_port("rust_out_l", j::AudioOutSpec::default())
126         .unwrap();
127     let mut out_b = client
128         .register_port("rust_out_r", j::AudioOutSpec::default())
129         .unwrap();
130     let process_callback = move |_: &j::Client, ps: &j::ProcessScope| -> j::JackControl {
131         let mut out_a_p = j::AudioOutPort::new(&mut out_a, ps);
132         let mut out_b_p = j::AudioOutPort::new(&mut out_b, ps);
133         let in_a_p = j::AudioInPort::new(&in_a, ps);
134         let in_b_p = j::AudioInPort::new(&in_b, ps);
135         out_a_p.clone_from_slice(&in_a_p);
136         out_b_p.clone_from_slice(&in_b_p);
137         j::JackControl::Continue
138     };
139     let process = j::ClosureProcessHandler::new(process_callback);
140 
141     // Activate the client, which starts the processing.
142     let active_client = j::AsyncClient::new(client, Notifications, process).unwrap();
143 
144     // Wait for user input to quit
145     println!("Press enter/return to quit...");
146     let mut user_input = String::new();
147     io::stdin().read_line(&mut user_input).ok();
148 
149     active_client.deactivate().unwrap();
150 }
151