def populate(self): self._textures = [] if __debug__: Logger.trace("Image: %r, populate to textures (%d)" % (self.filename, len(self._data))) for count in xrange(len(self._data)): # first, check if a texture with the same name already exist in the # cache uid = "%s|%s|%s" % (self.filename, self._mipmap, count) texture = Cache.get("kv.texture", uid) # if not create it and append to the cache if texture is None: imagedata = self._data[count] texture = Texture.create_from_data(imagedata, mipmap=self._mipmap) if not self._nocache: Cache.append("kv.texture", uid, texture) if imagedata.flip_vertical: texture.flip_vertical() # set as our current texture self._textures.append(texture) # release data if ask if not self.keep_data: self._data[count].release_data()
def populate(self): self._textures = [] fname = self.filename if __debug__: Logger.trace('Image: %r, populate to textures (%d)' % (fname, len(self._data))) for count in range(len(self._data)): # first, check if a texture with the same name already exist in the # cache chr = type(fname) uid = chr(u'%s|%d|%d') % (fname, self._mipmap, count) texture = Cache.get('kv.texture', uid) # if not create it and append to the cache if texture is None: imagedata = self._data[count] source = '{}{}|'.format( 'zip|' if fname.endswith('.zip') else '', self._nocache) imagedata.source = chr(source) + uid texture = Texture.create_from_data( imagedata, mipmap=self._mipmap) if not self._nocache: Cache.append('kv.texture', uid, texture) if imagedata.flip_vertical: texture.flip_vertical() # set as our current texture self._textures.append(texture) # release data if ask if not self.keep_data: self._data[count].release_data()
def _on_gst_message(bus, message): Logger.trace('gst-bus: %s' % str(message)) # log all error messages if message.type == gst.MESSAGE_ERROR: error, debug = map(str, message.parse_error()) Logger.error('gstreamer_video: %s' % error) Logger.debug('gstreamer_video: %s' % debug)
def _setState(self, stateDict): #Logger.trace(self.__class__.__name__ + ': in [' + whoAmI() + '] ') #assert type(stateDict) is ObservableDict for key, value in stateDict.items(): s = '<SET ID="{}" STATE="{}" />'.format(key, str(value)) Logger.trace(self.__class__.__name__ + ': in [' + whoAmI() + '] sending string to EyeTracker: ' + str(s)) self.transport.write(s + '\r\n') #the eyetracker requires a newline to terminate
def on_destroy_notify(self, event): Logger.trace(f'WindowMgr: window destroyed: {event}') ref = self.window_refs.pop(event.window.id, None) window = ref() if ref else None if window: window.dispatch('on_window_destroy') super(KivyWindowManager, self).on_destroy_notify(event)
def msg_rx_worker(self): Logger.info('RCPAPI: msg_rx_worker starting') comms = self.comms error_count = 0 while self._running.is_set(): msg = None try: msg = comms.read_message() if msg: # clean incoming string, and drop illegal characters msg = unicode(msg, errors='ignore') msgJson = json.loads(msg, strict=False) if 's' in msgJson: Logger.trace('RCPAPI: Rx: ' + str(msg)) else: Logger.debug('RCPAPI: Rx: ' + str(msg)) Clock.schedule_once(lambda dt: self.on_rx(True)) error_count = 0 for messageName in msgJson.keys(): Logger.trace('RCPAPI: processing message ' + messageName) listeners = self.msgListeners.get(messageName, None) if listeners: for listener in listeners: try: listener(msgJson) except Exception as e: Logger.error( 'RCPAPI: Message Listener Exception for' ) Logger.debug(traceback.format_exc()) break msg = '' else: sleep(NO_DATA_AVAILABLE_DELAY) except PortNotOpenException: Logger.debug("RCPAPI: Port not open...") msg = '' sleep(1.0) except Exception as e: Logger.warn( 'RCPAPI: Message rx worker exception: {} | {}'.format( repr(msg), str(e))) Logger.debug(traceback.format_exc()) msg = '' error_count += 1 if error_count > 5 and not self._auto_detect_event.is_set(): Logger.warn( "RCPAPI: Too many Rx exceptions; re-opening connection" ) self.recover_connection() self.connected_version = None sleep(5) else: sleep(0.25) safe_thread_exit() Logger.info("RCPAPI: msg_rx_worker exiting")
def _dispatch_item(self, uri, item): cb_set = self._callbacks.get(uri, set()) for callback in cb_set: Logger.trace( "{} : _dispatch_item on uri '{}'. Callback:{}".format( self.__class__.__name__, uri, callback)) Clock.schedule_once(partial(callback, item))
def core_register_libs(category, libs, base='kivy.core'): if 'KIVY_DOC' in os.environ: return category = category.lower() libs_loaded = [] libs_ignored = [] for option, lib in libs: try: # module activated in config ? if option not in kivy.kivy_options[category]: Logger.debug('{0}: option <{1}> ignored by config'.format( category.capitalize(), option)) libs_ignored.append(lib) continue # import module __import__(name='{2}.{0}.{1}'.format(category, lib, base), globals=globals(), locals=locals(), fromlist=[lib], level=0) libs_loaded.append(lib) except Exception as e: Logger.trace('{0}: Unable to use <{1}> as loader!'.format( category.capitalize(), option)) Logger.trace('', exc_info=e) libs_ignored.append(lib) Logger.info('{0}: Providers: {1} {2}'.format( category.capitalize(), ', '.join(libs_loaded), '({0} ignored)'.format( ', '.join(libs_ignored)) if libs_ignored else ''))
def _on_gst_message(bus, message): Logger.trace("VideoGi: (bus) {}".format(message)) # log all error messages if message.type == Gst.MessageType.ERROR: error, debug = list(map(str, message.parse_error())) Logger.error("VideoGi: {}".format(error)) Logger.debug("VideoGi: {}".format(debug))
def request_item(self, uri, callback): if not uri: return # Update callback cb_set = self._callbacks.get(uri, set()) cb_set.add(callback) self._callbacks.update({uri: cb_set}) # URI is found in cache cached_item = self._cache.get(uri) if cached_item: Logger.debug( "{} : _request_item on uri '{}'. Found in cache".format( self.__class__.__name__, uri) ) Clock.schedule_once(partial(callback, cached_item)) return # URI not found in cache. Add to request list self._requested_uris.add(uri) Logger.debug( "{} : _request_item on uri '{}'. Added to request list".format( self.__class__.__name__, uri) ) Logger.trace( "{} : _request_item on uri '{}'. Callbacks:{}".format( self.__class__.__name__, uri, cb_set) ) # Perform server request self._get_server_items()
def _process_events_before_frame(self): found = True count = self.max_iteration events = self._events while found: count -= 1 if count < 0: Logger.critical( 'Clock: Warning, too much iteration done before' ' the next frame. Check your code, or increase ' 'the Clock.max_iteration attribute') # search event that have timeout = -1 found = False for cid in events.keys()[:]: for event in events[cid][:]: if event.timeout != -1: continue found = True if event.tick(self._last_tick) is False: # event may be already removed by the callback if event in events[cid]: events[cid].remove(event) if count != self.max_iteration - 1: i = self.max_iteration - count + 1 if __debug__: Logger.trace('Clock: we done %d iteration before the frame' % i)
def populate(self): self._textures = [] if __debug__: Logger.trace('Image: %r, populate to textures (%d)' % (self.filename, len(self._data))) for count in range(len(self._data)): # first, check if a texture with the same name already exist in the # cache uid = '%s|%s|%s' % (self.filename, self._mipmap, count) texture = Cache.get('kv.texture', uid) # if not create it and append to the cache if texture is None: imagedata = self._data[count] imagedata.source = '{}{}|{}'.format( 'zip|' if self.filename.endswith('.zip') else '', self._nocache, uid) texture = Texture.create_from_data(imagedata, mipmap=self._mipmap) if not self._nocache: Cache.append('kv.texture', uid, texture) if imagedata.flip_vertical: texture.flip_vertical() # set as our current texture self._textures.append(texture) # release data if ask if not self.keep_data: self._data[count].release_data()
def core_register_libs(category, libs): if 'KIVY_DOC' in os.environ: return category = category.lower() libs_loaded = [] libs_ignored = [] for option, lib in libs: try: # module activated in config ? if option not in kivy.kivy_options[category]: Logger.debug('{0}: option <{1}> ignored by config'.format( category.capitalize(), option)) libs_ignored.append(lib) continue # import module __import__(name='%s.%s' % (category, lib), globals=globals(), locals=locals(), fromlist=[lib], level=-1) libs_loaded.append(lib) except Exception as e: Logger.trace('{0}: Unable to use <{1}> as loader!'.format( category.capitalize(), option)) Logger.trace('', exc_info=e) libs_ignored.append(lib) Logger.info('{0}: Providers: {1} {2}'.format( category.capitalize(), ', '.join(libs_loaded), '({0} ignored)'.format( ', '.join(libs_ignored)) if libs_ignored else ''))
def _purge_by_timeout(dt): curtime = Clock.get_time() for category in Cache._objects: if category not in Cache._categories: continue timeout = Cache._categories[category]['timeout'] if timeout is not None and dt > timeout: # XXX got a lag ! that may be because the frame take lot of # time to draw. and the timeout is not adapted to the current # framerate. So, increase the timeout by two. # ie: if the timeout is 1 sec, and framerate go to 0.7, newly # object added will be automatically trashed. timeout *= 2 Cache._categories[category]['timeout'] = timeout continue for key in list(Cache._objects[category].keys())[:]: lastaccess = Cache._objects[category][key]['lastaccess'] objtimeout = Cache._objects[category][key]['timeout'] # take the object timeout if available if objtimeout is not None: timeout = objtimeout # no timeout, cancel if timeout is None: continue if curtime - lastaccess > timeout: Logger.trace('Cache: Removed %s:%s from cache due to ' 'timeout' % (category, key)) Cache.remove(category, key)
def _on_gst_message(bus, message): Logger.trace('gst-bus: %s' % str(message)) # log all error messages if message.type == gst.MESSAGE_ERROR: error, debug = list(map(str, message.parse_error())) Logger.error('gstreamer_video: %s' % error) Logger.debug('gstreamer_video: %s' % debug)
def _update_progress_interval(self, delta_time): if not self.updating_progress: self.updating_progress = True if self.player.current_track and self.player.playback_started and self.player.playing: # time_played_ms = pygame.mixer.music.get_pos() # duration_ms = int(self.musicmanager.current_track['duration_ms']) # progress = time_played_ms / (duration_ms / 100) progress_percent = self.player.send_cmd_to_mplayer( 'get_percent_pos', 'ANS_PERCENT_POSITION') if progress_percent is not False and progress_percent is not None: old_progress_percent = self.player.progress_percent self.player.progress_percent = interpolate( old_progress_percent, int(progress_percent)) Logger.trace('Progress: ' + str(self.player.progress_percent)) elif progress_percent is False: Logger.debug('_update_progress_interval: Received ' + str(progress_percent) + ' as progress') self.player.playback_finished() self.play_next_track() else: Logger.debug('_update_progress_interval: Received ' + str(progress_percent) + ' as progress') # remove schedule if no track selected elif not self.player.playback_started and not self.player.playing: Logger.debug( 'No song playing, removing slider update interval..') self.updating_progress = False return False self.updating_progress = False
def populate(self): self._textures = [] if __debug__: Logger.trace('Image: %r, populate to textures (%d)' % (self.filename, len(self._data))) for count in xrange(len(self._data)): # first, check if a texture with the same name already exist in the # cache uid = '%s|%s|%s' % (self.filename, self._mipmap, count) texture = Cache.get('kv.texture', uid) # if not create it and append to the cache if texture is None: texture = Texture.create_from_data( self._data[count], mipmap=self._mipmap) Cache.append('kv.texture', uid, texture) # set as our current texture self._textures.append(texture) # release data if ask if not self.keep_data: self._data[count].release_data()
def _on_gst_message(bus, message): Logger.trace('VideoGi: (bus) {}'.format(message)) # log all error messages if message.type == Gst.MessageType.ERROR: error, debug = list(map(str, message.parse_error())) Logger.error('VideoGi: {}'.format(error)) Logger.debug('VideoGi: {}'.format(debug))
def on_unmap_notify(self, event): Logger.trace(f'WindowMgr: window unmapped: {event}') ref = self.window_refs.get(event.window.id) window = ref() if ref else None if window: window.dispatch('on_window_unmap') super(KivyWindowManager, self).on_unmap_notify(event)
def _process_events_before_frame(self): found = True count = self.max_iteration events = self._events while found: count -= 1 if count < 0: Logger.critical('Clock: Warning, too much iteration done before' ' the next frame. Check your code, or increase ' 'the Clock.max_iteration attribute') # search event that have timeout = -1 found = False for cid in events.keys()[:]: for event in events[cid][:]: if event.timeout != -1: continue found = True if event.tick(self._last_tick) is False: # event may be already removed by the callback if event in events[cid]: events[cid].remove(event) if count != self.max_iteration - 1: i = self.max_iteration - count + 1 if __debug__: Logger.trace('Clock: we done %d iteration before the frame' % i)
def populate(self): self._textures = [] if __debug__: Logger.trace('Image: %r, populate to textures (%d)' % (self.filename, len(self._data))) for count in xrange(len(self._data)): # first, check if a texture with the same name already exist in the # cache uid = '%s|%s|%s' % (self.filename, self._mipmap, count) texture = Cache.get('kv.texture', uid) # if not create it and append to the cache if texture is None: texture = Texture.create_from_data(self._data[count], mipmap=self._mipmap) Cache.append('kv.texture', uid, texture) # set as our current texture self._textures.append(texture) # release data if ask if not self.keep_data: self._data[count].release_data()
def _on_gst_message(bus, message): Logger.trace('VideoPyGst: (bus) %s' % str(message)) # log all error messages if message.type == gst.MESSAGE_ERROR: error, debug = list(map(str, message.parse_error())) Logger.error('VideoPyGst: %s' % error) Logger.debug('VideoPyGst: %s' % debug)
def test_log_handles_cp949(self): with mock.patch("locale.getpreferredencoding", return_value="cp949"): FileHandler.fd = None FileHandler.encoding = "utf-8" Config.set("kivy", "log_enable", 1) Config.set("kivy", "log_level", "trace") for string in ["한국어", "Niñas and niños"]: Logger.trace("Lang: call_fn => value=%r" % (string,))
def _bus_message(self, bus, message): Logger.trace("gst-bus:%s"%str(message)) # log all error messages if message.type == gst.MESSAGE_ERROR: error, debug = map(str, message.parse_error()) Logger.error("gstreamer_video: %s"%error) Logger.debug("gstreamer_video: %s"%debug)
def on_configure_notify(self, event): # TODO: Check if the window was actually resized ref = self.window_refs.get(event.window.id) window = ref() if ref else None if window: window.dispatch('on_window_resize') Logger.trace(f'WindowMgr: window configured: {event}') super(KivyWindowManager, self).on_configure_notify(event)
def test_non_utf8_encoding_raises_exception( self, ): # the old error before utf-8 was standard FileHandler.fd = None FileHandler.encoding = "cp949" Config.set("kivy", "log_enable", 1) Config.set("kivy", "log_level", "trace") with pytest.raises(UnicodeError): Logger.trace("Lang: call_fn => value=%r" % ("Niñas and niños",))
def play_track_from_id(self, track): # immediately display correct button label/icon and # prevent update_progress_interval from removing itself before song starts self.playing = True # get stream url mp3_url = Globals.API.get_stream_url(track['track_id'], self.streaming_quality) Logger.trace(mp3_url) # set current track self.current_track = track # start download Thread(target=self.download_and_play_track_thread, args=(mp3_url, Globals.MP3_PATH, Globals.BUFFER_ITERATIONS)).start()
def on_update(self, pieces, status, move=None): Logger.trace('{}: on_update {}'.format(__name__, pieces)) self.new_button.disabled = not self.engine.can_undo() self.undo_button.disabled = not self.engine.can_undo() self.redo_button.disabled = not self.engine.can_redo() self.status_label.text = '[b][i]{}[/b][/i]'.format(status) if pieces: self.board.pieces = pieces self.move_label.text = move or '' if move: self.board.select(move)
def msg_rx_worker(self): Logger.info('RCPAPI: msg_rx_worker starting') comms = self.comms error_count = 0 while self._running.is_set(): msg = None try: msg = comms.read_message() if msg: # clean incoming string, and drop illegal characters msg = unicode(msg, errors='ignore') msgJson = json.loads(msg, strict=False) if 's' in msgJson: Logger.trace('RCPAPI: Rx: ' + str(msg)) else: Logger.debug('RCPAPI: Rx: ' + str(msg)) Clock.schedule_once(lambda dt: self.on_rx(True)) error_count = 0 for messageName in msgJson.keys(): Logger.trace('RCPAPI: processing message ' + messageName) listeners = self.msgListeners.get(messageName, None) if listeners: for listener in listeners: try: listener(msgJson) except Exception as e: Logger.error('RCPAPI: Message Listener Exception for') Logger.debug(traceback.format_exc()) break msg = '' else: sleep(NO_DATA_AVAILABLE_DELAY) except PortNotOpenException: Logger.debug("RCPAPI: Port not open...") msg = '' sleep(1.0) except Exception as e: Logger.warn('RCPAPI: Message rx worker exception: {} | {}'.format(repr(msg), str(e))) Logger.debug(traceback.format_exc()) msg = '' error_count += 1 if error_count > 5 and not self._auto_detect_event.is_set(): Logger.warn("RCPAPI: Too many Rx exceptions; re-opening connection") self.recover_connection() self.connected_version = None sleep(5) else: sleep(0.25) safe_thread_exit() Logger.info("RCPAPI: msg_rx_worker exiting")
def msg_rx_worker(self): Logger.info('RCPAPI: msg_rx_worker started') comms = self.comms error_count = 0 while self._running.is_set(): msg = None try: msg = comms.read_message() if msg: Logger.trace('RCPAPI: msg_rx_worker Rx: ' + str(msg)) msgJson = json.loads(msg, strict=False) self.on_rx(True) error_count = 0 for messageName in msgJson.keys(): Logger.trace('RCPAPI: processing message ' + messageName) listeners = self.msgListeners.get(messageName, None) if listeners: for listener in listeners: try: listener(msgJson) except Exception as e: Logger.error( 'RCPAPI: Message Listener Exception for' ) Logger.debug(traceback.format_exc()) break msg = '' else: sleep(NO_DATA_AVAILABLE_DELAY) except PortNotOpenException: Logger.warn("RCPAPI: Port not open...") msg = '' sleep(1.0) except Exception: Logger.warn( 'RCPAPI: Message rx worker exception: {} | {}'.format( msg, str(Exception))) Logger.debug(traceback.format_exc()) msg = '' error_count += 1 if error_count > 5 and not self._auto_detect_event.is_set(): Logger.warn( "RCPAPI: Too many Rx exceptions; re-opening connection" ) self.recover_connection() sleep(5) else: sleep(0.25) Logger.info("RCPAPI: RxWorker exiting")
def dispatch_msg(self, msg_json, source): for msg_name in msg_json.keys(): Logger.trace('ApiDispatcher: processing message: {}'.format(msg_name)) listeners = self.msg_listeners.get(msg_name, None) if listeners: for listener in listeners: try: listener(msg_json, source) except Exception as e: Logger.error('ApiDispatcher: Message Listener Exception for {}'.format(msg_json)) Logger.error(traceback.format_exc()) break
def on_touch_down(self, touch): Logger.trace('{}.Board: on_touch_down({} {})'.format( __name__, touch.pos, self.xyo)) x, y = [(i - j) / self.cell_size for i, j in zip(touch.pos, self.xyo)] if 0 <= x < 8 and 0 <= y < 8: move = 'abcdefgh'[int(x)] + str(1 + int(y)) self.move += move if len(self.move) < 4: self.select(move) else: self.dispatch('on_move', self.move) self.move = ''
def on_size(self, *args): Logger.trace(f'WindowMgr: {self}: on_size: {self.size}') try: self._window.configure( width=round(self.width), height=round(self.height), ) except AttributeError: return self.invalidate_pixmap = True
def send_cmd_to_mplayer(self, cmd, expected_tag=''): if self.player: try: Logger.trace('Sending to mplayer: ' + cmd) output = self._perform_command(cmd, expected_tag) return output except BrokenPipeError: Logger.exception('Pipe unavailable..') return False else: Logger.warning('Could not execute cmd. No player!') return False
def on_create_notify(self, event): # Don't create a child for the Kivy window, or overlay window_info = self.app_window_info() if window_info and window_info.window == event.window.id: return if event.window == self.overlay_win: return self._add_child(event.window) Logger.trace(f'WindowMgr: window created: {event}') super(KivyWindowManager, self).on_create_notify(event)
def eyeTrackerAck(self, attribDict): #Logger.trace(self.__class__.__name__ + ': in [' + whoAmI() + '] ') #extract ID assert type(attribDict) is dict assert 'ID' in attribDict assert 'STATE' in attribDict key = attribDict['ID'] value = stringToBestType(attribDict['STATE']) if key in self.attribToParamDict: Logger.trace(self.__class__.__name__ + ': in [' + whoAmI() + '] Got implemented key: ' + key) #setattr(self.factory.eyeTracker, self.attribToParamDict[key], value) else: Logger.exception(self.__class__.__name__ + ': in [' + whoAmI() + '] Key not implemented yet: ' + key)
def connection_message_process(connection, device, rx_queue, tx_queue, command_queue): Logger.debug('Comms: connection process starting') try: connection.open(device) connection.flushInput() connection.flushOutput() reader_writer_should_run = threading.Event() reader_writer_should_run.set() reader_thread = threading.Thread( target=connection_process_message_reader, args=(rx_queue, connection, reader_writer_should_run)) reader_thread.start() writer_thread = threading.Thread( target=connection_process_message_writer, args=(tx_queue, connection, reader_writer_should_run)) writer_thread.start() while reader_writer_should_run.is_set(): try: command = command_queue.get(True, STAY_ALIVE_TIMEOUT) if command == COMMAND_CLOSE: Logger.debug( 'Comms: connection process: got close command') reader_writer_should_run.clear() except Empty: Logger.debug('Comms: keep alive timeout') reader_writer_should_run.clear() Logger.debug('Comms: connection worker exiting') reader_thread.join() writer_thread.join() try: connection.close() except: Logger.debug( 'Comms: Exception closing connection worker connection') Logger.debug(traceback.format_exc()) except Exception as e: Logger.debug('Comms: Exception setting up connection process: ' + str(type(e)) + str(e)) Logger.trace(traceback.format_exc()) Logger.debug('Comms: connection worker exited')
def sendCommand(self, cmd): try: self.sendCommandLock.acquire() rsp = None comms = self.comms cmdStr = json.dumps(cmd, separators=(',', ':')) + '\r' Logger.trace('RCPAPI: send cmd: ' + cmdStr) comms.write_message(cmdStr) except Exception: self.recover_connection() finally: self.sendCommandLock.release() self.on_tx(True)
def dispatch_msg(self, msg_json, source): for msg_name in msg_json.keys(): Logger.trace( 'ApiDispatcher: processing message: {}'.format(msg_name)) listeners = self.msg_listeners.get(msg_name, None) if listeners: for listener in listeners: try: listener(msg_json, source) except Exception as e: Logger.error( 'ApiDispatcher: Message Listener Exception for {}'. format(msg_json)) Logger.error(traceback.format_exc()) break
def msg_rx_worker(self): Logger.info('RCPAPI: msg_rx_worker started') comms = self.comms error_count = 0 while self._running.is_set(): msg = None try: msg = comms.read_message() if msg: Logger.trace('RCPAPI: msg_rx_worker Rx: ' + str(msg)) msgJson = json.loads(msg, strict = False) self.on_rx(True) error_count = 0 for messageName in msgJson.keys(): Logger.trace('RCPAPI: processing message ' + messageName) listeners = self.msgListeners.get(messageName, None) if listeners: for listener in listeners: try: listener(msgJson) except Exception as e: Logger.error('RCPAPI: Message Listener Exception for') Logger.debug(traceback.format_exc()) break msg = '' else: sleep(NO_DATA_AVAILABLE_DELAY) except PortNotOpenException: Logger.warn("RCPAPI: Port not open...") msg='' sleep(1.0) except Exception: Logger.warn('RCPAPI: Message rx worker exception: {} | {}'.format(msg, str(Exception))) Logger.debug(traceback.format_exc()) msg = '' error_count += 1 if error_count > 5 and not self._auto_detect_event.is_set(): Logger.warn("RCPAPI: Too many Rx exceptions; re-opening connection") self.recover_connection() sleep(5) else: sleep(0.25) Logger.info("RCPAPI: RxWorker exiting")
def run(self): dev = nfc = None mod_targets = None add = self.q.appendleft current_uids = [] while not self.quit: # create device if not dev: dev, nfc = self._connect() if dev is None: sleep(5) continue mod_targets = ( pynfc.Modulation(nmt=nfc.NMT_ISO14443A, nbr=nfc.NBR_106), pynfc.Modulation(nmt=nfc.NMT_ISO14443B, nbr=nfc.NBR_106), ) nfc.configure(nfc.NDO_INFINITE_SELECT, False) if dev: error = nfc.get_error() if 'error' in error: Logger.error('Rfid: An error occured %r' % error) dev = nfc = None continue # NFC library polling Logger.trace('Rfid: Polling target') targets = nfc.poll_targets(mod_targets, 1, 2) Logger.trace('Rfid: Read %d targets' % len(targets)) uids = [] for target in targets: uid = self._read_uid(target) uids.append(uid) if not uid in current_uids: add(uid) current_uids.append(uid) else: continue # remove old uid to accept further discovery for uid in current_uids[:]: if uid not in uids: current_uids.remove(uid) sleep(1)
def core_register_libs(category, libs, base='kivy.core'): if 'KIVY_DOC' in os.environ: return category = category.lower() kivy_options = kivy.kivy_options[category] libs_loadable = {} libs_ignored = [] for option, lib in libs: # module activated in config ? if option not in kivy_options: Logger.debug('{0}: option <{1}> ignored by config'.format( category.capitalize(), option)) libs_ignored.append(lib) continue libs_loadable[option] = lib libs_loaded = [] for item in kivy_options: try: # import module try: lib = libs_loadable[item] except KeyError: continue __import__(name='{2}.{0}.{1}'.format(category, lib, base), globals=globals(), locals=locals(), fromlist=[lib], level=0) libs_loaded.append(lib) except Exception as e: Logger.trace('{0}: Unable to use <{1}> as loader!'.format( category.capitalize(), option)) Logger.trace('', exc_info=e) libs_ignored.append(lib) Logger.info('{0}: Providers: {1} {2}'.format( category.capitalize(), ', '.join(libs_loaded), '({0} ignored)'.format( ', '.join(libs_ignored)) if libs_ignored else '')) return libs_loaded
def on_motion(self, instance, evtype, event): if not isinstance(event, GPIOEvent): return False Logger.trace('%s: on_motion: evtype=%r event=%r' % (self.__class__.__name__, evtype, event)) # Filter on event conditions if (not 'dial' in event.profile or (self.dial_device and self.dial_device != event.device) or (not self.dial_axis in event.push_attrs)): return False dial_value = getattr(event, self.dial_axis) * self.dial_step Logger.debug('DialBehavior: on_motion: dispatching on_dial(axis=%s, value=%d)' % (self.dial_axis, dial_value)) self.dispatch('on_dial', dial_value) return False
def connection_message_process(connection, device, rx_queue, tx_queue, command_queue): Logger.debug('Comms: connection process starting') try: connection.open(device) connection.flushInput() connection.flushOutput() reader_writer_should_run = threading.Event() reader_writer_should_run.set() reader_thread = threading.Thread(target=connection_process_message_reader, args=(rx_queue, connection, reader_writer_should_run)) reader_thread.start() writer_thread = threading.Thread(target=connection_process_message_writer, args=(tx_queue, connection, reader_writer_should_run)) writer_thread.start() while reader_writer_should_run.is_set(): try: command = command_queue.get(True, STAY_ALIVE_TIMEOUT) if command == COMMAND_CLOSE: Logger.debug('Comms: connection process: got close command') reader_writer_should_run.clear() except Empty: Logger.debug('Comms: keep alive timeout') reader_writer_should_run.clear() Logger.debug('Comms: connection worker exiting') reader_thread.join() writer_thread.join() try: connection.close() except: Logger.debug('Comms: Exception closing connection worker connection') Logger.debug(traceback.format_exc()) except Exception as e: Logger.debug('Comms: Exception setting up connection process: ' + str(type(e)) + str(e)) Logger.trace(traceback.format_exc()) Logger.debug('Comms: connection worker exited')
def _purge_oldest(category, maxpurge=1): Logger.debug('Cache: Remove oldest in %s' % category) import heapq time = Clock.get_time() heap_list = [] for key in Cache._objects[category]: obj = Cache._objects[category][key] if obj['lastaccess'] == obj['timestamp'] == time: continue heapq.heappush(heap_list, (obj['lastaccess'], key)) Logger.trace('Cache: <<< %f' % obj['lastaccess']) n = 0 while n <= maxpurge: try: n += 1 lastaccess, key = heapq.heappop(heap_list) Logger.trace('Cache: %d => %s %f %f' % (n, key, lastaccess, Clock.get_time())) except Exception: return Cache.remove(category, key)
def remove(category, key=None): '''Purge the cache. :Parameters: `category`: str Identifier of the category. `key`: str (optional) Unique identifier of the object in the store. If this argument is not supplied, the entire category will be purged. ''' try: if key is not None: del Cache._objects[category][key] Logger.trace('Cache: Removed %s:%s from cache' % (category, key)) else: Cache._objects[category] = {} Logger.trace('Cache: Flushed category %s from cache' % category) except Exception: pass
def core_select_lib(category, llist, create_instance=False, base='kivy.core'): if 'KIVY_DOC' in os.environ: return category = category.lower() libs_ignored = [] for option, modulename, classname in llist: try: # module activated in config ? try: if option not in kivy.kivy_options[category]: libs_ignored.append(modulename) Logger.debug( '{0}: Provider <{1}> ignored by config'.format( category.capitalize(), option)) continue except KeyError: pass # import module mod = __import__(name='{2}.{0}.{1}'.format(category, modulename, base), globals=globals(), locals=locals(), fromlist=[modulename], level=0) cls = mod.__getattribute__(classname) # ok ! Logger.info('{0}: Provider: {1}{2}'.format( category.capitalize(), option, '({0} ignored)'.format(libs_ignored) if libs_ignored else '')) if create_instance: cls = cls() return cls except ImportError as e: libs_ignored.append(modulename) Logger.debug('{0}: Ignored <{1}> (import error)'.format( category.capitalize(), option)) Logger.trace('', exc_info=e) except CoreCriticalException as e: Logger.error('{0}: Unable to use {1}'.format( category.capitalize(), option)) Logger.error( '{0}: The module raised an important error: {1!r}'.format( category.capitalize(), e.message)) raise except Exception as e: libs_ignored.append(modulename) Logger.trace('{0}: Unable to use {1}'.format( category.capitalize(), option, category)) Logger.trace('', exc_info=e) Logger.critical( '{0}: Unable to find any valuable {1} provider at all!'.format( category.capitalize(), category.capitalize()))
def core_select_lib(category, llist, create_instance=False, base='kivy.core'): if 'KIVY_DOC' in os.environ: return category = category.lower() libs_ignored = [] for option, modulename, classname in llist: try: # module activated in config ? try: if option not in kivy.kivy_options[category]: libs_ignored.append(modulename) Logger.debug('{0}: Provider <{1}> ignored by config'.format( category.capitalize(), option)) continue except KeyError: pass # import module mod = __import__(name='{2}.{0}.{1}'.format( category, modulename, base), globals=globals(), locals=locals(), fromlist=[modulename], level=0) cls = mod.__getattribute__(classname) # ok ! Logger.info('{0}: Provider: {1}{2}'.format( category.capitalize(), option, '({0} ignored)'.format(libs_ignored) if libs_ignored else '')) if create_instance: cls = cls() return cls except ImportError as e: libs_ignored.append(modulename) Logger.debug('{0}: Ignored <{1}> (import error)'.format( category.capitalize(), option)) Logger.trace('', exc_info=e) except CoreCriticalException as e: Logger.error('{0}: Unable to use {1}'.format( category.capitalize(), option)) Logger.error( '{0}: The module raised an important error: {1!r}'.format( category.capitalize(), e.message)) raise except Exception as e: libs_ignored.append(modulename) Logger.trace('{0}: Unable to use {1}'.format( category.capitalize(), option, category)) Logger.trace('', exc_info=e) Logger.critical( '{0}: Unable to find any valuable {1} provider at all!'.format( category.capitalize(), category.capitalize()))
def _purge_oldest(category, maxpurge=1): Logger.trace('Cache: Remove oldest in %s' % category) import heapq time = Clock.get_time() heap_list = [] for key in Cache._objects[category]: obj = Cache._objects[category][key] if obj['lastaccess'] == obj['timestamp'] == time: continue heapq.heappush(heap_list, (obj['lastaccess'], key)) Logger.trace('Cache: <<< %f' % obj['lastaccess']) n = 0 while n <= maxpurge: try: n += 1 lastaccess, key = heapq.heappop(heap_list) Logger.trace('Cache: %d => %s %f %f' % (n, key, lastaccess, Clock.get_time())) except Exception: return Cache.remove(category, key)
def unzip_extensions(): '''Unzips Kivy extensions. Internal usage only; Don't use it yourself unless you know what you're doing and really want to trigger installation of new extensions. For your file to be recognized as an extension, it has to fulfil a few requirements: * We require that the file has the ``*.kex`` extension to make the distinction between a Kivy extension and an ordinary zip file clear. * We require that the ``*.kex`` extension files be put into any of the directories listed in EXTENSION_PATHS which is normally ~/.kivy/extensions and extensions/ inside kivy's base dirextory. We do not look for extensions on sys.path or elsewhere in the system. * We require that the Kivy extension is zipped in a way so that Python's zipfile module can extract it properly. * We require that the extension internally obeys the common Kivy extension format, which looks like this:: |-- myextension/ |-- __init__.py |-- data/ The ``__init__.py`` file is the main entrypoint to the extension. All names that should be usable when the extension is loaded need to be exported (i.e. made available) in the namespace of that file. How the extension accesses the code of the library that it wraps (be it pure Python or binary code) is up to the extension. For example there could be another Python module adjacent to the ``__init__.py`` file from which the ``__init__.py`` file imports the usable names that it wants to expose. * We require that the version of the extension be specified in the ``setup.py`` file that is created by the Kivy extension wizard and that the version specification format as explained in :func:`~kivy.ext.load` be used. ''' Logger.debug('Searching for new extension in %s' % EXTENSION_PATHS) for epath in EXTENSION_PATHS: if not isdir(epath): try: mkdir(epath) except OSError: continue files = [] else: files = listdir(epath) for zipfn in glob(join(epath, '*.kex')): # ZipFile only became a context manager in python 2.7... # with ZipFile(zipfn, 'r') as zipf: # fail = is_invalid = False try: zipf = ZipFile(zipfn) # /path/to/MyExt-1.0.linux-x86_64.zip # /path/to/MyExt-1.0.macos-10.6-x86_64.zip extname = zipfn.rsplit(sep)[-1][:-4] # MyExt-1.0.linux-x86_64 # MyExt-1.0.macosx-10.6-x86_64 t = extname.split('-') extname = t[0] version = '-'.join(t[1:]) version = '.'.join(version.split('.')[:2]) extdir = extname + '_' + version # is_invalid = not _is_valid_ext_name(extdir) except IOError: Logger.warn("Malformed zipfile '%s'! Skipping it." % zipfn) continue except Exception, e: Logger.warn("Malformed extension '%s'! Skipping it." % zipfn) zipf.close() continue already_unzipped = False if extdir in files: Logger.trace(("Extension '%s' has already been " % extname) + \ "extracted manually, just moving the zip.") already_unzipped = True # Filter the namelist of zipfile to take only the members that start # with the extension name (MyExt/...) members = [x for x in zipf.namelist() \ if x.startswith(extname + '/')] if not already_unzipped: # Unzip the extension try: cache_directories = [] mkdir(join(epath, extdir)) # I know that there is zipf.extract() and zipf.extractall(), # but on OSX, Python 2.6 is the default and in that version, # both methods have a bug. Fixed in 2.7 only. So use this # workaround until apple upgrades its python. See # http://bugs.python.org/issue4710 for member in members: # In zipfiles, folders always end with '/' regardless # of the OS mempath = join(epath, extdir, member) directory = dirname(mempath) if not directory in cache_directories: cache_directories.append(directory) if not exists(directory): mkdir(join(epath, extdir, directory)) with open(join(epath, extdir, member), 'wb') as fd: fd.write(zipf.read(member)) except Exception, e: # Catch any error, e.g. non-writable directory, etc. Logger.error("Failed installing extension " + \ "'%s' %s." % (extname, e)) return finally:
def reactor_wake(twisted_loop_next): Logger.trace("Support: twisted wakeup call to schedule task") q.append(twisted_loop_next)
def _mainloop(self): EventLoop.idle() while True: event = self._win.poll() if event is False: break if event is None: continue action, args = event[0], event[1:] if action == 'quit': if self.dispatch('on_request_close'): continue EventLoop.quit = True self.close() break elif action in ('fingermotion', 'fingerdown', 'fingerup'): # for finger, pass the raw event to SDL motion event provider # XXX this is problematic. On OSX, it generates touches with 0, # 0 coordinates, at the same times as mouse. But it works. # We have a conflict of using either the mouse or the finger. # Right now, we have no mechanism that we could use to know # which is the preferred one for the application. if platform == "ios": SDL2MotionEventProvider.q.appendleft(event) pass elif action == 'mousemotion': x, y = args x, y = self._fix_mouse_pos(x, y) self._mouse_x = x self._mouse_y = y # don't dispatch motion if no button are pressed if len(self._mouse_buttons_down) == 0: continue self._mouse_meta = self.modifiers self.dispatch('on_mouse_move', x, y, self.modifiers) elif action in ('mousebuttondown', 'mousebuttonup'): x, y, button = args x, y = self._fix_mouse_pos(x, y) btn = 'left' if button == 3: btn = 'right' elif button == 2: btn = 'middle' eventname = 'on_mouse_down' self._mouse_buttons_down.add(button) if action == 'mousebuttonup': eventname = 'on_mouse_up' self._mouse_buttons_down.remove(button) self._mouse_x = x self._mouse_y = y self.dispatch(eventname, x, y, btn, self.modifiers) elif action.startswith('mousewheel'): self._update_modifiers() x, y, button = args btn = 'scrolldown' if action.endswith('up'): btn = 'scrollup' elif action.endswith('right'): btn = 'scrollright' elif action.endswith('left'): btn = 'scrollleft' self._mouse_meta = self.modifiers self._mouse_btn = btn #times = x if y == 0 else y #times = min(abs(times), 100) #for k in range(times): self._mouse_down = True self.dispatch('on_mouse_down', self._mouse_x, self._mouse_y, btn, self.modifiers) self._mouse_down = False self.dispatch('on_mouse_up', self._mouse_x, self._mouse_y, btn, self.modifiers) elif action == 'dropfile': dropfile = args self.dispatch('on_dropfile', dropfile[0]) # video resize elif action == 'windowresized': self._size = self._win.window_size # don't use trigger here, we want to delay the resize event cb = self._do_resize Clock.unschedule(cb) Clock.schedule_once(cb, .1) elif action == 'windowresized': self.canvas.ask_update() elif action == 'windowrestored': self.canvas.ask_update() elif action == 'windowexposed': self.canvas.ask_update() elif action == 'windowminimized': if Config.getboolean('kivy', 'pause_on_minimize'): self.do_pause() elif action == 'joyaxismotion': stickid, axisid, value = args self.dispatch('on_joy_axis', stickid, axisid, value) elif action == 'joyhatmotion': stickid, hatid, value = args self.dispatch('on_joy_hat', stickid, hatid, value) elif action == 'joyballmotion': stickid, ballid, xrel, yrel = args self.dispatch('on_joy_ball', stickid, ballid, xrel, yrel) elif action == 'joybuttondown': stickid, buttonid = args self.dispatch('on_joy_button_down', stickid, buttonid) elif action == 'joybuttonup': stickid, buttonid = args self.dispatch('on_joy_button_up', stickid, buttonid) elif action in ('keydown', 'keyup'): mod, key, scancode, kstr = args key_swap = { SDLK_LEFT: 276, SDLK_RIGHT: 275, SDLK_UP: 273, SDLK_DOWN: 274, SDLK_HOME: 278, SDLK_END: 279, SDLK_PAGEDOWN: 281, SDLK_PAGEUP: 280, SDLK_SHIFTR: 303, SDLK_SHIFTL: 304, SDLK_SUPER: 309, SDLK_LCTRL: 305, SDLK_RCTRL: 306, SDLK_LALT: 308, SDLK_RALT: 307, SDLK_CAPS: 301, SDLK_INSERT: 277, SDLK_F1: 282, SDLK_F2: 283, SDLK_F3: 284, SDLK_F4: 285, SDLK_F5: 286, SDLK_F6: 287, SDLK_F7: 288, SDLK_F8: 289, SDLK_F9: 290, SDLK_F10: 291, SDLK_F11: 292, SDLK_F12: 293, SDLK_F13: 294, SDLK_F14: 295, SDLK_F15: 296, SDLK_KEYPADNUM: 300, SDLK_KP_DEVIDE: 267, SDLK_KP_MULTIPLY: 268, SDLK_KP_MINUS: 269, SDLK_KP_PLUS: 270, SDLK_KP_ENTER: 271, SDLK_KP_DOT: 266, SDLK_KP_0: 256, SDLK_KP_1: 257, SDLK_KP_2: 258, SDLK_KP_3: 259, SDLK_KP_4: 260, SDLK_KP_5: 261, SDLK_KP_6: 262, SDLK_KP_7: 263, SDLK_KP_8: 264, SDLK_KP_9: 265} if platform == 'ios': # XXX ios keyboard suck, when backspace is hit, the delete # keycode is sent. fix it. key_swap[127] = 8 # back try: key = key_swap[key] except KeyError: pass if action == 'keydown': self._update_modifiers(mod, key) else: self._update_modifiers(mod) # ignore the key, it # has been released # if mod in self._meta_keys: if (key not in self._modifiers and key not in self.command_keys.keys()): try: kstr = unichr(key) except ValueError: pass #if 'shift' in self._modifiers and key\ # not in self.command_keys.keys(): # return if action == 'keyup': self.dispatch('on_key_up', key, scancode) continue # don't dispatch more key if down event is accepted if self.dispatch('on_key_down', key, scancode, kstr, self.modifiers): continue self.dispatch('on_keyboard', key, scancode, kstr, self.modifiers) elif action == 'textinput': text = args[0] self.dispatch('on_textinput', text) # XXX on IOS, keydown/up don't send unicode anymore. # With latest sdl, the text is sent over textinput # Right now, redo keydown/up, but we need to seperate both call # too. (and adapt on_key_* API.) #self.dispatch() #self.dispatch('on_key_down', key, None, args[0], # self.modifiers) #self.dispatch('on_keyboard', None, None, args[0], # self.modifiers) #self.dispatch('on_key_up', key, None, args[0], # self.modifiers) # unhandled event ! else: Logger.trace('WindowSDL: Unhandled event %s' % str(event))
def reactor_work(*args): '''Process the twisted reactor task queue ''' Logger.trace("Support: processing twisted task queue") while len(q): q.popleft()()
def reactor_wake(twisted_loop_next): '''Wakeup the twisted reactor to start processing the task queue ''' Logger.trace("Support: twisted wakeup call to schedule task") q.append(twisted_loop_next)
def unzip_extensions(): """Unzips Kivy extensions. Internal usage only; Don't use it yourself unless you know what you're doing and really want to trigger installation of new extensions. For your file to be recognized as an extension, it has to fulfil a few requirements: * We require that the file has the ``*.kex`` extension to make the distinction between a Kivy extension and an ordinary zip file clear. * We require that the ``*.kex`` extension files be put into any of the directories listed in EXTENSION_PATHS which is normally ~/.kivy/extensions and extensions/ inside kivy's base dirextory. We do not look for extensions on sys.path or elsewhere in the system. * We require that the Kivy extension is zipped in a way so that Python's zipfile module can extract it properly. * We require that the extension internally obeys the common Kivy extension format, which looks like this:: |-- myextension/ |-- __init__.py |-- data/ The ``__init__.py`` file is the main entrypoint to the extension. All names that should be usable when the extension is loaded need to be exported (i.e. made available) in the namespace of that file. How the extension accesses the code of the library that it wraps (be it pure Python or binary code) is up to the extension. For example there could be another Python module adjacent to the ``__init__.py`` file from which the ``__init__.py`` file imports the usable names that it wants to expose. * We require that the version of the extension be specified in the ``setup.py`` file that is created by the Kivy extension wizard and that the version specification format as explained in :func:`~kivy.ext.load` be used. """ Logger.debug("Searching for new extension in %s" % EXTENSION_PATHS) for epath in EXTENSION_PATHS: if not isdir(epath): mkdir(epath) files = [] else: files = listdir(epath) for zipfn in glob(join(epath, "*.kex")): # ZipFile only became a context manager in python 2.7... # with ZipFile(zipfn, 'r') as zipf: fail = is_invalid = False try: zipf = ZipFile(zipfn) # /path/to/MyExt-1.0.linux-x86_64.zip extname = zipfn.rsplit(sep)[-1][:-4] # MyExt-1.0.linux-x86_64 extname = ".".join(extname.split(".")[:-1]) # MyExt-1.0 extname, version = extname.split("-") extdir = extname + "_" + version is_invalid = not _is_valid_ext_name(extdir) except IOError: Logger.warn("Malformed zipfile '%s'! Skipping it." % zipfn) continue except Exception, e: Logger.warn("Malformed extension '%s'! Skipping it." % zipfn) zipf.close() continue already_unzipped = False if extdir in files: Logger.trace( ("Extension '%s' has already been " % extname) + "extracted manually, just moving the zip." ) already_unzipped = True members = zipf.namelist() def get_root_member(zipf): root = None multiple = False for m1 in members: for m2 in members: if not m2.startswith(m1): break else: if root != None: multiple = True root = m1 if not root or multiple: # There either is no root or there is more than one root. # We require only one root, so the extension is malformed. Logger.warn("Malformed extension '%s'! Skipping it." % extname) return # return root name without the trailing slash return root[:-1] root = get_root_member(zipf) if not root: # Skip this extension as we told the user continue if not already_unzipped: # Unzip the extension try: mkdir(join(epath, extdir)) # I know that there is zipf.extract() and zipf.extractall(), but on # OSX, Python 2.6 is the default and in that version, both methods # have a bug. Fixed in 2.7 only. So use this workaround until apple # upgrades its python. See http://bugs.python.org/issue4710 for member in members: # In zipfiles, folders always end with '/' regardless of the OS mempath = join(epath, extdir, member) if member.endswith("/") and not exists(mempath): mkdir(join(epath, extdir, member[:-1])) else: with open(join(epath, extdir, member), "wb") as memberfd: memberfd.write(zipf.read(member)) except Exception, e: # Catch any error, e.g. non-writable directory, etc. Logger.error("Failed installing extension " + "'%s' %s." % (extname, e)) return finally:
def inputhook_myrmidon_kivy(): """The kivy eventloop hook.""" from kivy.base import EventLoop from kivy.utils import platform engine_window = Game.engine['window'] if not engine_window or not engine_window.kivy_app: return 0 kivy_app = engine_window.kivy_app if not kivy_app.built: from kivy.uix.widget import Widget from kivy.core.window import Window from kivy.base import runTouchApp for x in Game._module_list: x._module_setup(cls) kivy_app.load_config() kivy_app.load_kv(filename=kivy_app.kv_file) kivy_app.root = kivy_app.build() if not isinstance(kivy_app.root, Widget): raise Exception('Invalid instance in App.root') Window.add_widget(kivy_app.root) # Check if the window is already created window = EventLoop.window if window: kivy_app._app_window = window window.set_title(kivy_app.get_application_name()) icon = kivy_app.get_application_icon() if icon: window.set_icon(icon) kivy_app._install_settings_keys(window) else: raise Exception("Application: No window is created." " Terminating application run.") kivy_app.dispatch('on_start') runTouchApp(kivy_app.root, slave=True) # Tick forward the Myrmidon event loop one frame Game.app_loop_callback(0) # Tick forward kivy to reflect events and changes from Myrmidon. # This has been directly lifted from `kivy.core.window.window_sdl2`. EventLoop.idle() window = EventLoop.window event = window._win.poll() if event is False or event is None: return 0 action, args = event[0], event[1:] if action == 'quit': EventLoop.quit = True window.close() return 0 elif action in ('fingermotion', 'fingerdown', 'fingerup'): # for finger, pass the raw event to SDL motion event provider # XXX this is problematic. On OSX, it generates touches with 0, # 0 coordinates, at the same times as mouse. But it works. # We have a conflict of using either the mouse or the finger. # Right now, we have no mechanism that we could use to know # which is the preferred one for the application. if platform == "ios": SDL2MotionEventProvider.q.appendleft(event) pass elif action == 'mousemotion': x, y = args x, y = window._fix_mouse_pos(x, y) window._mouse_x = x window._mouse_y = y # don't dispatch motion if no button are pressed if len(window._mouse_buttons_down) == 0: return 0 window._mouse_meta = window.modifiers window.dispatch('on_mouse_move', x, y, window.modifiers) elif action in ('mousebuttondown', 'mousebuttonup'): x, y, button = args x, y = window._fix_mouse_pos(x, y) btn = 'left' if button == 3: btn = 'right' elif button == 2: btn = 'middle' eventname = 'on_mouse_down' window._mouse_buttons_down.add(button) if action == 'mousebuttonup': eventname = 'on_mouse_up' window._mouse_buttons_down.remove(button) window._mouse_x = x window._mouse_y = y window.dispatch(eventname, x, y, btn, window.modifiers) elif action.startswith('mousewheel'): window._update_modifiers() x, y, button = args btn = 'scrolldown' if action.endswith('up'): btn = 'scrollup' elif action.endswith('right'): btn = 'scrollright' elif action.endswith('left'): btn = 'scrollleft' window._mouse_meta = window.modifiers window._mouse_btn = btn #times = x if y == 0 else y #times = min(abs(times), 100) #for k in range(times): window._mouse_down = True window.dispatch('on_mouse_down', window._mouse_x, window._mouse_y, btn, window.modifiers) window._mouse_down = False window.dispatch('on_mouse_up', window._mouse_x, window._mouse_y, btn, window.modifiers) elif action == 'dropfile': dropfile = args window.dispatch('on_dropfile', dropfile[0]) # video resize elif action == 'windowresized': window._size = window._win.window_size # don't use trigger here, we want to delay the resize event cb = window._do_resize from kivy.clock import Clock Clock.unschedule(cb) Clock.schedule_once(cb, .1) elif action == 'windowresized': window.canvas.ask_update() elif action == 'windowrestored': window.canvas.ask_update() elif action == 'windowexposed': window.canvas.ask_update() elif action == 'windowminimized': if Config.getboolean('kivy', 'pause_on_minimize'): window.do_pause() elif action == 'joyaxismotion': stickid, axisid, value = args window.dispatch('on_joy_axis', stickid, axisid, value) elif action == 'joyhatmotion': stickid, hatid, value = args window.dispatch('on_joy_hat', stickid, hatid, value) elif action == 'joyballmotion': stickid, ballid, xrel, yrel = args window.dispatch('on_joy_ball', stickid, ballid, xrel, yrel) elif action == 'joybuttondown': stickid, buttonid = args window.dispatch('on_joy_button_down', stickid, buttonid) elif action == 'joybuttonup': stickid, buttonid = args window.dispatch('on_joy_button_up', stickid, buttonid) elif action in ('keydown', 'keyup'): mod, key, scancode, kstr = args from kivy.core.window import window_sdl2 key_swap = { window_sdl2.SDLK_LEFT: 276, window_sdl2.SDLK_RIGHT: 275, window_sdl2.SDLK_UP: 273, window_sdl2.SDLK_DOWN: 274, window_sdl2.SDLK_HOME: 278, window_sdl2.SDLK_END: 279, window_sdl2.SDLK_PAGEDOWN: 281, window_sdl2.SDLK_PAGEUP: 280, window_sdl2.SDLK_SHIFTR: 303, window_sdl2.SDLK_SHIFTL: 304, window_sdl2.SDLK_SUPER: 309, window_sdl2.SDLK_LCTRL: 305, window_sdl2.SDLK_RCTRL: 306, window_sdl2.SDLK_LALT: 308, window_sdl2.SDLK_RALT: 307, window_sdl2.SDLK_CAPS: 301, window_sdl2.SDLK_INSERT: 277, window_sdl2.SDLK_F1: 282, window_sdl2.SDLK_F2: 283, window_sdl2.SDLK_F3: 284, window_sdl2.SDLK_F4: 285, window_sdl2.SDLK_F5: 286, window_sdl2.SDLK_F6: 287, window_sdl2.SDLK_F7: 288, window_sdl2.SDLK_F8: 289, window_sdl2.SDLK_F9: 290, window_sdl2.SDLK_F10: 291, window_sdl2.SDLK_F11: 292, window_sdl2.SDLK_F12: 293, window_sdl2.SDLK_F13: 294, window_sdl2.SDLK_F14: 295, window_sdl2.SDLK_F15: 296, window_sdl2.SDLK_KEYPADNUM: 300} if platform == 'ios': # XXX ios keyboard suck, when backspace is hit, the delete # keycode is sent. fix it. key_swap[127] = 8 # back try: key = key_swap[key] except KeyError: pass if action == 'keydown': window._update_modifiers(mod, key) else: window._update_modifiers(mod) # ignore the key, it # has been released # if mod in window._meta_keys: if (key not in window._modifiers and key not in window.command_keys.keys()): try: kstr = chr(key) except ValueError: pass #if 'shift' in window._modifiers and key\ # not in window.command_keys.keys(): # return if action == 'keyup': window.dispatch('on_key_up', key, scancode) return 0 # don't dispatch more key if down event is accepted if window.dispatch('on_key_down', key, scancode, kstr, window.modifiers): return 0 window.dispatch('on_keyboard', key, scancode, kstr, window.modifiers) elif action == 'textinput': text = args[0] window.dispatch('on_textinput', text) # XXX on IOS, keydown/up don't send unicode anymore. # With latest sdl, the text is sent over textinput # Right now, redo keydown/up, but we need to seperate both call # too. (and adapt on_key_* API.) #window.dispatch() #window.dispatch('on_key_down', key, None, args[0], # window.modifiers) #window.dispatch('on_keyboard', None, None, args[0], # window.modifiers) #window.dispatch('on_key_up', key, None, args[0], # window.modifiers) # unhandled event ! else: from kivy.logger import Logger Logger.trace('WindowSDL: Unhandled event %s' % str(event)) return 0
def _mainloop(self): EventLoop.idle() # for android/iOS, we don't want to have any event nor executing our # main loop while the pause is going on. This loop wait any event (not # handled by the event filter), and remove them from the queue. # Nothing happen during the pause on iOS, except gyroscope value sent # over joystick. So it's safe. while self._pause_loop: self._win.wait_event() if not self._pause_loop: break self._win.poll() while True: event = self._win.poll() if event is False: break if event is None: continue action, args = event[0], event[1:] if action == 'quit': if self.dispatch('on_request_close'): continue EventLoop.quit = True self.close() break elif action in ('fingermotion', 'fingerdown', 'fingerup'): # for finger, pass the raw event to SDL motion event provider # XXX this is problematic. On OSX, it generates touches with 0, # 0 coordinates, at the same times as mouse. But it works. # We have a conflict of using either the mouse or the finger. # Right now, we have no mechanism that we could use to know # which is the preferred one for the application. if platform in ('ios', 'android'): SDL2MotionEventProvider.q.appendleft(event) pass elif action == 'mousemotion': x, y = args x, y = self._fix_mouse_pos(x, y) self._mouse_x = x self._mouse_y = y # don't dispatch motion if no button are pressed if len(self._mouse_buttons_down) == 0: continue self._mouse_meta = self.modifiers self.dispatch('on_mouse_move', x, y, self.modifiers) elif action in ('mousebuttondown', 'mousebuttonup'): x, y, button = args x, y = self._fix_mouse_pos(x, y) btn = 'left' if button == 3: btn = 'right' elif button == 2: btn = 'middle' eventname = 'on_mouse_down' self._mouse_buttons_down.add(button) if action == 'mousebuttonup': eventname = 'on_mouse_up' self._mouse_buttons_down.remove(button) self._mouse_x = x self._mouse_y = y self.dispatch(eventname, x, y, btn, self.modifiers) elif action.startswith('mousewheel'): self._update_modifiers() x, y, button = args btn = 'scrolldown' if action.endswith('up'): btn = 'scrollup' elif action.endswith('right'): btn = 'scrollright' elif action.endswith('left'): btn = 'scrollleft' self._mouse_meta = self.modifiers self._mouse_btn = btn #times = x if y == 0 else y #times = min(abs(times), 100) #for k in range(times): self._mouse_down = True self.dispatch('on_mouse_down', self._mouse_x, self._mouse_y, btn, self.modifiers) self._mouse_down = False self.dispatch('on_mouse_up', self._mouse_x, self._mouse_y, btn, self.modifiers) elif action == 'dropfile': dropfile = args self.dispatch('on_dropfile', dropfile[0]) # video resize elif action == 'windowresized': self._size = self._win.window_size # don't use trigger here, we want to delay the resize event ev = self._do_resize_ev if ev is None: ev = self._do_resize_ev = Clock.schedule_once(self._do_resize, .1) else: ev() elif action == 'windowresized': self.canvas.ask_update() elif action == 'windowrestored': self.dispatch('on_restore') self.canvas.ask_update() elif action == 'windowexposed': self.canvas.ask_update() elif action == 'windowminimized': self.dispatch('on_minimize') if Config.getboolean('kivy', 'pause_on_minimize'): self.do_pause() elif action == 'windowmaximized': self.dispatch('on_maximize') elif action == 'windowhidden': self.dispatch('on_hide') elif action == 'windowshown': self.dispatch('on_show') elif action == 'windowfocusgained': self._focus = True elif action == 'windowfocuslost': self._focus = False elif action == 'windowenter': self.dispatch('on_cursor_enter') elif action == 'windowleave': self.dispatch('on_cursor_leave') elif action == 'joyaxismotion': stickid, axisid, value = args self.dispatch('on_joy_axis', stickid, axisid, value) elif action == 'joyhatmotion': stickid, hatid, value = args self.dispatch('on_joy_hat', stickid, hatid, value) elif action == 'joyballmotion': stickid, ballid, xrel, yrel = args self.dispatch('on_joy_ball', stickid, ballid, xrel, yrel) elif action == 'joybuttondown': stickid, buttonid = args self.dispatch('on_joy_button_down', stickid, buttonid) elif action == 'joybuttonup': stickid, buttonid = args self.dispatch('on_joy_button_up', stickid, buttonid) elif action in ('keydown', 'keyup'): mod, key, scancode, kstr = args try: key = self.key_map[key] except KeyError: pass if action == 'keydown': self._update_modifiers(mod, key) else: self._update_modifiers(mod) # ignore the key, it # has been released # if mod in self._meta_keys: if (key not in self._modifiers and key not in self.command_keys.keys()): try: kstr = unichr(key) except ValueError: pass #if 'shift' in self._modifiers and key\ # not in self.command_keys.keys(): # return if action == 'keyup': self.dispatch('on_key_up', key, scancode) continue # don't dispatch more key if down event is accepted if self.dispatch('on_key_down', key, scancode, kstr, self.modifiers): continue self.dispatch('on_keyboard', key, scancode, kstr, self.modifiers) elif action == 'textinput': text = args[0] self.dispatch('on_textinput', text) # unhandled event ! else: Logger.trace('WindowSDL: Unhandled event %s' % str(event))