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 |
|
---|
88 | pdf = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename(pdfFile))
|
---|
89 | numberOfPages = pdf.getNumberOfPages()
|
---|
90 |
|
---|
91 | writtenPaths = []
|
---|
92 | if numberOfPages == 1:
|
---|
93 | writtenPaths = [dumpPNG(pdf, None)]
|
---|
94 | else:
|
---|
95 | for pageNumber in xrange(1, numberOfPages+1):
|
---|
96 | writtenPaths.append(dumpPNG(pdf, pageNumber))
|
---|
97 |
|
---|
98 | os.remove(pdfFile)
|
---|
99 | os.rmdir(tempDir)
|
---|
100 |
|
---|
101 | for path in writtenPaths:
|
---|
102 | LSSetExtensionHiddenForRef(FSPathMakeRef(path)[0], True)
|
---|
103 |
|
---|
104 | # Carbon.File module doesn't implement FNNotify
|
---|
105 | execute(['/usr/bin/osascript', '-e', 'tell app "Finder" to update desktop'])
|
---|
106 | else:
|
---|
107 | check(args, output, retval)
|
---|
108 | if not os.path.exists(outFile):
|
---|
109 | # something could have gone wrong, or user cancelled, we don't know
|
---|
110 | sys.exit(0)
|
---|
111 | writtenPaths = [outFile]
|
---|
112 |
|
---|
113 | # LaunchServices module doesn't implement LSOpenFrom*Spec
|
---|
114 | execute([os.path.join(os.getenv('RESOURCEPATH'), 'launch'), '-i', 'tv.kungfoo.1001'] + writtenPaths)
|
---|