X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=local%2Fbin%2Fvidwhacker;fp=local%2Fbin%2Fvidwhacker;h=b35af3a140ead83d157a50e9c6e3033d645750d7;hb=41fae2ad67bc37e31c4d967bae81e4f3f50fa55a;hp=0000000000000000000000000000000000000000;hpb=278c59e14c53fd412b734e699bd4f314f766f804;p=xscreensaver diff --git a/local/bin/vidwhacker b/local/bin/vidwhacker new file mode 100755 index 00000000..b35af3a1 --- /dev/null +++ b/local/bin/vidwhacker @@ -0,0 +1,401 @@ +#!/bin/sh +# +# 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... +# +# 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... + +onroot=false +verbose=false +delay=3 +use_stdin=false +use_stdout=false + +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 + + +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" + + if [ "$onroot" = true ]; then + xvargs="$xvargs -root -rmode 5 -noresetroot -rfg black -rbg black -viewonly" + else + xvargs="$xvargs -geom +0+0" + fi + + + 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 +} + + +clean() { + 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. leaves it in $tmp_ppm1. +# +grab() { + 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_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 with a + # Brooktree 848 or 878 tuner card: + # + # bttvgrab -Q -d q -l 1 -F /dev/null -o gif -f ${tmp}.gif -N PAL + # giftopnm ${tmp}.gif > $tmp_ppm1 + # rm ${tmp}.gif + # + # He notes that you might need to run a TV application (e.g., xawtv) + # before the first time you run vidwhacker in order to initialize the + # tuner card and kernel modules. + + + else + echo "$0: don't know how to grab video on this OS." >&2 + clean2 + exit 1 + fi +} + + +# 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))' +} + +# Frobnicate the image in some random way. +# +frob() { + + w_h=`head -2 $tmp_ppm1 | tail -1` + width=`echo $w_h | awk '{print $1}'` + height=`echo $w_h | awk '{print $2}'` + + N=`perl -e 'srand; print int(rand() * 17)'` + + if [ "$verbose" = true ]; then + echo "mode $N..." >&2 + fi + + if [ $N = 0 ]; then + ppmtopgm $tmp_ppm1 | pgmedge | pgmtoppm `randcolor` | ppmnorm + + elif [ $N = 1 ]; then + ppmtopgm $tmp_ppm1 | + pgmenhance | + pgmtoppm `randcolor` + + elif [ $N = 2 ]; then + ppmtopgm $tmp_ppm1 | pgmoil | pgmtoppm `randcolor` + + elif [ $N = 3 ]; then + ppmrelief $tmp_ppm1 | ppmtopgm | pgmedge | ppmrelief | ppmtopgm | + pgmedge | pnminvert | pgmtoppm `randcolor` + + elif [ $N = 4 ]; then + ppmspread 71 $tmp_ppm1 > $tmp_ppm2 + pnmarith -add $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 5 ]; then + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3 + pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 6 ]; then + N2=`perl -e 'srand; print int(rand() * 3)'` + if [ $N2 = 0 ]; then + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + elif [ $N2 = 1 ]; then + pnmflip -tb $tmp_ppm1 > $tmp_ppm2 + else + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + pnmflip -tb $tmp_ppm2 > $tmp_ppm3 + cp $tmp_ppm3 $tmp_ppm2 + fi + + pnmarith -difference $tmp_ppm1 $tmp_ppm2 + + elif [ $N = 7 ]; then + + for i in 1 2 3 ; do + ppmtopgm $tmp_ppm1 | pgmedge > $tmp_ppm2 + pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3 + cp $tmp_ppm3 $tmp_ppm1 + done + ppmnorm < $tmp_ppm1 + + elif [ $N = 8 ]; then + pnmflip -lr $tmp_ppm1 > $tmp_ppm2 + pnmarith -multiply $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmnorm | pnminvert + + elif [ $N = 9 ]; then + 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` + + 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_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 + + if [ "$screen_width" != "" ]; then + frob | pnmscale -width $screen_width > $tmp_ppm3 + else + frob > $tmp_ppm3 + fi + + rm -f $tmp_ppm1 $tmp_ppm2 +} + + +# Kill off the xv subprocess, if it's running +# +kill_pid() { + if [ "$pid" != "" ]; then + + if [ "$verbose" = true ]; then + echo "killing pid $pid..." >&2 + fi + + # 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 + echo "trapped signal!" >&2 + fi + kill_pid + clean2 + exit 1 +} + +main() { + + getargs $@ + + trap my_trap 1 2 3 6 9 13 15 + + if [ "$use_stdin" = true ]; then + cat > $tmp_ppmS + fi + + while true; do + + # Loop grabbing and frobbing images. + # + # If we're running on the root, run xv in the foreground (with -exit) + # and then wait. + # + # If we're running in a window, spawn xv in the background; then when + # it's time to put up the new image, kill off the currently-running xv. + + if [ "$verbose" = true ]; then + whack + else + whack >/dev/null 2>&1 + fi + + kill_pid + + 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 + + if [ -s $tmp_ppm2 ]; then + if [ "$verbose" = true ]; then + echo "launching xv $xvargs $tmp_ppm2" >&2 + ls -lF $tmp_ppm2 + fi + + mv $tmp_ppm2 $tmp_ppm0 + xv $xvargs $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 | xv $xvargs - & + + pid=$! + fi + fi + + clean + sleep $delay + + done + exit 1 +} + +main $@ + +# to find stray xv data: +# xwininfo -root -children|grep 'xv image comments' | awk '{print "xkill -id ", $1}'