From http://www.jwz.org/xscreensaver/xscreensaver-5.27.tar.gz
[xscreensaver] / driver / xscreensaver-getimage-desktop
1 #!/usr/bin/perl -w
2 # Copyright © 2003-2013 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 #
13 # This script is invoked by "xscreensaver-getimage" on X11 MacOS systems
14 # to grab an image of the desktop, and then load it on to the given X11
15 # Drawable using the "xscreensaver-getimage-file" program.
16 #
17 # This script is only used in an *X11* build on MacOS systems.
18 #
19 # When running on non-Mac X11 systems, utils/grabscreen.c is used.
20 #
21 # However, when running under X11 on MacOS, that usual X11-based
22 # screen-grabbing mechanism doesn't work, so we need to invoke the
23 # "/usr/bin/screencapture" program to do it instead.  (This script).
24 #
25 # However again, for the MacOS-native (Cocoa) build of the screen savers,
26 # "utils/grabclient.c" instead links against "OSX/osxgrabscreen.m", which
27 # grabs screen images directly without invoking a sub-process to do it.
28 #
29 # Created: 20-Oct-2003.
30
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.6 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
38
39 my @grabber   = ("screencapture", "-x");
40 my @converter = ("pdf2jpeg");
41
42 my $verbose = 0;
43
44
45 sub error($) {
46   ($_) = @_;
47   print STDERR "$progname: $_\n";
48   exit 1;
49 }
50
51 # returns the full path of the named program, or undef.
52 #
53 sub which($) {
54   my ($prog) = @_;
55   foreach (split (/:/, $ENV{PATH})) {
56     if (-x "$_/$prog") {
57       return $prog;
58     }
59   }
60   return undef;
61 }
62
63 sub check_path() {
64   my $ok = 1;
65   foreach ($grabber[0], $converter[0]) {
66     if (! which ($_)) {
67       print STDERR "$progname: \"$_\" not found on \$PATH.\n";
68       $ok = 0;
69     }
70   }
71   exit (1) unless $ok;
72 }
73
74
75 sub grab_image() {
76
77   check_path();
78
79   my $tmpdir = $ENV{TMPDIR};
80   $tmpdir = "/tmp" unless $tmpdir;
81
82   my $tmpfile = sprintf ("%s/xssgrab.%08x.pdf", $tmpdir, rand(0xffffffff));
83   my @cmd     = (@grabber, $tmpfile);
84
85   unlink $tmpfile;
86
87   print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
88     if ($verbose);
89   system (join(' ', @cmd) . ' 2>/dev/null');
90
91   my @st = stat($tmpfile);
92   my $size = (@st ? $st[7] : 0);
93   if ($size <= 2048) {
94     unlink $tmpfile;
95     if ($size == 0) {
96       error "\"" . join(' ', @cmd) . "\" produced no data.";
97     } else {
98       error "\"" . join(' ', @cmd) . "\" produced only $size bytes.";
99     }
100   }
101
102   # On MacOS 10.3, "screencapture -x" always wrote a PDF.
103   # On 10.4.2, it writes a PNG by default, and the output format can be
104   # changed with the new "-t" argument.
105   #
106   # So, for maximal compatibility, we run it without "-t", but look at
107   # the first few bytes to see if it's a PDF, and if it is, convert it
108   # to a JPEG first.  Otherwise, we assume that whatever screencapture
109   # wrote is a file format that xscreensaver-getimage-file can already
110   # cope with (though it will have the extension ".pdf", regardless of
111   # what is actually in the file).
112   #
113   my $pdf_p = 0;
114   {
115     open (my $in, '<:raw', $tmpfile) || error ("$tmpfile: $!");
116     my $buf = '';
117     read ($in, $buf, 10);
118     close $in;
119     $pdf_p = ($buf =~ m/^%PDF-/s);
120   }
121
122   # If it's a PDF, convert it to a JPEG.
123   #
124   if ($pdf_p)
125     {
126       my $jpgfile = $tmpfile;
127       $jpgfile =~ s/\.[^.]+$//;
128       $jpgfile .= ".jpg";
129
130       @cmd = (@converter, $tmpfile, $jpgfile);
131       push @cmd, "--verbose" if ($verbose);
132
133       print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
134         if ($verbose);
135       system (@cmd);
136       unlink $tmpfile;
137       $tmpfile = $jpgfile;
138     }
139
140   @st = stat($tmpfile);
141   $size = (@st ? $st[7] : 0);
142   if ($size <= 2048) {
143     unlink $tmpfile;
144     if ($size == 0) {
145       error "\"" . join(' ', @cmd) . "\" produced no data.";
146     } else {
147       error "\"" . join(' ', @cmd) . "\" produced only $size bytes.";
148     }
149   }
150
151   print STDERR "$progname: wrote \"$tmpfile\"\n" if ($verbose);
152   print STDOUT "$tmpfile\n";
153 }
154
155
156 sub usage() {
157   print STDERR "usage: $progname [--verbose]\n";
158   exit 1;
159 }
160
161 sub main() {
162   while ($_ = $ARGV[0]) {
163     shift @ARGV;
164     if    (m/^--?verbose$/s) { $verbose++; }
165     elsif (m/^-v+$/s)        { $verbose += length($_)-1; }
166     elsif (m/^--?name$/s)    { }   # ignored, for compatibility
167     elsif (m/^-./)           { usage; }
168     else                     { usage; }
169   }
170   grab_image();
171 }
172
173 main;
174 exit 0;