SHARE
TWEET

multi_seat_alsa_utils.sh

a guest Apr 26th, 2014 142 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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="${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 [ -z "${INSTANCE}" ]; then
  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
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top