diff options
| author | Andreas Grois <andi@grois.info> | 2021-11-28 23:08:50 +0100 |
|---|---|---|
| committer | Andreas Grois <andi@grois.info> | 2021-11-28 23:09:09 +0100 |
| commit | a0457a3d4dcbf1060dbad850a915a3466575f665 (patch) | |
| tree | 644b1d789f85a6976812ef04ca71f4819ec6fbfb /pulse | |
| parent | ccfe9a7893c54c65246963ee27be31a13d3c2e92 (diff) | |
Implement working binning and sorting for pulse audio.
Diffstat (limited to 'pulse')
| -rw-r--r-- | pulse/src/config.rs | 90 | ||||
| -rw-r--r-- | pulse/src/runnable/mod.rs | 22 |
2 files changed, 94 insertions, 18 deletions
diff --git a/pulse/src/config.rs b/pulse/src/config.rs index a9c219c..740190d 100644 --- a/pulse/src/config.rs +++ b/pulse/src/config.rs @@ -13,6 +13,7 @@ use std::num::{ParseIntError,IntErrorKind}; pub(crate) enum Sink { Default, Specific { + #[serde(rename = "SinkName")] sink_name : String } } @@ -36,19 +37,68 @@ enum FormatableVolume<KeyTypeMetadata : VolumeKeyBackingTypeMetadata> { } #[derive(Serialize, Deserialize)] +enum FieldSorting { + MuteVolumeBalance, + MuteBalanceVolume, + VolumeMuteBalance, + VolumeBalanceMute, + BalanceMuteVolume, + BalanceVolumeMute, +} + +#[derive(Serialize, Deserialize)] +#[serde(tag = "Format")] +enum FormatableMute { + Off, + Symbol { + label : String, + mute_symbol : String, + unmute_symbol : String + } +} + +#[derive(Serialize, Deserialize)] #[serde(rename_all = "PascalCase", default)] pub struct PulseVolumeConfig { + sorting : FieldSorting, pub(crate) sink : Sink, volume : FormatableVolume<VolumeKeyVolume>, - balance : FormatableVolume<VolumeKeyBalance> + balance : FormatableVolume<VolumeKeyBalance>, + mute : FormatableMute, } impl PulseVolumeConfig { - fn format_volume(&self, value : f32) -> Result<Option<String>,FormattingError> { - self.volume.format_float(value) - } - fn format_balance(&self, value : f32) -> Result<Option<String>,FormattingError> { - self.balance.format_float(value) + pub(crate) fn format_volume(&self, volume : f32, balance : f32, mute : bool) -> Result<String,FormattingError> { + let formatted_volume = self.volume.format_float(volume); + let formatted_balance = self.balance.format_float(balance); + let have_errors_occured = formatted_volume.is_err() || formatted_balance.is_err(); + let formatted_mute_option = self.mute.format_mute(mute); + let formatted_mute = formatted_mute_option.as_deref().unwrap_or(""); + let get_numeric_fallback = |x| -> Option<String> { + match x { + FormattingError::EmptyMap{ numeric_fallback } => { Some(numeric_fallback) } + } + }; + let formatted_volume = formatted_volume.unwrap_or_else(get_numeric_fallback); + let formatted_volume = formatted_volume.as_deref().unwrap_or(""); + let formatted_balance = formatted_balance.unwrap_or_else(get_numeric_fallback); + let formatted_balance = formatted_balance.as_deref().unwrap_or(""); + + let sorted_values = match self.sorting { + FieldSorting::BalanceMuteVolume => {[formatted_balance, formatted_mute, formatted_volume]} + FieldSorting::BalanceVolumeMute => {[formatted_balance, formatted_volume, formatted_mute]} + FieldSorting::MuteBalanceVolume => {[formatted_mute, formatted_balance, formatted_volume]} + FieldSorting::MuteVolumeBalance => {[formatted_mute, formatted_volume, formatted_balance]} + FieldSorting::VolumeBalanceMute => {[formatted_volume, formatted_balance, formatted_mute]} + FieldSorting::VolumeMuteBalance => {[formatted_volume, formatted_mute, formatted_balance]} + }; + let formatted_string = format!("{}{}{}",sorted_values[0], sorted_values[1], sorted_values[2]); + if have_errors_occured { + Err(FormattingError::EmptyMap{ numeric_fallback : formatted_string }) + } + else { + Ok(formatted_string) + } } } @@ -56,9 +106,19 @@ impl Default for PulseVolumeConfig { fn default() -> Self { PulseVolumeConfig { sink : Sink::Default, - //volume : FormatableVolume::Numeric { label : String::new(), digits : 0 }, - volume : FormatableVolume::Binned { label : String::new(), bin_symbol_map : {let mut a = BTreeMap::new(); a.insert(VolumeKey(4),String::from("Blah")); a}}, - balance : FormatableVolume::Off + volume : FormatableVolume::Numeric { label : String::from(" "), digits : 0 }, + balance : FormatableVolume::Binned { + label : String::from(" "), + bin_symbol_map : { + let mut a = BTreeMap::new(); + a.insert(VolumeKey(-100),String::from("|..")); + a.insert(VolumeKey(-10), String::from(".|.")); + a.insert(VolumeKey(10), String::from("..|")); + a + } + }, + mute : FormatableMute::Symbol { label : String::new(), mute_symbol : String::from("🔇"), unmute_symbol : String::from(" ") }, + sorting : FieldSorting::MuteVolumeBalance, } } } @@ -114,6 +174,14 @@ impl<KeyTypeMetadata : VolumeKeyBackingTypeMetadata> FormatableVolume<KeyTypeMet } } +impl FormatableMute { + fn format_mute(&self, mute : bool) -> Option<String> { + match self { + FormatableMute::Off => { None } + FormatableMute::Symbol{ label, mute_symbol, unmute_symbol} => { Some(format!("{}{}", label, { if mute { mute_symbol } else { unmute_symbol }}))} + } + } +} ///Helper trait for conversion from float to integer backing type for volume binning keys. ///Needed because Rust seems not to offer a trait that indicates "can be rounded from float" ///in the standard library. There are thir-party crates that do this, but using a full crate @@ -177,8 +245,8 @@ impl<BackingType : VolumeKeyBackingTypeMetadata> VolumeKey<BackingType> { fn match_float(float : f32) -> Self { let x = (float - BackingType::FLOAT_MIN) / (BackingType::FLOAT_MAX - BackingType::FLOAT_MIN); let cx = x.clamp(0.0,1.0); - let interval = BackingType::MAX - BackingType::MIN; - let offset = interval.into() * cx; + let interval = BackingType::MAX.into() - BackingType::MIN.into(); + let offset = interval * cx; let result = BackingType::BackingType::round_from_float(offset) + BackingType::MIN; Self(result) } diff --git a/pulse/src/runnable/mod.rs b/pulse/src/runnable/mod.rs index 352a10a..bb2456b 100644 --- a/pulse/src/runnable/mod.rs +++ b/pulse/src/runnable/mod.rs @@ -31,12 +31,20 @@ impl<'p : 's, 's> PulseVolumeRunnable<'p> { self.to_main.send_update(Err(PluginError::PrintToStdErr(err.to_string()))).expect("Tried to tell main thread that an error occured. Main thread isn't listening any more."); } - fn send_updated_volume_to_main(&self, volume : &pulse::Volume) -> Result<(),PluginCommunicationError> { - self.to_main.send_update(Ok(self.format_volume(volume))) - } - - fn format_volume(&self, volume : &pulse::Volume) -> String { - format!("{}",volume.volume) + fn format_and_send_updated_volume_to_main(&self, volume : &pulse::Volume) -> Result<(),PluginCommunicationError> { + let formatted_volume = self.config.format_volume(volume.volume, volume.balance, volume.muted); + match formatted_volume { + Ok(msg) => { self.to_main.send_update(Ok(msg)) } + Err(e) => { + let full_message = e.to_string(); + match e { + FormattingError::EmptyMap{ numeric_fallback } => { + self.to_main.send_update(Err(PluginError::ShowInsteadOfText(numeric_fallback)))?; + self.to_main.send_update(Err(PluginError::PrintToStdErr(full_message))) + } + } + } + } } } @@ -140,7 +148,7 @@ impl<'p> SwayStatusModuleRunnable for PulseVolumeRunnable<'p> { } if volume.is_some() && volume != curr_volume { curr_volume = volume; - self.send_updated_volume_to_main(curr_volume.as_ref().unwrap()).expect("Tried to inform main thread about volume update. Main thread isn't listening."); + self.format_and_send_updated_volume_to_main(curr_volume.as_ref().unwrap()).expect("Tried to inform main thread about volume update. Main thread isn't listening."); } match self.from_main.try_recv() { Ok(x) => match x { |
