feat: microphone muting
This commit is contained in:
+4
-1
@@ -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 = []
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
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.
|
||||
|
||||
Mutes *all* input sources (not just the default one) so virtual
|
||||
sources like EasyEffects and their underlying hardware mics are
|
||||
silenced together.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.audio = Audio()
|
||||
|
||||
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)
|
||||
|
||||
# `changed` fires for any stream change (incl. mute state) and
|
||||
# `microphone-changed` when the default source switches.
|
||||
self.audio.connect("changed", self.update_icon)
|
||||
self.audio.connect("microphone-changed", self.update_icon)
|
||||
self.update_icon()
|
||||
|
||||
def on_clicked(self, *_):
|
||||
mics = self.audio.microphones or []
|
||||
if not mics and self.audio.microphone:
|
||||
mics = [self.audio.microphone]
|
||||
if not mics:
|
||||
return
|
||||
# if anything is live -> mute everything; else unmute everything
|
||||
mute = self._any_unmuted(mics)
|
||||
for mic in mics:
|
||||
mic.muted = mute
|
||||
self.update_icon()
|
||||
|
||||
def _any_unmuted(self, mics) -> bool:
|
||||
return any(not mic.muted for mic in mics)
|
||||
|
||||
def update_icon(self, *_):
|
||||
mics = self.audio.microphones or []
|
||||
if not mics and self.audio.microphone:
|
||||
mics = [self.audio.microphone]
|
||||
if not mics:
|
||||
self.set_visible(False)
|
||||
return
|
||||
self.set_visible(True)
|
||||
if self._any_unmuted(mics):
|
||||
self.icon_label.set_label(MIC_ICON)
|
||||
self.icon_label.remove_style_class("muted")
|
||||
else:
|
||||
self.icon_label.set_label(MIC_MUTED_ICON)
|
||||
self.icon_label.add_style_class("muted")
|
||||
@@ -53,6 +53,20 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#microphone-icon {
|
||||
color: var(--foreground);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#microphone-button {
|
||||
min-width: 28px;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
#microphone-icon.muted {
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
#cpu-progress-bar,
|
||||
#ram-progress-bar,
|
||||
#volume-progress-bar {
|
||||
|
||||
Reference in New Issue
Block a user