root/trunk/1001Screenshot/screenshot.py

Revision 178, 4.1 kB (checked in by nicholas, 4 years ago)

screenshot.py: Properly handle user cancellation in Panther, too.

  • Property svn:executable set to
Line 
1 from CoreGraphics import *
2 import sys
3 import os
4 import subprocess
5 import tempfile
6 from Carbon.File import FSPathMakeRef
7 from Carbon.Folder import FSFindFolder
8 from Carbon.Folders import kUserDomain, kDesktopFolderType
9 from Carbon.CF import CFURLCreateFromFileSystemRepresentation
10 from LaunchServices.Launch import LSSetExtensionHiddenForRef
11
12 class HandledError(Exception):
13     def __init__(self, args, message, retval):
14         # make the arguments look distinct
15         for index, arg in enumerate(args):
16             if '\\' in arg:
17                 args[index] = args[index].replace('\\', '\\\\')
18             if ' ' in arg:
19                 args[index] = '"%s"' % args[index].replace('"', '\"')
20         description = 'An error occurred while attempting to execute the command %s' % ' '.join(args)
21         if message:
22             description += ':\n\n%s' % message
23         else:
24             description += '.\n'
25         if retval:
26             description += '\nThe process exited with status %d.' % retval
27         Exception.__init__(self, description)
28
29 def check(args, output, retval):
30     if output:
31         for index, line in enumerate(output):
32             if line.lower().startswith('usage:'):
33                 output = output[:index]
34                 break
35         raise HandledError(args, ''.join(output), retval)
36     elif retval != 0:
37         raise HandledError(args, '', retval)
38
39 def execute(args):
40     process = subprocess.Popen(args, stderr=subprocess.PIPE)
41     retval = process.wait()
42     check(args, process.stderr.readlines(), retval)
43
44 desktopDir = FSFindFolder(kUserDomain, kDesktopFolderType, False).as_pathname()
45 desktopContents = os.listdir(desktopDir)
46 index = 1
47 outFileBase = None
48 while outFileBase is None:
49     outFileBase = 'Screenshot %d' % index
50     for filePath in desktopContents:
51         if filePath.startswith(outFileBase):
52             index += 1
53             outFileBase = None
54             break
55 outFileBase = os.path.join(desktopDir, outFileBase)
56 writtenPaths = []
57
58 SCREENCAPTURE_ARGS = ['/usr/sbin/screencapture', '-iW']
59
60 outFile = outFileBase + '.png'
61 args = SCREENCAPTURE_ARGS + ['-tpng', outFile]
62 screencapture = subprocess.Popen(args, stderr=subprocess.PIPE)
63 retval = screencapture.wait()
64 output = screencapture.stderr.readlines()
65
66 if retval == 1 and output and 'illegal option -- t' in output[0]:
67     # Panther: only PDF output; Finder doesn't notice new files
68     def dumpPNG(pdf, pageNumber):
69         if pageNumber is None:
70             outFile = outFileBase + ".png"
71             pageNumber = 1
72         else:
73             outFile = outFileBase + "-%03d.png" % pageNumber
74
75         w = pdf.getTrimBox(pageNumber).getWidth()
76         h = pdf.getTrimBox(pageNumber).getHeight()
77
78         ctx = CGBitmapContextCreateWithColor(int(w), int(h), CGColorSpaceCreateDeviceRGB(), (0,0,0,0))
79         ctx.drawPDFDocument(pdf.getTrimBox(pageNumber), pdf, pageNumber)
80         ctx.writeToFile(outFile, kCGImageFormatPNG)
81         return outFile
82
83     tempDir = tempfile.mkdtemp()
84     pdfFile = os.path.join(tempDir, 'screenshot.pdf')
85
86     execute(SCREENCAPTURE_ARGS + [pdfFile])
87     if not os.path.exists(pdfFile):
88         # something could have gone wrong, or user cancelled, we don't know
89         sys.exit(0)
90
91     pdf = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename(pdfFile))
92     numberOfPages = pdf.getNumberOfPages()
93
94     writtenPaths = []
95     if numberOfPages == 1:
96         writtenPaths = [dumpPNG(pdf, None)]
97     else:
98         for pageNumber in xrange(1, numberOfPages+1):
99             writtenPaths.append(dumpPNG(pdf, pageNumber))
100
101     os.remove(pdfFile)
102     os.rmdir(tempDir)
103
104     for path in writtenPaths:
105         LSSetExtensionHiddenForRef(FSPathMakeRef(path)[0], True)
106
107     # Carbon.File module doesn't implement FNNotify
108     execute(['/usr/bin/osascript', '-e', 'tell app "Finder" to update desktop'])
109 else:
110     check(args, output, retval)
111     if not os.path.exists(outFile):
112         # something could have gone wrong, or user cancelled, we don't know
113         sys.exit(0)
114     writtenPaths = [outFile]
115
116 # LaunchServices module doesn't implement LSOpenFrom*Spec
117 execute([os.path.join(os.getenv('RESOURCEPATH'), 'launch'), '-i', 'tv.kungfoo.1001'] + writtenPaths)
Note: See TracBrowser for help on using the browser.