117 lines
4.1 KiB
Python
117 lines
4.1 KiB
Python
from fabric.utils import GLib
|
|
from fabric.widgets.image import Image
|
|
from fabric.widgets.label import Label
|
|
from fabric.widgets.wayland import WaylandWindow as Window
|
|
|
|
from modules.osd.components.base import BaseOSDContainer
|
|
from services import Audio
|
|
|
|
|
|
class MicrophoneOSDContainer(BaseOSDContainer):
|
|
def __init__(self, window: Window, **kwargs):
|
|
super().__init__(window, **kwargs)
|
|
self.audio = Audio(controller_name="fabric-osd-microphone")
|
|
self._last_muted = None
|
|
self._connected_mics = set()
|
|
self._setup_specific_components()
|
|
self._connect_specific_signals()
|
|
|
|
def _setup_specific_components(self):
|
|
self.icon = Image(
|
|
icon_name="microphone-sensitivity-muted-symbolic", icon_size=26
|
|
)
|
|
self.label = Label()
|
|
|
|
self.update_icon(True) # Start with muted state
|
|
self.update_label(True)
|
|
self.children = self.icon, self.label
|
|
|
|
def _connect_specific_signals(self):
|
|
# Connect to audio service changed signal
|
|
self.audio.connect("changed", self._on_audio_changed)
|
|
|
|
# Connect to microphones list changes
|
|
self.audio.connect("notify::microphones", self._on_microphones_ready)
|
|
|
|
# Connect to default microphone changes
|
|
self.audio.connect("notify::microphone", self._on_default_microphone_changed)
|
|
|
|
# Initial connection to all existing microphones
|
|
self._on_microphones_ready()
|
|
|
|
# Defer initialization to allow services to initialize
|
|
GLib.timeout_add(100, self._initialize_state)
|
|
|
|
def _initialize_state(self):
|
|
"""Initialize the microphone mute state after component setup."""
|
|
mic = self.audio.microphone
|
|
if mic:
|
|
is_muted = mic.muted
|
|
self._last_muted = is_muted
|
|
self.update_icon(is_muted)
|
|
self.update_label(is_muted)
|
|
return False
|
|
|
|
def _on_microphones_ready(self, *_):
|
|
"""Called when audio microphones list changes."""
|
|
for mic in self.audio.microphones:
|
|
if mic not in self._connected_mics:
|
|
mic.connect("notify::is-muted", self._on_mute_changed)
|
|
self._connected_mics.add(mic)
|
|
|
|
def _on_default_microphone_changed(self, *_):
|
|
"""Handle default microphone changes."""
|
|
mic = self.audio.microphone
|
|
if mic:
|
|
self._on_mute_changed(mic)
|
|
|
|
def _on_audio_changed(self, *_):
|
|
"""Handle general audio service changes."""
|
|
mic = self.audio.microphone
|
|
if mic:
|
|
self._on_mute_changed(mic)
|
|
|
|
def _on_mute_changed(self, microphone, *_):
|
|
"""Handle microphone mute changes for any microphone."""
|
|
is_muted = microphone.muted
|
|
|
|
# Only update and show if mute state actually changed
|
|
if self._last_muted is None or is_muted != self._last_muted:
|
|
self._last_muted = is_muted
|
|
self.update_icon(is_muted)
|
|
self.update_label(is_muted)
|
|
self.show_microphone_osd()
|
|
|
|
def update_icon(self, is_muted: bool):
|
|
"""Update icon based on mute state."""
|
|
icon_name = (
|
|
"microphone-sensitivity-muted-symbolic"
|
|
if is_muted
|
|
else "microphone-sensitivity-high-symbolic"
|
|
)
|
|
self.icon.set_from_icon_name(icon_name, 26)
|
|
|
|
# Add style classes for styling
|
|
self.icon.style_classes = "mic-muted" if is_muted else "mic-unmuted"
|
|
|
|
def update_label(self, is_muted: bool):
|
|
"""Update label based on mute state."""
|
|
self.label.set_text("Microphone MUTED" if is_muted else "Microphone ON")
|
|
self.label.style_classes = "mic-muted" if is_muted else "mic-unmuted"
|
|
|
|
def show_microphone_osd(self):
|
|
"""Trigger the OSD to show."""
|
|
if self.osd:
|
|
self.osd.show_microphone_osd()
|
|
else:
|
|
self.update()
|
|
|
|
def update(self, *_):
|
|
"""Override to update display before showing OSD."""
|
|
mic = self.audio.microphone
|
|
if mic:
|
|
self._last_muted = mic.muted
|
|
self.update_icon(mic.muted)
|
|
self.update_label(mic.muted)
|
|
super().update()
|