mirror of
https://github.com/librespot-org/librespot.git
synced 2025-01-07 17:24:04 +00:00
Refactor Volume control, allow for a fixed volume option (#447)
Refactored the old `--linear-volume` flag to a more generic `--volume-ctrl` flag that takes the options of `[linear, log, fixed]`. It defaults as previously to log.
This commit is contained in:
parent
dc99cd73c0
commit
f0b3b2c7e8
3 changed files with 58 additions and 19 deletions
|
@ -14,8 +14,7 @@ use crate::playback::mixer::Mixer;
|
||||||
use crate::playback::player::{Player, PlayerEvent, PlayerEventChannel};
|
use crate::playback::player::{Player, PlayerEvent, PlayerEventChannel};
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
|
use crate::protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
|
||||||
|
use librespot_core::config::{ConnectConfig, VolumeCtrl};
|
||||||
use librespot_core::config::ConnectConfig;
|
|
||||||
use librespot_core::mercury::MercuryError;
|
use librespot_core::mercury::MercuryError;
|
||||||
use librespot_core::session::Session;
|
use librespot_core::session::Session;
|
||||||
use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId, SpotifyIdError};
|
use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId, SpotifyIdError};
|
||||||
|
@ -80,7 +79,7 @@ pub enum SpircCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SpircTaskConfig {
|
struct SpircTaskConfig {
|
||||||
linear_volume: bool,
|
volume_ctrl: VolumeCtrl,
|
||||||
autoplay: bool,
|
autoplay: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +160,11 @@ fn initial_device_state(config: ConnectConfig) -> DeviceState {
|
||||||
msg.set_typ(protocol::spirc::CapabilityType::kVolumeSteps);
|
msg.set_typ(protocol::spirc::CapabilityType::kVolumeSteps);
|
||||||
{
|
{
|
||||||
let repeated = msg.mut_intValue();
|
let repeated = msg.mut_intValue();
|
||||||
repeated.push(64)
|
if let VolumeCtrl::Fixed = config.volume_ctrl {
|
||||||
|
repeated.push(0)
|
||||||
|
} else {
|
||||||
|
repeated.push(64)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
msg
|
msg
|
||||||
};
|
};
|
||||||
|
@ -170,7 +173,7 @@ fn initial_device_state(config: ConnectConfig) -> DeviceState {
|
||||||
msg.set_typ(protocol::spirc::CapabilityType::kSupportsPlaylistV2);
|
msg.set_typ(protocol::spirc::CapabilityType::kSupportsPlaylistV2);
|
||||||
{
|
{
|
||||||
let repeated = msg.mut_intValue();
|
let repeated = msg.mut_intValue();
|
||||||
repeated.push(64)
|
repeated.push(1)
|
||||||
};
|
};
|
||||||
msg
|
msg
|
||||||
};
|
};
|
||||||
|
@ -230,12 +233,14 @@ fn calc_logarithmic_volume(volume: u16) -> u16 {
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
fn volume_to_mixer(volume: u16, linear_volume: bool) -> u16 {
|
fn volume_to_mixer(volume: u16, volume_ctrl: &VolumeCtrl) -> u16 {
|
||||||
if linear_volume {
|
match volume_ctrl {
|
||||||
debug!("linear volume: {}", volume);
|
VolumeCtrl::Linear => {
|
||||||
volume
|
debug!("linear volume: {}", volume);
|
||||||
} else {
|
volume
|
||||||
calc_logarithmic_volume(volume)
|
}
|
||||||
|
VolumeCtrl::Log => calc_logarithmic_volume(volume),
|
||||||
|
VolumeCtrl::Fixed => volume,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,9 +279,10 @@ impl Spirc {
|
||||||
|
|
||||||
let volume = config.volume;
|
let volume = config.volume;
|
||||||
let task_config = SpircTaskConfig {
|
let task_config = SpircTaskConfig {
|
||||||
linear_volume: config.linear_volume,
|
volume_ctrl: config.volume_ctrl.to_owned(),
|
||||||
autoplay: config.autoplay,
|
autoplay: config.autoplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
let device = initial_device_state(config);
|
let device = initial_device_state(config);
|
||||||
|
|
||||||
let player_events = player.get_player_event_channel();
|
let player_events = player.get_player_event_channel();
|
||||||
|
@ -1292,7 +1298,7 @@ impl SpircTask {
|
||||||
fn set_volume(&mut self, volume: u16) {
|
fn set_volume(&mut self, volume: u16) {
|
||||||
self.device.set_volume(volume as u32);
|
self.device.set_volume(volume as u32);
|
||||||
self.mixer
|
self.mixer
|
||||||
.set_volume(volume_to_mixer(volume, self.config.linear_volume));
|
.set_volume(volume_to_mixer(volume, &self.config.volume_ctrl));
|
||||||
if let Some(cache) = self.session.cache() {
|
if let Some(cache) = self.session.cache() {
|
||||||
cache.save_volume(Volume { volume })
|
cache.save_volume(Volume { volume })
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,32 @@ pub struct ConnectConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub device_type: DeviceType,
|
pub device_type: DeviceType,
|
||||||
pub volume: u16,
|
pub volume: u16,
|
||||||
pub linear_volume: bool,
|
pub volume_ctrl: VolumeCtrl,
|
||||||
pub autoplay: bool,
|
pub autoplay: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum VolumeCtrl {
|
||||||
|
Linear,
|
||||||
|
Log,
|
||||||
|
Fixed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for VolumeCtrl {
|
||||||
|
type Err = ();
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
use self::VolumeCtrl::*;
|
||||||
|
match s.to_lowercase().as_ref() {
|
||||||
|
"linear" => Ok(Linear),
|
||||||
|
"log" => Ok(Log),
|
||||||
|
"fixed" => Ok(Fixed),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VolumeCtrl {
|
||||||
|
fn default() -> VolumeCtrl {
|
||||||
|
VolumeCtrl::Linear
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
17
src/main.rs
17
src/main.rs
|
@ -15,7 +15,7 @@ use url::Url;
|
||||||
|
|
||||||
use librespot::core::authentication::{get_credentials, Credentials};
|
use librespot::core::authentication::{get_credentials, Credentials};
|
||||||
use librespot::core::cache::Cache;
|
use librespot::core::cache::Cache;
|
||||||
use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig};
|
use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig, VolumeCtrl};
|
||||||
use librespot::core::session::Session;
|
use librespot::core::session::Session;
|
||||||
use librespot::core::version;
|
use librespot::core::version;
|
||||||
|
|
||||||
|
@ -173,10 +173,11 @@ fn setup(args: &[String]) -> Setup {
|
||||||
"Pregain (dB) applied by volume normalisation",
|
"Pregain (dB) applied by volume normalisation",
|
||||||
"PREGAIN",
|
"PREGAIN",
|
||||||
)
|
)
|
||||||
.optflag(
|
.optopt(
|
||||||
"",
|
"",
|
||||||
"linear-volume",
|
"volume-ctrl",
|
||||||
"increase volume linear instead of logarithmic.",
|
"Volume control type - [linear, log, fixed]. Default is logarithmic",
|
||||||
|
"VOLUME_CTRL"
|
||||||
)
|
)
|
||||||
.optflag(
|
.optflag(
|
||||||
"",
|
"",
|
||||||
|
@ -337,11 +338,17 @@ fn setup(args: &[String]) -> Setup {
|
||||||
.map(|device_type| DeviceType::from_str(device_type).expect("Invalid device type"))
|
.map(|device_type| DeviceType::from_str(device_type).expect("Invalid device type"))
|
||||||
.unwrap_or(DeviceType::default());
|
.unwrap_or(DeviceType::default());
|
||||||
|
|
||||||
|
let volume_ctrl = matches
|
||||||
|
.opt_str("volume-ctrl")
|
||||||
|
.as_ref()
|
||||||
|
.map(|volume_ctrl| VolumeCtrl::from_str(volume_ctrl).expect("Invalid volume ctrl type"))
|
||||||
|
.unwrap_or(VolumeCtrl::default());
|
||||||
|
|
||||||
ConnectConfig {
|
ConnectConfig {
|
||||||
name: name,
|
name: name,
|
||||||
device_type: device_type,
|
device_type: device_type,
|
||||||
volume: initial_volume,
|
volume: initial_volume,
|
||||||
linear_volume: matches.opt_present("linear-volume"),
|
volume_ctrl: volume_ctrl,
|
||||||
autoplay: matches.opt_present("autoplay"),
|
autoplay: matches.opt_present("autoplay"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue