diff --git a/sims/modules/bar.py b/sims/modules/bar.py index cfb4dc5..e161fde 100644 --- a/sims/modules/bar.py +++ b/sims/modules/bar.py @@ -11,6 +11,7 @@ from sims.modules.notmuch import NotmuchWidget from sims.modules.buddy import Buddy from sims.modules.org import OrgDropdown, OrgWidget from sims.modules.screenrec import ScreenrecWidget +from sims.modules.microphone import MicrophoneWidget from fabric.widgets.wayland import WaylandWindow as Window from fabric.system_tray.widgets import SystemTray from sims.widgets.fenster import FensterWorkspaces, FensterActiveWindow @@ -110,11 +111,13 @@ class StatusBar(Window): if org_service is not None: self.org = OrgWidget(service=org_service, dropdown=org_dropdown) + self.microphone = MicrophoneWidget() + self.status_container = Box( name="widgets-container", spacing=4, orientation="h", - children=self.progress_bars_overlay, + children=[self.microphone, self.progress_bars_overlay], ) end_container_children = [] diff --git a/sims/modules/microphone.py b/sims/modules/microphone.py new file mode 100644 index 0000000..fe9bf26 --- /dev/null +++ b/sims/modules/microphone.py @@ -0,0 +1,64 @@ +from fabric.audio.service import Audio +from fabric.widgets.box import Box +from fabric.widgets.button import Button +from fabric.widgets.label import Label + +MIC_ICON = "󰍬" +MIC_MUTED_ICON = "󰍭" + + +class MicrophoneWidget(Box): + """Bar widget showing microphone state; click to toggle mute.""" + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.audio = Audio() + self._mic_connection = None + + self.icon_label = Label( + name="microphone-icon", + label=MIC_ICON, + ) + self.button = Button( + name="microphone-button", + child=self.icon_label, + on_clicked=self.on_clicked, + style="background: transparent; border: none; margin: 0; box-shadow: none;", + ) + self.add(self.button) + + self.audio.connect("notify::microphone", self.on_microphone_changed) + self.on_microphone_changed() + + def on_clicked(self, *_): + mic = self.audio.microphone + if not mic: + return + mic.muted = not mic.muted + + def on_microphone_changed(self, *_): + mic = self.audio.microphone + if not mic: + self.set_visible(False) + return + self.set_visible(True) + if self._mic_connection is not None: + mic_obj, handler = self._mic_connection + try: + mic_obj.disconnect(handler) + except Exception: + pass + handler_id = mic.connect("notify::is-muted", self.update_icon) + self._mic_connection = (mic, handler_id) + self.update_icon() + + def update_icon(self, *_): + mic = self.audio.microphone + if not mic: + return + if mic.muted: + self.icon_label.set_label(MIC_MUTED_ICON) + self.icon_label.add_style_class("muted") + else: + self.icon_label.set_label(MIC_ICON) + self.icon_label.remove_style_class("muted") diff --git a/sims/styles/bar.css b/sims/styles/bar.css index b0d19cf..779713e 100644 --- a/sims/styles/bar.css +++ b/sims/styles/bar.css @@ -53,6 +53,20 @@ font-weight: bold; } +#microphone-icon { + color: var(--foreground); + font-size: 16px; +} + +#microphone-button { + min-width: 24px; + padding: 0 4px; +} + +#microphone-icon.muted { + color: var(--red); +} + #cpu-progress-bar, #ram-progress-bar, #volume-progress-bar {