#
# To manually load a profile, you can use the --load <profile> option.
#
+# autorandr tries to avoid reloading an identical configuration. To force the
+# configuration, apply --force.
+#
# To prevent a profile from being loaded, place a script call "block" in its
# directory. The script is evaluated before the screen setup is inspected, and
# in case of it returning a value of 0 the profile is skipped. This can be used
XRANDR=/usr/bin/xrandr
PROFILES=~/.autorandr/
+CONFIG=~/.autorandr.conf
CHANGE_PROFILE=0
+FORCE_LOAD=0
DEFAULT_PROFILE=""
SAVE_PROFILE=""
-setup_fp_edid() {
+FP_METHODS="setup_fp_xrandr_edid setup_fp_sysfs_edid"
+
+test -f $CONFIG && . $CONFIG
+
+setup_fp_xrandr_edid() {
$XRANDR -q --verbose | awk '
- /^[^ ]+ (dis)?connected / { DEV=$1; ID[DEV] = ""; }
+ /^[^ ]+ (dis)?connected / { DEV=$1; }
$1 ~ /^[a-f0-9]+$/ { ID[DEV] = ID[DEV] $1 }
END { for (X in ID) { print X " " ID[X]; } }'
}
-setup_fp_dim() {
- $XRANDR -q --verbose | awk '
- /^[^ ]+ connected / { CONNECTED=1 }
- /^[^ ]+ disconnected / { CONNECTED=0 }
- /^[^ ]+ (dis)?connected / \
- && match($0, "([0-9]+mm) x ([0-9]+mm)", A) {
- print $1, (CONNECTED==1 ? A[1]"x"A[2] : "" )
- }'
+setup_fp_sysfs_edid() {
+ # xrandr triggers the reloading of EDID data
+ $XRANDR -q > /dev/null
+ # hash the EDIDs of all _connected_ devices
+ for P in /sys/class/drm/card*-*/; do
+ if grep -q "^connected$" < "${P}status"; then
+ echo -n "$(basename "$P") "
+ md5sum ${P}edid | awk '{print $1}'
+ fi
+ done
+}
+
+setup_fp() {
+ local FP="";
+ for M in $FP_METHODS; do
+ FP="$($M)"
+ [ -n "$FP" ] && break;
+ done
+ if [ -z "$FP" ]; then
+ echo "Unable to fingerprint display configuration" >&2
+ return
+ fi
+ echo "$FP"
}
}
blocked() {
- local PROFILE="$1"
- [ ! -x "$PROFILES/$PROFILE/block" ] && return 1
+ local PROFILE="$1"
+ [ ! -x "$PROFILES/$PROFILE/block" ] && return 1
- "$PROFILES/$PROFILE/block" "$PROFILE"
+ "$PROFILES/$PROFILE/block" "$PROFILE"
+}
+
+config_equal() {
+ local PROFILE="$1"
+ if [ "$(cat "$PROFILES/$PROFILE/config")" = "$(current_cfg)" ]; then
+ echo "Config already loaded"
+ return 0
+ else
+ return 1
+ fi
}
load() {
- local PROFILE="$1"
- if [ "$CHANGE_PROFILE" -eq 1 ]; then
- echo " -> loading profile $PROFILE"
- sed 's!^!--!' "$PROFILES/$PROFILE/config" | xargs xrandr
-
- [ -x "$PROFILES/$PROFILE/postswitch" ] && \
- "$PROFILES/$PROFILE/postswitch" "$PROFILE"
- [ -x "$PROFILES/postswitch" ] && \
- "$PROFILES/postswitch" "$PROFILE"
- fi
+ local PROFILE="$1"
+ if [ -e "$PROFILES/$PROFILE/config" ] ; then
+ echo " -> loading profile $PROFILE"
+ sed 's!^!--!' "$PROFILES/$PROFILE/config" | xargs xrandr
+
+ [ -x "$PROFILES/$PROFILE/postswitch" ] && \
+ "$PROFILES/$PROFILE/postswitch" "$PROFILE"
+ [ -x "$PROFILES/postswitch" ] && \
+ "$PROFILES/postswitch" "$PROFILE"
+ fi
}
+help() {
+ cat <<EOH
+Usage: autorandr action [profile-name]
+
+-h, --help get this small help
+-c, --change reload current setup
+-s, --save <profile> save your current setup to profile <profile>
+-l, --load <profile> load profile <profile>
+--force force loading of a profile
+--fingerprint fingerprints your actual config
+
+ To prevent a profile from being loaded, place a script call "block" in its
+ directory. The script is evaluated before the screen setup is inspected, and
+ in case of it returning a value of 0 the profile is skipped. This can be used
+ to query the status of a docking station you are about to leave.
+
+ If no suitable profile can be identified, the current configuration is kept.
+ To change this behaviour and switch to a fallback configuration, specify
+ --default <profile>
+
+ Another script called "postswitch "can be placed in the directory
+ ~/.auto-disper as well as in all profile directories: The scripts are
+ executed after a mode switch has taken place and can notify window managers
+
+EOH
+ exit
+}
# process parameters
-OPTS=$(getopt -n autorandr -o s:l:d:cf --long change,default:,save:,load:,fingerprint -- "$@")
+OPTS=$(getopt -n autorandr -o s:l:d:cfh --long change,default:,save:,load:,force,fingerprint,help -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
eval set -- "$OPTS"
while true; do
- case "$1" in
- -c|--change) CHANGE_PROFILE=1; shift ;;
- -d|--default) DEFAULT_PROFILE="$2"; shift 2 ;;
- -s|--save) SAVE_PROFILE="$2"; shift 2 ;;
- -l|--load) LOAD_PROFILE="$2"; shift 2 ;;
- --fingerprint) setup_fp_edid; exit 0;;
- --) shift; break ;;
- *) echo "Error: $1"; exit 1;;
- esac
+ case "$1" in
+ -c|--change) CHANGE_PROFILE=1; shift ;;
+ -d|--default) DEFAULT_PROFILE="$2"; shift 2 ;;
+ -s|--save) SAVE_PROFILE="$2"; shift 2 ;;
+ -l|--load) LOAD_PROFILE="$2"; shift 2 ;;
+ -h|--help) help ;;
+ --force) FORCE_LOAD=1; shift ;;
+ --fingerprint) setup_fp; exit 0;;
+ --) shift; break ;;
+ *) echo "Error: $1"; exit 1;;
+ esac
done
-CURRENT_SETUP="$(setup_fp_edid)"
+CURRENT_SETUP="$(setup_fp)"
if [ -n "$SAVE_PROFILE" ]; then
- echo "Saving current configuration as profile '${SAVE_PROFILE}'"
- mkdir -p "$PROFILES/$SAVE_PROFILE"
- echo "$CURRENT_SETUP" > "$PROFILES/$SAVE_PROFILE/setup"
- current_cfg > "$PROFILES/$SAVE_PROFILE/config"
- exit 0
+ echo "Saving current configuration as profile '${SAVE_PROFILE}'"
+ mkdir -p "$PROFILES/$SAVE_PROFILE"
+ echo "$CURRENT_SETUP" > "$PROFILES/$SAVE_PROFILE/setup"
+ current_cfg > "$PROFILES/$SAVE_PROFILE/config"
+ exit 0
fi
if [ -n "$LOAD_PROFILE" ]; then
- CHANGE_PROFILE=1 load "$LOAD_PROFILE"
- exit $?
+ CHANGE_PROFILE=1 FORCE_LOAD=1 load "$LOAD_PROFILE"
+ exit $?
fi
for SETUP_FILE in $PROFILES/*/setup; do
- if ! [ -e $SETUP_FILE ]; then
- break
- fi
- PROFILE="$(basename $(dirname "$SETUP_FILE"))"
- echo -n "$PROFILE"
-
- if blocked "$PROFILE"; then
- echo " (blocked)"
- continue
- fi
-
- FILE_SETUP="$(cat "$PROFILES/$PROFILE/setup")"
- if [ "$CURRENT_SETUP" = "$FILE_SETUP" ]; then
- echo " (detected)"
- load "$PROFILE"
- # found the profile, exit with success
- exit 0
- else
- echo ""
- fi
+ if ! [ -e $SETUP_FILE ]; then
+ break
+ fi
+ PROFILE="$(basename $(dirname "$SETUP_FILE"))"
+ echo -n "$PROFILE"
+
+ if blocked "$PROFILE"; then
+ echo " (blocked)"
+ continue
+ fi
+
+ FILE_SETUP="$(cat "$PROFILES/$PROFILE/setup")"
+ if [ "$CURRENT_SETUP" = "$FILE_SETUP" ]; then
+ echo " (detected)"
+ if [ "$CHANGE_PROFILE" -eq 1 ]; then
+ if [ "$FORCE_LOAD" -eq 1 ] || ! config_equal "$PROFILE"; then
+ load "$PROFILE"
+ fi
+ fi
+ # found the profile, exit with success
+ exit 0
+ else
+ echo ""
+ fi
done
# we did not find the profile, load default
if [ -n "$DEFAULT_PROFILE" ]; then
- echo "No suitable profile detected, falling back to $DEFAULT_PROFILE"
- load "$DEFAULT_PROFILE"
+ echo "No suitable profile detected, falling back to $DEFAULT_PROFILE"
+ load "$DEFAULT_PROFILE"
fi
exit 1