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) |
---|