feat(src/window/panel/notch/indicators): add MicrophoneIndicator class and integrate into Notch

Add MicrophoneIndicator to monitor microphone presence and mute state, updating UI via show/hide callbacks.
This commit is contained in:
sankalp committed 2026-07-06 20:35:21 +05:45
1 parent 59a80e47ea
commit eaaf9645a2
2 files changed
+97

No files matched your search

+90
View File
@@ -1,3 +1,4 @@
from fabric.audio import Audio
from fabric.utils import GLib, logger
from fabric.widgets.box import Box
from fabric.widgets.centerbox import CenterBox
@@ -286,3 +287,92 @@ class ChargingIndicator(Box):
except Exception as e:
logger.warning(f"[NotchIndicators] charging disconnect: {e}")
super().destroy()
# ── Microphone ─────────────────────────────────────────────────────────────────
class MicrophoneIndicator(Box):
def __init__(self, show_cb, hide_cb, **kwargs):
super().__init__(
name="notch-mic",
orientation="h",
h_expand=True,
v_align="center",
**kwargs,
)
self._show_cb = show_cb
self._hide_cb = hide_cb
self._hide_timer_id = 0
self._audio = Audio()
self._mic_muted = True
self._label = Label(
name="notch-indicator-label",
label="Microphone",
v_align="center",
)
self._state_icon = svg_file(
"notch/mic-off.svg",
size=16,
name="notch-indicator-icon",
v_align="center",
)
self.add(
CenterBox(
orientation="h",
h_expand=True,
start_children=self._label,
end_children=self._state_icon,
)
)
self._audio.connect("notify::microphone", self._on_mic_device_changed)
if self._audio.microphone:
self._connect_mic_signals()
def _connect_mic_signals(self):
if self._audio.microphone:
self._audio.microphone.connect("changed", self._on_mic_stream_changed)
self._sync_state()
def _on_mic_device_changed(self, *_):
self._connect_mic_signals()
self._show_cb(self)
self._schedule_hide()
def _on_mic_stream_changed(self, *_):
self._sync_state()
self._show_cb(self)
self._schedule_hide()
def _sync_state(self):
if self._audio.microphone:
self._mic_muted = self._audio.microphone.muted
self._state_icon.dynamic_file(
"notch/mic-off.svg" if self._mic_muted else "notch/mic-on.svg"
)
def _schedule_hide(self):
if self._hide_timer_id:
GLib.source_remove(self._hide_timer_id)
self._hide_timer_id = GLib.timeout_add(DISPLAY_MS, self._do_hide)
def _do_hide(self):
self._hide_timer_id = 0
self._hide_cb()
return False
def destroy(self):
if self._hide_timer_id:
GLib.source_remove(self._hide_timer_id)
self._hide_timer_id = 0
try:
self._audio.disconnect_by_func(self._on_mic_device_changed)
if self._audio.microphone:
self._audio.microphone.disconnect_by_func(self._on_mic_stream_changed)
except Exception as e:
logger.warning(f"[NotchIndicators] mic disconnect: {e}")
super().destroy()
+7
View File
@@ -9,6 +9,7 @@ from window.panel.notch.player import NotchPlayer
from window.panel.notch.indicators import (
CapsLockIndicator,
KeyboardLayoutIndicator,
MicrophoneIndicator,
NumLockIndicator,
ChargingIndicator,
)
@@ -61,6 +62,10 @@ class Notch(Box):
show_cb=self._show_transient,
hide_cb=self._hide_transient,
)
self.mic_indicator = MicrophoneIndicator(
show_cb=self._show_transient,
hide_cb=self._hide_transient,
)
# Persistent indicator — now also transient (2s), deferred via idle_add
self.charging_indicator = ChargingIndicator(
show_cb=self._show_transient,
@@ -86,6 +91,7 @@ class Notch(Box):
self.kbd_indicator,
self.caps_indicator,
self.num_indicator,
self.mic_indicator,
self.charging_indicator,
],
)
@@ -268,5 +274,6 @@ class Notch(Box):
self.kbd_indicator.destroy()
self.caps_indicator.destroy()
self.num_indicator.destroy()
self.mic_indicator.destroy()
self.charging_indicator.destroy()
super().destroy()