jackaudio.rs 2.5 KB

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