Merge pull request #821 from roderickvd/fix-alsa-mixer

Fix Alsa mixer and rename options
This commit is contained in:
Roderick van Domburg 2021-08-31 20:05:09 +02:00 committed by GitHub
commit 1540636ccc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 41 deletions

View file

@ -29,11 +29,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Deprecated ### Deprecated
- [connect] The `discovery` module was deprecated in favor of the `librespot-discovery` crate - [connect] The `discovery` module was deprecated in favor of the `librespot-discovery` crate
- [playback] `alsamixer`: renamed `mixer-card` to `alsa-mixer-device`
- [playback] `alsamixer`: renamed `mixer-name` to `alsa-mixer-control`
- [playback] `alsamixer`: renamed `mixer-index` to `alsa-mixer-index`
### Removed ### Removed
- [connect] Removed no-op mixer started/stopped logic (breaking) - [connect] Removed no-op mixer started/stopped logic (breaking)
- [playback] Removed `with-vorbis` and `with-tremor` features - [playback] Removed `with-vorbis` and `with-tremor` features
- [playback] `alsamixer`: removed `--mixer-linear-volume` option; use `--volume-ctrl linear` instead - [playback] `alsamixer`: removed `--mixer-linear-volume` option, now that `--volume-ctrl {linear|log}` work as expected on Alsa
### Fixed ### Fixed
- [connect] Fix step size on volume up/down events - [connect] Fix step size on volume up/down events

View file

@ -31,14 +31,14 @@ const ZERO_DB: MilliBel = MilliBel(0);
impl Mixer for AlsaMixer { impl Mixer for AlsaMixer {
fn open(config: MixerConfig) -> Self { fn open(config: MixerConfig) -> Self {
info!( info!(
"Mixing with alsa and volume control: {:?} for card: {} with mixer control: {},{}", "Mixing with Alsa and volume control: {:?} for device: {} with mixer control: {},{}",
config.volume_ctrl, config.card, config.control, config.index, config.volume_ctrl, config.device, config.control, config.index,
); );
let mut config = config; // clone let mut config = config; // clone
let mixer = let mixer =
alsa::mixer::Mixer::new(&config.card, false).expect("Could not open Alsa mixer"); alsa::mixer::Mixer::new(&config.device, false).expect("Could not open Alsa mixer");
let simple_element = mixer let simple_element = mixer
.find_selem(&SelemId::new(&config.control, config.index)) .find_selem(&SelemId::new(&config.control, config.index))
.expect("Could not find Alsa mixer control"); .expect("Could not find Alsa mixer control");
@ -56,8 +56,8 @@ impl Mixer for AlsaMixer {
// Query dB volume range -- note that Alsa exposes a different // Query dB volume range -- note that Alsa exposes a different
// API for hardware and software mixers // API for hardware and software mixers
let (min_millibel, max_millibel) = if is_softvol { let (min_millibel, max_millibel) = if is_softvol {
let control = let control = Ctl::new(&config.device, false)
Ctl::new(&config.card, false).expect("Could not open Alsa softvol with that card"); .expect("Could not open Alsa softvol with that device");
let mut element_id = ElemId::new(ElemIface::Mixer); let mut element_id = ElemId::new(ElemIface::Mixer);
element_id.set_name( element_id.set_name(
&CString::new(config.control.as_str()) &CString::new(config.control.as_str())
@ -144,7 +144,7 @@ impl Mixer for AlsaMixer {
fn volume(&self) -> u16 { fn volume(&self) -> u16 {
let mixer = let mixer =
alsa::mixer::Mixer::new(&self.config.card, false).expect("Could not open Alsa mixer"); alsa::mixer::Mixer::new(&self.config.device, false).expect("Could not open Alsa mixer");
let simple_element = mixer let simple_element = mixer
.find_selem(&SelemId::new(&self.config.control, self.config.index)) .find_selem(&SelemId::new(&self.config.control, self.config.index))
.expect("Could not find Alsa mixer control"); .expect("Could not find Alsa mixer control");
@ -184,7 +184,7 @@ impl Mixer for AlsaMixer {
fn set_volume(&self, volume: u16) { fn set_volume(&self, volume: u16) {
let mixer = let mixer =
alsa::mixer::Mixer::new(&self.config.card, false).expect("Could not open Alsa mixer"); alsa::mixer::Mixer::new(&self.config.device, false).expect("Could not open Alsa mixer");
let simple_element = mixer let simple_element = mixer
.find_selem(&SelemId::new(&self.config.control, self.config.index)) .find_selem(&SelemId::new(&self.config.control, self.config.index))
.expect("Could not find Alsa mixer control"); .expect("Could not find Alsa mixer control");
@ -249,7 +249,7 @@ impl AlsaMixer {
} }
let mixer = let mixer =
alsa::mixer::Mixer::new(&self.config.card, false).expect("Could not open Alsa mixer"); alsa::mixer::Mixer::new(&self.config.device, false).expect("Could not open Alsa mixer");
let simple_element = mixer let simple_element = mixer
.find_selem(&SelemId::new(&self.config.control, self.config.index)) .find_selem(&SelemId::new(&self.config.control, self.config.index))
.expect("Could not find Alsa mixer control"); .expect("Could not find Alsa mixer control");

View file

@ -30,7 +30,7 @@ use self::alsamixer::AlsaMixer;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MixerConfig { pub struct MixerConfig {
pub card: String, pub device: String,
pub control: String, pub control: String,
pub index: u32, pub index: u32,
pub volume_ctrl: VolumeCtrl, pub volume_ctrl: VolumeCtrl,
@ -39,7 +39,7 @@ pub struct MixerConfig {
impl Default for MixerConfig { impl Default for MixerConfig {
fn default() -> MixerConfig { fn default() -> MixerConfig {
MixerConfig { MixerConfig {
card: String::from("default"), device: String::from("default"),
control: String::from("PCM"), control: String::from("PCM"),
index: 0, index: 0,
volume_ctrl: VolumeCtrl::default(), volume_ctrl: VolumeCtrl::default(),

View file

@ -43,7 +43,7 @@ impl Mixer for SoftMixer {
} }
impl SoftMixer { impl SoftMixer {
pub const NAME: &'static str = "softmixer"; pub const NAME: &'static str = "softvol";
} }
struct SoftVolumeApplier { struct SoftVolumeApplier {

View file

@ -205,9 +205,10 @@ fn get_setup(args: &[String]) -> Setup {
const FORMAT: &str = "format"; const FORMAT: &str = "format";
const HELP: &str = "h"; const HELP: &str = "h";
const INITIAL_VOLUME: &str = "initial-volume"; const INITIAL_VOLUME: &str = "initial-volume";
const MIXER_CARD: &str = "mixer-card"; const MIXER_TYPE: &str = "mixer";
const MIXER_INDEX: &str = "mixer-index"; const ALSA_MIXER_DEVICE: &str = "alsa-mixer-device";
const MIXER_NAME: &str = "mixer-name"; const ALSA_MIXER_INDEX: &str = "alsa-mixer-index";
const ALSA_MIXER_CONTROL: &str = "alsa-mixer-control";
const NAME: &str = "name"; const NAME: &str = "name";
const NORMALISATION_ATTACK: &str = "normalisation-attack"; const NORMALISATION_ATTACK: &str = "normalisation-attack";
const NORMALISATION_GAIN_TYPE: &str = "normalisation-gain-type"; const NORMALISATION_GAIN_TYPE: &str = "normalisation-gain-type";
@ -295,24 +296,42 @@ fn get_setup(args: &[String]) -> Setup {
"Specify the dither algorithm to use - [none, gpdf, tpdf, tpdf_hp]. Defaults to 'tpdf' for formats S16, S24, S24_3 and 'none' for other formats.", "Specify the dither algorithm to use - [none, gpdf, tpdf, tpdf_hp]. Defaults to 'tpdf' for formats S16, S24, S24_3 and 'none' for other formats.",
"DITHER", "DITHER",
) )
.optopt("", "mixer", "Mixer to use {alsa|softvol}.", "MIXER") .optopt("m", MIXER_TYPE, "Mixer to use {alsa|softvol}.", "MIXER")
.optopt( .optopt(
"m", "",
MIXER_NAME, "mixer-name", // deprecated
"",
"",
)
.optopt(
"",
ALSA_MIXER_CONTROL,
"Alsa mixer control, e.g. 'PCM' or 'Master'. Defaults to 'PCM'.", "Alsa mixer control, e.g. 'PCM' or 'Master'. Defaults to 'PCM'.",
"NAME", "NAME",
) )
.optopt( .optopt(
"", "",
MIXER_CARD, "mixer-card", // deprecated
"Alsa mixer card, e.g 'hw:0' or similar from `aplay -l`. Defaults to DEVICE if specified, 'default' otherwise.", "",
"MIXER_CARD", "",
) )
.optopt( .optopt(
"", "",
MIXER_INDEX, ALSA_MIXER_DEVICE,
"Alsa mixer device, e.g 'hw:0' or similar from `aplay -l`. Defaults to `--device` if specified, 'default' otherwise.",
"DEVICE",
)
.optopt(
"",
"mixer-index", // deprecated
"",
"",
)
.optopt(
"",
ALSA_MIXER_INDEX,
"Alsa index of the cards mixer. Defaults to 0.", "Alsa index of the cards mixer. Defaults to 0.",
"INDEX", "NUMBER",
) )
.optopt( .optopt(
"", "",
@ -454,28 +473,58 @@ fn get_setup(args: &[String]) -> Setup {
exit(0); exit(0);
} }
let mixer_name = matches.opt_str(MIXER_NAME); let mixer_type = matches.opt_str(MIXER_TYPE);
let mixer = mixer::find(mixer_name.as_deref()).expect("Invalid mixer"); let mixer = mixer::find(mixer_type.as_deref()).expect("Invalid mixer");
let mixer_config = { let mixer_config = {
let card = matches.opt_str(MIXER_CARD).unwrap_or_else(|| { let mixer_device = match matches.opt_str("mixer-card") {
if let Some(ref device_name) = device { Some(card) => {
device_name.to_string() warn!("--mixer-card is deprecated and will be removed in a future release.");
} else { warn!("Please use --alsa-mixer-device instead.");
MixerConfig::default().card card
} }
}); None => matches.opt_str(ALSA_MIXER_DEVICE).unwrap_or_else(|| {
let index = matches if let Some(ref device_name) = device {
.opt_str(MIXER_INDEX) device_name.to_string()
.map(|index| index.parse::<u32>().unwrap()) } else {
.unwrap_or(0); MixerConfig::default().device
let control = matches }
.opt_str(MIXER_NAME) }),
.unwrap_or_else(|| MixerConfig::default().control); };
let index = match matches.opt_str("mixer-index") {
Some(index) => {
warn!("--mixer-index is deprecated and will be removed in a future release.");
warn!("Please use --alsa-mixer-index instead.");
index
.parse::<u32>()
.expect("Mixer index is not a valid number")
}
None => matches
.opt_str(ALSA_MIXER_INDEX)
.map(|index| {
index
.parse::<u32>()
.expect("Alsa mixer index is not a valid number")
})
.unwrap_or(0),
};
let control = match matches.opt_str("mixer-name") {
Some(name) => {
warn!("--mixer-name is deprecated and will be removed in a future release.");
warn!("Please use --alsa-mixer-control instead.");
name
}
None => matches
.opt_str(ALSA_MIXER_CONTROL)
.unwrap_or_else(|| MixerConfig::default().control),
};
let mut volume_range = matches let mut volume_range = matches
.opt_str(VOLUME_RANGE) .opt_str(VOLUME_RANGE)
.map(|range| range.parse::<f64>().unwrap()) .map(|range| range.parse::<f64>().unwrap())
.unwrap_or_else(|| match mixer_name.as_deref() { .unwrap_or_else(|| match mixer_type.as_deref() {
#[cfg(feature = "alsa-backend")] #[cfg(feature = "alsa-backend")]
Some(AlsaMixer::NAME) => 0.0, // let Alsa query the control Some(AlsaMixer::NAME) => 0.0, // let Alsa query the control
_ => VolumeCtrl::DEFAULT_DB_RANGE, _ => VolumeCtrl::DEFAULT_DB_RANGE,
@ -502,7 +551,7 @@ fn get_setup(args: &[String]) -> Setup {
}); });
MixerConfig { MixerConfig {
card, device: mixer_device,
control, control,
index, index,
volume_ctrl, volume_ctrl,
@ -563,7 +612,7 @@ fn get_setup(args: &[String]) -> Setup {
} }
(volume as f32 / 100.0 * VolumeCtrl::MAX_VOLUME as f32) as u16 (volume as f32 / 100.0 * VolumeCtrl::MAX_VOLUME as f32) as u16
}) })
.or_else(|| match mixer_name.as_deref() { .or_else(|| match mixer_type.as_deref() {
#[cfg(feature = "alsa-backend")] #[cfg(feature = "alsa-backend")]
Some(AlsaMixer::NAME) => None, Some(AlsaMixer::NAME) => None,
_ => cache.as_ref().and_then(Cache::volume), _ => cache.as_ref().and_then(Cache::volume),