linux observer
1# SPDX-License-Identifier: AGPL-3.0-only
2# Copyright (c) 2026 sol pbc
3
4"""Linux audio mute detection using PulseAudio/PipeWire.
5
6Direct copy from solstone's observe/linux/audio.py — no solstone imports.
7"""
8
9import asyncio
10import logging
11
12logger = logging.getLogger(__name__)
13
14
15async def is_sink_muted() -> bool:
16 """
17 Check if the default audio sink is muted using PulseAudio.
18
19 Uses `pactl get-sink-mute @DEFAULT_SINK@` to query mute status.
20
21 Returns:
22 True if muted, False otherwise (including on error).
23 """
24 try:
25 proc = await asyncio.create_subprocess_exec(
26 "pactl",
27 "get-sink-mute",
28 "@DEFAULT_SINK@",
29 stdout=asyncio.subprocess.PIPE,
30 stderr=asyncio.subprocess.PIPE,
31 )
32 stdout, stderr = await proc.communicate()
33
34 if proc.returncode != 0:
35 stderr_text = stderr.decode().strip() if stderr else ""
36 logger.warning(f"pactl failed (rc={proc.returncode}): {stderr_text}")
37 return False
38
39 output = stdout.decode().strip()
40 return "Mute: yes" in output
41
42 except FileNotFoundError:
43 logger.warning("pactl not found, assuming unmuted")
44 return False
45 except Exception as e:
46 logger.warning(f"Error checking sink mute status: {e}")
47 return False