From fcc41f8148ae298eb559dfedd44b1fe6c1b3892a Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Sun, 28 Nov 2021 12:08:50 +0100 Subject: Rework Balance/Volume Settings to use the same generic struct. This is unfinished. The serialize/deserialize methods currently just return errors. --- pulse/src/config.rs | 118 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 23 deletions(-) diff --git a/pulse/src/config.rs b/pulse/src/config.rs index efe5803..3ead0ce 100644 --- a/pulse/src/config.rs +++ b/pulse/src/config.rs @@ -1,11 +1,14 @@ -use serde::{Serialize,Deserialize}; +use serde::{Serialize,Deserialize,Serializer,Deserializer}; use std::collections::BTreeMap; use swaystatus_plugin::*; +use std::ops::{Add, Sub}; +use std::str::FromStr; +use std::num::{ParseIntError,IntErrorKind}; #[derive(Serialize, Deserialize)] #[serde(tag = "Sink")] -pub enum Sink { +pub(crate) enum Sink { Default, Specific { sink_name : String @@ -14,45 +17,32 @@ pub enum Sink { #[derive(Serialize, Deserialize)] #[serde(tag = "Format")] -pub enum Volume { +enum FormatableVolume { Off, Numeric { label : String }, Binned { label: String, - bin_symbol_map : BTreeMap + bin_symbol_map : BTreeMap,String> } } -#[derive(Serialize, Deserialize)] -#[serde(tag = "Format")] -pub enum Balance { - Off, - Numeric { - label : String - }, - Binned { - label :String, - bin_symbol_map : BTreeMap - } -} - - #[derive(Serialize, Deserialize)] #[serde(rename_all = "PascalCase", default)] pub struct PulseVolumeConfig { - pub sink : Sink, - pub volume : Volume, - pub balance : Balance + pub(crate) sink : Sink, + volume : FormatableVolume, + balance : FormatableVolume } impl Default for PulseVolumeConfig { fn default() -> Self { PulseVolumeConfig { sink : Sink::Default, - volume : Volume::Numeric { label : String::new()}, - balance : Balance::Off + volume : FormatableVolume::Numeric { label : String::new() }, + //volume : FormatableVolume::Binned { label : String::new(), bin_symbol_map : {let mut a = BTreeMap::new(); a.insert(4,String::from("Blah")); a}}, + balance : FormatableVolume::Off } } } @@ -64,3 +54,85 @@ impl SwayStatusModuleInstance for PulseVolumeConfig { } } + +///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 +///for a few lines of code sounds a bit excessive... +trait VolumeKeyBackingTypeFromFloat { + fn round_from_float(float : f32) -> Self; +} +macro_rules! impl_volume_key_backing_type_from_float_for { + ($( $t:ty ), *) => { + $( impl VolumeKeyBackingTypeFromFloat for $t { + fn round_from_float(float : f32) -> $t { float.round() as $t } + } )* + } +} + +///Metadata description for VolumeKeys. Basically a workaround for Rust's lack of +///constant generics. Having Ord as supertrait is because of the BTreeMap's trait +///bounds. +trait VolumeKeyBackingTypeMetadata : Ord { + type BackingType + : Ord + + Add + + Sub + + Into + + VolumeKeyBackingTypeFromFloat; + const MIN : Self::BackingType; + const MAX : Self::BackingType; + const FLOAT_MIN : f32; + const FLOAT_MAX : f32; +} +#[derive(PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +struct VolumeKeyVolume; +#[derive(PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +struct VolumeKeyBalance; + +impl VolumeKeyBackingTypeMetadata for VolumeKeyVolume{ + type BackingType = u8; + const MIN : Self::BackingType = 0; + const MAX : Self::BackingType = 100; + const FLOAT_MIN : f32 = 0.0; + const FLOAT_MAX : f32 = 1.0; +} + +impl VolumeKeyBackingTypeMetadata for VolumeKeyBalance{ + type BackingType = i8; + const MIN : Self::BackingType = -100; + const MAX : Self::BackingType = 100; + const FLOAT_MIN : f32 = -1.0; + const FLOAT_MAX : f32 = 1.0; +} + +impl_volume_key_backing_type_from_float_for!(i8, u8); + +#[derive(Debug,PartialEq,Eq,PartialOrd,Ord)] +struct VolumeKey(BackingType::BackingType); + +impl VolumeKey { + 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 result = BackingType::BackingType::round_from_float(offset) + BackingType::MIN; + Self(result) + } +} + +impl Serialize for VolumeKey { + fn serialize(&self, serializer: S) -> Result + where S : Serializer + { + Err(serde::ser::Error::custom("Unimplemented")) + } +} +impl<'de, Metadata : VolumeKeyBackingTypeMetadata> Deserialize<'de> for VolumeKey { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + Err(serde::de::Error::custom("Unimplemented")) + } +} -- cgit v1.2.3