aboutsummaryrefslogtreecommitdiff
path: root/gammatrip.sh
blob: 2f5553a9807369950e7d4a02c1399eb7bb201f6d (plain)
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
#!/bin/bash

# gammatrip.sh by B. Watson <urchlay@slackware.uk>.
# Licensed under the WTFPL. See http://www.wtfpl.net/txt/copying/ for details.
# Developed on Slackware 14.2, should work on most modern Linux distros.

# Randomly change gamma in X, crude simulation of an acid trip.
# It's also similar to the Atari 400/800/XL/XE "Attract Mode".
# Runs until killed via ^C or closing its terminal window, at which time
# it restores the original gamma setting, then exits.

#### User-tweakable knobs. If you don't feel like editing the script,
#    just put them on the command line, in front of the command:
#    $ DELAY=0.5 MAX=150 MIN=0 gammatrip.sh

# XRandR output to use. Leaving this blank means to use the
# first output listed by the xrandr command. Usual values are
# e.g. VGA-1 or DVI-1.
OUTPUT=

# Seconds to sleep between gamma changes. Decimal point allowed, so
# long as your system's sleep command allows it.
DELAY=${DELAY:-3}

# Max gamma for each individual color. Lower number here means darker
# colors on average. Units are 1/100ths of xrandr's --gamma floats,
# MAX=100 means 1.0. Maximum value for MAX is 999.
MAX=${MAX:-100}

# Minimum gamma for each color. Don't set higher than MAX!
# Same units as MAX.
MIN=${MIN:-30}

# VERBOSE=y to see the commands as they're executed, anything else
# means don't display them.
VERBOSE=y

#### End of user-tweakable knobs.

printmsg() {
	[ "$VERBOSE" = "y" ] && echo "$@"
}

errmsg() {
	echo "$SELF:" "$@" 1>&2
}

# Check knobs for sane(ish) settings, set up signal handlers,
# guess the active XRandR output if not provided. Get original
# gamma setting, so we can restore it later.
init() {
	SELF="$( basename $0 )"
	err=0

	if [ "$MAX" -ge 1000 ]; then
		errmsg "You can't set MAX >= 1000"
		err=1
	fi

	if [ "$MIN" -ge "$MAX" ]; then
		errmsg "You can't set MIN >= MAX"
		err=1
	fi

	if [ "$#" != "0" ]; then
		errmsg "No arguments accepted."
		errmsg "Edit script or set MIN/MAX/OUTPUT/DELAY/VERBOSE in environment."
		err=1
	fi

	if [ -z "$DISPLAY" ]; then
		errmsg "DISPLAY not set (are you running X?)"
		err=1
	fi

	[ "$err" -gt 0 ] && exit "$err"

	# SIGINT is ^C, SIGHUP is what we get when our xterm is closed.
	# SIGABRT is ^\, I hardly ever remember it exists. Trapping it here
	# doesn't work: ^\ sends the abort signal to the active child
	# process (usually sleep). Oh well. The other signals are 'just in case'.
	trap cleanup SIGINT SIGABRT SIGHUP SIGTERM SIGHUP

	OUTPUT="${OUTPUT:-$( xrandr | grep ' connected' | cut -d' ' -f1 )}"

	if [ -z "$OUTPUT" ]; then
		errmsg "Invalid OUTPUT in environment, or XRandR not supported."
		exit 1
	fi

	# Try to save the old gamma, for cleanup() to restore. Not thoroughly
	# tested (works on my system).
	OLDGAMMA="$( xrandr --verbose | sed -n '/^'$OUTPUT' /,/^[A-Z]/s/.*Gamma: *//p' )"

	# If the above command fails:
	OLDGAMMA="${OLDGAMMA:-1.0:1.0:1.0}"

	printmsg "Using output '$OUTPUT', old gamma '$OLDGAMMA'. Have a nice trip!"
}

# Called when we get a signal we trapped in init().
cleanup() {
	echo
	printmsg "Restoring old gamma"
	xrandr --output "$OUTPUT" --gamma "$OLDGAMMA"
	exit 0
}

# Takes 2 agruments: min and max. Returns a random number between
# min and max (actually >= min and < max).
getrand() {
	min="$1"
	max="$2"
	range=$(( max - min ))
	echo $(( ( RANDOM % range ) + min ))
}

# Pick random RBG values between MIN and MAX, use them to set the gamma.
cycle() {
	r="$( getrand $MIN $MAX )"
	g="$( getrand $MIN $MAX )"
	b="$( getrand $MIN $MAX )"

	cmd="xrandr --output $OUTPUT --gamma "

	for i in $r $g $b; do
		cmd="$cmd$( printf "%03d" $i | sed 's,^.,&.,' ):"
	done

	# Remove trailing colon. Actually, xrandr doesn't care about it,
	# but someday it might.
	cmd="$( echo $cmd | sed 's,:$,,' )"

	printmsg $cmd
	$cmd
}

### main()
init "$@"

while true; do
	cycle
	sleep "$DELAY"
done