]> git.donarmstrong.com Git - deb_pkgs/autorandr.git/blob - autorandr
call xrandr to refresh sysfs
[deb_pkgs/autorandr.git] / autorandr
1 #!/bin/sh
2 #
3 # Automatically select a display configuration based on connected devives
4 #
5 # Stefan Tomanek <stefan.tomanek@wertarbyte.de>
6 #
7 # How to use:
8 #
9 # Save your current display configuration and setup with
10 # autorandr --save mobile
11 #
12 # Connect an additional display, configure your setup and save it
13 # autorand --save docked
14 #
15 # Now autorandr can detect which hardware setup is active:
16 # # autorandr
17 # mobile
18 # docked (detected)
19 #
20 # To automatically reload your setup, just append --change to the command line
21 #
22 # To manually load a profile, you can use the --load <profile> option.
23 #
24 # To prevent a profile from being loaded, place a script call "block" in its
25 # directory. The script is evaluated before the screen setup is inspected, and
26 # in case of it returning a value of 0 the profile is skipped. This can be used
27 # to query the status of a docking station you are about to leave.
28 #
29 # If no suitable profile can be identified, the current configuration is kept.
30 # To change this behaviour and switch to a fallback configuration, specify
31 # --default <profile>
32 #
33 # Another script called "postswitch "can be placed in the directory
34 # ~/.auto-disper as well as in all profile directories: The scripts are
35 # executed after a mode switch has taken place and can notify window managers
36 # or other applications about it.
37
38 XRANDR=/usr/bin/xrandr
39 PROFILES=~/.autorandr/
40 CONFIG=~/.autorandr.conf
41
42 CHANGE_PROFILE=0
43 DEFAULT_PROFILE=""
44 SAVE_PROFILE=""
45
46 FP_METHODS="setup_fp_xrandr_edid setup_fp_sysfs_edid"
47
48 test -f $CONFIG && . $CONFIG 
49
50 setup_fp_xrandr_edid() {
51         $XRANDR -q --verbose | awk '
52         /^[^ ]+ (dis)?connected / { DEV=$1; }
53         $1 ~ /^[a-f0-9]+$/ { ID[DEV] = ID[DEV] $1 }
54         END { for (X in ID) { print X " " ID[X]; } }'
55 }
56
57 setup_fp_sysfs_edid() {
58         # xrandr triggers the reloading of EDID data
59         $XRANDR -q > /dev/null
60         # hash the EDIDs of all _connected_ devices
61         for P in /sys/class/drm/card*-*/; do
62                 if grep -q "^connected$" < "${P}status"; then
63                         echo -n "$(basename "$P") "
64                         md5sum ${P}edid | awk '{print $1}'
65                 fi
66         done
67 }
68
69 setup_fp() {
70         local FP="";
71         for M in $FP_METHODS; do
72                 FP="$($M)"
73                 [ -n "$FP" ] && break;
74         done
75         if [ -z "$FP" ]; then
76                 echo "Unable to fingerprint display configuration" >&2
77                 return
78         fi
79         echo "$FP"
80 }
81
82
83 current_cfg() {
84         $XRANDR -q | awk '
85         /^[^ ]+ disconnected / {
86         print "output "$1;
87                 print "off";
88         }
89         /^[^ ]+ connected / {
90                 split($3, A, "+");
91                 print "output "$1;
92                 print "mode "A[1];
93                 print "pos "A[2]"x"A[3];
94         }'
95 }
96
97 blocked() {
98         local PROFILE="$1"
99         [ ! -x "$PROFILES/$PROFILE/block" ] && return 1
100
101         "$PROFILES/$PROFILE/block" "$PROFILE"
102 }
103
104 load() {
105         local PROFILE="$1"
106         if [ "$CHANGE_PROFILE" -eq 1 ] && [ -e "$PROFILES/$PROFILE/config" ] ; then
107                 echo " -> loading profile $PROFILE"
108                 sed 's!^!--!' "$PROFILES/$PROFILE/config" | xargs xrandr
109
110                 [ -x "$PROFILES/$PROFILE/postswitch" ] && \
111                         "$PROFILES/$PROFILE/postswitch" "$PROFILE"
112                 [ -x "$PROFILES/postswitch" ] && \
113                         "$PROFILES/postswitch" "$PROFILE"
114         fi
115 }
116
117 help() {
118         cat <<EOH
119 Usage: autorandr action [profile-name]
120
121 -h, --help              get this small help
122 -c, --change            reload current setup
123 -s, --save <profile>    save your current setup to profile <profile>
124 -l, --load <profile>    load profile <profile>
125 --fingerprint           fingerprints your actual config 
126
127  To prevent a profile from being loaded, place a script call "block" in its
128  directory. The script is evaluated before the screen setup is inspected, and
129  in case of it returning a value of 0 the profile is skipped. This can be used
130  to query the status of a docking station you are about to leave.
131
132  If no suitable profile can be identified, the current configuration is kept.
133  To change this behaviour and switch to a fallback configuration, specify
134  --default <profile>
135
136  Another script called "postswitch "can be placed in the directory
137  ~/.auto-disper as well as in all profile directories: The scripts are
138  executed after a mode switch has taken place and can notify window managers
139
140 EOH
141         exit
142 }
143 # process parameters
144 OPTS=$(getopt -n autorandr -o s:l:d:cfh --long change,default:,save:,load:,fingerprint,help -- "$@")
145 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
146 eval set -- "$OPTS"
147
148 while true; do
149         case "$1" in
150                 -c|--change) CHANGE_PROFILE=1; shift ;;
151                 -d|--default) DEFAULT_PROFILE="$2"; shift 2 ;;
152                 -s|--save) SAVE_PROFILE="$2"; shift 2 ;;
153                 -l|--load) LOAD_PROFILE="$2"; shift 2 ;;
154                 -h|--help) help ;; 
155                 --fingerprint) setup_fp; exit 0;;
156                 --) shift; break ;;
157                 *) echo "Error: $1"; exit 1;;
158         esac
159 done
160
161 CURRENT_SETUP="$(setup_fp)"
162
163 if [ -n "$SAVE_PROFILE" ]; then
164         echo "Saving current configuration as profile '${SAVE_PROFILE}'"
165         mkdir -p "$PROFILES/$SAVE_PROFILE"
166         echo "$CURRENT_SETUP" > "$PROFILES/$SAVE_PROFILE/setup"
167         current_cfg > "$PROFILES/$SAVE_PROFILE/config"
168         exit 0
169 fi
170
171 if [ -n "$LOAD_PROFILE" ]; then
172         CHANGE_PROFILE=1 load "$LOAD_PROFILE"
173         exit $?
174 fi
175
176 for SETUP_FILE in $PROFILES/*/setup; do
177         if ! [ -e $SETUP_FILE ]; then
178                 break
179         fi
180         PROFILE="$(basename $(dirname "$SETUP_FILE"))"
181         echo -n "$PROFILE"
182
183         if blocked "$PROFILE"; then
184                 echo " (blocked)"
185                 continue
186         fi
187
188         FILE_SETUP="$(cat "$PROFILES/$PROFILE/setup")"
189         if [ "$CURRENT_SETUP" = "$FILE_SETUP" ]; then
190                 echo " (detected)"
191                 load "$PROFILE"
192                 # found the profile, exit with success
193                 exit 0
194         else
195                 echo ""
196         fi
197 done
198
199 # we did not find the profile, load default
200 if [ -n "$DEFAULT_PROFILE" ]; then
201         echo "No suitable profile detected, falling back to $DEFAULT_PROFILE"
202         load "$DEFAULT_PROFILE"
203 fi
204 exit 1