feat(audio): update volume sliders when changing volume with media keys
This commit is contained in:
parent
b4d280c477
commit
a630428f08
2 changed files with 134 additions and 33 deletions
|
|
@ -66,10 +66,6 @@ pub struct Audio {
|
|||
current_input: Option<DeviceInfo>,
|
||||
outputs: Vec<DeviceInfo>,
|
||||
inputs: Vec<DeviceInfo>,
|
||||
sink_mute: bool,
|
||||
sink_volume: u32,
|
||||
source_mute: bool,
|
||||
source_volume: u32,
|
||||
pulse_state: PulseState,
|
||||
popup: Option<window::Id>,
|
||||
timeline: Timeline,
|
||||
|
|
@ -84,13 +80,15 @@ impl Audio {
|
|||
}
|
||||
|
||||
fn output_icon_name(&self) -> &'static str {
|
||||
if self.sink_mute || self.sink_volume == 0 {
|
||||
let volume = self.current_output_volume_percent();
|
||||
let mute = self.current_output_mute();
|
||||
if mute || volume == 0. {
|
||||
"audio-volume-muted-symbolic"
|
||||
} else if self.sink_volume < 33 {
|
||||
} else if volume < 33. {
|
||||
"audio-volume-low-symbolic"
|
||||
} else if self.sink_volume < 66 {
|
||||
} else if volume < 66. {
|
||||
"audio-volume-medium-symbolic"
|
||||
} else if self.sink_volume <= 100 {
|
||||
} else if volume <= 100. {
|
||||
"audio-volume-high-symbolic"
|
||||
} else {
|
||||
"audio-volume-overamplified-symbolic"
|
||||
|
|
@ -102,11 +100,13 @@ impl Audio {
|
|||
}
|
||||
|
||||
fn input_icon_name(&self) -> &'static str {
|
||||
if self.source_mute || self.source_volume == 0 {
|
||||
let volume = self.current_input_volume_percent();
|
||||
let mute = self.current_input_mute();
|
||||
if mute || volume == 0. {
|
||||
"microphone-sensitivity-muted-symbolic"
|
||||
} else if self.source_volume < 33 {
|
||||
} else if volume < 33. {
|
||||
"microphone-sensitivity-low-symbolic"
|
||||
} else if self.source_volume < 66 {
|
||||
} else if volume < 66. {
|
||||
"microphone-sensitivity-medium-symbolic"
|
||||
} else {
|
||||
"microphone-sensitivity-high-symbolic"
|
||||
|
|
@ -126,6 +126,8 @@ pub enum Message {
|
|||
Ignore,
|
||||
SetOutputVolume(f64),
|
||||
SetInputVolume(f64),
|
||||
SetOutputMute(bool),
|
||||
SetInputMute(bool),
|
||||
OutputToggle,
|
||||
InputToggle,
|
||||
OutputChanged(String),
|
||||
|
|
@ -253,6 +255,38 @@ impl Audio {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn current_output_volume_percent(&self) -> f64 {
|
||||
volume_to_percent(
|
||||
self.current_output
|
||||
.as_ref()
|
||||
.map(|o| o.volume.avg())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn current_input_volume_percent(&self) -> f64 {
|
||||
volume_to_percent(
|
||||
self.current_input
|
||||
.as_ref()
|
||||
.map(|o| o.volume.avg())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn current_output_mute(&self) -> bool {
|
||||
self.current_output
|
||||
.as_ref()
|
||||
.map(|o| o.mute)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn current_input_mute(&self) -> bool {
|
||||
self.current_input
|
||||
.as_ref()
|
||||
.map(|o| o.mute)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl cosmic::Application for Audio {
|
||||
|
|
@ -358,6 +392,34 @@ impl cosmic::Application for Audio {
|
|||
}
|
||||
}
|
||||
}
|
||||
Message::SetOutputMute(mute) => {
|
||||
if let Some(output) = self.current_output.as_mut() {
|
||||
output.mute = mute;
|
||||
}
|
||||
if let PulseState::Connected(connection) = &mut self.pulse_state {
|
||||
if let Some(device) = &self.current_output {
|
||||
if let Some(name) = &device.name {
|
||||
connection
|
||||
.send(pulse::Message::SetSinkMuteByName(name.clone(), device.mute))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::SetInputMute(mute) => {
|
||||
if let Some(input) = self.current_input.as_mut() {
|
||||
input.mute = mute;
|
||||
}
|
||||
if let PulseState::Connected(connection) = &mut self.pulse_state {
|
||||
if let Some(device) = &self.current_input {
|
||||
if let Some(name) = &device.name {
|
||||
connection.send(pulse::Message::SetSourceMuteByName(
|
||||
name.clone(),
|
||||
device.mute,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::OutputChanged(val) => {
|
||||
if let Some(conn) = self.pulse_state.connection() {
|
||||
if let Some(val) = self.outputs.iter().find(|o| o.name.as_ref() == Some(&val)) {
|
||||
|
|
@ -539,16 +601,28 @@ impl cosmic::Application for Audio {
|
|||
},
|
||||
Message::PulseSub(event) => match event {
|
||||
sub_pulse::Event::SinkVolume(value) => {
|
||||
self.sink_volume = value;
|
||||
self.current_output.as_mut().map(|output| {
|
||||
output
|
||||
.volume
|
||||
.set(output.volume.len(), percent_to_volume(value as f64))
|
||||
});
|
||||
}
|
||||
sub_pulse::Event::SinkMute(value) => {
|
||||
self.sink_mute = value;
|
||||
if let Some(output) = self.current_output.as_mut() {
|
||||
output.mute = value;
|
||||
}
|
||||
}
|
||||
sub_pulse::Event::SourceVolume(value) => {
|
||||
self.source_volume = value;
|
||||
self.current_input.as_mut().map(|input| {
|
||||
input
|
||||
.volume
|
||||
.set(input.volume.len(), percent_to_volume(value as f64))
|
||||
});
|
||||
}
|
||||
sub_pulse::Event::SourceMute(value) => {
|
||||
self.source_mute = value;
|
||||
if let Some(input) = self.current_input.as_mut() {
|
||||
input.mute = value;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -615,18 +689,10 @@ impl cosmic::Application for Audio {
|
|||
|
||||
fn view_window(&self, _id: window::Id) -> Element<Message> {
|
||||
let audio_disabled = matches!(self.pulse_state, PulseState::Disconnected(_));
|
||||
let out_f64 = volume_to_percent(
|
||||
self.current_output
|
||||
.as_ref()
|
||||
.map(|o| o.volume.avg())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
let in_f64 = volume_to_percent(
|
||||
self.current_input
|
||||
.as_ref()
|
||||
.map(|o| o.volume.avg())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
let out_f64 = self.current_output_volume_percent();
|
||||
let in_f64 = self.current_input_volume_percent();
|
||||
let out_mute = self.current_output_mute();
|
||||
let in_mute = self.current_input_mute();
|
||||
|
||||
let mut audio_content = if audio_disabled {
|
||||
column![padded_control(
|
||||
|
|
@ -639,9 +705,15 @@ impl cosmic::Application for Audio {
|
|||
column![
|
||||
padded_control(
|
||||
row![
|
||||
icon::from_name(self.output_icon_name())
|
||||
.size(24)
|
||||
.symbolic(true),
|
||||
button::icon(
|
||||
icon::from_name(self.output_icon_name())
|
||||
.size(24)
|
||||
.symbolic(true),
|
||||
)
|
||||
.style(cosmic::theme::Button::Icon)
|
||||
.icon_size(24)
|
||||
.line_height(24)
|
||||
.on_press(Message::SetOutputMute(!out_mute)),
|
||||
slider(0.0..=100.0, out_f64, Message::SetOutputVolume)
|
||||
.width(Length::FillPortion(5)),
|
||||
text(format!("{}%", out_f64.round()))
|
||||
|
|
@ -654,9 +726,15 @@ impl cosmic::Application for Audio {
|
|||
),
|
||||
padded_control(
|
||||
row![
|
||||
icon::from_name(self.input_icon_name())
|
||||
.size(24)
|
||||
.symbolic(true),
|
||||
button::icon(
|
||||
icon::from_name(self.input_icon_name())
|
||||
.size(24)
|
||||
.symbolic(true),
|
||||
)
|
||||
.style(cosmic::theme::Button::Icon)
|
||||
.icon_size(24)
|
||||
.line_height(24)
|
||||
.on_press(Message::SetInputMute(!in_mute)),
|
||||
slider(0.0..=100.0, in_f64, Message::SetInputVolume)
|
||||
.width(Length::FillPortion(5)),
|
||||
text(format!("{}%", in_f64.round()))
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@ pub enum Message {
|
|||
SetDefaultSource(DeviceInfo),
|
||||
SetSinkVolumeByName(String, ChannelVolumes),
|
||||
SetSourceVolumeByName(String, ChannelVolumes),
|
||||
SetSinkMuteByName(String, bool),
|
||||
SetSourceMuteByName(String, bool),
|
||||
}
|
||||
|
||||
struct PulseHandle {
|
||||
|
|
@ -290,6 +292,27 @@ impl PulseHandle {
|
|||
};
|
||||
server.set_source_volume_by_name(&name, &channel_volumes)
|
||||
}
|
||||
Message::SetSinkMuteByName(name, mute) => {
|
||||
let server = match server.as_mut() {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let op =
|
||||
server.introspector.set_sink_mute_by_name(&name, mute, None);
|
||||
server.wait_for_result(op).ok();
|
||||
}
|
||||
Message::SetSourceMuteByName(name, mute) => {
|
||||
let server = match server.as_mut() {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let op = server
|
||||
.introspector
|
||||
.set_source_mute_by_name(&name, mute, None);
|
||||
server.wait_for_result(op).ok();
|
||||
}
|
||||
Message::UpdateConnection => {
|
||||
tracing::info!(
|
||||
"Updating Connection, server exists: {:?}",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue