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!

Advertisements