♻️ refactor(osd): improve audio and microphone volume/mute handling with 'changed' signal
This commit is contained in:
1 parent
93a002b475
commit
50d5ba42f5
2 files changed
+169
-164
No files matched your search
+166
-161
@@ -129,16 +129,40 @@ class AudioOSDContainer(Box):
|
||||
|
||||
self.scale.connect("value-changed", self.on_volume_changed)
|
||||
self.audio.connect("notify::speaker", self.on_audio_speaker_changed)
|
||||
|
||||
# Connect to speaker-changed signal directly
|
||||
self.audio.connect("speaker-changed", self.on_speaker_changed)
|
||||
|
||||
# Connect to current speaker if available
|
||||
self._connect_speaker_signals()
|
||||
|
||||
def _connect_speaker_signals(self):
|
||||
"""Connect to speaker's changed signal which should fire on both volume and mute changes"""
|
||||
if self.audio.speaker:
|
||||
self.audio.speaker.connect(
|
||||
"notify::volume", self.on_volume_property_changed
|
||||
# Connect to the main 'changed' signal from AudioStream
|
||||
self.audio.speaker.connect("changed", self.on_speaker_stream_changed)
|
||||
|
||||
def on_speaker_stream_changed(self, *_):
|
||||
"""This should be called whenever the speaker stream changes (volume OR mute)"""
|
||||
if self.audio.speaker:
|
||||
current_volume = (
|
||||
round(self.audio.speaker.volume)
|
||||
if hasattr(self.audio.speaker, "volume")
|
||||
else 0
|
||||
)
|
||||
self.audio.speaker.connect("notify::muted", self.on_mute_changed)
|
||||
current_muted = (
|
||||
self.audio.speaker.muted
|
||||
if hasattr(self.audio.speaker, "muted")
|
||||
else False
|
||||
)
|
||||
|
||||
# Check if either volume or mute state changed
|
||||
if (
|
||||
self.previous_volume != current_volume
|
||||
or self.previous_muted != current_muted
|
||||
):
|
||||
self.previous_volume = current_volume
|
||||
self.previous_muted = current_muted
|
||||
self.update_volume()
|
||||
self.emit("volume-changed")
|
||||
|
||||
def get_svg(self, value):
|
||||
audio_level = 0 if value == 0 else min(int(math.ceil(value / 33)), 3)
|
||||
@@ -146,92 +170,75 @@ class AudioOSDContainer(Box):
|
||||
|
||||
def sync_with_audio(self):
|
||||
if self.audio.speaker:
|
||||
volume = round(self.audio.speaker.volume)
|
||||
volume = (
|
||||
round(self.audio.speaker.volume)
|
||||
if hasattr(self.audio.speaker, "volume")
|
||||
else 0
|
||||
)
|
||||
self.scale.set_value(volume)
|
||||
# self.update_icon(volume)
|
||||
self.previous_volume = volume
|
||||
self.previous_muted = self.audio.speaker.muted
|
||||
self.previous_muted = (
|
||||
self.audio.speaker.muted
|
||||
if hasattr(self.audio.speaker, "muted")
|
||||
else False
|
||||
)
|
||||
|
||||
def on_volume_changed(self, *_):
|
||||
if self.audio.speaker:
|
||||
volume = self.scale.value
|
||||
if 0 <= volume <= 100:
|
||||
self.audio.speaker.set_volume(volume)
|
||||
|
||||
if volume == 0 or (self.audio.speaker and self.audio.speaker.muted):
|
||||
self.scale.add_style_class("muted")
|
||||
volume = 0
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/volume/audio-volume-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
self.on_volume_property_changed()
|
||||
self.scale.remove_style_class("muted")
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/volume/audio-volume-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
# self.icon.remove_style_class("muted")
|
||||
|
||||
self.update_volume_display(volume)
|
||||
self.emit("volume-changed")
|
||||
|
||||
def update_volume_display(self, volume=None):
|
||||
"""Update the visual display based on current volume/mute state"""
|
||||
if not self.audio.speaker:
|
||||
return
|
||||
|
||||
if volume is None:
|
||||
volume = (
|
||||
round(self.audio.speaker.volume)
|
||||
if hasattr(self.audio.speaker, "volume")
|
||||
else 0
|
||||
)
|
||||
|
||||
is_muted = (
|
||||
self.audio.speaker.muted if hasattr(self.audio.speaker, "muted") else False
|
||||
)
|
||||
|
||||
if volume == 0 or is_muted:
|
||||
self.scale.add_style_class("muted")
|
||||
display_volume = 0
|
||||
else:
|
||||
self.scale.remove_style_class("muted")
|
||||
display_volume = volume
|
||||
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/volume/audio-volume-{
|
||||
self.get_svg(display_volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
|
||||
def on_audio_speaker_changed(self, *_):
|
||||
if self.audio.speaker:
|
||||
self.audio.speaker.connect(
|
||||
"notify::volume", self.on_volume_property_changed
|
||||
)
|
||||
self.audio.speaker.connect("notify::muted", self.on_mute_changed)
|
||||
self.update_volume()
|
||||
|
||||
def on_speaker_changed(self, *_):
|
||||
self._connect_speaker_signals()
|
||||
self.update_volume()
|
||||
|
||||
def on_volume_property_changed(self, *_):
|
||||
if self.audio.speaker:
|
||||
current_volume = round(self.audio.speaker.volume)
|
||||
if self.previous_volume is None or current_volume != self.previous_volume:
|
||||
self.previous_volume = current_volume
|
||||
self.update_volume()
|
||||
self.emit("volume-changed")
|
||||
def on_speaker_changed(self, *_):
|
||||
self._connect_speaker_signals()
|
||||
self.update_volume()
|
||||
|
||||
def update_volume(self, *_):
|
||||
if self.audio.speaker and not self.is_hovered():
|
||||
volume = round(self.audio.speaker.volume)
|
||||
volume = (
|
||||
round(self.audio.speaker.volume)
|
||||
if hasattr(self.audio.speaker, "volume")
|
||||
else 0
|
||||
)
|
||||
self.scale.set_value(volume)
|
||||
if volume == 0 or (self.audio.speaker and self.audio.speaker.muted):
|
||||
self.scale.add_style_class("muted")
|
||||
volume = 0
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/volume/audio-volume-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.scale.remove_style_class("muted")
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/volume/audio-volume-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
|
||||
def on_mute_changed(self, *_):
|
||||
if self.audio.speaker:
|
||||
current_muted = self.audio.speaker.muted
|
||||
if self.previous_muted is None or current_muted != self.previous_muted:
|
||||
self.previous_muted = current_muted
|
||||
self.emit("volume-changed")
|
||||
self.update_volume_display(volume)
|
||||
|
||||
|
||||
class MicrophoneOSDContainer(Box):
|
||||
@@ -269,15 +276,40 @@ class MicrophoneOSDContainer(Box):
|
||||
|
||||
self.scale.connect("value-changed", self.on_volume_changed)
|
||||
self.audio.connect("notify::microphone", self.on_audio_microphone_changed)
|
||||
|
||||
# Connect to microphone-changed signal directly
|
||||
self.audio.connect("microphone-changed", self.on_microphone_changed)
|
||||
|
||||
# Connect to current microphone if available
|
||||
self._connect_microphone_signals()
|
||||
|
||||
def _connect_microphone_signals(self):
|
||||
"""Connect to microphone's changed signal which should fire on both volume and mute changes"""
|
||||
if self.audio.microphone:
|
||||
self.audio.microphone.connect(
|
||||
"notify::volume", self.on_volume_property_changed
|
||||
# Connect to the main 'changed' signal from AudioStream
|
||||
self.audio.microphone.connect("changed", self.on_microphone_stream_changed)
|
||||
|
||||
def on_microphone_stream_changed(self, *_):
|
||||
"""This should be called whenever the microphone stream changes (volume OR mute)"""
|
||||
if self.audio.microphone:
|
||||
current_volume = (
|
||||
round(self.audio.microphone.volume)
|
||||
if hasattr(self.audio.microphone, "volume")
|
||||
else 0
|
||||
)
|
||||
self.audio.microphone.connect("notify::muted", self.on_mute_changed)
|
||||
current_muted = (
|
||||
self.audio.microphone.muted
|
||||
if hasattr(self.audio.microphone, "muted")
|
||||
else False
|
||||
)
|
||||
|
||||
# Check if either volume or mute state changed
|
||||
if (
|
||||
self.previous_volume != current_volume
|
||||
or self.previous_muted != current_muted
|
||||
):
|
||||
self.previous_volume = current_volume
|
||||
self.previous_muted = current_muted
|
||||
self.update_volume()
|
||||
self.emit("mic-changed")
|
||||
|
||||
def get_svg(self, value):
|
||||
audio_level = 0 if value == 0 else min(int(math.ceil(value / 33)), 3)
|
||||
@@ -285,105 +317,77 @@ class MicrophoneOSDContainer(Box):
|
||||
|
||||
def sync_with_audio(self):
|
||||
if self.audio.microphone:
|
||||
volume = round(self.audio.microphone.volume)
|
||||
volume = (
|
||||
round(self.audio.microphone.volume)
|
||||
if hasattr(self.audio.microphone, "volume")
|
||||
else 0
|
||||
)
|
||||
self.scale.set_value(volume)
|
||||
self.previous_volume = volume
|
||||
self.previous_muted = self.audio.microphone.muted
|
||||
self.previous_muted = (
|
||||
self.audio.microphone.muted
|
||||
if hasattr(self.audio.microphone, "muted")
|
||||
else False
|
||||
)
|
||||
|
||||
def on_volume_changed(self, *_):
|
||||
if self.audio.microphone:
|
||||
volume = self.scale.value
|
||||
if 0 <= volume <= 100:
|
||||
self.audio.microphone.set_volume(volume)
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
|
||||
if volume == 0 or (
|
||||
self.audio.microphone and self.audio.microphone.muted
|
||||
):
|
||||
volume = 0
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
self.scale.remove_style_class("muted")
|
||||
|
||||
self.update_volume_display(volume)
|
||||
self.emit("mic-changed")
|
||||
|
||||
def update_volume_display(self, volume=None):
|
||||
"""Update the visual display based on current volume/mute state"""
|
||||
if not self.audio.microphone:
|
||||
return
|
||||
|
||||
if volume is None:
|
||||
volume = (
|
||||
round(self.audio.microphone.volume)
|
||||
if hasattr(self.audio.microphone, "volume")
|
||||
else 0
|
||||
)
|
||||
|
||||
is_muted = (
|
||||
self.audio.microphone.muted
|
||||
if hasattr(self.audio.microphone, "muted")
|
||||
else False
|
||||
)
|
||||
|
||||
if volume == 0 or is_muted:
|
||||
self.scale.add_style_class("muted")
|
||||
display_volume = 0
|
||||
else:
|
||||
self.scale.remove_style_class("muted")
|
||||
display_volume = volume
|
||||
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(display_volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
|
||||
def on_audio_microphone_changed(self, *_):
|
||||
if self.audio.microphone:
|
||||
self.audio.microphone.connect(
|
||||
"notify::volume", self.on_volume_property_changed
|
||||
)
|
||||
self.audio.microphone.connect("notify::muted", self.on_mute_changed)
|
||||
self.update_volume()
|
||||
|
||||
def on_microphone_changed(self, *_):
|
||||
self._connect_microphone_signals()
|
||||
self.update_volume()
|
||||
|
||||
def on_volume_property_changed(self, *_):
|
||||
if self.audio.microphone:
|
||||
current_volume = round(self.audio.microphone.volume)
|
||||
if self.previous_volume is None or current_volume != self.previous_volume:
|
||||
self.previous_volume = current_volume
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(current_volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
self.update_volume()
|
||||
self.emit("mic-changed")
|
||||
def on_microphone_changed(self, *_):
|
||||
self._connect_microphone_signals()
|
||||
self.update_volume()
|
||||
|
||||
def update_volume(self, *_):
|
||||
if self.audio.microphone and not self.is_hovered():
|
||||
volume = round(self.audio.microphone.volume)
|
||||
volume = (
|
||||
round(self.audio.microphone.volume)
|
||||
if hasattr(self.audio.microphone, "volume")
|
||||
else 0
|
||||
)
|
||||
self.scale.set_value(volume)
|
||||
|
||||
if volume == 0 or (self.audio.microphone and self.audio.microphone.muted):
|
||||
self.scale.add_style_class("muted")
|
||||
volume = 0
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.osd_window_image.set_from_file(
|
||||
get_relative_path(
|
||||
f"../config/assets/icons/mic/microphone-{
|
||||
self.get_svg(volume)
|
||||
}.svg"
|
||||
)
|
||||
)
|
||||
self.scale.remove_style_class("muted")
|
||||
|
||||
def on_mute_changed(self, *_):
|
||||
if self.audio.microphone:
|
||||
current_muted = self.audio.microphone.muted
|
||||
if self.previous_muted is None or current_muted != self.previous_muted:
|
||||
self.previous_muted = current_muted
|
||||
GLib.idle_add(lambda: self.emit("mic-changed"))
|
||||
self.update_volume_display(volume)
|
||||
|
||||
|
||||
class OSD(Window):
|
||||
@@ -419,6 +423,7 @@ class OSD(Window):
|
||||
|
||||
self.last_activity_time = time.time()
|
||||
|
||||
# Connect to the containers' signals
|
||||
self.audio_container.connect("volume-changed", self.show_audio)
|
||||
self.brightness_container.brightness_service.connect(
|
||||
"screen", self.show_brightness
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
#osd {
|
||||
background-color: alpha(#fff, 0.09);
|
||||
background-color: alpha(#fff, 0.09);
|
||||
padding: 12px 20px;
|
||||
margin: 70px;
|
||||
min-height: 200px;
|
||||
min-height: 200px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
#osd trough highlight {
|
||||
border-radius: 100px 0px 0px 100px;
|
||||
border-radius: 100px;
|
||||
background: var(--primary);
|
||||
transition: all 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user