blob: 33abb3407136d6e077928f23e52d63488dc59438 (
plain) (
blame)
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
|
#!/bin/bash
set -eu
# shellcheck disable=2034
description="audio/sound manager"
export FUZL_PROMPT=audm
export FUZL_ICON=
. libfuzl.sh
main() {
local sink source
sink=$(inspect_node '@DEFAULT_SINK@' | awk -F\\t '{print $2}')
fuzl_action_add 'change_sink' "" "$sink"
source=$(inspect_node '@DEFAULT_SOURCE@' | awk -F\\t '{print $2}')
fuzl_action_add 'change_source' "" "$source"
fuzl_action_add 'change_profile' "" "Change profile"
fuzl_action_add 'mixsource' "" "Mix source into sink"
fuzl_action_menu || exit 1
}
#
# helpers
#
inspect_node() {
local nid
nid=$(wpctl inspect "${1:?}" | awk '/^id/{match($0,/[0-9]+,/); print substr($0,RSTART,RLENGTH-1);}')
test -n "$nid" || exit 1 # TODO handle error
pw-dump | jq -r --argjson nid "$nid" \
'.[]|select(.id==$nid)|.info.props|[.["object.id"],.["node.description"],.["node.name"]]|join("\t")'
}
list_nodes() {
pw-dump | jq -rc --arg class "${1:?}" \
'.[]|select((.info.props["media.class"]//"")|test($class))|.info.props|[.["object.id"],.["node.description"],.["node.name"]]|join("\t")'
}
#
# actions
#
audm_change_sink() {
local id
id=$(list_nodes 'Audio/Sink' |
FUZL_PROMPT='sink' fuzl_menu $FUZL_MENU_FILTER --with-nth='{2} [{3}]' --accept-nth=1)
test -n "$id" || main
fuzl_try -- wpctl set-default "$id"
}
audm_change_source() {
local id
id=$(list_nodes 'Audio/Source' |
FUZL_PROMPT='source' fuzl_menu $FUZL_MENU_FILTER --with-nth='{2} [{3}]' --accept-nth=1)
test -n "$id" || main
fuzl_try -- wpctl set-default "$id"
}
audm_change_profile() {
local device did dname profile
device=$(pw-dump | jq -rc --arg class "Audio/Device" \
'.[]|select((.info.props["media.class"]//"")|test($class))|.info.props|[.["object.id"],.["device.description"],.["device.nick"]]|join("\t")' |
FUZL_PROMPT='device' fuzl_menu $FUZL_MENU_FILTER --with-nth='{2} {3}')
test -n "$device" || main
did=$(awk -F\\t '{print $1}' <<<"$device")
dname=$(awk -F\\t '{print $2}' <<<"$device")
profile=$(pw-dump | jq -r --argjson did "$did" \
'.[]|select(.id==$did)|.info.params.EnumProfile[]|[.index,.description]|join("\t")' |
FUZL_PROMPT="profile ($dname)" fuzl_menu $FUZL_MENU_FILTER --with-nth=2 --accept-nth=1)
test -n "$profile" || audm_change_profile
fuzl_try -- wpctl set-profile "$did" "$profile"
}
audm_mixsource() {
sink=$(inspect_node '@DEFAULT_SINK@' | awk -F\\t '{print $1}')
sink_json=$(pw-dump -R "$sink" | jq -rc --argjson id "$sink" '.[]|select(.id==$id)')
sink_node=$(jq -rc '.info.props["node.name"]' <<<$sink_json)
sink_ports=$(jq -r '.info.params.PortConfig[]|select(.direction=="Input")|.format.position[]' <<<$sink_json)
source=$(inspect_node '@DEFAULT_SOURCE@' | awk -F\\t '{print $1}')
source_json=$(pw-dump -R "$source" | jq -rc --argjson id "$source" '.[]|select(.id==$id)')
source_node=$(jq -rc '.info.props["node.name"]' <<<$source_json)
source_ports=$(jq -rc '.info.params.PortConfig[]|select(.direction=="Output")|.format.position[]' <<<$source_json)
for source_port in $source_ports; do
for sink_port in $sink_ports; do
(
pw-link --passive "$source_node":capture_"$source_port" "$sink_node":playback_"$sink_port" ||
pw-link --disconnect "$source_node":capture_"$source_port" "$sink_node":playback_"$sink_port"
) &
done
done
}
main
|