Advertisement
Guest User

multi_seat_alsa_utils.sh

a guest
Apr 25th, 2014
88
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="$(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.     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.  
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement