]> git.donarmstrong.com Git - deb_pkgs/autorandr.git/blob - autorandr
6ef1add9b90d43f4805c40a16134ea389cdcfb6e
[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         # hash the EDIDs of all _connected_ devices
59         for P in /sys/class/drm/card*-*/; do
60                 if grep -q "^connected$" < "${P}status"; then
61                         echo -n "$(basename "$P") "
62                         md5sum ${P}edid | awk '{print $1}'
63                 fi
64         done
65 }
66
67 setup_fp() {
68         local FP="";
69         for M in $FP_METHODS; do
70                 FP="$($M)"
71                 [ -n "$FP" ] && break;
72         done
73         if [ -z "$FP" ]; then
74                 echo "Unable to fingerprint display configuration" >&2
75                 return
76         fi
77         echo "$FP"
78 }
79
80
81 current_cfg() {
82         $XRANDR -q | awk '
83         /^[^ ]+ disconnected / {
84         print "output "$1;
85                 print "off";
86         }
87         /^[^ ]+ connected / {
88                 split($3, A, "+");
89                 print "output "$1;
90                 print "mode "A[1];
91                 print "pos "A[2]"x"A[3];
92         }'
93 }
94
95 blocked() {
96         local PROFILE="$1"
97         [ ! -x "$PROFILES/$PROFILE/block" ] && return 1
98
99         "$PROFILES/$PROFILE/block" "$PROFILE"
100 }
101
102 load() {
103         local PROFILE="$1"
104         if [ "$CHANGE_PROFILE" -eq 1 ] && [ -e "$PROFILES/$PROFILE/config" ] ; then
105                 echo " -> loading profile $PROFILE"
106                 sed 's!^!--!' "$PROFILES/$PROFILE/config" | xargs xrandr
107
108                 [ -x "$PROFILES/$PROFILE/postswitch" ] && \
109                         "$PROFILES/$PROFILE/postswitch" "$PROFILE"
110                 [ -x "$PROFILES/postswitch" ] && \
111                         "$PROFILES/postswitch" "$PROFILE"
112         fi
113 }
114
115 help() {
116         cat <<EOH
117 Usage: autorandr action [profile-name]
118
119 -h, --help              get this small help
120 -c, --change            reload current setup
121 -s, --save <profile>    save your current setup to profile <profile>
122 -l, --load <profile>    load profile <profile>
123 --fingerprint           fingerprints your actual config 
124
125  To prevent a profile from being loaded, place a script call "block" in its
126  directory. The script is evaluated before the screen setup is inspected, and
127  in case of it returning a value of 0 the profile is skipped. This can be used
128  to query the status of a docking station you are about to leave.
129
130  If no suitable profile can be identified, the current configuration is kept.
131  To change this behaviour and switch to a fallback configuration, specify
132  --default <profile>
133
134  Another script called "postswitch "can be placed in the directory
135  ~/.auto-disper as well as in all profile directories: The scripts are
136  executed after a mode switch has taken place and can notify window managers
137
138 EOH
139         exit
140 }
141 # process parameters
142 OPTS=$(getopt -n autorandr -o s:l:d:cfh --long change,default:,save:,load:,fingerprint,help -- "$@")
143 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
144 eval set -- "$OPTS"
145
146 while true; do
147         case "$1" in
148                 -c|--change) CHANGE_PROFILE=1; shift ;;
149                 -d|--default) DEFAULT_PROFILE="$2"; shift 2 ;;
150                 -s|--save) SAVE_PROFILE="$2"; shift 2 ;;
151                 -l|--load) LOAD_PROFILE="$2"; shift 2 ;;
152                 -h|--help) help ;; 
153                 --fingerprint) setup_fp; exit 0;;
154                 --) shift; break ;;
155                 *) echo "Error: $1"; exit 1;;
156         esac
157 done
158
159 CURRENT_SETUP="$(setup_fp)"
160
161 if [ -n "$SAVE_PROFILE" ]; then
162         echo "Saving current configuration as profile '${SAVE_PROFILE}'"
163         mkdir -p "$PROFILES/$SAVE_PROFILE"
164         echo "$CURRENT_SETUP" > "$PROFILES/$SAVE_PROFILE/setup"
165         current_cfg > "$PROFILES/$SAVE_PROFILE/config"
166         exit 0
167 fi
168
169 if [ -n "$LOAD_PROFILE" ]; then
170         CHANGE_PROFILE=1 load "$LOAD_PROFILE"
171         exit $?
172 fi
173
174 for SETUP_FILE in $PROFILES/*/setup; do
175         if ! [ -e $SETUP_FILE ]; then
176                 break
177         fi
178         PROFILE="$(basename $(dirname "$SETUP_FILE"))"
179         echo -n "$PROFILE"
180
181         if blocked "$PROFILE"; then
182                 echo " (blocked)"
183                 continue
184         fi
185
186         FILE_SETUP="$(cat "$PROFILES/$PROFILE/setup")"
187         if [ "$CURRENT_SETUP" = "$FILE_SETUP" ]; then
188                 echo " (detected)"
189                 load "$PROFILE"
190                 # found the profile, exit with success
191                 exit 0
192         else
193                 echo ""
194         fi
195 done
196
197 # we did not find the profile, load default
198 if [ -n "$DEFAULT_PROFILE" ]; then
199         echo "No suitable profile detected, falling back to $DEFAULT_PROFILE"
200         load "$DEFAULT_PROFILE"
201 fi
202 exit 1