http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.tar.gz
[xscreensaver] / driver / xscreensaver-getimage-desktop
1 #!/usr/bin/perl -w
2 # Copyright © 2003, 2005 Jamie Zawinski <jwz@jwz.org>.
3 #
4 # Permission to use, copy, modify, distribute, and sell this software and its
5 # documentation for any purpose is hereby granted without fee, provided that
6 # the above copyright notice appear in all copies and that both that
7 # copyright notice and this permission notice appear in supporting
8 # documentation.  No representations are made about the suitability of this
9 # software for any purpose.  It is provided "as is" without express or 
10 # implied warranty.
11 #
12 # This program attempts to grab an image of the desktop, and then load
13 # it on to the root window using the "xscreensaver-getimage-file"
14 # program.  Various frame-grabbing programs are known, and the first
15 # one found is used.
16 #
17 # NOTE:  This script is only used on MacOS X / XDarwin systems, because
18 #        on those systems, it's necessary to use the "screencapture"
19 #        program to get an image of the desktop -- the usual X11
20 #        mechanism for grabbing the screen doesn't work on OSX.
21 #
22 # The various xscreensaver hacks that manipulate images ("slidescreen",
23 # "jigsaw", etc.) get the image to manipulate by running the
24 # "xscreensaver-getimage" program.
25 #
26 # "xscreensaver-getimage" will invoke this program, depending on the
27 # value of the "grabDesktopImages" setting in the ~/.xscreensaver file
28 # (or in /usr/lib/X11/app-defaults/XScreenSaver).
29 #
30 # Created: 20-Oct-2003.
31
32 require 5;
33 #use diagnostics;       # Fails on some MacOS 10.5 systems
34 use strict;
35
36 my $progname = $0; $progname =~ s@.*/@@g;
37 my $version = q{ $Revision: 1.4 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
38
39 my @grabber   = ("screencapture", "-x");
40 my @converter = ("pdf2jpeg");
41
42 my $verbose = 0;
43 my $use_stdout_p = 0;
44 my $return_filename_p = 0;
45
46
47 sub error {
48   ($_) = @_;
49   print STDERR "$progname: $_\n";
50   exit 1;
51 }
52
53 # returns the full path of the named program, or undef.
54 #
55 sub which {
56   my ($prog) = @_;
57   foreach (split (/:/, $ENV{PATH})) {
58     if (-x "$_/$prog") {
59       return $prog;
60     }
61   }
62   return undef;
63 }
64
65 sub check_path {
66   my $ok = 1;
67   foreach ($grabber[0], $converter[0]) {
68     if (! which ($_)) {
69       print STDERR "$progname: \"$_\" not found on \$PATH.\n";
70       $ok = 0;
71     }
72   }
73   exit (1) unless $ok;
74 }
75
76
77 sub grab_image {
78
79   check_path();
80
81   my $tmpdir = $ENV{TMPDIR};
82   $tmpdir = "/tmp" unless $tmpdir;
83
84   my $tmpfile = sprintf ("%s/xssgrab.%08x.pdf", $tmpdir, rand(0xffffffff));
85   my @cmd     = (@grabber, $tmpfile);
86
87   unlink $tmpfile;
88
89   print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
90     if ($verbose);
91   system (@cmd);
92
93   my @st = stat($tmpfile);
94   my $size = (@st ? $st[7] : 0);
95   if ($size <= 2048) {
96     unlink $tmpfile;
97     if ($size == 0) {
98       error "\"" . join(' ', @cmd) . "\" produced no data.";
99     } else {
100       error "\"" . join(' ', @cmd) . "\" produced only $size bytes.";
101     }
102   }
103
104   # On MacOS 10.3, "screencapture -x" always wrote a PDF.
105   # On 10.4.2, it writes a PNG by default, and the output format can be
106   # changed with the new "-t" argument.
107   #
108   # So, for maximal compatibility, we run it without "-t", but look at
109   # the first few bytes to see if it's a PDF, and if it is, convert it
110   # to a JPEG first.  Otherwise, we assume that whatever screencapture
111   # wrote is a file format that xscreensaver-getimage-file can already
112   # cope with (though it will have the extension ".pdf", regardless of
113   # what is actually in the file).
114   #
115   my $pdf_p = 0;
116   {
117     local *IN;
118     open (IN, "<$tmpfile") || error ("$tmpfile: $!");
119     my $buf = '';
120     read (IN, $buf, 10);
121     close IN;
122     $pdf_p = ($buf =~ m/^%PDF-/s);
123   }
124
125   # If it's a PDF, convert it to a JPEG.
126   #
127   if ($pdf_p)
128     {
129       my $jpgfile = $tmpfile;
130       $jpgfile =~ s/\.[^.]+$//;
131       $jpgfile .= ".jpg";
132
133       @cmd = (@converter, $tmpfile, $jpgfile);
134       push @cmd, "--verbose" if ($verbose);
135
136       print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
137         if ($verbose);
138       system (@cmd);
139       unlink $tmpfile;
140       $tmpfile = $jpgfile;
141     }
142
143   @st = stat($tmpfile);
144   $size = (@st ? $st[7] : 0);
145   if ($size <= 2048) {
146     unlink $tmpfile;
147     if ($size == 0) {
148       error "\"" . join(' ', @cmd) . "\" produced no data.";
149     } else {
150       error "\"" . join(' ', @cmd) . "\" produced only $size bytes.";
151     }
152   }
153
154   if ($return_filename_p) {
155     print STDERR "$progname: wrote \"$tmpfile\"\n" if ($verbose);
156     print STDOUT "$tmpfile\n";
157
158   } elsif ($use_stdout_p) {
159     local *IN;
160     my $ppm = "";
161     my $reader = "djpeg $tmpfile";
162     $reader .= " 2>/dev/null" if ($verbose <= 1);
163     $reader .= " |";
164
165     open(IN, $reader) || error "reading $tmpfile: $!";
166     print STDERR "$progname: reading $tmpfile\n" if ($verbose > 1);
167     while (<IN>) { $ppm .= $_; }
168     close IN;
169     unlink $tmpfile;
170     print STDOUT $ppm;
171
172   } else {
173
174     @cmd = ("xscreensaver-getimage-file");
175     push @cmd, "--verbose" if ($verbose);
176     push @cmd, $tmpfile;
177
178     print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
179       if ($verbose);
180     system (@cmd);
181
182     unlink $tmpfile;
183   }
184 }
185
186
187 sub usage {
188   print STDERR "usage: $progname [--verbose] [--name | --stdout]\n";
189   exit 1;
190 }
191
192 sub main {
193   while ($_ = $ARGV[0]) {
194     shift @ARGV;
195     if ($_ eq "--verbose") { $verbose++; }
196     elsif (m/^-v+$/) { $verbose += length($_)-1; }
197     elsif (m/^--?stdout$/) { $use_stdout_p = 1; }
198     elsif (m/^--?name$/)   { $return_filename_p = 1; }
199     elsif (m/^-./) { usage; }
200     else { usage; }
201   }
202
203   grab_image();
204 }
205
206 main;
207 exit 0;