diff --git a/core/src/config.rs b/core/src/config.rs index 46b22e4..aab65e6 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -122,4 +122,5 @@ pub struct ConnectConfig { pub name: String, pub device_type: DeviceType, pub volume: i32, + pub progressive_volume: bool, } diff --git a/src/main.rs b/src/main.rs index c6208f2..27d91d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,7 +101,8 @@ fn setup(args: &[String]) -> Setup { .optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND") .optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE") .optopt("", "mixer", "Mixer to use", "MIXER") - .optopt("", "initial-volume", "Initial volume in %, once connected (must be from 0 to 100)", "VOLUME"); + .optopt("", "initial-volume", "Initial volume in %, once connected (must be from 0 to 100)", "VOLUME") + .optflag("", "progressive-volume", "Increase volume slowly at low level, faster at high level"); let matches = match opts.parse(&args[1..]) { Ok(m) => m, @@ -159,8 +160,11 @@ fn setup(args: &[String]) -> Setup { // if argument not present use default values (50%) else{ initial_volume = 0x8000 as i32; - } - debug!("Volume \"{}\" !", initial_volume); + } + + let progressive_volume = matches.opt_present("progressive-volume"); + info!("Volume:{}, progressive_volume: {}.", initial_volume, progressive_volume); + let name = matches.opt_str("name").unwrap(); let use_audio_cache = !matches.opt_present("disable-audio-cache"); @@ -209,6 +213,7 @@ fn setup(args: &[String]) -> Setup { name: name, device_type: device_type, volume: initial_volume, + progressive_volume, } }; diff --git a/src/spirc.rs b/src/spirc.rs index 795ba68..f60d7ac 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -17,12 +17,14 @@ use protocol::spirc::{PlayStatus, State, MessageType, Frame, DeviceState}; use mixer::Mixer; use player::Player; +use std; use rand; use rand::Rng; pub struct SpircTask { player: Player, mixer: Box, + progressive_volume:bool, sequence: SeqGenerator, @@ -122,6 +124,33 @@ fn initial_device_state(config: ConnectConfig, volume: u16) -> DeviceState { }) } +fn volume_to_mixer(volume: u16, progressive: bool) -> u16 { + if progressive { + // Some by trail determined volume calculation algorithm. Start increasing slowly, + // then after 50% increase in bigger steps. + let d = volume / (std::u16::MAX / 100); + let mut v:u32 = 0; + let mut incr:u32 = 0; + for i in 0..d { + v += incr; + incr +=3; + if i > 50 { + // Increase faster to reach max volume + incr += 42; + } + } + + // Clip the vulume to the max + if v > std::u16::MAX as u32 {v = std::u16::MAX as u32;} + debug!("volume_to_mixer {} {}", volume, v); + return v as u16; + } else { + debug!("volume_to_mixer {}", volume); + return volume; + } +} + + impl Spirc { pub fn new(config: ConnectConfig, session: Session, player: Player, mixer: Box) -> (Spirc, SpircTask) @@ -144,15 +173,15 @@ impl Spirc { })); let (cmd_tx, cmd_rx) = mpsc::unbounded(); - + let progressive_volume = config.progressive_volume; let volume = config.volume as u16; let device = initial_device_state(config, volume); - mixer.set_volume(volume as u16); + mixer.set_volume(volume_to_mixer(volume as u16, progressive_volume)); let mut task = SpircTask { player: player, mixer: mixer, - + progressive_volume, sequence: SeqGenerator::new(1), ident: ident, @@ -439,9 +468,9 @@ impl SpircTask { } MessageType::kMessageTypeVolume => { - let volume = frame.get_volume(); - self.device.set_volume(volume); - self.mixer.set_volume(frame.get_volume() as u16); + self.device.set_volume(frame.get_volume()); + self.mixer.set_volume( + volume_to_mixer(frame.get_volume() as u16, self.progressive_volume)); self.notify(None); } @@ -536,21 +565,21 @@ impl SpircTask { } fn handle_volume_up(&mut self) { - let mut volume: u32 = self.mixer.volume() as u32 + 4096; + let mut volume: u32 = self.device.get_volume() as u32 + 4096; if volume > 0xFFFF { volume = 0xFFFF; } self.device.set_volume(volume); - self.mixer.set_volume(volume as u16); + self.mixer.set_volume(volume_to_mixer(volume as u16, self.progressive_volume)); } fn handle_volume_down(&mut self) { - let mut volume: i32 = self.mixer.volume() as i32 - 4096; + let mut volume: i32 = self.device.get_volume() as i32 - 4096; if volume < 0 { volume = 0; } self.device.set_volume(volume as u32); - self.mixer.set_volume(volume as u16); + self.mixer.set_volume(volume_to_mixer(volume as u16, self.progressive_volume)); } fn handle_end_of_track(&mut self) {