librespot/playback/src/audio_backend/rodio.rs

97 lines
2.9 KiB
Rust
Raw Normal View History

2019-03-20 13:24:03 +00:00
use super::{Open, Sink};
extern crate rodio;
use std::{io, thread, time};
2019-03-20 13:24:03 +00:00
use std::process::exit;
pub struct RodioSink {
rodio_sink: rodio::Sink,
}
fn list_outputs() {
println!("Default Audio Device:\n {:?}", rodio::default_output_device().map(|e| e.name()));
println!("Available Audio Devices:");
for device in rodio::output_devices() {
println!("- {}", device.name());
// Output formats
if let Ok(fmt) = device.default_output_format() {
println!(" Default format:\n {:?}", fmt);
}
let mut output_formats = match device.supported_output_formats() {
Ok(f) => f.peekable(),
Err(e) => {
println!("Error: {:?}", e);
continue;
},
};
if output_formats.peek().is_some() {
println!(" All formats:");
for format in output_formats {
println!(" {:?}", format);
}
}
}
}
impl Open for RodioSink {
fn open(device: Option<String>) -> RodioSink {
info!("Using rodio sink");
let mut rodio_device = rodio::default_output_device().expect("no output device available");
if device.is_some() {
let device_name = device.unwrap();
if device_name == "?".to_string() {
list_outputs();
exit(0)
}
let mut found = false;
for d in rodio::output_devices() {
if d.name() == device_name {
rodio_device = d;
found = true;
break;
}
}
if !found {
println!("No output sink matching '{}' found.", device_name);
exit(0)
}
}
let sink = rodio::Sink::new(&rodio_device);
RodioSink {
rodio_sink: sink,
}
}
}
impl Sink for RodioSink {
fn start(&mut self) -> io::Result<()> {
// More similar to an "unpause" than "play". Doesn't undo "stop".
// self.rodio_sink.play();
2019-03-20 13:24:03 +00:00
Ok(())
}
fn stop(&mut self) -> io::Result<()> {
// This will immediately stop playback, but the sink is then unusable.
// We just have to let the current buffer play till the end.
// self.rodio_sink.stop();
2019-03-20 13:24:03 +00:00
Ok(())
}
fn write(&mut self, data: &[i16]) -> io::Result<()> {
let source = rodio::buffer::SamplesBuffer::new(2, 44100, data);
self.rodio_sink.append(source);
// Chunk sizes seem to be about 256 to 3000 ish items long.
// Assuming they're on average 1628 then a half second buffer is:
// 44100 elements --> about 27 chunks
while self.rodio_sink.len() > 26 {
// sleep and wait for rodio to drain a bit
thread::sleep(time::Duration::from_millis(10));
}
2019-03-20 13:24:03 +00:00
Ok(())
}
}