X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fvidwhacker;h=a82da03ef9b1803856424d1a3e80c8a7e5c5439d;hb=06e9a7886a77cad92f9ddbc169d6d199a4d8b76d;hp=445219637485f95e68a6643a36f4264348b28a3a;hpb=6bb727f03bff0389fbb1349d7df4c9d8d7532959;p=xscreensaver diff --git a/hacks/vidwhacker b/hacks/vidwhacker index 44521963..a82da03e 100755 --- a/hacks/vidwhacker +++ b/hacks/vidwhacker @@ -1,264 +1,440 @@ #!/bin/sh # -# vidwhacker, for xscreensaver. Copyright (c) 1998 Jamie Zawinski. +# vidwhacker, for xscreensaver. Copyright (c) 1998, 1999 Jamie Zawinski. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation. No representations are made about the suitability of this +# software for any purpose. It is provided "as is" without express or +# implied warranty. +# # # This script grabs a frame of video, then uses various pbm filters to -# munge the image in random nefarious ways, then uses xv to put it on -# the root window. This works out really nicely if you just feed some -# random TV station into it... +# munge the image in random nefarious ways, then uses xloadimage, xli, or xv +# to put it on the root window. This works out really nicely if you just +# feed some random TV station into it... # # The video grabbing part is SGI-specific -- if you want to use this on # another system, add a new clause to the grab() procedure. -# Process command-line args... +# need perl to generate random numbers -- I don't know another way to do +# that from a shell script. +perl=perl + onroot=false verbose=false delay=3 +use_stdin=false +use_stdout=false -if [ "$1" = "-root" ]; then - onroot=true - shift -fi - -if [ "$1" = "-verbose" ]; then - verbose=true - shift -fi +pid="" +tmp=${TMPDIR:-/tmp}/vidwhacker.$$ +tmp_rgb=$tmp-00000.rgb +tmp_ppm0=$tmp-0.ppm +tmp_ppm1=$tmp-1.ppm +tmp_ppm2=$tmp-2.ppm +tmp_ppm3=$tmp-3.ppm +tmp_ppm4=$tmp-4.ppm +tmp_ppmS=$tmp-S.ppm + + +# Figure out whether to use xloadimage, xli, or xv. +pick_displayer() { + displayer= + for prog in xloadimage xli xv ; do + IFS=: + for p in $PATH; do + IFS= + if [ "$p" = "" ]; then p=. ; fi + if [ -x $p/$prog ]; then + displayer=$prog + break 2 + fi + done + done -if [ "$1" != "" ]; then - echo "usage: $0 [-root] [-verbose]" >&2 - exit 1 -fi + if [ "$displayer" = "xloadimage" ]; then + displayer_args="-quiet" + displayer_win_args="" + displayer_root_args="-onroot" + elif [ "$displayer" = "xli" ]; then + displayer_args="-quiet" + displayer_win_args="" + displayer_root_args="-onroot -center -border black" + elif [ "$displayer" = "xv" ]; then + displayer_args="-quick24" + displayer_win_args="-geom +0+0" + displayer_root_args="-root -rmode 5 -noresetroot -rfg black -rbg black -viewonly" + else + echo "$0: neither xli nor xv found on \$PATH" + exit -1 + fi +} +# Process command-line args +getargs() { + + while [ $# != 0 ]; do + case "$1" in + -display | -disp | -dis | -dpy | -d ) + shift + DISPLAY="$1" + export DISPLAY + ;; + -root ) + onroot=true + ;; + -window ) + onroot=false + ;; + -verbose ) + verbose=true + ;; + -stdin ) + use_stdin=true + ;; + -stdout ) + use_stdout=true + ;; + -delay) + shift + delay="$1" + ;; + * ) + echo "VidWhacker, Copyright (c) 1999 Jamie Zawinski " >&2 + echo " http://www.jwz.org/xscreensaver/" >&2 + echo "" >&2 + echo "usage: $0 [-display dpy] [-verbose] [-root | -window]" >&2 + echo " [-stdin] [-stdout] [-delay secs]" >&2 + exit 1 + ;; + esac + shift + done -xvargs="-quick24" + pick_displayer -if [ "$onroot" = true ]; then - xvargs="$xvargs -root -rmode 5 -quit" -else - xvargs="$xvargs -geom +0+0" -fi + if [ "$onroot" = true ]; then + displayer_args="$displayer_args $displayer_root_args" + else + displayer_args="$displayer_args $displayer_win_args" + fi -screen_width=`xdpyinfo | sed -n 's/.* dimensions: *\([0-9]*\).*/\1/p'` -# global vars... + screen_width='' + if [ "$use_stdout" = false ]; then + screen_width=`xdpyinfo 2>/dev/null | + sed -n 's/.* dimensions: *\([0-9]*\).*/\1/p'` + if [ "$screen_width" = "" ]; then + screen_width=800 + fi + fi +} -tmp=/tmp/vd$$ -tmp_rgb=$tmp-00000.rgb -tmp_ppm=$tmp.ppm -tmp_ppm2=$tmp-2.ppm -tmp_ppm3=$tmp-3.ppm clean() { - rm -f $tmp_rgb $tmp_ppm $tmp_ppm2 $tmp_ppm3 + rm -f $tmp_rgb $tmp_ppm1 $tmp_ppm2 $tmp_ppm3 $tmp_ppm4 +} + +clean2() { + clean + rm -f $tmp_ppm0 $tmp_ppmS } -# Grab a frame of video. +# Grab a frame of video. leaves it in $tmp_ppm1. # grab() { - if [ `uname` = IRIX ]; then + uname=`uname` + if [ $uname = IRIX ]; then # # SGI's "vidtomem" returns an SGI RGB image of the default video input, # and has stupid non-overridable ouput-file-naming conventions. So, let # it write its file; and then convert it to a pgm. # + vidtomem -f $tmp - sgitopnm $tmp_rgb > $tmp_ppm + sgitopnm $tmp_rgb > $tmp_ppm1 + # Cut off the close-captioning blips in the NTSC overscan region. YMMV. # | pnmcut 12 7 695 477 + elif [ $uname = Linux ]; then + + # Marcus Herbert says the following works with his Connectix Qcam. + # Don't have qcam? Well, do something else then... and send me a patch. + + qcam > $tmp_ppm1 + + # Friedrich Delgado Friedrichs says the following works if you have + # XawTV installed: + # + # streamer -o $tmp_ppm1 + # + else echo "$0: don't know how to grab video on this OS." >&2 - clean + clean2 exit 1 fi - - - # I got this message from Marcus Herbert . - # I'm not sure of the best way to make the presence of qcam be - # auto-detected, but here's what he said, FYI... - # - # i am using a black/white Connectix Qcam on linux and its very simple - # to adept the script: - # - # # qcam: Version 0.91 - # # Options: - # # O -x width Set width - # # O y height Setheight - # # O B bpp Setbits per pixel - # # O W Auto-set white balance - # # O E "vals" Autoexposure mode, parameters required - # # O D Remove dark speckling - # # O s val Set scaling factor (1, 2, or 4) - # # - # qcam -x 320 -y 240 -B 6 -W -E 1 -D -s 1 > $tmp_ppm - # - # You dont really need the parameters for qcam as it reads out a system - # config file where you store the values for brightnes, contrast and - # white balance. But with this parameters you are independant of the - # light ratios at the place the cam is set up. - # - # Other versions of qcam (0.7, 0.96..) don't support the autoexposure and - # auto- whitebalance commandline parameters. On such systems (and on - # color-qcam systems) a simple qcam > $tmp_ppm (or cqcam > $tmp_ppm) is - # enough. - # - # I dont know about other systems but afaik fBSD uses the Qcam in this way: - # - # qcamcontrol -bla -foo -bar > picture.pgm - # } # Use perl to pick a random foreground/background color in pbm's syntax. # randcolor() { - perl -e 'srand; - printf("#%02x%02x%02x-#%02x%02x%02x", - int(rand()*60), - int(rand()*60), - int(rand()*60), - 120+int(rand()*135), - 120+int(rand()*135), - 120+int(rand()*135))' + $perl -e 'srand(time ^ $$); + printf("#%02x%02x%02x-#%02x%02x%02x", + int(rand()*60), + int(rand()*60), + int(rand()*60), + 120+int(rand()*135), + 120+int(rand()*135), + 120+int(rand()*135))' +} + +rand() { + $perl -e "srand(time ^ $$); print int(rand() * $1)" } + + # Frobnicate the image in some random way. # frob() { - N=`perl -e 'srand; print int(rand() * 10)'` + w_h=`head -2 $tmp_ppm1 | tail -1` + width=`echo $w_h | awk '{print $1}'` + height=`echo $w_h | awk '{print $2}'` + + N=`rand 17` if [ "$verbose" = true ]; then echo "mode $N..." >&2 fi if [ $N = 0 ]; then - ppmtopgm $tmp_ppm | pgmedge | pgmtoppm `randcolor` | ppmnorm + ppmtopgm $tmp_ppm1 | pgmedge | pgmtoppm `randcolor` | ppmnorm elif [ $N = 1 ]; then - ppmtopgm $tmp_ppm | + ppmtopgm $tmp_ppm1 | pgmenhance | pgmtoppm `randcolor` elif [ $N = 2 ]; then - ppmtopgm $tmp_ppm | pgmoil | pgmtoppm `randcolor` + ppmtopgm $tmp_ppm1 | pgmoil | pgmtoppm `randcolor` elif [ $N = 3 ]; then - ppmrelief $tmp_ppm | ppmtopgm | pgmedge | ppmrelief | ppmtopgm | + ppmrelief $tmp_ppm1 | ppmtopgm | pgmedge | ppmrelief | ppmtopgm | pgmedge | pnminvert | pgmtoppm `randcolor` elif [ $N = 4 ]; then - ppmspread 71 $tmp_ppm > $tmp_ppm2 - pnmarith -add $tmp_ppm $tmp_ppm2 + ppmspread 71 $tmp_ppm1 > $tmp_ppm2 + pnmarith -add $tmp_ppm1 $tmp_ppm2 elif [ $N = 5 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmarith -multiply $tmp_ppm $tmp_ppm2 > $tmp_ppm3 + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3 pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2 - pnmarith -multiply $tmp_ppm $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 elif [ $N = 6 ]; then - N2=`perl -e 'srand; print int(rand() * 3)'` + N2=`rand 3` if [ $N2 = 0 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 elif [ $N2 = 1 ]; then - pnmflip -tb $tmp_ppm > $tmp_ppm2 + pnmflip -tb $tmp_ppm1 > $tmp_ppm2 else - pnmflip -lr $tmp_ppm > $tmp_ppm2 + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 pnmflip -tb $tmp_ppm2 > $tmp_ppm3 cp $tmp_ppm3 $tmp_ppm2 fi - pnmarith -difference $tmp_ppm $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 elif [ $N = 7 ]; then for i in 1 2 3 ; do - ppmtopgm $tmp_ppm | pgmedge > $tmp_ppm2 - pnmarith -difference $tmp_ppm $tmp_ppm2 > $tmp_ppm3 - cp $tmp_ppm3 $tmp_ppm + ppmtopgm $tmp_ppm1 | pgmedge > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3 + cp $tmp_ppm3 $tmp_ppm1 done - ppmnorm < $tmp_ppm + ppmnorm < $tmp_ppm1 elif [ $N = 8 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmarith -multiply $tmp_ppm $tmp_ppm2 | ppmrelief | ppmnorm | pnminvert + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmnorm | pnminvert elif [ $N = 9 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmarith -subtract $tmp_ppm $tmp_ppm2 | ppmrelief | ppmtopgm | pgmedge + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + pnmarith -subtract $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmtopgm | pgmedge + + elif [ $N = 10 ]; then + ppmtopgm $tmp_ppm1 | pgmbentley | pgmtoppm `randcolor` - else cat $tmp_ppm + elif [ $N = 11 ]; then + pgmcrater -number 20000 -height $height -width $width | pgmtoppm `randcolor` > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3 + pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 12 ]; then + ppmshift 30 $tmp_ppm1 | ppmtopgm | pgmoil | pgmedge | pgmtoppm `randcolor` > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 13 ]; then + ppmpat -madras $width $height | pnmdepth 255 > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 14 ]; then + ppmpat -tartan $width $height | pnmdepth 255 > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 15 ]; then + ppmpat -camo $width $height | pnmdepth 255 | ppmshift 50 > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 16 ]; then + pgmnoise $width $height | pgmedge | pgmtoppm `randcolor` > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 | pnmdepth 255 | pnmsmooth + + else cat $tmp_ppm1 fi } - # Grab a frame and frob it. leave it in $tmp_ppm3. # whack() { clean - while [ ! -f $tmp_ppm ]; do - grab + while [ ! -f $tmp_ppm1 ]; do + if [ "$use_stdin" != true ]; then + grab + else + cp $tmp_ppmS $tmp_ppm0 + cp $tmp_ppm0 $tmp_ppm1 + fi done rm -f $tmp_rgb - frob | pnmscale -width $screen_width > $tmp_ppm3 - rm -f $tmp_ppm $tmp_ppm2 + + if [ "$screen_width" != "" ]; then + frob | pnmscale -width $screen_width > $tmp_ppm3 + else + frob > $tmp_ppm3 + fi + + rm -f $tmp_ppm1 $tmp_ppm2 } -pid="" +# Kill off the xli or xv subprocess, if it's running +# +kill_pid() { + if [ "$pid" != "" ]; then -if [ "$onroot" != true ]; then - trap "kill \$pid; clean; exit 1" 2 15 -fi + if [ "$verbose" = true ]; then + echo "killing pid $pid..." >&2 + fi -while true; do + # need to do this to avoid "6898 Terminated" messages! + # apparently one can't redirect the output of the builtin `kill' command. +# ( sh -c "kill $pid" ) >/dev/null 2>/dev/null /dev/null 2>&1 + pid="" + fi +} + +# called when this process is signalled (for cleanup) +# +my_trap() { if [ "$verbose" = true ]; then - whack - else - whack >&- 2>&- + echo "trapped signal!" >&2 fi + kill_pid + clean2 + exit 1 +} - if [ "$pid" != "" ]; then - kill $pid - pid="" +main() { + + getargs $@ + + trap my_trap 1 2 3 6 9 13 15 + + if [ "$use_stdin" = true ]; then + cat > $tmp_ppmS fi - if [ ! -s $tmp_ppm3 ]; then - echo "$0: no image grabbed" >&2 - else + while true; do - pnmtosgi < $tmp_ppm3 > $tmp_ppm2 - rm -f $tmp_ppm3 + # Loop grabbing and frobbing images. + # + # If we're running on the root, run xv or xli in the foreground + # (with -exit, if xv) and then wait. + # + # If we're running in a window, spawn xv or xli in the background; then + # when it's time to put up the new image, kill off the currently-running + # xv or xli. - if [ "$onroot" = true ]; then - xv $xvargs $tmp_ppm2 + if [ "$verbose" = true ]; then + whack else - xv $xvargs $tmp_ppm2 & - pid=$! + whack >/dev/null 2>&1 fi - #xv -geom =320x220 $tmp_ppm3 & - #pid= - fi + kill_pid - clean - sleep $delay + if [ ! -s $tmp_ppm3 ]; then + echo "$0: no image grabbed" >&2 + + elif [ "$use_stdout" = true ]; then + + cat $tmp_ppm3 + clean2 + exit 0 + + else + +# pnmtosgi < $tmp_ppm3 > $tmp_ppm2 +# rm -f $tmp_ppm3 + mv $tmp_ppm3 $tmp_ppm2 + + if [ -s $tmp_ppm2 ]; then + if [ "$verbose" = true ]; then + echo "launching $displayer $displayer_args $tmp_ppm2" >&2 + ls -lF $tmp_ppm2 + fi + + mv $tmp_ppm2 $tmp_ppm0 + eval "$displayer $displayer_args $tmp_ppm0 &" + +# this doesn't work -- leaves xv processes around, instead of stray xset +# data. Sigh. +# +# # cat the file so that we can nuke it without racing against xv. +# cat $tmp_ppm2 | $displayer $displayer_args - & + + pid=$! + fi + fi + + clean + sleep $delay + + done + exit 1 +} + +main $@ -done +# to find stray xv data: +# xwininfo -root -children|grep 'xv image comments' | awk '{print "xkill -id ", $1}'