Skip to content

Commit aac89d9

Browse files
committed
Made the listener more robust to pulseaudio restarts
Sometimes when I boot up my laptop, pulseaudio can't detect the devices properly. I run `pulseaudio -k` to restart it, but this changes the device ids and crashes the listener. Now this should work without any action from the user.
1 parent dc9201c commit aac89d9

2 files changed

Lines changed: 62 additions & 15 deletions

File tree

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99

1010
## Installation
1111
1. Make sure `BRIGHTNESS_FILE_PATH` in set_micmute_led.c corresponds to the LED file path on your system.
12-
2. Run `./install.sh`
12+
2. Make sure `mic_name` in micmute_listener_pa.py corresponds to your mic device name. This name can be found within the sources printed out when the client is started. (This will be made more user-friendly with upcoming releases)
13+
3. Run `./install.sh`
1314

1415
## Running
15-
If you have systemd and want to enable the script as soon as you log in, run `systemctl --user enable micmute_listener_pa.service`.
1616

17+
### With systemd
18+
If you want to enable the script as soon as you log in, run `systemctl --user enable micmute_listener_pa.service`.
1719
To start the service immediately, run `systemctl --user start micmute_listener_pa.service`.
1820

21+
### Without systemd
22+
Simply run `~/.local/bin/micmute_listener_pa.py &` after installation. For starting the client at boot, look up your distro's individual way to achieve this.
23+
1924
## Contributions
2025
I'm very intrested in your opinions in terms of the architecture of this service. If you have suggestions on how to avoid SETUID or make the whole thing cleaner or more secure, please start a discussion!

micmute_listener_pa.py

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,72 @@
22

33
import pulsectl
44
import os
5-
pulse = pulsectl.Pulse('my-client-name')
5+
import sys
6+
import signal
7+
pulse = pulsectl.Pulse('micmute-listener')
8+
9+
# TODO: Read this from an external config file
10+
mic_name = 'alsa_input.pci-0000_04_00.6.analog-stereo'
611

712
active_index = 1 # This is the index of the source
813
pulse_event = None
914

10-
with pulsectl.Pulse('event-printer') as pulse:
15+
def shutdown(signum, frame):
16+
print('Shutting down client...')
17+
pulse.disconnect()
18+
quit(0)
19+
20+
def find_mic_index():
21+
global active_index
22+
23+
for source in pulse.source_list():
24+
if(source.name == mic_name):
25+
active_index = int(source.index)
26+
print('Mic index set: %d' % (active_index))
27+
return
28+
29+
raise RuntimeError('Could not find a device corresponding to %s!' % (mic_name))
30+
31+
def catch_events(ev):
32+
print('Pulse event:', ev)
33+
global pulse_event
34+
pulse_event = ev
35+
### Raise PulseLoopStop for event_listen() to return before timeout (if any)
36+
raise pulsectl.PulseLoopStop
37+
38+
def set_led_value(value):
39+
os.system("/usr/local/bin/set_micmute_led " + str(value))
40+
41+
def init():
42+
pulse.connect(wait= True)
43+
1144
#print('Event types:', pulsectl.PulseEventTypeEnum)
1245
#print('Event facilities:', pulsectl.PulseEventFacilityEnum)
1346
#print('Event masks:', pulsectl.PulseEventMaskEnum)
14-
#print('Source list:', pulse.source_list())
15-
16-
def print_events(ev):
17-
#print('Pulse event:', ev)
18-
global pulse_event
19-
pulse_event = ev
20-
### Raise PulseLoopStop for event_listen() to return before timeout (if any)
21-
raise pulsectl.PulseLoopStop
47+
print('Source list:', pulse.source_list())
48+
49+
find_mic_index()
50+
init_led_value = 0 if pulse.source_info(active_index).mute == 1 else 1
51+
set_led_value(init_led_value)
2252

2353
pulse.event_mask_set('all')
24-
pulse.event_callback_set(print_events)
54+
pulse.event_callback_set(catch_events)
55+
56+
57+
if __name__ == '__main__':
58+
print('Starting the micmute listener...')
59+
signal.signal(signal.SIGINT, shutdown)
60+
init()
2561

2662
while True:
27-
pulse.event_listen()
63+
try:
64+
pulse.event_listen()
65+
except pulsectl.pulsectl.PulseDisconnected:
66+
# TODO: check the docu, maybe this isn't the best way to restart the connection
67+
print('PulseAudio disconnected! Attempting to reconnect...', file=sys.stderr)
68+
init()
69+
continue
2870

2971
if pulse_event.index == active_index:
3072
led_value = 0 if pulse.source_info(active_index).mute == 1 else 1
31-
os.system("/usr/local/bin/set_micmute_led " + str(led_value))
73+
set_led_value(led_value)

0 commit comments

Comments
 (0)