View difference between Paste ID: nUwsxYEx and ns7MqCBi
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 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)"
21+
INSTANCE="${BASH_SOURCE[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
29+
if [ -z "${INSTANCE}" ]; then
30-
	INSTANCE="${BASH_SOURCE[0]}"
30+
	INSTANCE="$(basename $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
	if [ ! -e ${LINKS_PATH} ]; then
99
		mkdir -p ${LINKS_PATH}
100
	fi
101
	for option in "${CONNECTORS[@]}"; do
102
		target_path="$(dirname ${option})/${PREFIX}$(basename ${option})"
103
		if [ ! -h "${target_path}" ]; then
104
			echo "creating link ${target_path}..."
105
			ln -s ${link_path} ${target_path}
106
		fi
107
	done
108
	chown root:${GROUP} $0 ${CONF_FILE_PATH}
109
	chmod 754 $0 ${CONF_FILE_PATH}
110
	IFS=$'\n'
111
	for entry in $(getent passwd); do
112
		username="$(echo ${entry} | cut -d: -f1)"
113
		if [ $(groups ${username} | grep -c users) -eq 1 ]; then
114
			local home="$(getent passwd ${username} | cut -d: -f6)"
115
			rm -rf ${home}/.asoundrc
116
			for option in "${ASOUNDRC_ADDONS[@]}"; do
117
				echo "${option} 0" >> ${home}/.asoundrc
118
			done
119
		fi
120
	done
121
	unset IFS
122
}
123
124
get_seat_id()
125
{
126
	local seat=$(echo ${DISPLAY} | sed 's/^://g')
127
128
	if ! [[ ${seat} =~ ${INT_REGEX} ]]; then
129
		echo "invalid seat id"
130
		exit 1
131
	fi
132
	echo ${seat}
133
}
134
 
135
get_data_from_entry()
136
{
137
	local entry="$*"
138
	local vid=$(echo ${entry} | cut -f 1 -d ';')
139
	local did=$(echo ${entry} | cut -f 2 -d ';')
140
	local hdr=$(echo ${entry} | cut -f 3 -d ';')
141
	local is_type_usb=$(echo ${entry} | cut -f 4 -d ';')
142
	local line=""
143
144
	for card in $(egrep -lR "^id: " /proc/asound/card* | egrep "pcm[0-9]{1,}p" | egrep -v "sub[0-9]{1,}"); do
145
		local folder="$(realpath $(dirname ${card})/..)"
146
		local card_path_id="$(basename ${folder})"
147
		local vendor=""
148
		local device=""
149
		local header=""
150
		local type_usb=0
151
152
		if [ -f "${folder}/usbid" ]; then
153
			vendor=$(cat ${folder}/usbid | cut -f1 -d:)
154
			device=$(cat ${folder}/usbid | cut -f2 -d:)
155
			type_usb=1
156
		else
157
			vendor=$(cat /sys/class/sound/${card_path_id}/device/vendor | sed 's/0x//g')
158
			device=$(cat /sys/class/sound/${card_path_id}/device/device | sed 's/0x//g')
159
		fi
160
		header="$(grep "^name: " ${card} | sed 's/^name: //g')"
161
		if [ "${vid}" == "${vendor}" -a "${did}" == "${device}" -a  "${hdr}" == "${header}" -a ${is_type_usb} -eq ${type_usb} ]; then
162
			line="${card}"
163
			break
164
		fi
165
	done
166
	echo "${line}"
167
 }
168
 
169
get_card_id()
170
{
171
	local path_to_file=$(get_data_from_entry $*)
172
173
	if [ -z "${path_to_file}" ]; then
174
		echo ""
175
	else
176
		echo "$(egrep "^card: " ${path_to_file} | cut -f 2 -d ':' | sed 's/ //g')"
177
	fi
178
}
179
180
get_dev_id()
181
{
182
	local path_to_file=$(get_data_from_entry $*)
183
184
	if [ -z "${path_to_file}" ]; then
185
		echo ""
186
	else
187
		echo "$(egrep "^device: " ${path_to_file} | cut -f 2 -d ':' | sed 's/ //g')"
188
	fi
189
}
190
191
list_seats()
192
{
193
	IFS=$'\n'
194
	echo "Seats sound config:"
195
	for entry in $(cat ${CONF_FILE_PATH}); do
196
		local key=$(echo ${entry} | cut -f1 -d=)
197
		local value=$(echo ${entry} | cut -f2 -d=)
198
		local vid=$(echo ${value} | cut -f 1 -d ';')
199
		local did=$(echo ${value} | cut -f 2 -d ';')
200
		local type_usb=$(echo ${value} | cut -f 4 -d ';')
201
		local label="$(get_card_label ${vid} ${did} ${type_usb})"
202
		echo -n "	 - $(echo ${key} | sed 's/t/t /g')) Vendor ID ${vid}, Device ID ${did}: ${label}, type: "
203
		if [ ${type_usb} -eq 1 ]; then
204
			echo "usb."
205
		else
206
			echo "pci."
207
		fi
208
	done
209
	unset IFS
210
}
211
212
install()
213
{
214
	if [ "$(whoami)" != "root" ]; then
215
		echo "this program must be run as root"
216
		exit 1
217
	fi
218
	local i=0
219
	populate_cards
220
221
	avail_enteries=("${cards_info[@]}")
222
	local selection=""
223
	local seat_id=0
224
	local avail_card
225
226
	while [ 1 ]; do
227
		echo "Available cards:"
228
		avail_card=0
229
		while [ ${#avail_enteries[@]} -gt ${avail_card} ]; do
230
			local vid=$(echo ${avail_enteries[${avail_card}]} | cut -f 1 -d ';')
231
			local did=$(echo ${avail_enteries[${avail_card}]} | cut -f 2 -d ';')
232
			local type_usb=$(echo ${avail_enteries[${avail_card}]} | cut -f 4 -d ';')
233
			local label="$(get_card_label ${vid} ${did} ${type_usb})"
234
			echo "	$((avail_card+1)). ${vid}:${did}, Label: ${label}, type $(echo ${avail_enteries[${avail_card}]} | cut -f 3 -d ';')"
235
			avail_card=$((${avail_card} + 1))
236
		done
237
238
		echo -n "please select card for seat ${seat_id}, I to install or q to quit: "
239
		read selection
240
		if [ "${selection}" = "I" -o "${selection}" = "q" ]; then
241
			break
242
		fi
243
		if ! [[ ${selection} =~ ${INT_REGEX} ]]; then
244
			echo "invalid seletion, please select again."
245
			continue
246
		elif [ ${selection} -lt 1 -o ${selection} -gt ${#avail_enteries[@]} ]; then
247
			echo "invalid seletion, please select again."
248
			continue
249
		fi
250
		local pos=$((${selection} - 1))
251
		assignments=("${assignments[@]}" "Seat${seat_id}=$(echo ${avail_enteries[${pos}]})")
252
		seat_id=$((seat_id + 1))
253
		local last_entry_idx=${#avail_enteries[@]}
254
		last_entry_idx=$((last_entry_idx-1))
255
		avail_enteries[${pos}]=${avail_enteries[${last_entry_idx}]}
256
		unset avail_enteries[${last_entry_idx}]
257
	done
258
 	if [ "${selection}" = "I" ]; then
259
 		install_files
260
 	fi
261
 }
262
263
uninstall()
264
{
265
	for option in "${CONNECTORS[@]}"; do
266
		target_path="$(dirname ${option})/${PREFIX}$(basename ${option})"
267
		if [ -h "${target_path}" ]; then
268
			rm -f ${target_path}
269
		fi
270
	done
271
}
272
273
update_asoundrc()
274
{
275
	if [ "$(whoami)" != "root" -a -f ~/.asoundrc -a $(who | grep "${USER}" | grep -cv "pts") -eq 1 ]; then
276
		local entry=$(grep "^Seat$(get_seat_id)=" ${CONF_FILE_PATH} | cut -f 2 -d '=')
277
		sed -i "s/\.card [0-9]*/\.card $(get_card_id ${entry})/g" ~/.asoundrc
278
		sed -i "s/\.device [0-9]*/\.device $(get_dev_id ${entry} )/g" ~/.asoundrc
279
	fi
280
}
281
282
for option in "${CONNECTORS[@]}"; do
283
	cmd="${PREFIX}$(basename ${option})"
284
	if [ "$(basename ${INSTANCE})" = "${cmd}" ]; then
285
		func=$(echo "$(basename ${option})" | sed 's/\.sh$//g')
286
		${func} $*
287
		SERVED=1
288
		break
289
	fi
290
done
291
292
if [ ${SERVED} -eq 0 ]; then
293
	entry=${CONNECTORS[0]}
294
	if [ ! -h "$(dirname ${entry})/${PREFIX}$(basename ${entry})" ]; then
295
		$(basename ${entry}) $*
296
	else
297
		echo -n "possible commands: "
298
		line=""
299
		for option in "${CONNECTORS[@]}"; do
300
			line="${line} ${PREFIX}$(basename ${option}), "
301
		done
302
		echo "$(echo ${line} | sed 's/,$/./g')"
303
	fi
304
fi