librespot/playback/src/audio_backend/subprocess.rs

64 lines
1.6 KiB
Rust
Raw Normal View History

use super::{Open, Sink, SinkAsBytes};
use crate::config::AudioFormat;
2021-04-13 08:29:34 +00:00
use crate::decoder::AudioPacket;
2020-01-24 00:35:24 +00:00
use shell_words::split;
2021-03-01 02:37:22 +00:00
2020-01-24 00:35:24 +00:00
use std::io::{self, Write};
use std::process::{Child, Command, Stdio};
pub struct SubprocessSink {
shell_command: String,
child: Option<Child>,
format: AudioFormat,
2020-01-24 00:35:24 +00:00
}
impl Open for SubprocessSink {
2021-04-05 21:14:02 +00:00
fn open(shell_command: Option<String>, format: AudioFormat) -> Self {
info!("Using subprocess sink with format: {:?}", format);
2020-01-24 00:35:24 +00:00
if let Some(shell_command) = shell_command {
SubprocessSink {
2021-03-01 02:37:22 +00:00
shell_command,
2020-01-24 00:35:24 +00:00
child: None,
format,
2020-01-24 00:35:24 +00:00
}
} 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(())
}
sink_as_bytes!();
}
impl SinkAsBytes for SubprocessSink {
fn write_bytes(&mut self, data: &[u8]) -> io::Result<()> {
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)?;
child_stdin.flush()?;
2020-01-24 00:35:24 +00:00
}
Ok(())
}
}