Skip to content

Commit 6bdc0eb

Browse files
authored
spirc: Configurable volume control steps (#1498)
* spirc: Configurable volume control steps Allow the volume control steps to be configured via the `--volume-steps` command line parameter. The author personally found the default volume steps of `1024` to be completely unusable, and is presently using `128` as his configuration. Perhaps consider this as a more reasonable default. Additionally, reduce the delay in volume update from a wopping two seconds to 500ms, again for usability. Also clean up the seemingly unnecessary use of a pattern match on whether or not `--initial-volume` was supplied. * fixup! spirc: Configurable volume control steps * fixup! spirc: Configurable volume control steps * fixup! spirc: Configurable volume control steps * fixup! spirc: Configurable volume control steps * fixup! spirc: Configurable volume control steps * fixup! spirc: Configurable volume control steps --------- Co-authored-by: Scott S. McCoy <[email protected]>
1 parent 59381cc commit 6bdc0eb

File tree

4 files changed

+54
-23
lines changed

4 files changed

+54
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020

2121
### Added
2222

23+
- [connect] Add command line parameter for setting volume steps.
2324
- [connect] Add support for `seek_to`, `repeat_track` and `autoplay` for `Spirc` loading
2425
- [connect] Add `pause` parameter to `Spirc::disconnect` method (breaking)
2526
- [connect] Add `volume_steps` to `ConnectConfig` (breaking)

connect/src/spirc.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ enum SpircCommand {
133133
const CONTEXT_FETCH_THRESHOLD: usize = 2;
134134

135135
// delay to update volume after a certain amount of time, instead on each update request
136-
const VOLUME_UPDATE_DELAY: Duration = Duration::from_secs(2);
136+
const VOLUME_UPDATE_DELAY: Duration = Duration::from_millis(500);
137137
// to reduce updates to remote, we group some request by waiting for a set amount of time
138138
const UPDATE_STATE_DELAY: Duration = Duration::from_millis(200);
139139

@@ -1514,16 +1514,16 @@ impl SpircTask {
15141514
}
15151515

15161516
fn handle_volume_up(&mut self) {
1517-
let volume_steps = self.connect_state.device_info().capabilities.volume_steps as u16;
1517+
let volume = (self.connect_state.device_info().volume as u16)
1518+
.saturating_add(self.connect_state.volume_step_size);
15181519

1519-
let volume = (self.connect_state.device_info().volume as u16).saturating_add(volume_steps);
15201520
self.set_volume(volume);
15211521
}
15221522

15231523
fn handle_volume_down(&mut self) {
1524-
let volume_steps = self.connect_state.device_info().capabilities.volume_steps as u16;
1524+
let volume = (self.connect_state.device_info().volume as u16)
1525+
.saturating_sub(self.connect_state.volume_step_size);
15251526

1526-
let volume = (self.connect_state.device_info().volume as u16).saturating_sub(volume_steps);
15271527
self.set_volume(volume);
15281528
}
15291529

@@ -1639,6 +1639,8 @@ impl SpircTask {
16391639
}
16401640

16411641
fn set_volume(&mut self, volume: u16) {
1642+
debug!("SpircTask::set_volume({})", volume);
1643+
16421644
let old_volume = self.connect_state.device_info().volume;
16431645
let new_volume = volume as u32;
16441646
if old_volume != new_volume || self.mixer.volume() != volume {

connect/src/state.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub struct ConnectConfig {
8787
pub initial_volume: u16,
8888
/// Disables the option to control the volume remotely (default: false)
8989
pub disable_volume: bool,
90-
/// The steps in which the volume is incremented (default: 1024)
90+
/// Number of incremental steps (default: 64)
9191
pub volume_steps: u16,
9292
}
9393

@@ -99,7 +99,7 @@ impl Default for ConnectConfig {
9999
is_group: false,
100100
initial_volume: u16::MAX / 2,
101101
disable_volume: false,
102-
volume_steps: 1024,
102+
volume_steps: 64,
103103
}
104104
}
105105
}
@@ -127,10 +127,15 @@ pub(super) struct ConnectState {
127127

128128
/// a context to keep track of the autoplay context
129129
autoplay_context: Option<StateContext>,
130+
131+
/// The volume adjustment per step when handling individual volume adjustments.
132+
pub volume_step_size: u16,
130133
}
131134

132135
impl ConnectState {
133136
pub fn new(cfg: ConnectConfig, session: &Session) -> Self {
137+
let volume_step_size = u16::MAX.checked_div(cfg.volume_steps).unwrap_or(1024);
138+
134139
let device_info = DeviceInfo {
135140
can_play: true,
136141
volume: cfg.initial_volume.into(),
@@ -195,6 +200,7 @@ impl ConnectState {
195200
}),
196201
..Default::default()
197202
},
203+
volume_step_size,
198204
..Default::default()
199205
};
200206
state.reset();

src/main.rs

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ fn get_setup() -> Setup {
276276
const VERSION: &str = "version";
277277
const VOLUME_CTRL: &str = "volume-ctrl";
278278
const VOLUME_RANGE: &str = "volume-range";
279+
const VOLUME_STEPS: &str = "volume-steps";
279280
const ZEROCONF_PORT: &str = "zeroconf-port";
280281
const ZEROCONF_INTERFACE: &str = "zeroconf-interface";
281282
const ZEROCONF_BACKEND: &str = "zeroconf-backend";
@@ -291,6 +292,7 @@ fn get_setup() -> Setup {
291292
const DEVICE_SHORT: &str = "d";
292293
const VOLUME_CTRL_SHORT: &str = "E";
293294
const VOLUME_RANGE_SHORT: &str = "e";
295+
const VOLUME_STEPS_SHORT: &str = ""; // no short flag
294296
const DEVICE_TYPE_SHORT: &str = "F";
295297
const FORMAT_SHORT: &str = "f";
296298
const DISABLE_AUDIO_CACHE_SHORT: &str = "G";
@@ -371,6 +373,8 @@ fn get_setup() -> Setup {
371373
#[cfg(not(feature = "alsa-backend"))]
372374
const VOLUME_RANGE_DESC: &str =
373375
"Range of the volume control (dB) from 0.0 to 100.0. Defaults to 60.0.";
376+
const VOLUME_STEPS_DESC: &str =
377+
"Number of incremental steps when responding to volume control updates. Defaults to 64.";
374378

375379
let mut opts = getopts::Options::new();
376380
opts.optflag(
@@ -570,6 +574,12 @@ fn get_setup() -> Setup {
570574
VOLUME_RANGE_DESC,
571575
"RANGE",
572576
)
577+
.optopt(
578+
VOLUME_STEPS_SHORT,
579+
VOLUME_STEPS,
580+
VOLUME_STEPS_DESC,
581+
"STEPS",
582+
)
573583
.optopt(
574584
NORMALISATION_METHOD_SHORT,
575585
NORMALISATION_METHOD,
@@ -1457,7 +1467,8 @@ fn get_setup() -> Setup {
14571467
} else {
14581468
cache.as_ref().and_then(Cache::volume)
14591469
}
1460-
});
1470+
})
1471+
.unwrap_or_default();
14611472

14621473
let device_type = opt_str(DEVICE_TYPE)
14631474
.as_deref()
@@ -1480,23 +1491,34 @@ fn get_setup() -> Setup {
14801491
})
14811492
.unwrap_or_default();
14821493

1494+
let volume_steps = opt_str(VOLUME_STEPS)
1495+
.map(|steps| match steps.parse::<u16>() {
1496+
Ok(value) => value,
1497+
_ => {
1498+
let default_value = &connect_default_config.volume_steps.to_string();
1499+
1500+
invalid_error_msg(
1501+
VOLUME_STEPS,
1502+
VOLUME_STEPS_SHORT,
1503+
&steps,
1504+
"a positive whole number <= 65535",
1505+
default_value,
1506+
);
1507+
1508+
exit(1);
1509+
}
1510+
})
1511+
.unwrap_or_else(|| connect_default_config.volume_steps);
1512+
14831513
let is_group = opt_present(DEVICE_IS_GROUP);
14841514

1485-
if let Some(initial_volume) = initial_volume {
1486-
ConnectConfig {
1487-
name,
1488-
device_type,
1489-
is_group,
1490-
initial_volume,
1491-
..Default::default()
1492-
}
1493-
} else {
1494-
ConnectConfig {
1495-
name,
1496-
device_type,
1497-
is_group,
1498-
..Default::default()
1499-
}
1515+
ConnectConfig {
1516+
name,
1517+
device_type,
1518+
is_group,
1519+
initial_volume,
1520+
volume_steps,
1521+
..connect_default_config
15001522
}
15011523
};
15021524

0 commit comments

Comments
 (0)