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