jackaudio.rs 2.4 KB

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