mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Fix --device
argument to various backends (#938)
Fix `--device` argument to various backends
This commit is contained in:
parent
a605444d18
commit
1e54913523
5 changed files with 42 additions and 57 deletions
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- [contrib] Hardened security of the systemd service units
|
||||
- [main] Verbose logging mode (`-v`, `--verbose`) now logs all parsed environment variables and command line arguments (credentials are redacted).
|
||||
- [playback] `Sink`: `write()` now receives ownership of the packet (breaking).
|
||||
- [playback] `pipe`: create file if it doesn't already exist
|
||||
|
||||
### Added
|
||||
- [cache] Add `disable-credential-cache` flag (breaking).
|
||||
|
|
|
@ -4,19 +4,27 @@ use crate::convert::Converter;
|
|||
use crate::decoder::AudioPacket;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{self, Write};
|
||||
use std::process::exit;
|
||||
|
||||
pub struct StdoutSink {
|
||||
output: Option<Box<dyn Write>>,
|
||||
path: Option<String>,
|
||||
file: Option<String>,
|
||||
format: AudioFormat,
|
||||
}
|
||||
|
||||
impl Open for StdoutSink {
|
||||
fn open(path: Option<String>, format: AudioFormat) -> Self {
|
||||
fn open(file: Option<String>, format: AudioFormat) -> Self {
|
||||
if let Some("?") = file.as_deref() {
|
||||
info!("Usage:");
|
||||
println!(" Output to stdout: --backend pipe");
|
||||
println!(" Output to file: --backend pipe --device {{filename}}");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
info!("Using pipe sink with format: {:?}", format);
|
||||
Self {
|
||||
output: None,
|
||||
path,
|
||||
file,
|
||||
format,
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +33,12 @@ impl Open for StdoutSink {
|
|||
impl Sink for StdoutSink {
|
||||
fn start(&mut self) -> SinkResult<()> {
|
||||
if self.output.is_none() {
|
||||
let output: Box<dyn Write> = match self.path.as_deref() {
|
||||
Some(path) => {
|
||||
let output: Box<dyn Write> = match self.file.as_deref() {
|
||||
Some(file) => {
|
||||
let open_op = OpenOptions::new()
|
||||
.write(true)
|
||||
.open(path)
|
||||
.create(true)
|
||||
.open(file)
|
||||
.map_err(|e| SinkError::ConnectionRefused(e.to_string()))?;
|
||||
Box::new(open_op)
|
||||
}
|
||||
|
|
|
@ -135,21 +135,18 @@ fn create_sink(
|
|||
host: &cpal::Host,
|
||||
device: Option<String>,
|
||||
) -> Result<(rodio::Sink, rodio::OutputStream), RodioError> {
|
||||
let rodio_device = match device {
|
||||
Some(ask) if &ask == "?" => {
|
||||
let exit_code = match list_outputs(host) {
|
||||
Ok(()) => 0,
|
||||
let rodio_device = match device.as_deref() {
|
||||
Some("?") => match list_outputs(host) {
|
||||
Ok(()) => exit(0),
|
||||
Err(e) => {
|
||||
error!("{}", e);
|
||||
1
|
||||
}
|
||||
};
|
||||
exit(exit_code)
|
||||
exit(1);
|
||||
}
|
||||
},
|
||||
Some(device_name) => {
|
||||
host.output_devices()?
|
||||
.find(|d| d.name().ok().map_or(false, |name| name == device_name)) // Ignore devices for which getting name fails
|
||||
.ok_or(RodioError::DeviceNotAvailable(device_name))?
|
||||
.ok_or_else(|| RodioError::DeviceNotAvailable(device_name.to_string()))?
|
||||
}
|
||||
None => host
|
||||
.default_output_device()
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::decoder::AudioPacket;
|
|||
use shell_words::split;
|
||||
|
||||
use std::io::Write;
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::process::{exit, Child, Command, Stdio};
|
||||
|
||||
pub struct SubprocessSink {
|
||||
shell_command: String,
|
||||
|
@ -15,17 +15,25 @@ pub struct SubprocessSink {
|
|||
|
||||
impl Open for SubprocessSink {
|
||||
fn open(shell_command: Option<String>, format: AudioFormat) -> Self {
|
||||
let shell_command = match shell_command.as_deref() {
|
||||
Some("?") => {
|
||||
info!("Usage: --backend subprocess --device {{shell_command}}");
|
||||
exit(0);
|
||||
}
|
||||
Some(cmd) => cmd.to_owned(),
|
||||
None => {
|
||||
error!("subprocess sink requires specifying a shell command");
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
info!("Using subprocess sink with format: {:?}", format);
|
||||
|
||||
if let Some(shell_command) = shell_command {
|
||||
SubprocessSink {
|
||||
Self {
|
||||
shell_command,
|
||||
child: None,
|
||||
format,
|
||||
}
|
||||
} else {
|
||||
panic!("subprocess sink requires specifying a shell command");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
30
src/main.rs
30
src/main.rs
|
@ -748,18 +748,7 @@ fn get_setup() -> Setup {
|
|||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
#[cfg(any(
|
||||
feature = "alsa-backend",
|
||||
feature = "rodio-backend",
|
||||
feature = "portaudio-backend"
|
||||
))]
|
||||
let device = opt_str(DEVICE);
|
||||
|
||||
#[cfg(any(
|
||||
feature = "alsa-backend",
|
||||
feature = "rodio-backend",
|
||||
feature = "portaudio-backend"
|
||||
))]
|
||||
if let Some(ref value) = device {
|
||||
if value == "?" {
|
||||
backend(device, format);
|
||||
|
@ -769,25 +758,6 @@ fn get_setup() -> Setup {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "alsa-backend",
|
||||
feature = "rodio-backend",
|
||||
feature = "portaudio-backend"
|
||||
)))]
|
||||
let device: Option<String> = None;
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "alsa-backend",
|
||||
feature = "rodio-backend",
|
||||
feature = "portaudio-backend"
|
||||
)))]
|
||||
if opt_present(DEVICE) {
|
||||
warn!(
|
||||
"The `--{}` / `-{}` option is not supported by the included audio backend(s), and has no effect.",
|
||||
DEVICE, DEVICE_SHORT,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "alsa-backend")]
|
||||
let mixer_type = opt_str(MIXER_TYPE);
|
||||
#[cfg(not(feature = "alsa-backend"))]
|
||||
|
|
Loading…
Reference in a new issue