Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- # Copyright 2014 Dagg Stompler <daggs@gmx.com>
- #
- # This script manages sound card selection for non PulseAudio based systems.
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- PREFIX="ms_alsa_"
- INSTANCE="$(basename $0)"
- SERVED=0
- CONF_FILE_PATH="/etc/conf.d/multiseat_alsa_sound.conf"
- LINKS_PATH="/usr/local/bin"
- GROUP="users"
- INT_REGEX='^[0-9]+$'
- LABELS_DB_PATH="/usr/share/misc"
- # entry 0 must be install.
- declare -a CONNECTORS=("${LINKS_PATH}/install" "${LINKS_PATH}/uninstall" "/etc/profile.d/update_asoundrc" "${LINKS_PATH}/list_seats")
- declare -a ASOUNDRC_ADDONS=("defaults.pcm.card" "defaults.ctl.card" "defaults.pcm.device" "defaults.ctl.device")
- declare cards_info=()
- declare assignments=()
- populate_cards()
- {
- OLDIFS=${IFS}
- IFS=$'\n'
- i=0
- for card in $(egrep -lR "^id: " /proc/asound/card* | egrep "pcm[0-9]{1,}p" | egrep -v "sub[0-9]{1,}"); do
- local line=""
- local folder="$(realpath $(dirname ${card})/..)"
- local card_path_id="$(basename ${folder})"
- local vendor=""
- local device=""
- local type_usb=0
- if [ -f "${folder}/usbid" ]; then
- vendor=$(cat ${folder}/usbid | cut -f1 -d:)
- device=$(cat ${folder}/usbid | cut -f2 -d:)
- type_usb=1
- else
- vendor=$(cat /sys/class/sound/${card_path_id}/device/vendor | sed 's/0x//g')
- device=$(cat /sys/class/sound/${card_path_id}/device/device | sed 's/0x//g')
- fi
- line+="${vendor};${device}"
- line+=";$(grep "^name: " ${card} | sed 's/^name: //g');${type_usb}"
- cards_info[${i}]=${line}
- i=$((i+1))
- done
- IFS=${OLDIFS}
- }
- get_card_label()
- {
- local vid="$1"
- local did="$2"
- local type_usb="$3"
- local db_file=${LABELS_DB_PATH}
- if [ ${type_usb} -eq 1 ]; then
- db_file+="/usb.ids"
- else
- db_file+="/pci.ids"
- fi
- local sline=$(egrep -n "^[0-9a-f]{4} " ${db_file} | grep -A1 ${vid} | head -1 | cut -f 1 -d ':')
- local eline=$(egrep -n "^[0-9a-f]{4} " ${db_file} | grep -A1 ${vid} | tail -1 | cut -f 1 -d ':')
- local label="$(sed -n "${sline},${eline}p" ${db_file} | grep ${did} | head -1 | cut -d' ' -f2- | sed 's/^\s*//g')"
- echo "${label}"
- }
- install_files()
- {
- echo "installing..."
- rm ${CONF_FILE_PATH} -rf
- for i in $(seq 0 $((${#assignments[@]}-1))); do
- echo "${assignments[${i}]}" >> ${CONF_FILE_PATH}
- done
- local link_path="$(realpath $0)"
- local target_path
- for option in "${CONNECTORS[@]}"; do
- target_path="$(dirname ${option})/${PREFIX}$(basename ${option})"
- if [ ! -h "${target_path}" ]; then
- echo "creating link ${target_path}..."
- ln -s ${link_path} ${target_path}
- fi
- done
- chown root:${GROUP} $0 ${CONF_FILE_PATH}
- chmod 754 $0 ${CONF_FILE_PATH}
- IFS=$'\n'
- for entry in $(getent passwd); do
- username="$(echo ${entry} | cut -d: -f1)"
- if [ $(groups ${username} | grep -c users) -eq 1 ]; then
- local home="$(getent passwd ${username} | cut -d: -f6)"
- rm -rf ${home}/.asoundrc
- for option in "${ASOUNDRC_ADDONS[@]}"; do
- echo "${option} 0" >> ${home}/.asoundrc
- done
- fi
- done
- unset IFS
- }
- get_seat_id()
- {
- local seat=$(echo ${DISPLAY} | sed 's/^://g')
- if ! [[ ${seat} =~ ${INT_REGEX} ]]; then
- echo "invalid seat id"
- exit 1
- fi
- echo ${seat}
- }
- #
- get_data_from_entry()
- {
- local entry="$*"
- local vid=$(echo ${entry} | cut -f 1 -d ';')
- local did=$(echo ${entry} | cut -f 2 -d ';')
- local hdr=$(echo ${entry} | cut -f 3 -d ';')
- local is_type_usb=$(echo ${entry} | cut -f 4 -d ';')
- local line=""
- for card in $(egrep -lR "^id: " /proc/asound/card* | egrep "pcm[0-9]{1,}p" | egrep -v "sub[0-9]{1,}"); do
- local folder="$(realpath $(dirname ${card})/..)"
- local card_path_id="$(basename ${folder})"
- local vendor=""
- local device=""
- local header=""
- local type_usb=0
- if [ -f "${folder}/usbid" ]; then
- vendor=$(cat ${folder}/usbid | cut -f1 -d:)
- device=$(cat ${folder}/usbid | cut -f2 -d:)
- type_usb=1
- else
- vendor=$(cat /sys/class/sound/${card_path_id}/device/vendor | sed 's/0x//g')
- device=$(cat /sys/class/sound/${card_path_id}/device/device | sed 's/0x//g')
- fi
- header="$(grep "^name: " ${card} | sed 's/^name: //g')"
- if [ "${vid}" == "${vendor}" -a "${did}" == "${device}" -a "${hdr}" == "${header}" -a ${is_type_usb} -eq ${type_usb} ]; then
- line="${card}"
- break
- fi
- done
- echo "${line}"
- }
- get_card_id()
- {
- local path_to_file=$(get_data_from_entry $*)
- if [ -z "${path_to_file}" ]; then
- echo ""
- else
- echo "$(egrep "^card: " ${path_to_file} | cut -f 2 -d ':' | sed 's/ //g')"
- fi
- }
- get_dev_id()
- {
- local path_to_file=$(get_data_from_entry $*)
- if [ -z "${path_to_file}" ]; then
- echo ""
- else
- echo "$(egrep "^device: " ${path_to_file} | cut -f 2 -d ':' | sed 's/ //g')"
- fi
- }
- list_seats()
- {
- IFS=$'\n'
- echo "Seats sound config:"
- for entry in $(cat ${CONF_FILE_PATH}); do
- local key=$(echo ${entry} | cut -f1 -d=)
- local value=$(echo ${entry} | cut -f2 -d=)
- local vid=$(echo ${value} | cut -f 1 -d ';')
- local did=$(echo ${value} | cut -f 2 -d ';')
- local type_usb=$(echo ${value} | cut -f 4 -d ';')
- local label="$(get_card_label ${vid} ${did} ${type_usb})"
- echo -n " - $(echo ${key} | sed 's/t/t /g')) Vendor ID ${vid}, Device ID ${did}: ${label}, type: "
- if [ ${type_usb} -eq 1 ]; then
- echo "usb."
- else
- echo "pci."
- fi
- done
- unset IFS
- }
- install()
- {
- if [ "$(whoami)" != "root" ]; then
- echo "this program must be run as root"
- exit 1
- fi
- local i=0
- populate_cards
- avail_enteries=("${cards_info[@]}")
- local selection=""
- local seat_id=0
- local avail_card
- while [ 1 ]; do
- echo "Available cards:"
- avail_card=0
- while [ ${#avail_enteries[@]} -gt ${avail_card} ]; do
- local vid=$(echo ${avail_enteries[${avail_card}]} | cut -f 1 -d ';')
- local did=$(echo ${avail_enteries[${avail_card}]} | cut -f 2 -d ';')
- local type_usb=$(echo ${avail_enteries[${avail_card}]} | cut -f 4 -d ';')
- local label="$(get_card_label ${vid} ${did} ${type_usb})"
- echo " $((avail_card+1)). ${vid}:${did}, Label: ${label}, type $(echo ${avail_enteries[${avail_card}]} | cut -f 3 -d ';')"
- avail_card=$((${avail_card} + 1))
- done
- echo -n "please select card for seat ${seat_id}, I to install or q to quit: "
- read selection
- if [ "${selection}" = "I" -o "${selection}" = "q" ]; then
- break
- fi
- if ! [[ ${selection} =~ ${INT_REGEX} ]]; then
- echo "invalid seletion, please select again."
- continue
- elif [ ${selection} -lt 1 -o ${selection} -gt ${#avail_enteries[@]} ]; then
- echo "invalid seletion, please select again."
- continue
- fi
- local pos=$((${selection} - 1))
- assignments=("${assignments[@]}" "Seat${seat_id}=$(echo ${avail_enteries[${pos}]})")
- seat_id=$((seat_id + 1))
- local last_entry_idx=${#avail_enteries[@]}
- last_entry_idx=$((last_entry_idx-1))
- avail_enteries[${pos}]=${avail_enteries[${last_entry_idx}]}
- unset avail_enteries[${last_entry_idx}]
- done
- if [ "${selection}" = "I" ]; then
- install_files
- fi
- }
- uninstall()
- {
- for option in "${CONNECTORS[@]}"; do
- target_path="$(dirname ${option})/${PREFIX}$(basename ${option})"
- if [ -h "${target_path}" ]; then
- rm -f ${target_path}
- fi
- done
- }
- update_asoundrc()
- {
- if [ "$(whoami)" != "root" -a -f ~/.asoundrc -a $(who | grep "${USER}" | grep -cv "pts") -eq 1 ]; then
- local entry=$(grep "^Seat$(get_seat_id)=" ${CONF_FILE_PATH} | cut -f 2 -d '=')
- sed -i "s/\.card [0-9]*/\.card $(get_card_id ${entry})/g" ~/.asoundrc
- sed -i "s/\.device [0-9]*/\.device $(get_dev_id ${entry} )/g" ~/.asoundrc
- fi
- }
- for option in "${CONNECTORS[@]}"; do
- cmd="${PREFIX}$(basename ${option})"
- if [ "$(basename ${INSTANCE})" = "${cmd}" ]; then
- $(basename ${option}) $*
- SERVED=1
- fi
- done
- if [ ${SERVED} -eq 0 ]; then
- entry=${CONNECTORS[0]}
- if [ ! -h "$(dirname ${entry})/${PREFIX}$(basename ${entry})" ]; then
- $(basename ${entry}) $*
- else
- echo -n "possible commands: "
- line=""
- for option in "${CONNECTORS[@]}"; do
- line="${line} ${PREFIX}$(basename ${option}), "
- done
- echo "$(echo ${line} | sed 's/,$/./g')"
- fi
- fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement