1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
#! /bin/bash
# This script needs bash for the arrays
# This script adds the common resolutions to the Xserver if and only if there
# is a beamer connected. Additionally, if the preferred resolution is known,
# (i.e. the Xserver received a proper EDID) the latter will be applied.
################################################################################
# Add or remove additional modes here.
declare -a MODES
MODES=("${MODES[@]}" "1280x800 83.50 1280 1352 1480 1680 800 803 809 831 -hsync +vsync")
MODES=("${MODES[@]}" "1440x1050 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync")
MODES=("${MODES[@]}" "1680x1200 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync")
MODES=("${MODES[@]}" "1920x1200 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync")
MODES=("${MODES[@]}" "1280x720 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync")
MODES=("${MODES[@]}" "1368x768 85.25 1368 1440 1576 1784 768 771 781 798 -hsync +vsync")
MODES=("${MODES[@]}" "1600x900 118.25 1600 1696 1856 2112 900 903 908 934 -hsync +vsync")
MODES=("${MODES[@]}" "1920x1080 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync")
MODES=("${MODES[@]}" "800x600 38.25 800 832 912 1024 600 603 607 624 -hsync +vsync")
MODES=("${MODES[@]}" "1024x768 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync")
MODES=("${MODES[@]}" "1152x864 81.75 1152 1216 1336 1520 864 867 871 897 -hsync +vsync")
MODES=("${MODES[@]}" "1280x960 101.25 1280 1360 1488 1696 960 963 967 996 -hsync +vsync")
MODES=("${MODES[@]}" "1280x1024 109.00 1280 1368 1496 1712 1024 1027 1034 1063 -hsync +vsync")
################################################################################
CONFIGFILE="/opt/openslx/beamergui/beamer.conf"
# Hard-code a few models known to be problematic
declare -a FORCE_BEAMER
FORCE_BEAMER=("AT-HDVS-RX")
################################################################################
#DRIVER=$(lspci -nnk | grep -i vga -A3 | grep 'in use'| awk '{ print $NF }')
XRANDR=$( xrandr )
XRANDRV=$( xrandr --verbose )
################################################################################
echo "$XRANDR"
#echo "$XRANDRV"
# Get the names of the connected outputs
# This is a rigid approach to determine the connected outputs
declare -a OUTPUTNAMES
while read -r line || [[ -n "$line" ]]; do
OUTPUTNAMES+=("$( <<<"$line" awk '{print $1}' )")
done < <( <<<"$XRANDR" grep -E "[[:digit:]]+mm x [[:digit:]]+mm" )
echo -e "Connected outputs: \e[32m${OUTPUTNAMES[@]}\e[0m"
# The goal is to add more modelines to the X server. While this is done the
# screen is flickering. Hence this is just necessary if there is a beamer. Do
# the flickering magic only if there are two outputs and one is a projector.
#Two outputs?
if [ ${#OUTPUTNAMES[@]} -eq 2 ]; then
echo "Two outputs detected."
if ! [ -f "$CONFIGFILE" ]; then
echo "No additional beamer file (${CONFIGFILE}) found."
elif ! [ -r "$CONFIGFILE" ]; then
echo "$CONFIGFILE found but not readable."
else
echo "beamer.conf found, contains the following beamer definitions:"
<"$CONFIGFILE" grep '=beamer$'
fi
# Either of them a projector?
BEAMER=
MAYBEAMER=
SMALL=
for i in 0 1; do
# See if we hard-coded the device as a beamer
# Use echo -e -n "" instead of piping the sed output into xargs printf, as xargs
# handles backslashes differently depending on the version.
EDID=$( echo -e -n "$( <<<"$XRANDRV" grep -Pzo "\n${OUTPUTNAMES[$i]}\N*connected\N*\n(\s+\N*\n)+" | grep -Eao '[0-9a-f]{32}' | sed -r ':a;N;$!ba;s/[^0-9a-f]//gI;s/([0-9a-f]{2})/\\x\1/gI' )" | parse-edid )
MODEL_NAME=$( <<<"$EDID" awk '{if ($1 == "ModelName") { A=$2$3$4$5; print substr(A, 2, length(A) - 2)}}' )
echo "'${OUTPUTNAMES[$i]}' is connected to device '$MODEL_NAME'"
# Have a name, do the checks
if [ -n "$MODEL_NAME" ]; then
FOUND=
# Try hard coded values from above
for model in "${FORCE_BEAMER[@]}"; do
if [ "x$model" = "x$MODEL_NAME" ]; then
echo "Model is hard-coded as beamer"
FOUND=ya
break
fi
done
# Now try user supplied config
if [ -z "$FOUND" ] && [ -f "$CONFIGFILE" ] && grep -Fxq "${MODEL_NAME}=beamer" "$CONFIGFILE"; then
echo "Model is defined as beamer in beamer.conf"
FOUND=ya
fi
# Set beamer if any match
if [ -n "$FOUND" ]; then
BEAMER=$i
continue
fi
fi
# Classic test by what X(randr) figured out
WIDTH=$( <<<"$XRANDR" grep -E "^${OUTPUTNAMES[$i]}.*[0-9]+mm x [0-9]+mm" | head -n 1 | grep -o -E ' [0-9]+mm x' | grep -o -E '[0-9]+' )
if [ -z "$WIDTH" ] || [ "$WIDTH" -eq 0 ] || [ "$WIDTH" -gt 900 ]; then
echo "Screen $i is beamer, width is '$WIDTH'"
BEAMER=$i
elif [ -n "$WIDTH" ] && [ "$WIDTH" -gt 700 ]; then
MAYBEAMER=$i
elif [ -n "$WIDTH" ] && [ "$WIDTH" -lt 550 ]; then
SMALL=yes
fi
done
if [ -z "$BEAMER" ] && [ -n "$MAYBEAMER" ] && [ -n "$SMALL" ]; then
# This is a hack on top of the other hack; we already treat outputs reporting a sufficiently large width
# as beamers, as we have encountered such devices in the wild. However, we might have just a large TV connected
# that is intended to be used just like a beamer to present the screen to the audience. So if we have a screen
# that is at least 70cm wide and the other one is no wider than 55cm we treat this as a beamer setup aswell.
# The reasoning here is that if it were a dual screen setup, the screens should be roughly the same size.
echo "Treating $MAYBEAMER as beamer as size difference is big enough"
BEAMER=$MAYBEAMER
fi
if [ -n "$BEAMER" ]; then
echo "${OUTPUTNAMES[$BEAMER]} is a beamer. "
# Create all modes, so that X knows them by name "<width>x<height>"
# Add the modes to the outputs, this means that, if this action is
# successful they can be applied to the screens.
for i in "${MODES[@]}"; do
if xrandr --current --newmode $i; then # No quotes around $i here!
echo -e "Created mode ${i%% *}."
else
echo -e "\e[31mFailed to create mode ${i%% *}!\e[0m"
fi
for j in "${OUTPUTNAMES[@]}"; do
if xrandr --current --addmode "$j" "${i%% *}"; then
echo -e "Added mode ${i%% *} to $j."
else
echo -e "\e[31mFailed to add mode ${i%% *} to $j!\e[0m"
break
fi
done
done
# Finally, if the EDID is present, apply a proper resolution.
# Find out whether the beamer transmits reliable EDID data.
# The data in xrandr should be reliable if the EDID is present.
if <<<"$XRANDRV" grep -Pzo \
"\n${OUTPUTNAMES[$BEAMER]}\N*\n(\s+\N*\n)+" \
| grep EDID > /dev/null ; then
echo "${OUTPUTNAMES[$BEAMER]} [Beamer] provides EDID."
# If the breamer transmits the EDID there shall be a preferred resolution.
OPTIMALRES=$( <<<"$XRANDRV" grep -Pzo "\n${OUTPUTNAMES[$BEAMER]}\N*\n(\s+\N*\n)+" \
| grep preferred | awk '{print $1}' )
# (try to) make sure the display has the preferred mode of the beamer added to it, in case it wasn't in our list from above
xrandr --current --addmode "${OUTPUTNAMES[$((1-$BEAMER))]}" "$OPTIMALRES"
# Apply the optimal resolution tho either of the outputs. The beamer has
# to be the secondary output.
if xrandr \
--output "${OUTPUTNAMES[$((1-$BEAMER))]}" --mode "$OPTIMALRES" \
--primary \
--output "${OUTPUTNAMES[$BEAMER]}" --mode "$OPTIMALRES" \
--same-as "${OUTPUTNAMES[$((1-$BEAMER))]}"
then
echo "Applied optimal resolution successfully."
fi
elif [[ -f "$CONFIGFILE" ]]; then
echo "Config file found."
# Get local ip
. /opt/openslx/config
# Try to get a probed mode
PROBEDMODE=$( <<<"$CONFIGFILE" grep "^\s*$SLX_PXE_CLIENT_IP" | cut -d '=' -f2 )
# If a probed mode was found, ..
if [[ -n "$PROBEDMODE" ]]; then
echo "Probed mode found in config file."
# Apply the probed mode from the config file
if xrandr \
--output "${OUTPUTNAMES[$((1-$BEAMER))]}" --mode "$PROBEDMODE" \
--primary \
--output "${OUTPUTNAMES[$BEAMER]}" --mode "$PROBEDMODE" \
--same-as "${OUTPUTNAMES[$((1-$BEAMER))]}"
then
echo "Applied probed mode successfully."
fi
else
echo -e "\e[31mERROR: Beamer provides no EDID and no probed mode given in $CONFIGFILE.\e[0m"
fi
else
# Apply a fallback mode
echo -e "\e[31mERROR: Beamer provides no EDID and no config file found in $CONFIGFILE. Falling back to 1024x768.\e[0m"
xrandr \
--output "${OUTPUTNAMES[$((1-$BEAMER))]}" --mode "1024x768" \
--primary \
--output "${OUTPUTNAMES[$BEAMER]}" --mode "1024x768" \
--same-as "${OUTPUTNAMES[$((1-$BEAMER))]}"
fi
else
# In case of two monitors just sort the outputs lexicographically and apply
# the preffered resolution
echo "Dualhead setup deteced. Sorting outputs lexicographically."
readarray -t OUTPUTNAMES \
< <(for a in "${OUTPUTNAMES[@]}"; do echo "$a"; done | sort)
echo "${OUTPUTNAMES[@]}"
if xrandr \
--output "${OUTPUTNAMES[0]}" --preferred \
--primary \
--output "${OUTPUTNAMES[1]}" --preferred \
--right-of "${OUTPUTNAMES[0]}"
then
echo "Successfully applied preferred modes on outputs in sorted order."
fi
fi
else
echo -e "\e[32mOther than two outputs.\e[0m"
fi
|