X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fvidwhacker;h=d958c5623c7eddfbf533cbc6f0339360ce4aa0db;hp=445219637485f95e68a6643a36f4264348b28a3a;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=6bb727f03bff0389fbb1349d7df4c9d8d7532959 diff --git a/hacks/vidwhacker b/hacks/vidwhacker index 44521963..d958c562 100755 --- a/hacks/vidwhacker +++ b/hacks/vidwhacker @@ -1,264 +1,498 @@ -#!/bin/sh +#!/usr/bin/perl -w +# vidwhacker, for xscreensaver. Copyright (c) 1998-2004 Jamie Zawinski. # -# vidwhacker, for xscreensaver. Copyright (c) 1998 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... +# This program grabs a frame of video, then uses various pbm filters to +# 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. +# Created: 14-Apr-01. +require 5; +use diagnostics; +use strict; -# Process command-line args... +my $progname = $0; $progname =~ s@.*/@@g; +my $version = q{ $Revision: 1.25 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; -onroot=false -verbose=false -delay=3 +my $verbose = 0; +my $use_stdin = 0; +my $use_stdout = 0; +my $video_p = 0; +my $file_p = 1; +my $delay = 5; +my $imagedir; -if [ "$1" = "-root" ]; then - onroot=true - shift -fi +my $screen_width = -1; -if [ "$1" = "-verbose" ]; then - verbose=true - shift -fi +my $displayer = "xscreensaver-getimage -root -file"; -if [ "$1" != "" ]; then - echo "usage: $0 [-root] [-verbose]" >&2 - exit 1 -fi +# apparently some versions of netpbm call it "pamoil" instead of "pgmoil"... +# +my $pgmoil = (which("pamoil") ? "pamoil" : "pgmoil"); + + +# List of interesting PPM filter pipelines. +# In this list, the following magic words may be used: +# +# COLORS a randomly-selected pair of RGB foreground/background colors. +# FILE1 the (already-existing) input PPM file (ok to overwrite it). +# FILE2-FILE4 names of other tmp files you can use. +# +# These commands should read from FILE1, and write to stdout. +# All tmp files will be deleted afterward. +# +my @filters = ( + "ppmtopgm FILE1 | pgmedge | pgmtoppm COLORS | ppmnorm", + "ppmtopgm FILE1 | pgmenhance | pgmtoppm COLORS", + "ppmtopgm FILE1 | $pgmoil | pgmtoppm COLORS", + "ppmtopgm FILE1 | pgmbentley | pgmtoppm COLORS", + + "ppmrelief FILE1 | ppmtopgm | pgmedge | ppmrelief | ppmtopgm |" . + " pgmedge | pnminvert | pgmtoppm COLORS", + + "ppmspread 71 FILE1 > FILE2 ; " . + " pnmarith -add FILE1 FILE2 ; ", + + "pnmflip -lr < FILE1 > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2 > FILE3 ; " . + " pnmflip -tb FILE3 | ppmnorm > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2", + + "pnmflip -lr FILE1 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "pnmflip -tb FILE1 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", -xvargs="-quick24" + "pnmflip -lr FILE1 | pnmflip -tb > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", -if [ "$onroot" = true ]; then - xvargs="$xvargs -root -rmode 5 -quit" -else - xvargs="$xvargs -geom +0+0" -fi + "ppmtopgm < FILE1 | pgmedge > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 > FILE3 ; " . + " cp FILE3 FILE1 ; " . + " ppmtopgm < FILE1 | pgmedge > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 > FILE3 ; " . + " ppmnorm < FILE1", -screen_width=`xdpyinfo | sed -n 's/.* dimensions: *\([0-9]*\).*/\1/p'` + "pnmflip -lr < FILE1 > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2 | ppmrelief | ppmnorm | pnminvert", -# global vars... + "pnmflip -lr FILE1 > FILE2 ; " . + " pnmarith -subtract FILE1 FILE2 | ppmrelief | ppmtopgm | pgmedge", -tmp=/tmp/vd$$ -tmp_rgb=$tmp-00000.rgb -tmp_ppm=$tmp.ppm -tmp_ppm2=$tmp-2.ppm -tmp_ppm3=$tmp-3.ppm + "pgmcrater -number 20000 -width WIDTH -height HEIGHT FILE1 | " . + " pgmtoppm COLORS > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 > FILE3 ; " . + " pnmflip -tb FILE3 | ppmnorm > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2", -clean() { - rm -f $tmp_rgb $tmp_ppm $tmp_ppm2 $tmp_ppm3 + "ppmshift 30 FILE1 | ppmtopgm | $pgmoil | pgmedge | " . + " pgmtoppm COLORS > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmpat -madras WIDTH HEIGHT | pnmdepth 255 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmpat -tartan WIDTH HEIGHT | pnmdepth 255 > FILE2 ; " . + " pnmarith -difference FILE1 FILE2", + + "ppmpat -camo WIDTH HEIGHT | pnmdepth 255 | ppmshift 50 > FILE2 ; " . + " pnmarith -multiply FILE1 FILE2", + + "pgmnoise WIDTH HEIGHT | pgmedge | pgmtoppm COLORS > FILE2 ; " . + " pnmarith -difference FILE1 FILE2 | pnmdepth 255 | pnmsmooth", +); + + +sub error { + ($_) = @_; + print STDERR "$progname: $_\n"; + exit 1; } +# Any files on this list will be deleted at exit. +# +my @all_tmpfiles = (); + +sub exit_cleanup { + print STDERR "$progname: delete tmp files\n" if ($verbose); + unlink @all_tmpfiles; +} + +sub signal_cleanup { + my ($sig) = @_; + print STDERR "$progname: caught SIG$sig\n" if ($verbose); + exit 1; +} -# Grab a frame of video. +sub init_signals { + + $SIG{HUP} = \&signal_cleanup; + $SIG{INT} = \&signal_cleanup; + $SIG{QUIT} = \&signal_cleanup; + $SIG{ABRT} = \&signal_cleanup; + $SIG{KILL} = \&signal_cleanup; + $SIG{TERM} = \&signal_cleanup; + + # Need this so that if giftopnm dies, we don't die. + $SIG{PIPE} = 'IGNORE'; +} + +END { exit_cleanup(); } + + + + +# returns the full path of the named program, or undef. # -grab() { - 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 - # Cut off the close-captioning blips in the NTSC overscan region. YMMV. - # | pnmcut 12 7 695 477 - - else - echo "$0: don't know how to grab video on this OS." >&2 - clean - 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 - # +sub which { + my ($prog) = @_; + foreach (split (/:/, $ENV{PATH})) { + if (-x "$_/$prog") { + return $prog; + } + } + return undef; } -# Use perl to pick a random foreground/background color in pbm's syntax. +# Choose random foreground and background colors # -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))' +sub randcolors { + return sprintf ("#%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)); +} + + + +sub filter_subst { + my ($filter, $width, $height, @tmpfiles) = @_; + my $colors = randcolors(); + $filter =~ s/\bWIDTH\b/$width/g; + $filter =~ s/\bHEIGHT\b/$height/g; + $filter =~ s/\bCOLORS\b/'$colors'/g; + my $i = 1; + foreach my $t (@tmpfiles) { + $filter =~ s/\bFILE$i\b/$t/g; + $i++; + } + if ($filter =~ m/([A-Z]+)/) { + error "internal error: what is \"$1\"?"; + } + $filter =~ s/ +/ /g; + return $filter; } # Frobnicate the image in some random way. # -frob() { - - N=`perl -e 'srand; print int(rand() * 10)'` - - if [ "$verbose" = true ]; then - echo "mode $N..." >&2 - fi - - if [ $N = 0 ]; then - ppmtopgm $tmp_ppm | pgmedge | pgmtoppm `randcolor` | ppmnorm - - elif [ $N = 1 ]; then - ppmtopgm $tmp_ppm | - pgmenhance | - pgmtoppm `randcolor` - - elif [ $N = 2 ]; then - ppmtopgm $tmp_ppm | pgmoil | pgmtoppm `randcolor` - - elif [ $N = 3 ]; then - ppmrelief $tmp_ppm | ppmtopgm | pgmedge | ppmrelief | ppmtopgm | - pgmedge | pnminvert | pgmtoppm `randcolor` - - elif [ $N = 4 ]; then - ppmspread 71 $tmp_ppm > $tmp_ppm2 - pnmarith -add $tmp_ppm $tmp_ppm2 - - elif [ $N = 5 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmarith -multiply $tmp_ppm $tmp_ppm2 > $tmp_ppm3 - pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2 - pnmarith -multiply $tmp_ppm $tmp_ppm2 - - elif [ $N = 6 ]; then - N2=`perl -e 'srand; print int(rand() * 3)'` - if [ $N2 = 0 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - elif [ $N2 = 1 ]; then - pnmflip -tb $tmp_ppm > $tmp_ppm2 - else - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmflip -tb $tmp_ppm2 > $tmp_ppm3 - cp $tmp_ppm3 $tmp_ppm2 - fi - - pnmarith -difference $tmp_ppm $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 - done - ppmnorm < $tmp_ppm - - elif [ $N = 8 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmarith -multiply $tmp_ppm $tmp_ppm2 | ppmrelief | ppmnorm | pnminvert - - elif [ $N = 9 ]; then - pnmflip -lr $tmp_ppm > $tmp_ppm2 - pnmarith -subtract $tmp_ppm $tmp_ppm2 | ppmrelief | ppmtopgm | pgmedge - - else cat $tmp_ppm - fi +sub frob_ppm { + my ($ppm_data) = @_; + $_ = $ppm_data; + + error "0-length data" if (!defined($ppm_data) || $ppm_data eq ""); + error "not a PPM file" unless (m/^P\d\n/s); + my ($width, $height) = m/^P\d\n(\d+) (\d+)\n/s; + error "got a bogus PPM" unless ($width && $height); + + my $tmpdir = $ENV{TMPDIR}; + $tmpdir = "/tmp" unless $tmpdir; + my $fn = sprintf ("%s/vidwhacker-0-%08x", $tmpdir, rand(0xFFFFFFFF)); + my $fn1 = sprintf ("%s/vidwhacker-1-%08x", $tmpdir, rand(0xFFFFFFFF)); + my $fn2 = sprintf ("%s/vidwhacker-2-%08x", $tmpdir, rand(0xFFFFFFFF)); + my $fn3 = sprintf ("%s/vidwhacker-3-%08x", $tmpdir, rand(0xFFFFFFFF)); + my @files = ( "$fn", "$fn1", "$fn2", "$fn3" ); + push @all_tmpfiles, @files; + + my $n = int(rand($#filters+1)); + my $filter = $filters[$n]; + + if ($verbose == 1) { + printf STDERR "$progname: running filter $n\n"; + } elsif ($verbose > 1) { + my $f = $filter; + $f =~ s/ +/ /g; + $f =~ s/^ */\t/; + $f =~ s/ *\|/\n\t|/g; + $f =~ s/ *\; */ ;\n\t/g; + print STDERR "$progname: filter $n:\n\n$f\n\n" if $verbose; + } + + $filter = filter_subst ($filter, $width, $height, @files); + + unlink @files; + + local *OUT; + open (OUT, ">$files[0]") || error ("writing $files[0]: $!"); + print OUT $ppm_data; + close OUT; + + $filter = "( $filter )"; + $filter .= "2>/dev/null" unless ($verbose > 1); + + local *IN; + open (IN, "$filter |") || error ("opening pipe: $!"); + $ppm_data = ""; + while () { $ppm_data .= $_; } + close IN; + + unlink @files; + return $ppm_data; } +sub read_config { + my $conf = "$ENV{HOME}/.xscreensaver"; -# Grab a frame and frob it. leave it in $tmp_ppm3. -# -whack() { - clean + my $had_dir = defined($imagedir); - while [ ! -f $tmp_ppm ]; do - grab - done + local *IN; + open (IN, "<$conf") || error "reading $conf: $!"; + while () { + if (!$imagedir && m/^imageDirectory:\s+(.*)\s*$/i) { $imagedir = $1; } + elsif (m/^grabVideoFrames:\s+true\s*$/i) { $video_p = 1; } + elsif (m/^grabVideoFrames:\s+false\s*$/i) { $video_p = 0; } + elsif (m/^chooseRandomImages:\s+true\s*$/i) { $file_p = 1; } + elsif (m/^chooseRandomImages:\s+false\s*$/i) { $file_p = 0; } + } + close IN; - rm -f $tmp_rgb - frob | pnmscale -width $screen_width > $tmp_ppm3 - rm -f $tmp_ppm $tmp_ppm2 -} + $file_p = 1 if $had_dir; + $imagedir = undef unless ($imagedir && $imagedir ne ''); -pid="" + if (!$file_p && !$video_p) { +# error "neither grabVideoFrames nor chooseRandomImages are set\n\t" . +# "in $conf; $progname requires one or both." + $file_p = 1; + } -if [ "$onroot" != true ]; then - trap "kill \$pid; clean; exit 1" 2 15 -fi + if ($file_p) { + error "no imageDirectory set in $conf" unless $imagedir; + error "imageDirectory $imagedir doesn't exist" unless (-d $imagedir); + } -while true; do + if ($verbose > 1) { + printf STDERR "$progname: grab video: $video_p\n"; + printf STDERR "$progname: grab images: $file_p\n"; + printf STDERR "$progname: directory: $imagedir\n"; + } + +} - # 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 >&- 2>&- - fi +sub get_ppm { + if ($use_stdin) { + print STDERR "$progname: reading from stdin\n" if ($verbose > 1); + my $ppm = ""; + while () { $ppm .= $_; } + return $ppm; + + } else { + + my $do_file_p; + + if ($file_p && $video_p) { + $do_file_p = (int(rand(2)) == 0); + print STDERR "$progname: doing " . ($do_file_p ? "files" : "video") ."\n" + if ($verbose); + } + elsif ($file_p) { $do_file_p = 1; } + elsif ($video_p) { $do_file_p = 0; } + else { + error "internal error: not grabbing files or video?"; + } + + my $v = ($verbose <= 1 ? "" : "-" . ("v" x ($verbose-1))); + my $cmd; + if ($do_file_p) { + $cmd = "xscreensaver-getimage-file $v --name \"$imagedir\""; + } else { + $cmd = "xscreensaver-getimage-video $v --stdout"; + } + + my $ppm; + + if ($do_file_p) { + + print STDERR "$progname: running: $cmd\n" if ($verbose > 1); + my $fn = `$cmd`; + $fn =~ s/\n$//s; + error "didn't get a file?" if ($fn eq ""); + + print STDERR "$progname: selected file $fn\n" if ($verbose > 1); + + if ($fn =~ m/\.gif/i) { $cmd = "giftopnm < \"$fn\""; } + elsif ($fn =~ m/\.jpe?g/i) { $cmd = "djpeg < \"$fn\""; } + elsif ($fn =~ m/\.png/i) { $cmd = "pngtopnm < \"$fn\""; } + elsif ($fn =~ m/\.xpm/i) { $cmd = "xpmtoppm < \"$fn\""; } + elsif ($fn =~ m/\.bmp/i) { $cmd = "bmptoppm < \"$fn\""; } + elsif ($fn =~ m/\.tiff?/i) { $cmd = "tifftopnm < \"$fn\""; } + elsif ($fn =~ m/\.p[bgp]m/i) { return `cat \"$fn\"`; } + else { + error "unrecognized file extension on $fn"; + } + + print STDERR "$progname: converting with: $cmd\n" if ($verbose > 1); + $cmd .= " 2>/dev/null" unless ($verbose > 1); + $ppm = `$cmd`; + + } else { + + print STDERR "$progname: running: $cmd\n" if ($verbose > 1); + $ppm = `$cmd`; + error "no data?" if ($ppm eq ""); + error "not a PPM file" unless ($ppm =~ m/^P\d\n/s); + + $_ = $ppm; + my ($width, $height) = m/^P\d\n(\d+) (\d+)\n/s; + error "got a bogus PPM" unless ($width && $height); + print STDERR "$progname: grabbed ${width}x$height PPM\n" + if ($verbose > 1); + $_ = 0; + } + + return $ppm; + } +} - if [ "$pid" != "" ]; then - kill $pid - pid="" - fi +sub dispose_ppm { + my ($ppm) = @_; + + error "0-length data" if (!defined($ppm) || $ppm eq ""); + error "not a PPM file" unless ($ppm =~ m/^P\d\n/s); + + if ($use_stdout) { + print STDERR "$progname: writing to stdout\n" if ($verbose > 1); + print $ppm; + + } else { + my $tmpdir = $ENV{TMPDIR}; + $tmpdir = "/tmp" unless $tmpdir; + my $fn = sprintf ("%s/vidwhacker-%08x", $tmpdir, rand(0xFFFFFFFF)); + local *OUT; + unlink $fn; + push @all_tmpfiles, $fn; + open (OUT, ">$fn") || error "writing $fn: $!"; + print OUT $ppm; + close OUT; + + my @cmd = split (/ +/, $displayer); + push @cmd, $fn; + print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n" + if ($verbose); + system (@cmd); + + my $exit_value = $? >> 8; + my $signal_num = $? & 127; + my $dumped_core = $? & 128; + + unlink $fn; + + error ("$cmd[0]: core dumped!") if ($dumped_core); + error ("$cmd[0]: signal $signal_num!") if ($signal_num); + error ("$cmd[0]: exited with $exit_value!") if ($exit_value); + } +} - if [ ! -s $tmp_ppm3 ]; then - echo "$0: no image grabbed" >&2 - else - pnmtosgi < $tmp_ppm3 > $tmp_ppm2 - rm -f $tmp_ppm3 +my $stdin_ppm = undef; + +sub vidwhack { + my $ppm; + if ($use_stdin) { + if (!defined($stdin_ppm)) { + $stdin_ppm = get_ppm(); + } + $ppm = $stdin_ppm; + } else { + my $max_err_count = 20; + my $err_count = 0; + while (!defined($ppm)) { + $ppm = get_ppm(); + $err_count++ if (!defined ($ppm)); + error ("too many errors, too few images!") + if ($err_count > $max_err_count); + } + } + + $ppm = frob_ppm ($ppm); + dispose_ppm ($ppm); + $ppm = undef; +} - if [ "$onroot" = true ]; then - xv $xvargs $tmp_ppm2 - else - xv $xvargs $tmp_ppm2 & - pid=$! - fi - #xv -geom =320x220 $tmp_ppm3 & - #pid= - fi +sub usage { + print STDERR "VidWhacker, Copyright (c) 2001 Jamie Zawinski \n"; + print STDERR " http://www.jwz.org/xscreensaver/"; + print STDERR "\n"; + print STDERR "usage: $0 [-display dpy] [-verbose]\n"; + print STDERR "\t\t[-root | -window | -window-id 0xXXXXX ]\n"; + print STDERR "\t\t[-stdin] [-stdout] [-delay secs]\n"; + print STDERR "\t\t[-directory image_directory]\n"; + exit 1; +} - clean - sleep $delay +sub main { + while ($_ = $ARGV[0]) { + shift @ARGV; + if ($_ eq "--verbose") { $verbose++; } + elsif (m/^-v+$/) { $verbose += length($_)-1; } + elsif (m/^(-display|-disp|-dis|-dpy|-d)$/) { $ENV{DISPLAY} = shift @ARGV; } + elsif (m/^--?stdin$/) { $use_stdin = 1; } + elsif (m/^--?stdout$/) { $use_stdout = 1; } + elsif (m/^--?delay$/) { $delay = shift @ARGV; } + elsif (m/^--?dir(ectory)?$/) { $imagedir = shift @ARGV; } + elsif (m/^--?root$/) { } + elsif (m/^--?window-id$/) { + my $id = shift @ARGV; + error ("unparsable window id: $id") + unless ($id =~ m/^\d+$|^0x[\da-f]+$/i); + $displayer =~ s/--?root\b/$id/ || + error ("unable to munge displayer: $displayer"); + } + elsif (m/^--?window$/) { + print STDERR "$progname: sorry, \"-window\" is unimplemented.\n"; + print STDERR "$progname: use \"-stdout\" and pipe to a displayer.\n"; + exit 1; + } + elsif (m/^-./) { usage; } + else { usage; } + } + + init_signals(); + + read_config; + + if (!$use_stdout) { + $_ = `xdpyinfo 2>&-`; + ($screen_width) =~ m/ dimensions: +(\d+)x(\d+) pixels/; + $screen_width = 800 unless $screen_width > 0; + } + + if ($use_stdout) { + vidwhack(); + } else { + while (1) { + vidwhack(); + sleep $delay; + } + } +} -done +main; +exit 0;