Quellcode durchsuchen

cpal backend builds. Panics building output stream on my system.

Will Stott vor 6 Jahren
Ursprung
Commit
ac9423d9d9
1 geänderte Dateien mit 33 neuen und 53 gelöschten Zeilen
  1. 33 53
      playback/src/audio_backend/cpal.rs

+ 33 - 53
playback/src/audio_backend/cpal.rs

@@ -2,18 +2,21 @@ use super::{Open, Sink};
 extern crate cpal;
 use std::io;
 use std::thread;
-use std::collections::VecDeque;
+use std::sync::mpsc::{sync_channel, SyncSender};
 
 pub struct CpalSink {
-    event_loop: cpal::EventLoop,
-    buffer: mut VecDeque<i16>,
-    stream_id: Option<cpal::StreamId>,
+    // event_loop: cpal::EventLoop,
+    send: SyncSender<i16>,
 }
 
 impl Open for CpalSink {
     fn open(device: Option<String>) -> CpalSink {
         info!("Using cpal sink");
 
+        // buffer for samples from librespot (~10ms)
+        let (tx, rx) = sync_channel::<i16>(2 * 1024 * 4);
+        let event_loop = cpal::EventLoop::new();
+
         if device.is_some() {
             // N.B. This is perfectly possible to support.
             // TODO: First need to enable listing of devices.
@@ -21,72 +24,49 @@ impl Open for CpalSink {
             // TODO: Choose cpal sink by name.
             panic!("cpal sink does not support specifying a device name");
         }
+        let cpal_device = cpal::default_output_device().expect("no output device available");
+        // TODO: Support more formats? Surely cpal will handle that.
+        let format = cpal::Format{channels: 2, sample_rate: cpal::SampleRate(44100), data_type: cpal::SampleFormat::I16};
 
-        let event_loop = cpal::EventLoop::new();
+        let stream_id = event_loop.build_output_stream(&cpal_device, &format).expect("could not build output stream");
+        event_loop.play_stream(stream_id);
+
+        thread::spawn(move |/*event_loop, rx*/| {
+            event_loop.run(move |_stream_id, stream_data| {
+                match stream_data {
+                    cpal::StreamData::Output { buffer: cpal::UnknownTypeOutputBuffer::I16(mut buffer) } => {
+                        for (sample, recv) in buffer.iter_mut().zip(rx.try_iter()) {
+                            *sample = recv;
+                        }
+                    },
+                    _ => (),
+                }
+            });
+        });
 
         CpalSink {
-            // Allow an (arbitrary) 2 second buffer before resizing.
-            buffer: VecDeque::with_capacity(44100 * 2 * 2),
-            event_loop: event_loop,
+            send: tx,
+            // event_loop: event_loop,
         }
     }
 }
 
 impl Sink for CpalSink {
     fn start(&mut self) -> io::Result<()> {
-
-        if self.stream_id.is_none() {
-
-            let device = cpal::default_output_device().expect("no output device available");
-            // TODO: Support more formats.
-            let format = cpal::Format(2, 44100, cpal::SampleFormat::I16);
-
-            self.stream_id = self.event_loop.build_output_stream(&device, &format)?;
-
-            self.event_loop.play_stream(self.stream_id.clone());
-        }
-
-        if self.thread.is_none() {
-            let event_loop = self.event_loop;
-            let source  = self.buffer;
-            thread::spawn(move |event_loop, source| {
-                event_loop.run(move |_stream_id, mut stream_data| {
-                    match data {
-                        cpal::StreamData::Output { buffer: cpal::UnknownTypeOutputBuffer::I16(mut buffer) } => {
-                            let sl = source.len();
-                            if (sl > buffer.len()) {
-                                sl = buffer.len();
-                            }
-                            // let u: Vec<_> = source.drain(..sl).collect();
-                            // buffer[..s1].copy_from_slice(u[..s1]);
-
-                            for (sample, data) in buffer.iter_mut().zip(source.drain(..sl)) {
-                                *sample = data;
-                            }
-                        },
-                        _ => (),
-                    }
-                });
-            })
-        }
-
         Ok(())
     }
 
     fn stop(&mut self) -> io::Result<()> {
-        if !self.stream_id.is_none() {
-            self.event_loop.destroy_stream(self.stream_id);
-            self.stream_id = None;
-            self.buffer.clear();
-        }
         Ok(())
     }
 
     fn write(&mut self, data: &[i16]) -> io::Result<()> {
-        // self.0.as_mut().unwrap().write_interleaved(&data).unwrap();
-        // self.buffer.reserve(data.len()); // Unneccessary?
-        // self.buffer.extend_from_slice(data);
-        self.buffer.extend(data);
+        for s in data.iter() {
+            let res = self.send.send(*s);
+            if res.is_err() {
+                error!("jackaudio: cannot write to channel");
+            }
+        }
         Ok(())
     }
 }