librespot/playback/src/audio_backend/subprocess.rs

61 lines
1.6 KiB
Rust
Raw Normal View History

2020-01-24 00:35:24 +00:00
use super::{Open, Sink};
2021-01-07 06:42:38 +00:00
use crate::audio::AudioPacket;
2020-01-24 00:35:24 +00:00
use shell_words::split;
use std::io::{self, Write};
use std::mem;
use std::process::{Child, Command, Stdio};
use std::slice;
pub struct SubprocessSink {
shell_command: String,
child: Option<Child>,
}
impl Open for SubprocessSink {
fn open(shell_command: Option<String>) -> SubprocessSink {
if let Some(shell_command) = shell_command {
SubprocessSink {
shell_command: shell_command,
child: None,
}
} else {
panic!("subprocess sink requires specifying a shell command");
}
}
}
impl Sink for SubprocessSink {
fn start(&mut self) -> io::Result<()> {
let args = split(&self.shell_command).unwrap();
self.child = Some(
Command::new(&args[0])
.args(&args[1..])
.stdin(Stdio::piped())
.spawn()?,
);
Ok(())
}
fn stop(&mut self) -> io::Result<()> {
if let Some(child) = &mut self.child.take() {
child.kill()?;
child.wait()?;
}
Ok(())
}
2021-01-07 06:42:38 +00:00
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
2020-01-24 00:35:24 +00:00
let data: &[u8] = unsafe {
slice::from_raw_parts(
2021-01-07 06:42:38 +00:00
packet.samples().as_ptr() as *const u8,
packet.samples().len() * mem::size_of::<f32>(),
2020-01-24 00:35:24 +00:00
)
};
if let Some(child) = &mut self.child {
let child_stdin = child.stdin.as_mut().unwrap();
child_stdin.write_all(data)?;
}
Ok(())
}
}