class PlayerLayerView (ui.View): def __init__(self,player, *args, **kwargs): ui.View.__init__(self,*args,**kwargs) if type(player) == Player: self._layer = AVPlayerLayer.playerLayerWithPlayer_(player._objc) self.player = player else: raise TypeError('Must be a Player item') self._layer.setVideoGravity_( 'AVLayerVideoGravityResizeAspect') self._rootLayer=ObjCInstance(self).layer() self._rootLayer.setMasksToBounds_(True) self._layer.setFrame_( CGRect(CGPoint(0, 0), CGSize(self.width ,self.height))) self._rootLayer.insertSublayer_atIndex_(self._layer,0) @property def layerResizeMode(self): return self._layer.videoGravity() @layerResizeMode.setter def layerResizeMode(self, mode): if mode in LAYER_RESIZE_MODES: self._layer.setVideoGravity_(mode) else: raise TypeError('{} is not a valid mode'.format(mode)) def layout(self): self._layer.setFrame_( CGRect(CGPoint(0, 0), CGSize(self.width, self.height)))
def create_accessory_toolbar(self): from objc_util import ObjCClass, ObjCInstance, sel def create_button(label, func): button_width = 25 black = ObjCClass('UIColor').alloc().initWithWhite_alpha_(0.0, 1.0) action_button = ui.Button() action_button.action = func accessory_button = ObjCClass('UIBarButtonItem').alloc().initWithTitle_style_target_action_(label, 0, action_button, sel('invokeAction:')) accessory_button.width = button_width accessory_button.tintColor = black return (action_button, accessory_button) vobj = ObjCInstance(self.markup) keyboardToolbar = ObjCClass('UIToolbar').alloc().init() keyboardToolbar.sizeToFit() button_width = 25 black = ObjCClass('UIColor').alloc().initWithWhite_alpha_(0.0, 1.0) # Create the buttons # Need to retain references to the buttons used # to handle clicks (self.indentButton, indentBarButton) = create_button(u'\u21E5', self.indent) (self.outdentButton, outdentBarButton) = create_button(u'\u21E4', self.outdent) (self.quoteButton, quoteBarButton) = create_button('>', self.block_quote) (self.linkButton, linkBarButton) = create_button('[]', self.link) #(self.anchorButton, anchorBarButton) = create_button('<>', self.anchor) (self.hashButton, hashBarButton) = create_button('#', self.heading) (self.numberedButton, numberedBarButton) = create_button('1.', self.numbered_list) (self.listButton, listBarButton) = create_button('•', self.unordered_list) (self.underscoreButton, underscoreBarButton) = create_button('_', self.insert_underscore) (self.backtickButton, backtickBarButton) = create_button('`', self.insert_backtick) # Flex between buttons f = ObjCClass('UIBarButtonItem').alloc().initWithBarButtonSystemItem_target_action_(5, None, None) doneBarButton = ObjCClass('UIBarButtonItem').alloc().initWithBarButtonSystemItem_target_action_(0, vobj, sel('endEditing:')) keyboardToolbar.items = [indentBarButton, f, outdentBarButton, f, quoteBarButton, f, linkBarButton, f, hashBarButton, f, numberedBarButton, f, listBarButton, f, underscoreBarButton, f, backtickBarButton, f, doneBarButton] vobj.inputAccessoryView = keyboardToolbar
def searchBarSearchButtonClicked_(_self, _cmd, _sb): searchbar = ObjCInstance(_sb) term = str(searchbar.text()) searchbar.resignFirstResponder() if term: det = NSDataDetector.dataDetectorWithTypes_error_(1<<5, None) res = det.firstMatchInString_options_range_(term, 0, (0, len(term))) view = ObjCInstance(_self).view() if res: view.loadRequest_(NSURLRequest.requestWithURL_(res.URL())) searchbar.text = res.URL().absoluteString() else: view.loadRequest_(NSURLRequest.requestWithURL_(nsurl('https://google.com/search?q=' + urllib.quote(term))))
def __init__(self, player = None, pause= True, autoplay = False, pip = False): self._pause_on_dismiss = pause self._objc = ObjCInstance(self) self._playerViewController = AVPlayerViewController.new() self._objc.addSubview_(self._playerViewController.view()) self.player = player self._autoplay = autoplay self._playerViewController.setAllowsPictureInPicturePlayback_(pip)
def __init__(self,player, *args, **kwargs): ui.View.__init__(self,*args,**kwargs) if type(player) == Player: self._layer = AVPlayerLayer.playerLayerWithPlayer_(player._objc) self.player = player else: raise TypeError('Must be a Player item') self._layer.setVideoGravity_( 'AVLayerVideoGravityResizeAspect') self._rootLayer=ObjCInstance(self).layer() self._rootLayer.setMasksToBounds_(True) self._layer.setFrame_( CGRect(CGPoint(0, 0), CGSize(self.width ,self.height))) self._rootLayer.insertSublayer_atIndex_(self._layer,0)
def recognizer_should_simultaneously_recognize(gr,ogr): g=ObjCInstance(gr) o=ObjCInstance(ogr) ispinch=g._get_objc_classname()==b'UIPinchGestureRecognizer' ispan=g._get_objc_classname()==b'UIPanGestureRecognizer' istap=g._get_objc_classname()==b'UITapGestureRecognizer' if (ispinch or ispan or istap) and (g.view()==o.view()) : return True else: return False
def ObjCConstant(name): return ObjCInstance(ctypes.c_void_p.in_dll(objc_util.c, name))
def handler(_cmd, _data, _error): global pressure pressure = ObjCInstance(_data).pressure()
def searchBarSearchButtonClicked_(sel, cmd, searchBar): sb = ObjCInstance(searchBar) sb.resignFirstResponder()
def searchBarTextDidEndEditing_(sel, cmd, searchBar): sb = ObjCInstance(searchBar)
def searchBar_textDidChange_(sel, cmd, searchBar, searchText): s = ObjCInstance(sel) if s.resultController.firstRun: s.resultController.tableView().position = CGPoint(s.resultController.tableView().position().x, s.resultController.tableView().position().y-40) s.resultController.firstRun = False
def tableView_numberOfRowsInSection_(sel,cmd, tableView,section): ds = ObjCInstance(sel) return len(ds.data)
def get_filename(asset): r = ObjCInstance(asset) root, ext = os.path.splitext(str(r.filename())) return root, ext
def searchBar_textDidChange_(sel, cmd, searchBar, searchText): sb = ObjCInstance(searchBar) s = ObjCInstance(sel) ObjCInstance(sel).filt(sb.text())
def show(self): self.newVC.View = ObjCInstance(self.uiView) self.newVC.title = self.name self.newVC.navigationItem( ).rightBarButtonItems = self.right_button_items tabVC.addTabWithViewController_(self.newVC)
def attach(self): self.uiView = ui.View() self.present = self.uiView.present ObjCInstance(self.uiView).addSubview_(self._scene_objc)
def main(assets, keep_meta, geo_tag, dest_dir, size): minumum_size = True resizePercent = 0 # This is time in seconds to allow for dropbox to process each photo. Older iOS devices will require more time. upload_pause = 3 if size == 'fifty': scale = float(50) / 100 elif size == 'custom': scale = tf2 # Numbers only for textbox entries scale.keyboard_type = ui.KEYBOARD_NUMBER_PAD # Display ui locked in portrait orientation and wait till user selects something from it. v2.present(orientations=['portrait']) v2.wait_modal() scale = float(scale.text) / 100 # No minumums here...reduce all photos no matter what their size. minumum_size = False # If user pressed the close button then cancel script if not ok: console.hud_alert('Script Cancelled') sys.exit() elif size == 'none': scale = 1 # Disable idle timer to cover working with a large batch of photos console.set_idle_timer_disabled(True) start = time.clock() # Create an instance of Dropbox client drop_client = get_client() for asset in assets: print('\nProcessing photo...') ''' Get date & time photo was created on YOUR iOS device. Note that in some cases the creation date may not be the date the photo was taken (ie you got it via text, email, Facebook, etc), but rather the date the photo was saved to the camera roll on your device. ''' the_year, the_date, the_time = get_date_time(asset.creation_date) file_name = '' # Formulate file name for photo old_filename = str(ObjCInstance(asset).filename()) if the_date: folder_name = '{}/{}'.format(the_year, the_date) new_filename = '{}.{}'.format(the_time, old_filename) else: folder_name = 'NoDates' new_filename = old_filename keep_meta = False new_filename = '{}/{}/{}'.format(dest_dir, folder_name, new_filename) if folder_name == 'NoDates': no_exif.append(new_filename) file_name = '{}.{}'.format(the_time, file_name) # Get dimensions for resize based on size of original photo new_w, new_h, w, h, resizeOk = get_dimensions(asset, scale, new_filename, minumum_size) fmt = '\nOriginal Name: {}\nNew Name: {}' print(fmt.format(old_filename, new_filename)) fmt = '\nOriginal Size: {}x{}\nNew Size: {}x{}' print(fmt.format(w, h, new_w, new_h)) addToMsg = 'with' if keep_meta else 'without' if resizeOk: msg = '\nCreating resized copy of original photo {} the metadata from original.' else: msg = '\nCreating copy of original photo {} the metadata from original.' print(msg.format(addToMsg)) # Fetch asset's image data & return it as a io.BytesIO object and then as a byte string img = asset.get_image_data(original=False).getvalue() # Write string image of original photo to Pythonista script dir with open('with_meta.jpg', 'wb') as out_file: out_file.write(img) # Open image, resize it, and write new image to scripts dir img = Image.open('with_meta.jpg') # Retrieve a number that represents the orientation of photo orientation = str(ObjCInstance(asset).orientation()) # Landscape if orientation in ('1', '3'): img = img.resize((new_w, new_h), Image.ANTIALIAS) # Occasionally metadata will say the photo orientation is 1 even though the width is less than the height of photo. oriented = 'portrait' if new_w < new_h else 'landscape' # Portrait elif orientation in ('6', '8'): img = img.resize((new_h, new_w), Image.ANTIALIAS) oriented = 'portrait' # Unavailable else: img = img.resize((new_w, new_h), Image.ANTIALIAS) oriented = 'unknown' print('\nThe orientation for photo is {}.'.format(oriented)) if geo_tag: # Get geo-tagging info the_location = get_location(asset.location) if the_location: print('\nGeo-tagging photo...') the_time = the_time.replace('.', ':') the_location = '{} @ {} in {}'.format(the_date, the_time, the_location) ''' Get degrees needed to rotate photo for it's proper orientation. See www.impulsesdventue.com/photoexif orientation.html for more details. ''' degrees = get_degrees_to_rotate(orientation) # Rotate photo so tag is on bottom of photo regardless of orientation img = img.rotate(degrees).convert('RGBA') # Tuple w, h = img.size draw = ImageDraw.Draw(img) # Font for geo-tag will be 28 pt Helvetica fontsize = 28 font = ImageFont.truetype('Helvetica', fontsize) y = h - 35 # Put red text @ bottom left of photo draw.text((25, y), the_location, (255, 0, 0), font=font) # Rotate photo back to original position img = img.rotate(-degrees) else: print('\nNo gps metadata for photo.') no_gps.append(new_filename) else: print('\nPhoto will not be geo_tagged. Flag is set to false.') # Save new image img.save('without_meta.jpg') if keep_meta: ''' Copy metadata from 'with_meta.jpg' to 'without_meta.jpg and call this reprocessed image file 'meta_resized.jpg'. ''' copy_meta('with_meta.jpg', 'without_meta.jpg', new_w, new_h) jpg_file = 'meta_resized.jpg' else: # Use resized photo that has not had metadata added back into it jpg_file = 'without_meta.jpg' print('\nUploading photo to Dropbox...') ''' Upload resized photo with or without original metadata to Dropbox...use 'with' statement to open file so file closes automatically at end of 'with'. ''' with open(jpg_file, 'r') as img: response = drop_client.put_file(new_filename, img) # Give Dropbox server time to process...pause time is user defined. time.sleep(upload_pause) response = jpg_file = the_location = img = the_date = the_time = the_year = new_filename = old_filename = '' print('\nUpload successful.') finish = time.clock() print('{} photos processed in {}'.format( count, timer(start, finish, count, upload_pause))) if no_exif: print( '\nPhotos with no DateTimeOriginal tag in their metadata and will need categorizing manually:' ) print('\n'.join(no_exif)) if no_resize: print( '\nPhotos that did not get resized because either you chose not to resize, or they were smaller than the minumum size of 1600x1200:' ) print('\n'.join(no_resize)) if no_gps: print( '\nPhotos that did not get geo-tagged because there was no gps info in the photo\'s metadata:' ) print('\n'.join(no_gps)) # Re-enable idle timer console.set_idle_timer_disabled(False)
def add_constraint(self, constraint): ObjCInstance(self.superview).addConstraint_(constraint)
def remove_constraint(self, constraint): ObjCInstance(self.superview).removeConstraint_(constraint)
class PlayerView (ui.View): '''A player view with controls''' def __init__(self, player = None, pause= True, autoplay = False, pip = False): self._pause_on_dismiss = pause self._objc = ObjCInstance(self) self._playerViewController = AVPlayerViewController.new() self._objc.addSubview_(self._playerViewController.view()) self.player = player self._autoplay = autoplay self._playerViewController.setAllowsPictureInPicturePlayback_(pip) @property def player(self): return self._playerItem @player.setter def player(self, player): if type(player) == Player: self._playerViewController.setPlayer_(player._objc) self._playerItem = player self.controller = PlayerController(self._playerViewController.playerController()) elif type(player) == type(None): self._playerViewController.setPlayer_(player) self._playerItem = None elif type(player) == ObjCInstance: self._playerItem = Player(player.currentItem()) self._playerViewController.setPlayer_(self._playerItem) self.controller = PlayerController(self._playerViewController.playerController()) else: raise TypeError("player is not able to be set") @player.deleter def player(self): self._playerViewController.setPlayer_(None) def will_close(self): if self._pause_on_dismiss: self.player.pause() def did_load(self): if self._autoplay: self.player.play() def layout(self): pass @property def pipSupported(self): self._playerViewController.allowsPictureInPicturePlayback() @pipSupported.setter def pipSupported(self, value): self._playerViewController.setAllowsPictureInPicturePlayback_(value) @property def showsPlaybackControls(self): return self._playerViewController.showsPlaybackControls() @showsPlaybackControls.setter def showsPlaybackControls(self, state): self._playerViewController.setShowsPlaybackControls_(state)
def __init__(self): self.instance = ObjCInstance(self) self.setup_objc() self.setup_ui()
def searchBarTextDidBeginEditing_(sel, cmd, searchBar): sb = ObjCInstance(searchBar) sb.becomeFirstResponder()
def __init__(self, tableView, filterData, selectCallBack, theme_manager, soofflineSelectCallBack, *args, **kwargs): ui.View.__init__(self, *args, **kwargs) self.width, self.height = ui.get_screen_size() frame = CGRect(CGPoint(0, 0), CGSize(self.width, self.height)) theme_manager_g = theme_manager self.theme_manager = theme_manager bkg_view = ui.View() bkg_view.background_color = self.theme_manager.currentTheme.backgroundColour self.tv = tableView self.tv.width = self.width self.tv.height = self.height self.tableView = ObjCInstance(self.tv) self.tableView.setBackgroundView(bkg_view) flex_width, flex_height = (1<<1), (1<<4) self.tableView.setAutoresizingMask_(flex_width|flex_height) self.selectCallBack = selectCallBack self.soofflineSelectCallBack = soofflineSelectCallBack v = UITableViewController.alloc().init().autorelease() tvd = createTableViewDelegateClass(theme_manager) self.tb_ds = tvd.alloc().init().autorelease() v.tableView().setDataSource_(self.tb_ds) v.tableView().setDelegate_(self.tb_ds) v.tableView().dataSource().data = [] v.tableView().dataSource().selectCallBack = self.performSelectCallBack self.searchController = UISearchController.alloc().initWithSearchResultsController_(v) self.searchController.resultController = v self.searchController.firstRun = True sd = createSearchDelegateClass() self.searchDelegate = sd.alloc().init().autorelease() self.searchDelegate.filter = filterData self.searchDelegate.resultController = v self.tableView.extendedLayoutIncludesOpaqueBars = True self.searchController.searchResultsUpdater = self.searchDelegate self.searchController.dimsBackgroundDuringPresentation = True self.searchController.hidesNavigationBarDuringPresentation = True self.searchController.searchBar().delegate = self.searchDelegate self.searchController.searchBar().setPlaceholder_(ns('Search')) self.tableView.tableHeaderView =self.searchController.searchBar(); self.searchController.searchBar().sizeToFit(); tColour = tuple(int(self.theme_manager.currentTheme.searchTintColour.lstrip('#')[i:i+2], 16) for i in (0, 2 ,4)) bTColour = tuple(int(self.theme_manager.currentTheme.searchBackgroundColour.lstrip('#')[i:i+2], 16) for i in (0, 2 ,4)) tColour = (tColour[0]/255, tColour[1]/255, tColour[2]/255) bTColour = (bTColour[0]/255, bTColour[1]/255, bTColour[2]/255) searchTintColour = UIColor.colorWithRed_green_blue_alpha_(tColour[0], tColour[1], tColour[2], 1) self.searchController.searchBar().tintColor = searchTintColour searchBackgroundTintColour = UIColor.colorWithRed_green_blue_alpha_(bTColour[0], bTColour[1], bTColour[2], 1) self.searchController.searchBar().tintColor = searchTintColour self.searchController.searchBar().barTintColor = searchBackgroundTintColour # self.tb_ds.textColour = searchTColour self.tv.border_color = self.theme_manager.currentTheme.borderColour self.tv.background_color = self.theme_manager.currentTheme.backgroundColour self.tv.bg_color = self.theme_manager.currentTheme.backgroundColour self.tv.tint_color = self.theme_manager.currentTheme.tintColour self.tv.separator_color = self.theme_manager.currentTheme.separatorColour bk_view = ui.View() bk_view.background_color = self.theme_manager.currentTheme.backgroundColour v.tableView().setBackgroundView(bk_view) self_objc = ObjCInstance(self) self_objc.addSubview_(self.tableView) self.tableView.release()
def touch_moved(self, touch): ui_touch = ObjCInstance(touch) force = ui_touch.force() # To keep it simple, just show the force in the view's title bar: self.name = 'Force: %0.2f' % (force, )
def tableView_didSelectRowAtIndexPath_(sel,cmd,tableView,indexPath): ds = ObjCInstance(sel) ip = ObjCInstance(indexPath) data = ds.data[ip.row()] ds.selectCallBack(data)
def _str_symbol(name): return ObjCInstance(c_void_p.in_dll(c, name))
def searchBarTextDidBeginEditing_(sel, cmd, searchBar): s = ObjCInstance(sel) sb = ObjCInstance(searchBar) sb.becomeFirstResponder() sb.position = CGPoint(sb.position().x,sb.size().height*2-2)
def pickerView_attributedTitleForRow_forComponent_(self, cmd, picker_view, row, component): tag = ObjCInstance(picker_view).tag() return NSAttributedString.alloc().initWithString_attributes_( ns(_data[tag - 1][row]), ns(_default_attributes)).ptr
def searchBarCancelButtonClicked_(sel, cmd, searchBar): s = ObjCInstance(sel) sb = ObjCInstance(searchBar) sb.setText_('') sb.resignFirstResponder()
def pickerView_titleForRow_forComponent_(self, cmd, picker_view, row, component): tag = ObjCInstance(picker_view).tag() return ns(_data[tag - 1][row]).ptr
# coding: utf-8 # https://forum.omz-software.com/topic/3728/having-trouble-writing-a-video-file-to-local-storage-ends-up-corrupted import vimeo import photos from io import BytesIO from objc_util import ObjCInstance client = vimeo.VimeoClient(token='my_api_token') video_asset = photos.pick_asset() video_data = video_asset.get_image_data() video_bytes = video_data.getvalue() filename = str(ObjCInstance(video_asset).filename()) with open(filename, 'wb') as video: video.write(video_bytes) video.close() video_uri = client.upload(filename)
def pickerView_numberOfRowsInComponent_(self, cmd, picker_view, component): tag = ObjCInstance(picker_view).tag() return len(_data[tag - 1])
def row_for_view(self, sender): '''Helper to find the row index for an 'expand' button''' cell = ObjCInstance(sender) while not cell.isKindOfClass_(ObjCClass('UITableViewCell')): cell = cell.superview() return ObjCInstance(self.table_view).indexPathForCell_(cell).row()
def wtShare(_self, _cmd): url = ObjCInstance(_self).view().URL() if url: dialogs.share_url(str(url.absoluteString()))
def UIImagePNGRepresentation(image): return ObjCInstance(quartz.UIImagePNGRepresentation(image))
def layout(self): self._picker_view.frame = ObjCInstance(self).bounds()
def pickerView_didSelectRow_inComponent_(self, cmd, picker_view, row, component): tag = ObjCInstance(picker_view).tag() print(f'Did select {_data[tag - 1][row]}')
def __init__(self, **kwargs): super().__init__(**kwargs) self._picker_view = UIPickerView.alloc().initWithFrame_( ObjCInstance(self).bounds()).autorelease() ObjCInstance(self).addSubview_(self._picker_view)
def png_buffer(img): data=ObjCInstance(UIImagePNGRepresentation(img)) b64 = decodestring(data.base64EncodedString().cString()) buffer = BytesIO(b64) return buffer