Added subprocess audio backend

This commit is contained in:
misuzu 2020-01-24 02:35:24 +02:00
parent 01be8e7efa
commit b8617f54a9
5 changed files with 72 additions and 0 deletions

7
Cargo.lock generated
View file

@ -908,6 +908,7 @@ dependencies = [
"portaudio-rs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "portaudio-rs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rodio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rodio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)",
"shell-words 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1725,6 +1726,11 @@ dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "shell-words"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.1.10" version = "0.1.10"
@ -2540,6 +2546,7 @@ dependencies = [
"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
"checksum shannon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ea5b41c9427b56caa7b808cb548a04fb50bb5b9e98590b53f28064ff4174561" "checksum shannon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ea5b41c9427b56caa7b808cb548a04fb50bb5b9e98590b53f28064ff4174561"
"checksum shell-words 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39acde55a154c4cd3ae048ac78cc21c25f3a0145e44111b523279113dce0d94a"
"checksum signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4f61c4d59f3aaa9f61bba6450a9b80ba48362fd7d651689e7a10c453b1f6dc68" "checksum signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4f61c4d59f3aaa9f61bba6450a9b80ba48362fd7d651689e7a10c453b1f6dc68"
"checksum signal-hook-registry 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "913661ac8848a61e39684a3c3e7a7a14a4deec7f54b4976d0641e70dda3939b1" "checksum signal-hook-registry 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "913661ac8848a61e39684a3c3e7a7a14a4deec7f54b4976d0641e70dda3939b1"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"

View file

@ -20,6 +20,7 @@ version = "0.1.0"
futures = "0.1" futures = "0.1"
log = "0.4" log = "0.4"
byteorder = "1.3" byteorder = "1.3"
shell-words = "0.1.0"
alsa = { version = "0.2.1", optional = true } alsa = { version = "0.2.1", optional = true }
portaudio-rs = { version = "0.3.0", optional = true } portaudio-rs = { version = "0.3.0", optional = true }

View file

@ -46,6 +46,9 @@ use self::sdl::SdlSink;
mod pipe; mod pipe;
use self::pipe::StdoutSink; use self::pipe::StdoutSink;
mod subprocess;
use self::subprocess::SubprocessSink;
pub const BACKENDS: &'static [(&'static str, fn(Option<String>) -> Box<dyn Sink>)] = &[ pub const BACKENDS: &'static [(&'static str, fn(Option<String>) -> Box<dyn Sink>)] = &[
#[cfg(feature = "alsa-backend")] #[cfg(feature = "alsa-backend")]
("alsa", mk_sink::<AlsaSink>), ("alsa", mk_sink::<AlsaSink>),
@ -60,6 +63,7 @@ pub const BACKENDS: &'static [(&'static str, fn(Option<String>) -> Box<dyn Sink>
#[cfg(feature = "sdl-backend")] #[cfg(feature = "sdl-backend")]
("sdl", mk_sink::<SdlSink>), ("sdl", mk_sink::<SdlSink>),
("pipe", mk_sink::<StdoutSink>), ("pipe", mk_sink::<StdoutSink>),
("subprocess", mk_sink::<SubprocessSink>),
]; ];
pub fn find(name: Option<String>) -> Option<fn(Option<String>) -> Box<dyn Sink>> { pub fn find(name: Option<String>) -> Option<fn(Option<String>) -> Box<dyn Sink>> {

View file

@ -0,0 +1,59 @@
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(())
}
}

View file

@ -3,6 +3,7 @@ extern crate log;
extern crate byteorder; extern crate byteorder;
extern crate futures; extern crate futures;
extern crate shell_words;
#[cfg(feature = "alsa-backend")] #[cfg(feature = "alsa-backend")]
extern crate alsa; extern crate alsa;