#!/usr/bin/perl -w
# Copyright © 2003-2013 Jamie Zawinski <jwz@jwz.org>.
#
# 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 is invoked by "xscreensaver-getimage" on X11 MacOS systems
# to grab an image of the desktop, and then load it on to the given X11
# Drawable using the "xscreensaver-getimage-file" program.
#
# This script is only used in an *X11* build on MacOS systems.
#
# When running on non-Mac X11 systems, utils/grabscreen.c is used.
#
# However, when running under X11 on MacOS, that usual X11-based
# screen-grabbing mechanism doesn't work, so we need to invoke the
# "/usr/bin/screencapture" program to do it instead. (This script).
#
# However again, for the MacOS-native (Cocoa) build of the screen savers,
# "utils/grabclient.c" instead links against "OSX/osxgrabscreen.m", which
# grabs screen images directly without invoking a sub-process to do it.
#
# Created: 20-Oct-2003.
require 5;
#use diagnostics; # Fails on some MacOS 10.5 systems
use strict;
my $progname = $0; $progname =~ s@.*/@@g;
my $version = q{ $Revision: 1.6 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
my @grabber = ("screencapture", "-x");
my @converter = ("pdf2jpeg");
my $verbose = 0;
sub error($) {
($_) = @_;
print STDERR "$progname: $_\n";
exit 1;
}
# returns the full path of the named program, or undef.
#
sub which($) {
my ($prog) = @_;
foreach (split (/:/, $ENV{PATH})) {
if (-x "$_/$prog") {
return $prog;
}
}
return undef;
}
sub check_path() {
my $ok = 1;
foreach ($grabber[0], $converter[0]) {
if (! which ($_)) {
print STDERR "$progname: \"$_\" not found on \$PATH.\n";
$ok = 0;
}
}
exit (1) unless $ok;
}
sub grab_image() {
check_path();
my $tmpdir = $ENV{TMPDIR};
$tmpdir = "/tmp" unless $tmpdir;
my $tmpfile = sprintf ("%s/xssgrab.%08x.pdf", $tmpdir, rand(0xffffffff));
my @cmd = (@grabber, $tmpfile);
unlink $tmpfile;
print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
if ($verbose);
system (join(' ', @cmd) . ' 2>/dev/null');
my @st = stat($tmpfile);
my $size = (@st ? $st[7] : 0);
if ($size <= 2048) {
unlink $tmpfile;
if ($size == 0) {
error "\"" . join(' ', @cmd) . "\" produced no data.";
} else {
error "\"" . join(' ', @cmd) . "\" produced only $size bytes.";
}
}
# On MacOS 10.3, "screencapture -x" always wrote a PDF.
# On 10.4.2, it writes a PNG by default, and the output format can be
# changed with the new "-t" argument.
#
# So, for maximal compatibility, we run it without "-t", but look at
# the first few bytes to see if it's a PDF, and if it is, convert it
# to a JPEG first. Otherwise, we assume that whatever screencapture
# wrote is a file format that xscreensaver-getimage-file can already
# cope with (though it will have the extension ".pdf", regardless of
# what is actually in the file).
#
my $pdf_p = 0;
{
open (my $in, '<:raw', $tmpfile) || error ("$tmpfile: $!");
my $buf = '';
read ($in, $buf, 10);
close $in;
$pdf_p = ($buf =~ m/^%PDF-/s);
}
# If it's a PDF, convert it to a JPEG.
#
if ($pdf_p)
{
my $jpgfile = $tmpfile;
$jpgfile =~ s/\.[^.]+$//;
$jpgfile .= ".jpg";
@cmd = (@converter, $tmpfile, $jpgfile);
push @cmd, "--verbose" if ($verbose);
print STDERR "$progname: executing \"" . join(' ', @cmd) . "\"\n"
if ($verbose);
system (@cmd);
unlink $tmpfile;
$tmpfile = $jpgfile;
}
@st = stat($tmpfile);
$size = (@st ? $st[7] : 0);
if ($size <= 2048) {
unlink $tmpfile;
if ($size == 0) {
error "\"" . join(' ', @cmd) . "\" produced no data.";
} else {
error "\"" . join(' ', @cmd) . "\" produced only $size bytes.";
}
}
print STDERR "$progname: wrote \"$tmpfile\"\n" if ($verbose);
print STDOUT "$tmpfile\n";
}
sub usage() {
print STDERR "usage: $progname [--verbose]\n";
exit 1;
}
sub main() {
while ($_ = $ARGV[0]) {
shift @ARGV;
if (m/^--?verbose$/s) { $verbose++; }
elsif (m/^-v+$/s) { $verbose += length($_)-1; }
elsif (m/^--?name$/s) { } # ignored, for compatibility
elsif (m/^-./) { usage; }
else { usage; }
}
grab_image();
}
main;
exit 0;