1 use super::{Open, Sink};
2 use jack::prelude::{
3 client_options, AsyncClient, AudioOutPort, AudioOutSpec, Client, JackControl, Port,
4 ProcessHandler, ProcessScope,
5 };
6 use std::io;
7 use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
8
9 pub struct JackSink {
10 send: SyncSender<i16>,
11 active_client: AsyncClient<(), JackData>,
12 }
13
14 pub struct JackData {
15 rec: Receiver<i16>,
16 port_l: Port<AudioOutSpec>,
17 port_r: Port<AudioOutSpec>,
18 }
19
pcm_to_f32(sample: i16) -> f3220 fn pcm_to_f32(sample: i16) -> f32 {
21 sample as f32 / 32768.0
22 }
23
24 impl ProcessHandler for JackData {
process(&mut self, _: &Client, ps: &ProcessScope) -> JackControl25 fn process(&mut self, _: &Client, ps: &ProcessScope) -> JackControl {
26 // get output port buffers
27 let mut out_r = AudioOutPort::new(&mut self.port_r, ps);
28 let mut out_l = AudioOutPort::new(&mut self.port_l, ps);
29 let buf_r: &mut [f32] = &mut out_r;
30 let buf_l: &mut [f32] = &mut out_l;
31 // get queue iterator
32 let mut queue_iter = self.rec.try_iter();
33
34 let buf_size = buf_r.len();
35 for i in 0..buf_size {
36 buf_r[i] = pcm_to_f32(queue_iter.next().unwrap_or(0));
37 buf_l[i] = pcm_to_f32(queue_iter.next().unwrap_or(0));
38 }
39 JackControl::Continue
40 }
41 }
42
43 impl Open for JackSink {
open(client_name: Option<String>) -> JackSink44 fn open(client_name: Option<String>) -> JackSink {
45 info!("Using jack sink!");
46
47 let client_name = client_name.unwrap_or("librespot".to_string());
48 let (client, _status) =
49 Client::new(&client_name[..], client_options::NO_START_SERVER).unwrap();
50 let ch_r = client
51 .register_port("out_0", AudioOutSpec::default())
52 .unwrap();
53 let ch_l = client
54 .register_port("out_1", AudioOutSpec::default())
55 .unwrap();
56 // buffer for samples from librespot (~10ms)
57 let (tx, rx) = sync_channel(2 * 1024 * 4);
58 let jack_data = JackData {
59 rec: rx,
60 port_l: ch_l,
61 port_r: ch_r,
62 };
63 let active_client = AsyncClient::new(client, (), jack_data).unwrap();
64
65 JackSink {
66 send: tx,
67 active_client: active_client,
68 }
69 }
70 }
71
72 impl Sink for JackSink {
start(&mut self) -> io::Result<()>73 fn start(&mut self) -> io::Result<()> {
74 Ok(())
75 }
76
stop(&mut self) -> io::Result<()>77 fn stop(&mut self) -> io::Result<()> {
78 Ok(())
79 }
80
write(&mut self, data: &[i16]) -> io::Result<()>81 fn write(&mut self, data: &[i16]) -> io::Result<()> {
82 for s in data.iter() {
83 let res = self.send.send(*s);
84 if res.is_err() {
85 error!("jackaudio: cannot write to channel");
86 }
87 }
88 Ok(())
89 }
90 }
91