View difference between Paste ID: ns7MqCBi and WxgSwTwZ
SHOW: | | - or go back to the newest paste.
1
#!/bin/bash
2
3
# Copyright 2014 Dagg Stompler <daggs@gmx.com>
4
# 
5-
# This script manages sound card selection for non PulseAudio based systems.
5+
# This script manages sound card selection for non PuleAudio based systems.
6
# 
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 2 of the License, or
10
# (at your option) any later version.
11
# 
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
# 
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
PREFIX="ms_alsa_"
21
INSTANCE="$(basename $0)"
22
SERVED=0
23
CONF_FILE_PATH="/etc/conf.d/multiseat_alsa_sound.conf"
24
LINKS_PATH="/usr/local/bin"
25
GROUP="users"
26
INT_REGEX='^[0-9]+$'
27
LABELS_DB_PATH="/usr/share/misc"
28
29
if [ "${INSTANCE}" == "bash" ]; then
30-
declare -a CONNECTORS=("${LINKS_PATH}/install" "${LINKS_PATH}/uninstall" "/etc/profile.d/update_asoundrc" "${LINKS_PATH}/list_seats")
30+
	INSTANCE="${BASH_SOURCE[0]}"
31
fi
32
33
# entry 0 must be install.
34
declare -a CONNECTORS=("${LINKS_PATH}/install" "${LINKS_PATH}/uninstall" "/etc/profile.d/update_asoundrc.sh" "${LINKS_PATH}/list_seats")
35
declare -a ASOUNDRC_ADDONS=("defaults.pcm.card" "defaults.ctl.card" "defaults.pcm.device" "defaults.ctl.device")
36
declare cards_info=()
37
declare assignments=()
38
39
populate_cards()
40
{
41
	OLDIFS=${IFS}
42
	IFS=$'\n'
43
	i=0
44
45
	for card in $(egrep -lR "^id: " /proc/asound/card* | egrep "pcm[0-9]{1,}p" | egrep -v "sub[0-9]{1,}"); do
46
		local line=""
47
		local folder="$(realpath $(dirname ${card})/..)"
48
		local card_path_id="$(basename ${folder})"
49
		local vendor=""
50
		local device=""
51
		local type_usb=0
52
53
		if [ -f "${folder}/usbid" ]; then
54
			vendor=$(cat ${folder}/usbid | cut -f1 -d:)
55
			device=$(cat ${folder}/usbid | cut -f2 -d:)
56
			type_usb=1
57
		else
58
			vendor=$(cat /sys/class/sound/${card_path_id}/device/vendor | sed 's/0x//g')
59
			device=$(cat /sys/class/sound/${card_path_id}/device/device | sed 's/0x//g')
60
		fi
61
		line+="${vendor};${device}"
62
		line+=";$(grep "^name: " ${card} | sed 's/^name: //g');${type_usb}"
63
		cards_info[${i}]=${line}
64
		i=$((i+1))
65
	done
66
	IFS=${OLDIFS}
67
}
68
69
get_card_label()
70
{
71
	local vid="$1"
72
	local did="$2"
73
	local type_usb="$3"
74
	local db_file=${LABELS_DB_PATH}
75
76
	if [ ${type_usb} -eq 1 ]; then
77
		db_file+="/usb.ids"
78
	else
79
		db_file+="/pci.ids"
80
	fi
81
	local sline=$(egrep -n "^[0-9a-f]{4} " ${db_file} | grep -A1 ${vid} | head -1 | cut -f 1 -d ':')
82
	local eline=$(egrep -n "^[0-9a-f]{4} " ${db_file} | grep -A1 ${vid} | tail -1 | cut -f 1 -d ':')
83
	local label="$(sed -n "${sline},${eline}p" ${db_file} | grep ${did} | head -1 | cut -d' ' -f2- | sed 's/^\s*//g')"
84
85
	echo "${label}"
86
}
87
88
install_files()
89
{
90
	echo "installing..."
91
	rm ${CONF_FILE_PATH} -rf
92
	for i in $(seq 0 $((${#assignments[@]}-1))); do
93
		echo "${assignments[${i}]}" >> ${CONF_FILE_PATH}
94
	done
95
96
	local link_path="$(realpath $0)"
97
	local target_path
98
	for option in "${CONNECTORS[@]}"; do
99
		target_path="$(dirname ${option})/${PREFIX}$(basename ${option})"
100
		if [ ! -h "${target_path}" ]; then
101
			echo "creating link ${target_path}..."
102
			ln -s ${link_path} ${target_path}
103
		fi
104
	done
105
	chown root:${GROUP} $0 ${CONF_FILE_PATH}
106
	chmod 754 $0 ${CONF_FILE_PATH}
107
	IFS=$'\n'
108
	for entry in $(getent passwd); do
109
		username="$(echo ${entry} | cut -d: -f1)"
110
		if [ $(groups ${username} | grep -c users) -eq 1 ]; then
111
			local home="$(getent passwd ${username} | cut -d: -f6)"
112
			rm -rf ${home}/.asoundrc
113
			for option in "${ASOUNDRC_ADDONS[@]}"; do
114
				echo "${option} 0" >> ${home}/.asoundrc
115
			done
116
		fi
117
	done
118
	unset IFS
119
}
120
121
get_seat_id()
122
{
123
	local seat=$(echo ${DISPLAY} | sed 's/^://g')
124
125
	if ! [[ ${seat} =~ ${INT_REGEX} ]]; then
126
		echo "invalid seat id"
127
		exit 1
128
	fi
129
	echo ${seat}
130
}
131
 
132
get_data_from_entry()
133
{
134
	local entry="$*"
135
	local vid=$(echo ${entry} | cut -f 1 -d ';')
136
	local did=$(echo ${entry} | cut -f 2 -d ';')
137
	local hdr=$(echo ${entry} | cut -f 3 -d ';')
138
	local is_type_usb=$(echo ${entry} | cut -f 4 -d ';')
139
	local line=""
140
141
	for card in $(egrep -lR "^id: " /proc/asound/card* | egrep "pcm[0-9]{1,}p" | egrep -v "sub[0-9]{1,}"); do
142
		local folder="$(realpath $(dirname ${card})/..)"
143
		local card_path_id="$(basename ${folder})"
144
		local vendor=""
145
		local device=""
146
		local header=""
147
		local type_usb=0
148
149
		if [ -f "${folder}/usbid" ]; then
150
			vendor=$(cat ${folder}/usbid | cut -f1 -d:)
151
			device=$(cat ${folder}/usbid | cut -f2 -d:)
152
			type_usb=1
153
		else
154
			vendor=$(cat /sys/class/sound/${card_path_id}/device/vendor | sed 's/0x//g')
155
			device=$(cat /sys/class/sound/${card_path_id}/device/device | sed 's/0x//g')
156
		fi
157
		header="$(grep "^name: " ${card} | sed 's/^name: //g')"
158
		if [ "${vid}" == "${vendor}" -a "${did}" == "${device}" -a  "${hdr}" == "${header}" -a ${is_type_usb} -eq ${type_usb} ]; then
159
			line="${card}"
160
			break
161
		fi
162
	done
163
	echo "${line}"
164
 }
165
 
166
get_card_id()
167
{
168
	local path_to_file=$(get_data_from_entry $*)
169
170
	if [ -z "${path_to_file}" ]; then
171
		echo ""
172
	else
173
		echo "$(egrep "^card: " ${path_to_file} | cut -f 2 -d ':' | sed 's/ //g')"
174
	fi
175
}
176
177
get_dev_id()
178
{
179
	local path_to_file=$(get_data_from_entry $*)
180
181
	if [ -z "${path_to_file}" ]; then
182
		echo ""
183
	else
184
		echo "$(egrep "^device: " ${path_to_file} | cut -f 2 -d ':' | sed 's/ //g')"
185
	fi
186
}
187
188
list_seats()
189
{
190
	IFS=$'\n'
191
	echo "Seats sound config:"
192
	for entry in $(cat ${CONF_FILE_PATH}); do
193
		local key=$(echo ${entry} | cut -f1 -d=)
194
		local value=$(echo ${entry} | cut -f2 -d=)
195
		local vid=$(echo ${value} | cut -f 1 -d ';')
196
		local did=$(echo ${value} | cut -f 2 -d ';')
197
		local type_usb=$(echo ${value} | cut -f 4 -d ';')
198
		local label="$(get_card_label ${vid} ${did} ${type_usb})"
199
		echo -n "	 - $(echo ${key} | sed 's/t/t /g')) Vendor ID ${vid}, Device ID ${did}: ${label}, type: "
200
		if [ ${type_usb} -eq 1 ]; then
201
			echo "usb."
202
		else
203
			echo "pci."
204
		fi
205
	done
206
	unset IFS
207
}
208
209
install()
210
{
211
	if [ "$(whoami)" != "root" ]; then
212
		echo "this program must be run as root"
213
		exit 1
214
	fi
215
	local i=0
216
	populate_cards
217
218
	avail_enteries=("${cards_info[@]}")
219
	local selection=""
220
	local seat_id=0
221
	local avail_card
222
223
	while [ 1 ]; do
224
		echo "Available cards:"
225
		avail_card=0
226
		while [ ${#avail_enteries[@]} -gt ${avail_card} ]; do
227
			local vid=$(echo ${avail_enteries[${avail_card}]} | cut -f 1 -d ';')
228
			local did=$(echo ${avail_enteries[${avail_card}]} | cut -f 2 -d ';')
229
			local type_usb=$(echo ${avail_enteries[${avail_card}]} | cut -f 4 -d ';')
230
			local label="$(get_card_label ${vid} ${did} ${type_usb})"
231
			echo "	$((avail_card+1)). ${vid}:${did}, Label: ${label}, type $(echo ${avail_enteries[${avail_card}]} | cut -f 3 -d ';')"
232
			avail_card=$((${avail_card} + 1))
233
		done
234
235
		echo -n "please select card for seat ${seat_id}, I to install or q to quit: "
236
		read selection
237
		if [ "${selection}" = "I" -o "${selection}" = "q" ]; then
238
			break
239
		fi
240
		if ! [[ ${selection} =~ ${INT_REGEX} ]]; then
241
			echo "invalid seletion, please select again."
242
			continue
243
		elif [ ${selection} -lt 1 -o ${selection} -gt ${#avail_enteries[@]} ]; then
244
			echo "invalid seletion, please select again."
245
			continue
246
		fi
247
		local pos=$((${selection} - 1))
248
		assignments=("${assignments[@]}" "Seat${seat_id}=$(echo ${avail_enteries[${pos}]})")
249
		seat_id=$((seat_id + 1))
250
		local last_entry_idx=${#avail_enteries[@]}
251
		last_entry_idx=$((last_entry_idx-1))
252
		avail_enteries[${pos}]=${avail_enteries[${last_entry_idx}]}
253
		unset avail_enteries[${last_entry_idx}]
254
	done
255
 	if [ "${selection}" = "I" ]; then
256
 		install_files
257
 	fi
258
 }
259
260
uninstall()
261
{
262
	for option in "${CONNECTORS[@]}"; do
263
		target_path="$(dirname ${option})/${PREFIX}$(basename ${option})"
264
		if [ -h "${target_path}" ]; then
265
			rm -f ${target_path}
266
		fi
267
	done
268
}
269
270
update_asoundrc()
271
{
272
	if [ "$(whoami)" != "root" -a -f ~/.asoundrc -a $(who | grep "${USER}" | grep -cv "pts") -eq 1 ]; then
273
		local entry=$(grep "^Seat$(get_seat_id)=" ${CONF_FILE_PATH} | cut -f 2 -d '=')
274
		sed -i "s/\.card [0-9]*/\.card $(get_card_id ${entry})/g" ~/.asoundrc
275
		sed -i "s/\.device [0-9]*/\.device $(get_dev_id ${entry} )/g" ~/.asoundrc
276
	fi
277
}
278-
		$(basename ${option}) $*
278+
279
for option in "${CONNECTORS[@]}"; do
280
	cmd="${PREFIX}$(basename ${option})"
281
	if [ "$(basename ${INSTANCE})" = "${cmd}" ]; then
282
		func=$(echo "$(basename ${option})" | sed 's/\.sh$//g')
283
		${func} $*
284
		SERVED=1
285
	fi
286
done
287
288
if [ ${SERVED} -eq 0 ]; then
289
	entry=${CONNECTORS[0]}
290
	if [ ! -h "$(dirname ${entry})/${PREFIX}$(basename ${entry})" ]; then
291
		$(basename ${entry}) $*
292
	else
293
		echo -n "possible commands: "
294
		line=""
295
		for option in "${CONNECTORS[@]}"; do
296
			line="${line} ${PREFIX}$(basename ${option}), "
297
		done
298
		echo "$(echo ${line} | sed 's/,$/./g')"
299
	fi
300
fi