jackaudio.rs 2.4 KB

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