Ubuntu 12.04: Sound Toggle 1.3 – HDMI sound toggle/switch

So I did a few edits to my script that allows me to:

  • Enable/disable the lockscreen. That way, I can close my laptop without having the lockscreen coming up.
  • Restore the backlight level based off of set values.
  • Added notifications.

Script:
#!/bin/bash
# Sound Toggle
# By Charles Cruz
#
# The following script toggles the between laptop speakers and hdmi audio (if detected).
# This also disables/enables
# Version 1.3
 
########### Settings ###########
# Backlight Settings
BACKLIGHT_BATTERY=20
BACKLIGHT_AC=100
 
USERID="$(cat /var/run/ConsoleKit/database | grep -B 6 is_active=true | grep uid= | cut -f 2 -d '=')"
USER="$(grep $USERID /etc/passwd | cut -f 1 -d ':')"
HDMI_STATUS="$(cat /sys/class/drm/card0-HDMI-A-1/status)"
GNOME_SCREENSAVER_PROC=`ps xa | grep gnome-screensaver | head -n 1 | awk '{print $1}'`
 
export `grep -z DBUS_SESSION_BUS_ADDRESS /proc/$GNOME_SCREENSAVER_PROC/environ`
export XAUTHORITY="/home/$USER/.Xauthority"
export DISPLAY="$(cat /var/run/ConsoleKit/database | grep x11_display= | cut -f 2 -d '=')"
 
# HDMI is connected
if [ "$HDMI_STATUS" = connected ]; then
# Send notification
sudo -u $USER notify-send -i display "HDMI connected"
 
# Set the sound card profile
sudo -u $USER pactl set-card-profile 0 output:hdmi-stereo+input:analog-stereo
 
# Disable the lockscreen if it's enabled so you can close the lockscreen
if [[ $(sudo -u $USER gsettings get org.gnome.desktop.screensaver lock-enabled) = true ]]; then
sudo -u $USER gsettings set org.gnome.desktop.screensaver lock-enabled false
fi
 
# HDMI is not connected
else
# Send notification
sudo -u $USER notify-send -i computer "HDMI disconnected"
 
# Set the sound card profile
sudo -u $USER pactl set-card-profile 0 output:analog-stereo+input:analog-stereo
 
# Restore the lock setting, if necessary
if [[ $(sudo -u $USER gsettings get org.gnome.desktop.screensaver lock-enabled) = false ]]; then
sudo -u $USER gsettings set org.gnome.desktop.screensaver lock-enabled true
fi
 
# Restore default battery/power brightness
cat /proc/acpi/ac_adapter/AC/state | grep "on-line"
if [ $? -eq 0 ]; then
xbacklight -set $BACKLIGHT_AC # Power cable is connected
else
xbacklight -set $BACKLIGHT_BATTERY # Power cable is not connected
fi
fi
 
exit 0

BTW, I renamed the script to “toggle-sound” so if you used a different name, be sure to change the name in the instructions below.

Instructions:

  1. In a terminal:
    sudo gedit /usr/local/bin/toggle-sound
  2. Copy and paste the script above into the document. Save and close it.
  3. In the terminal:
    sudo chmod 755 /usr/local/bin/toggle-sound
     
    echo 'KERNEL=="card0", SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/toggle-sound"' | sudo tee /etc/udev/rules.d/hdmi.rules
     
    sudo udevadm control --reload-rules

Ubuntu 11.10 – Automatic HDMI Toggle (with audio!)

This took me forever (well, three days)! I didn’t really know what I was doing for the most part – I never heard of or used xrandr, xbacklight, and udev rules. After hours of googling and through trial and error, I somehow managed to get this script together and working.

A few notes though:

  • I made this for my laptop and specifically for a HDMI connection. Haven’t tested anything else like VGA (but I put it there in my script as an option just in case I ever wanted to try it out).
  • This only toggles between one display. So if more than one external monitor connection is present (such as HDMI or VGA), according to the order of if/then statements in the script, only the HDMI connection is used.
  • Most of my googling brought up solutions for external/dedicated graphics cards from AMD or Nvidia. HOWEVER, this script has only been tested on my laptop which has integrated graphics (Intel HD 3000).
  • This was tested on Ubuntu 11.10 on an HP-DM4-2191US laptop.

Thanks to this wiki, I learned how to create a udev rule.
/etc/udev/rules.d/hdmi.rules
SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/MToggle-udev"

Here’s my script (may need to adjust some stuff such as paths and the index/name of the audio profile):
/usr/local/bin/MToggle-udev
#!/bin/sh
#
# Charles Cruz
# Monitor Toggle
# The following script toggles between the internal monitor and an external monitor.
#
# Version 1.3
# Export Xauthority and display
USER="$(who | grep :0\) | cut -f 1 -d ' ')"
export XAUTHORITY=/home/$USER/.Xauthority
export DISPLAY=:0
########### Settings ###########
# Use 'xrandr' to find these
DP="DP1"
VGA="VGA1"
HDMI="HDMI1"
INTERNAL_DISPLAY="LVDS1"
# Check /sys/class/drm for the exact location
DP_STATUS="$(cat /sys/class/drm/card0-DP-1/status)"
VGA_STATUS="$(cat /sys/class/drm/card0-VGA-1/status)"
HDMI_STATUS="$(cat /sys/class/drm/card0-HDMI-A-1/status)"
# Backlight settings
BACKLIGHT_BATTERY=15
BACKLIGHT_AC=50
# Do no change!
EXTERNAL_DISPLAY=""
# Check to see if the external display is connected
if [ "${DP_STATUS}" = connected ]; then
EXTERNAL_DISPLAY=$DP
fi
if [ "${VGA_STATUS}" = connected ]; then
EXTERNAL_DISPLAY=$VGA
fi
if [ "${HDMI_STATUS}" = connected ]; then
EXTERNAL_DISPLAY=$HDMI
fi
# The external display is connected
if [ "$EXTERNAL_DISPLAY" != "" ]; then
# Set the display settings
xrandr --output $INTERNAL_DISPLAY --off        # Turn off internal display
xrandr --output $EXTERNAL_DISPLAY --auto     # Turn on external display
# If connected via HDMI, change the sound profile to output HDMI audio
if [ $EXTERNAL_DISPLAY=$HDMI ]; then
sudo -u $USER pactl set-card-profile 0 output:hdmi-surround
fi
# The external display is not connected
else
# Restore internal display
xrandr --output $EXTERNAL_DISPLAY --off        # Turn off internal display
xrandr --output $INTERNAL_DISPLAY --auto
# Restore default battery/power brightness
cat /proc/acpi/ac_adapter/AC/state | grep "on-line"
if [ $? -eq 0 ]; then
xbacklight -set    $BACKLIGHT_AC        # Power cable is connected
else
xbacklight -set    $BACKLIGHT_BATTERY    # Power cable is not connected
fi
# Restore laptop sound profile
sudo -u $USER pactl set-card-profile 0 output:analog-stereo+input:analog-stereo
fi
exit 0

Afterwards, in a terminal I made sure the script was executable and that I update the udev rules:
sudo udevadm control --reload-rules
sudo chmod 755 /usr/local/bin/MToggle-udev

and done! Now it should work!