-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathovos-audio-setup
361 lines (315 loc) · 12.1 KB
/
ovos-audio-setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
#!/bin/bash
OVOS_USER="$(getent passwd 1000 | cut -d: -f1)"
# I2C_DEVICE_FILE and UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE are used for detecting and configuring soundcards automatically.
I2C_DEVICE_FILE="/etc/OpenVoiceOS/i2c_platform"
UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE="/etc/udev/rules.d/99-autoconfigure-sound.rules"
UDEV_USB_AUTO_VOLUME_RULE_FILE="/etc/udev/rules.d/99-usb-autovolume.rules"
UDEV_USB_MERGE_SINKS_FILE="/etc/udev/rules.d/99-usb-mergesinks.rules"
# UDEV rule for auto-configuring soundcard when a USB soundcard is added/removed
# It will trigger the soundcard autoconfigure systemd service instead of running a script directly
UDEV_SOUNDCARD_AUTOSELECT_RULE='ACTION=="add|remove", SUBSYSTEM=="sound", RUN+="/usr/libexec/soundcard-autoconfigure"'
PIPEWIRE_AUTOSWITCH_CONF="/home/$OVOS_USER/.config/pipewire/pipewire-pulse.conf.d/switch-on-connect.conf"
PIPEWIRE_ECHOCANCEL_CONF="/home/$OVOS_USER/.config/pipewire/pipewire.conf.d/echo-cancel.conf"
# UDEV rule for auto setting USB soundcard volume and recreating combined sinks
# - set default sink volume for that card
# - recreate combined sinks for output
UDEV_USB_MERGE_SINKS_RULE='ACTION=="add|remove", SUBSYSTEM=="sound", ENV{ID_BUS}=="usb", RUN+="/usr/libexec/combine-sinks"'
UDEV_USB_AUTO_VOLUME_RULE='ACTION=="add", SUBSYSTEM=="sound", ENV{ID_BUS}=="usb", RUN+="/usr/libexec/usb-autovolume"'
# Service names
COMBINED_SINKS_SERVICE="combine_sinks.service"
AUTOCONFIGURE_SERVICE="autoconfigure_soundcard.service"
detect_sound_server() {
# Check if PipeWire is installed
if command -v pipewire > /dev/null; then
echo "pipewire"
# Check if PulseAudio is installed
elif command -v pulseaudio > /dev/null; then
echo "pulse"
# Check if ALSA is available
elif command -v aplay > /dev/null && command -v amixer > /dev/null; then
echo "alsa"
else
echo "No sound server detected"
exit 1
fi
}
SOUND_SERVER=$(detect_sound_server)
# Function to prompt for confirmation
prompt_user() {
while true; do
read -p "$1 (y/n): " choice
case "$choice" in
y|Y ) return 0;; # User chose yes
n|N ) return 1;; # User chose no
* ) echo "Please answer y or n.";; # Invalid input
esac
done
}
# Function to disable conflicting services
# Disables a service if it is active.
disable_service() {
local service_name=$1
if systemctl is-active --quiet "$service_name"; then
echo "Disabling $service_name..."
sudo systemctl stop "$service_name"
sudo systemctl disable --now "$service_name"
if [ $? -eq 0 ]; then
echo "$service_name disabled successfully."
else
echo "Error: Failed to disable $service_name."
fi
fi
}
# Function to print usage instructions
usage() {
echo "Usage: $0 [choice]"
echo "Choices:"
echo "1) Manually select default soundcard"
echo "2) Enable soundcard-autoselect - select default soundcard (on boot)"
echo "3) Enable switch-on-connect - if a new soundcard is connected automatically switch to it"
echo "4) Enable USB auto-volume - set default volume for USB cards on connection"
echo "5) Enable combine-sinks - output audio trough all outputs at once"
echo "6) Enable echo cancellation"
echo "7) Revert changes - you will be prompted to interactively revert the above actions"
echo "8) Exit"
}
# Get the choice from the command-line argument or prompt the user
if [ $# -gt 0 ]; then
choice=$1
else
usage
read -p "Choose an option: " choice
fi
disable_usb_autovol(){
if [ -f "$UDEV_USB_AUTO_VOLUME_RULE_FILE" ]; then
sudo rm "$UDEV_USB_AUTO_VOLUME_RULE_FILE"
echo "Removed udev USB auto volume rule - $UDEV_USB_AUTO_VOLUME_RULE_FILE"
fi
}
disable_combine_sinks(){
disable_service "$COMBINED_SINKS_SERVICE"
if [ -f "$UDEV_USB_MERGE_SINKS_FILE" ]; then
sudo rm "$UDEV_USB_MERGE_SINKS_FILE"
echo "Removed udev USB combine_sinks rule"
fi
}
disable_soundcard_autoselect(){
disable_service "$AUTOCONFIGURE_SERVICE"
}
disable_switch_on_connect(){
if [ "$SOUND_SERVER" == "pulse"]; then
pactl unload-module module-switch-on-connect
pactl unload-module module-switch-on-port-available
# Remove the load-module line from default.pa
sed -i '/module-switch-on-connect/d' "/home/$OVOS_USER/.config/pulse/default.pa"
sed -i '/module-switch-on-port-available/d' "/home/$OVOS_USER/.config/pulse/default.pa"
elif [ "$SOUND_SERVER" == "pipewire"]; then
if [ -f "$PIPEWIRE_AUTOSWITCH_CONF" ]; then
sudo rm "$PIPEWIRE_AUTOSWITCH_CONF"
echo "Removed soundcard auto-switch pipewire config - $PIPEWIRE_AUTOSWITCH_CONF"
pw-cli reload
fi
else
if [ -f "$UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE" ]; then
sudo rm "$UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE"
echo "Removed udev soundcard rule - $UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE"
fi
fi
}
disable_echo_cancel(){
if [ "$SOUND_SERVER" == "pulse"]; then
pactl unload-module module-echo-cancel
# Remove the load-module line from default.pa
sed -i '/load-module module-echo-cancel aec_method=webrtc/d' "/home/$OVOS_USER/.config/pulse/default.pa"
elif [ "$SOUND_SERVER" == "alsa"]; then
echo "ERROR: alsa does not support echo cancellation"
else
if [ -f "$PIPEWIRE_ECHOCANCEL_CONF" ]; then
sudo rm "$PIPEWIRE_ECHOCANCEL_CONF"
echo "Removed echo cancellation pipewire config - $PIPEWIRE_ECHOCANCEL_CONF"
pw-cli reload
fi
fi
}
reset_alsa_config(){
if [ -f "/home/$OVOS_USER/.asoundrc" ]; then
if ! rm "/home/$OVOS_USER/.asoundrc"; then
echo "Failed to remove .asoundrc"
exit 1
fi
fi
if [ "$SOUND_SERVER" != "alsa" ]; then
echo -e "pcm.!default $SOUND_SERVER\nctl.!default $SOUND_SERVER" > /home/$OVOS_USER/.asoundrc
chmod 644 /home/$OVOS_USER/.asoundrc
else
if [ -f "/home/$OVOS_USER/.asoundrc.bak" ]; then
mv /home/$OVOS_USER/.asoundrc.bak /home/$OVOS_USER/.asoundrc
fi
fi
}
####################
# user choices
manual_select(){
echo "Available sound cards:"
aplay -l
read -p "Enter the card number to set as default: " user_card
echo "Setting ALSA default card to: $user_card"
echo "defaults.pcm.card $user_card" > "/home/$OVOS_USER/.asoundrc"
echo "defaults.ctl.card $user_card" >> "/home/$OVOS_USER/.asoundrc"
chmod 644 /home/$OVOS_USER/.asoundrc
# Check if the auto-configure service is active
if systemctl is-active --quiet "$AUTOCONFIGURE_SERVICE"; then
# Prompt user about disabling sound card auto-select
if prompt_user "Do you want to disable sound card auto-select?"; then
disable_soundcard_autoselect
fi
fi
if systemctl is-active --quiet "$COMBINED_SINKS_SERVICE"; then
# Prompt user about disabling combine_sinks
if prompt_user "Do you want to disable combined-sinks?"; then
disable_combine_sinks
fi
fi
}
enable_usb_autovol(){
echo "Creating udev rule for USB autovolume."
echo "$UDEV_USB_AUTO_VOLUME_RULE" | sudo tee "$UDEV_USB_AUTO_VOLUME_RULE_FILE" > /dev/null
echo "Udev rule for USB autovolume created: $UDEV_USB_AUTO_VOLUME_RULE_FILE"
echo "$UDEV_USB_AUTO_VOLUME_RULE"
}
enable_combine_sinks(){
echo "Enabling $COMBINED_SINKS_SERVICE..."
sudo systemctl enable --now "$COMBINED_SINKS_SERVICE"
if [ $? -eq 0 ]; then
echo "$COMBINED_SINKS_SERVICE enabled successfully."
else
echo "Error: Failed to enable $COMBINED_SINKS_SERVICE."
fi
# Enable USB autoconfigure udev rule
# TODO - use native pipewire/pulse transfer sink instead
echo "Creating udev rule for USB merge sinks."
echo "$UDEV_USB_MERGE_SINKS_RULE" | sudo tee "$UDEV_USB_MERGE_SINKS_FILE" > /dev/null
echo "Udev rule for USB merge sinks created: $UDEV_USB_MERGE_SINKS_FILE"
echo "$UDEV_USB_MERGE_SINKS_RULE"
}
enable_switch_on_connect(){
if [ "$SOUND_SERVER" = "pipewire" ]; then
if ! mkdir -p "/home/$OVOS_USER/.config/pipewire/pipewire-pulse.conf.d"; then
echo "Failed to create pipewire config directory"
exit 1
fi
if ! cp "/usr/share/ovos/pipewire/switch-on-connect.conf" "$PIPEWIRE_AUTOSWITCH_CONF"; then
echo "Failed to copy switch-on-connect configuration"
exit 1
fi
pw-cli reload
echo "switch-on-connect enabled. if a new soundcard is detected pipewire will automatically switch to it"
elif [ "$SOUND_SERVER" = "alsa" ]; then
# Enable autoconfigure rule by creating udev rule
echo "Creating udev rule for autoconfiguration of new soundcards."
echo "$UDEV_SOUNDCARD_AUTOSELECT_RULE" | sudo tee "$UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE" > /dev/null
echo "Udev rule created: $UDEV_SOUNDCARD_AUTOSELECT_RULE_FILE"
echo "$UDEV_SOUNDCARD_AUTOSELECT_RULE"
else
pactl load-module module-switch-on-connect
echo "switch-on-connect enabled. if a new soundcard is detected pulse will automatically switch"
pactl load-module module-switch-on-port-available
echo "switch-on-port-available enabled. if headphones are plugged in pulse will automatically switch"
fi
}
enable_soundcard_autoselect(){
echo "Enabling $AUTOCONFIGURE_SERVICE..."
sudo systemctl enable --now "$AUTOCONFIGURE_SERVICE"
if [ $? -eq 0 ]; then
echo "$AUTOCONFIGURE_SERVICE enabled successfully."
else
echo "Error: Failed to enable $AUTOCONFIGURE_SERVICE."
fi
}
enable_echo_cancel(){
if [ "$SOUND_SERVER" == "pulse" ]; then
pactl unload-module module-echo-cancel
pactl load-module module-echo-cancel aec_method=webrtc source_name=echocancel sink_name=echocancel_sink
pacmd set-default-source echocancel
pacmd set-default-sink echocancel_sink
# make it happen on boot
mkdir -p "/home/$OVOS_USER/.config/pulse"
if ! grep -q "load-module module-echo-cancel aec_method=webrtc" "/home/$OVOS_USER/.config/pulse/default.pa"; then
echo "load-module module-echo-cancel aec_method=webrtc" >> "/home/$OVOS_USER/.config/pulse/default.pa"
fi
elif [ "$SOUND_SERVER" == "alsa" ]; then
echo "ERROR: ALSA does not support echo cancellation. Consider using PipeWire or PulseAudio."
else
# Ensure the config directory exists
mkdir -p "$(dirname "$PIPEWIRE_ECHOCANCEL_CONF")"
cp "/usr/share/ovos/pipewire/echo-cancel.conf" "$PIPEWIRE_ECHOCANCEL_CONF"
pw-cli reload
echo "Echo cancellation enabled for PipeWire."
fi
}
#############################
# Main logic based on user's choice
case $choice in
1)
# Choice 1: Set default soundcard
manual_select
;;
2)
# Choice 2: autoselect default soundcard
disable_combine_sinks
enable_soundcard_autoselect
;;
3)
# Choice 3: autoselect default soundcard
enable_switch_on_connect
;;
4)
# Choice 4: Automatically set volume of USB devices to a audible level
enable_usb_autovol
;;
5)
# Choice 5: Enable combined audio sinks
disable_soundcard_autoselect
enable_combine_sinks
;;
6)
# Choice 6: Enable echo cancellation
enable_echo_cancel
;;
7)
# Choice 6: Reset everything (clean state)
# Prompt for each action
if prompt_user "Do you want to reset ALSA configuration?"; then
reset_alsa_config
fi
if prompt_user "Do you want to disable switch on connect?"; then
disable_switch_on_connect
fi
if prompt_user "Do you want to disable soundcard auto-select?"; then
disable_soundcard_autoselect
fi
if prompt_user "Do you want to disable combine_sinks?"; then
disable_combine_sinks
fi
if prompt_user "Do you want to disable USB auto volume?"; then
disable_usb_autovol
fi
if prompt_user "Do you want to disable echo cancellation?"; then
disable_echo_cancel
fi
echo "Audio configuration reset process completed."
;;
8)
# Exit
echo "Exiting audio setup."
;;
*)
# Invalid choice
echo "Invalid choice."
usage
exit 1
;;
esac
# Reload udev rules after removing the rule
echo "Reloading udev rules to apply any changes..."
sudo udevadm control --reload