librespot/playback/src/audio_backend/subprocess.rs
2020-01-24 02:35:48 +02:00

59 lines
1.5 KiB
Rust

use super::{Open, Sink};
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(())
}
fn write(&mut self, data: &[i16]) -> io::Result<()> {
let data: &[u8] = unsafe {
slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * mem::size_of::<i16>(),
)
};
if let Some(child) = &mut self.child {
let child_stdin = child.stdin.as_mut().unwrap();
child_stdin.write_all(data)?;
}
Ok(())
}
}