Advertisement
Guest User

multi_seat_alsa_utils.sh

a guest
Apr 26th, 2014
340
0
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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement