summaryrefslogtreecommitdiffstats
path: root/driver/xscreensaver-getimage-desktop
blob: 2a6d345180eb53833ef7333f0e00196f1bdc7c65 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/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;