3 # vidwhacker, for xscreensaver. Copyright (c) 1998, 1999 Jamie Zawinski.
5 # Permission to use, copy, modify, distribute, and sell this software and its
6 # documentation for any purpose is hereby granted without fee, provided that
7 # the above copyright notice appear in all copies and that both that
8 # copyright notice and this permission notice appear in supporting
9 # documentation. No representations are made about the suitability of this
10 # software for any purpose. It is provided "as is" without express or
14 # This script grabs a frame of video, then uses various pbm filters to
15 # munge the image in random nefarious ways, then uses xloadimage, xli, or xv
16 # to put it on the root window. This works out really nicely if you just
17 # feed some random TV station into it...
19 # The video grabbing part is SGI-specific -- if you want to use this on
20 # another system, add a new clause to the grab() procedure.
23 # need perl to generate random numbers -- I don't know another way to do
24 # that from a shell script.
35 tmp=${TMPDIR:-/tmp}/vidwhacker.$$
36 tmp_rgb=$tmp-00000.rgb
45 # Figure out whether to use xloadimage, xli, or xv.
48 for prog in xloadimage xli xv ; do
52 if [ "$p" = "" ]; then p=. ; fi
53 if [ -x $p/$prog ]; then
60 if [ "$displayer" = "xloadimage" ]; then
61 displayer_args="-quiet"
63 displayer_root_args="-onroot"
64 elif [ "$displayer" = "xli" ]; then
65 displayer_args="-quiet"
67 displayer_root_args="-onroot -center -border black"
68 elif [ "$displayer" = "xv" ]; then
69 displayer_args="-quick24"
70 displayer_win_args="-geom +0+0"
71 displayer_root_args="-root -rmode 5 -noresetroot -rfg black -rbg black -viewonly"
73 echo "$0: neither xli nor xv found on \$PATH"
78 # Process command-line args
83 -display | -disp | -dis | -dpy | -d )
108 echo "VidWhacker, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org>" >&2
109 echo " http://www.jwz.org/xscreensaver/" >&2
111 echo "usage: $0 [-display dpy] [-verbose] [-root | -window]" >&2
112 echo " [-stdin] [-stdout] [-delay secs]" >&2
121 if [ "$onroot" = true ]; then
122 displayer_args="$displayer_args $displayer_root_args"
124 displayer_args="$displayer_args $displayer_win_args"
129 if [ "$use_stdout" = false ]; then
130 screen_width=`xdpyinfo 2>/dev/null |
131 sed -n 's/.* dimensions: *\([0-9]*\).*/\1/p'`
132 if [ "$screen_width" = "" ]; then
140 rm -f $tmp_rgb $tmp_ppm1 $tmp_ppm2 $tmp_ppm3 $tmp_ppm4
145 rm -f $tmp_ppm0 $tmp_ppmS
149 # Grab a frame of video. leaves it in $tmp_ppm1.
153 if [ $uname = IRIX ]; then
155 # SGI's "vidtomem" returns an SGI RGB image of the default video input,
156 # and has stupid non-overridable ouput-file-naming conventions. So, let
157 # it write its file; and then convert it to a pgm.
161 sgitopnm $tmp_rgb > $tmp_ppm1
163 # Cut off the close-captioning blips in the NTSC overscan region. YMMV.
164 # | pnmcut 12 7 695 477
166 elif [ $uname = Linux ]; then
168 # Marcus Herbert says the following works with his Connectix Qcam.
169 # Don't have qcam? Well, do something else then... and send me a patch.
173 # Friedrich Delgado Friedrichs says the following works if you have
176 # streamer -o $tmp_ppm1
179 # James Isaacs says this works for the ATI video capture card:
181 # atitv snap $tmp_ppm1
185 echo "$0: don't know how to grab video on this OS." >&2
192 # Use perl to pick a random foreground/background color in pbm's syntax.
195 $perl -e 'srand(time ^ $$);
196 printf("#%02x%02x%02x-#%02x%02x%02x",
202 120+int(rand()*135))'
206 $perl -e "srand(time ^ $$); print int(rand() * $1)"
211 # Frobnicate the image in some random way.
215 w_h=`head -2 $tmp_ppm1 | tail -1`
216 width=`echo $w_h | awk '{print $1}'`
217 height=`echo $w_h | awk '{print $2}'`
221 if [ "$verbose" = true ]; then
222 echo "mode $N..." >&2
226 ppmtopgm $tmp_ppm1 | pgmedge | pgmtoppm `randcolor` | ppmnorm
228 elif [ $N = 1 ]; then
233 elif [ $N = 2 ]; then
234 ppmtopgm $tmp_ppm1 | pgmoil | pgmtoppm `randcolor`
236 elif [ $N = 3 ]; then
237 ppmrelief $tmp_ppm1 | ppmtopgm | pgmedge | ppmrelief | ppmtopgm |
238 pgmedge | pnminvert | pgmtoppm `randcolor`
240 elif [ $N = 4 ]; then
241 ppmspread 71 $tmp_ppm1 > $tmp_ppm2
242 pnmarith -add $tmp_ppm1 $tmp_ppm2
244 elif [ $N = 5 ]; then
245 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
246 pnmarith -multiply $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3
247 pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2
248 pnmarith -multiply $tmp_ppm1 $tmp_ppm2
250 elif [ $N = 6 ]; then
253 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
254 elif [ $N2 = 1 ]; then
255 pnmflip -tb $tmp_ppm1 > $tmp_ppm2
257 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
258 pnmflip -tb $tmp_ppm2 > $tmp_ppm3
259 cp $tmp_ppm3 $tmp_ppm2
262 pnmarith -difference $tmp_ppm1 $tmp_ppm2
264 elif [ $N = 7 ]; then
267 ppmtopgm $tmp_ppm1 | pgmedge > $tmp_ppm2
268 pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3
269 cp $tmp_ppm3 $tmp_ppm1
273 elif [ $N = 8 ]; then
274 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
275 pnmarith -multiply $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmnorm | pnminvert
277 elif [ $N = 9 ]; then
278 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
279 pnmarith -subtract $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmtopgm | pgmedge
281 elif [ $N = 10 ]; then
282 ppmtopgm $tmp_ppm1 | pgmbentley | pgmtoppm `randcolor`
284 elif [ $N = 11 ]; then
285 pgmcrater -number 20000 -height $height -width $width | pgmtoppm `randcolor` > $tmp_ppm2
286 pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3
287 pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2
288 pnmarith -multiply $tmp_ppm1 $tmp_ppm2
290 elif [ $N = 12 ]; then
291 ppmshift 30 $tmp_ppm1 | ppmtopgm | pgmoil | pgmedge | pgmtoppm `randcolor` > $tmp_ppm2
292 pnmarith -difference $tmp_ppm1 $tmp_ppm2
294 elif [ $N = 13 ]; then
295 ppmpat -madras $width $height | pnmdepth 255 > $tmp_ppm2
296 pnmarith -difference $tmp_ppm1 $tmp_ppm2
298 elif [ $N = 14 ]; then
299 ppmpat -tartan $width $height | pnmdepth 255 > $tmp_ppm2
300 pnmarith -difference $tmp_ppm1 $tmp_ppm2
302 elif [ $N = 15 ]; then
303 ppmpat -camo $width $height | pnmdepth 255 | ppmshift 50 > $tmp_ppm2
304 pnmarith -multiply $tmp_ppm1 $tmp_ppm2
306 elif [ $N = 16 ]; then
307 pgmnoise $width $height | pgmedge | pgmtoppm `randcolor` > $tmp_ppm2
308 pnmarith -difference $tmp_ppm1 $tmp_ppm2 | pnmdepth 255 | pnmsmooth
315 # Grab a frame and frob it. leave it in $tmp_ppm3.
320 while [ ! -f $tmp_ppm1 ]; do
321 if [ "$use_stdin" != true ]; then
324 cp $tmp_ppmS $tmp_ppm0
325 cp $tmp_ppm0 $tmp_ppm1
331 if [ "$screen_width" != "" ]; then
332 frob | pnmscale -width $screen_width > $tmp_ppm3
337 rm -f $tmp_ppm1 $tmp_ppm2
341 # Kill off the xli or xv subprocess, if it's running
344 if [ "$pid" != "" ]; then
346 if [ "$verbose" = true ]; then
347 echo "killing pid $pid..." >&2
350 # need to do this to avoid "6898 Terminated" messages!
351 # apparently one can't redirect the output of the builtin `kill' command.
352 # ( sh -c "kill $pid" ) >/dev/null 2>/dev/null </dev/null
354 # wtf? that doesn't work either. Is it writing to /dev/tty??
355 kill $pid >/dev/null 2>&1
361 # called when this process is signalled (for cleanup)
364 if [ "$verbose" = true ]; then
365 echo "trapped signal!" >&2
376 trap my_trap 1 2 3 6 9 13 15
378 if [ "$use_stdin" = true ]; then
384 # Loop grabbing and frobbing images.
386 # If we're running on the root, run xv or xli in the foreground
387 # (with -exit, if xv) and then wait.
389 # If we're running in a window, spawn xv or xli in the background; then
390 # when it's time to put up the new image, kill off the currently-running
393 if [ "$verbose" = true ]; then
396 whack >/dev/null 2>&1
401 if [ ! -s $tmp_ppm3 ]; then
402 echo "$0: no image grabbed" >&2
404 elif [ "$use_stdout" = true ]; then
412 # pnmtosgi < $tmp_ppm3 > $tmp_ppm2
414 mv $tmp_ppm3 $tmp_ppm2
416 if [ -s $tmp_ppm2 ]; then
417 if [ "$verbose" = true ]; then
418 echo "launching $displayer $displayer_args $tmp_ppm2" >&2
422 mv $tmp_ppm2 $tmp_ppm0
423 eval "$displayer $displayer_args $tmp_ppm0 &"
425 # this doesn't work -- leaves xv processes around, instead of stray xset
428 # # cat the file so that we can nuke it without racing against xv.
429 # cat $tmp_ppm2 | $displayer $displayer_args - &
444 # to find stray xv data:
445 # xwininfo -root -children|grep 'xv image comments' | awk '{print "xkill -id ", $1}'