def main(): c1 = kaa.candy.Container() r1 = kaa.candy.Rectangle((0,0), (None, '50%'), '0x444444') r2 = kaa.candy.Rectangle((0,0), (None, '50%'), '0x888888') r3 = kaa.candy.Rectangle((0,0), (100,100), '0xffffff') r4 = kaa.candy.Rectangle((200,200), (100,100), '0xffffff') c1.passive = True stage.add(c1) c1.add(r1) c1.add(r2) r2.passive = True stage.add(r3) stage.add(r4) yield kaa.delay(0.3) r5 = kaa.candy.Rectangle((300,300), (100,100), '0xffffff') stage.add(r5) yield kaa.delay(0.3) c1.width = 300 yield kaa.delay(0.3) print r1.height = '30%' print 'done' yield kaa.delay(0.3) stage.sync()
def resync(self, force, series_only=False): """ The database has changed, check against beacon """ log.info('check web metadata changes') if force: self.todo = [] self.failed = [] for item in (yield self.beacondb.query(type='video')): if not item.filename: continue if item.filename and \ (not series_only or \ (item.get('series') and item.get('season') and item.get('episode'))): self.todo.append(item._beacon_id[1]) kaa.webmetadata.set_metadata('beacon_todo', self.todo) kaa.webmetadata.set_metadata('beacon_failed', []) else: self.todo = kaa.webmetadata.get_metadata('beacon_todo') self.failed = kaa.webmetadata.get_metadata('beacon_failed') kaa.webmetadata.set_metadata('beacon_init', PLUGIN_VERSION) kaa.webmetadata.set_metadata('beacon_version', kaa.webmetadata.db_version()) yield kaa.delay(2) while self.todo: items = yield self.beacondb.query(type='video', id=self.todo.pop(0)) if items: self.parser(items[0], None, 'video') kaa.webmetadata.set_metadata('beacon_todo', self.todo)
def image_osd(widget, event): if event != 'TOGGLE_OSD': yield None visible = getattr(widget, 'image_osd_status', False) if not visible: widget.get_widget('player').animate('EASE_IN_QUAD', 0.2, scale_x=0.7, scale_y=0.7, x=30 * widget.osd.scale_x, y=120 * widget.osd.scale_y) yield kaa.delay(0.2) idlebar = widget.stage.get_widget('idlebar') if idlebar: idlebar.show() widget.osd.show('listing') widget.osd.show('info') else: idlebar = widget.stage.get_widget('idlebar') if idlebar: idlebar.hide() widget.osd.hide('listing') yield widget.osd.hide('info') widget.get_widget('player').animate('EASE_IN_QUAD', 0.2, scale_x=1.0, scale_y=1.0, x=0, y=0) widget.image_osd_status = not visible
def _monitor(self, address, buffer_size, retry): while True: try: self.status = CONNECTING yield kaa.inprogress(self) # Python 2.4 code # TODO: remove all python 2.4 supporting code self._connect_inprogress.result self.status = CONNECTED # wait until the socket is closed yield self.signals.subset('closed').any() except Exception, e: # connection failed pass self._connect_inprogress = kaa.InProgress() self.status = DISCONNECTED # wait some time until we retry yield kaa.delay(retry) # reset variables self._authenticated = False self._pending_challenge = None self._read_buffer = [] self.status = CONNECTING self._socket = kaa.Socket(buffer_size) self._socket.chunk_size = 1024 self._socket.signals['read'].connect(self._handle_read) self._socket.signals['closed'].connect(self._handle_close) self._socket.connect(address).exception.connect( self._handle_refused)
def add_movie_by_id(self, filename, metadata, id): """ Match movie id to the given filename for future lookups """ if not metadata.get('hash') or not metadata.get('filesize'): yield False # check if we already have that movie in the db data = self._db.query(type='movie', moviedb=id) if not data: # We are limited to 30 requests per 10 seconds. Wait one # second before doing the searches. yield kaa.delay(1) result = yield self._server_call('movie/%s' % id) if result: result['/images'] = yield self._server_call('movie/%s/images' % id) result['/casts'] = yield self._server_call('movie/%s/casts' % id) result['/keywords'] = yield self._server_call('movie/%s/keywords' % id) movie = Movie(result, self) if movie.poster and not os.path.isfile(movie.poster): data = yield (yield movie.get_all_posters())[0].fetch() open(movie.poster, 'w').write(data) if movie.image and not os.path.isfile(movie.image): data = yield (yield movie.get_all_images())[0].fetch() open(movie.image, 'w').write(data) self._db.add('movie', moviedb=int(id), name=movie.name, imdb=movie.imdb, data=movie._data) self._db.commit() data = self._db.query(type='movie', moviedb=id) if data: self._db.add('hash', moviedb=id, value=u'%s|%s' % (metadata.get('hash'), metadata.filesize)) self._db.commit() yield True
def _monitor(self, address, buffer_size, retry): while True: try: self.status = CONNECTING yield kaa.inprogress(self) # Python 2.4 code # TODO: remove all python 2.4 supporting code self._connect_inprogress.result self.status = CONNECTED # wait until the socket is closed yield self.signals.subset('closed').any() except Exception, e: # connection failed pass self._connect_inprogress = kaa.InProgress() self.status = DISCONNECTED # wait some time until we retry yield kaa.delay(retry) # reset variables self._authenticated = False self._pending_challenge = None self._read_buffer = [] self.status = CONNECTING self._socket = kaa.Socket(buffer_size) self._socket.chunk_size = 1024 self._socket.signals['read'].connect(self._handle_read) self._socket.signals['closed'].connect(self._handle_close) self._socket.connect(address).exception.connect(self._handle_refused)
def main(): device = (yield tvserver.devices.get())[0] print device.multiplexes id = device.schedule('ZDF', int(time.time()) + 5, int(time.time()) + 20, 'file:///tmp/foo') device.schedule('3sat', int(time.time()) + 10, int(time.time()) + 30, 'file:///tmp/foo2') yield kaa.delay(6)
def search(self, filename, metadata): """ Search for possible movie information for the given filename """ if not os.path.exists(filename): yield [] # We are limited to 30 requests per 10 seconds. Wait one # second before doing some searches. yield kaa.delay(1) result = [] nfo = os.path.splitext(filename)[0] + '.nfo' if os.path.exists(nfo) and not result: match = IMDB_REGEXP.search(open(nfo).read()) if match: result = yield self._server_call('movie/tt%s' % match.groups()[0]) if result: movie = Movie(result, self) movie.likely = True result = [ movie ] if not result: # try guessing title and year m = TITLE_REGEXP.match(os.path.basename(filename)) data = None if m: name, year = m.groups() if int(year) > 1900 and int(year) <= time.localtime().tm_year: # valid year name = name.lower().replace('.', ' ').replace('-', ' ').replace('_', ' ') data = yield self._server_call('search/movie', query=name, year=year) if not data or not data.get('results', None) and name.find('3d') > 0: name = name[:name.find('3d')] data = yield self._server_call('search/movie', query=name, year=year) # guess by kaa.metadata title if not data or not data.get('results', None): metadata = kaa.metadata.parse(filename) if metadata and metadata.title: name = metadata.title else: name = os.path.basename(filename) name = name.lower().replace('.', ' ').replace('-', ' ').replace('_', ' ') data = yield self._server_call('search/movie', query=name) if not data or not data.get('results', None) and name.find('3d') > 0: name = name[:name.find('3d')] data = yield self._server_call('search/movie', query=name) if data and data.get('results', None): result = [] for r in data.get('results'): movie = Movie(r, self) # mark the best matches if movie.name.lower().replace('.', ' ').replace('-', ' ').replace('_', ' ') == name: movie.likely = True else: movie.likely = False result.append(movie) yield result
def animate(self, ease, secs, unparent=False, **kwargs): args = [item for sublist in kwargs.items() for item in sublist] if secs: self.backend.animate(ease, secs, *args) yield kaa.delay(secs) for key, value in kwargs.items(): self.__sync_cache[key] = value for key, value in kwargs.items(): setattr(self, key, value) if unparent: self.parent = None
def suspend(self): """ Release the audio resource that others can use it. """ if not self.player: yield False if self.player.state == kaa.candy.STATE_PLAYING: self.player.pause() # there is no feedback from kaa.candy if that worked. Just # wait half a second yield kaa.delay(0.5) self.free_resources() yield True
def auto_sync(self): """ Check if the database requires a sync """ if float(self.db.get_metadata('webmetadata::version', 0)) != PLUGIN_VERSION: log.info('force webmetadata resync') # force a complete resync here for item in (yield kaa.beacon.query(type='video')): item['webmetadata'] = '' self.db.set_metadata('webmetadata::lastsync', 0) self.db.set_metadata('webmetadata::version', PLUGIN_VERSION) while True: last = int(self.db.get_metadata('webmetadata::lastsync', 0)) if time.time() + 10 < last + SYNC_INTERVAL: # wait until 24 hours are over yield kaa.delay(last + SYNC_INTERVAL - time.time()) try: yield self.sync() self.db.set_metadata('webmetadata::lastsync', int(time.time())) except Exception: log.exception('sync error') # something went wrong, maybe network down or # something else. Try again in 600 seconds yield kaa.delay(600)
def guess_metadata(self, filename, timestamp): """ Guess metadata based on filename and attributes """ if not filename in self.guessing: # already done yield None self.guessing.remove(filename) # Slow down guessing and make sure the file is in sync in the database if timestamp + 1 > time.time(): log.info('wait for database sync') yield kaa.delay(1) try: attributes = (yield kaa.beacon.get(filename)) except Exception, e: # something is wrong here, maybe the item does not exist # anymore. yield None
def connect(self): start = time.time() while True: try: channel = kaa.rpc.connect('thumb/socket') channel.register(self) self.rpc = channel.rpc yield kaa.inprogress(channel) yield None except Exception, e: # FIXME: rather than this kludge, catch only the exceptions likely to happen # if connection to thumbnail server fails. if isinstance(e, GeneratorExit): raise if start + 3 < time.time(): # start time is up, something is wrong here raise RuntimeError('unable to connect to thumbnail server') yield kaa.delay(0.01)
def menu(prev, next): logo = next.stage.get_widget('idlebar').get_widget('logo') next.opacity = 0 if prev.type == 'main': prev.animate('EASE_IN_QUAD', 0.4, scale_x=10, scale_y=10, opacity=0) yield kaa.delay(0.2) next.animate('EASE_OUT_CUBIC', 0.2, opacity=255) yield logo.animate('EASE_OUT_CUBIC', 0.2, opacity=255) yield None if next.type == 'main': next.scale_x = 10 next.scale_y = 10 logo.animate('EASE_IN_CUBIC', 0.2, opacity=0) prev.animate('EASE_IN_CUBIC', 0.2, opacity=0) yield next.animate('EASE_OUT_QUAD', 0.4, scale_x=1, scale_y=1, opacity=255) yield None # default fade next.animate('EASE_OUT_CUBIC', 0.3, opacity=255) yield prev.animate('EASE_IN_CUBIC', 0.3, opacity=0)
def _thumbnailer(self): while self.jobs and not kaa.main.is_stopped(): job = self.jobs.pop(0) log.info('Now processing video thumbnail job: file=%s, qlen=%d', job.filename, len(self.jobs)) for size in ('large', 'normal'): imagefile = job.imagefile % size if not os.path.isfile(imagefile): # One (or both) of the large and normal thumbnails don't exist, so # we must generate. break metadata = kaa.metadata.parse(imagefile) mtime = metadata.get('Thumb::MTime') if mtime != str(os.stat(job.filename)[stat.ST_MTIME]): # File mtime doesn't match the stored mtime in the thumbnail metadata, # so must regenerate. break else: # No thumb generation needed. continue # XXX: this isn't very effective because we can't throttle mplayer # once it's running. We run mplayer at the lowest possible priority # (if schedtool is available), so that'll have to suffice. # IDEA: actually we can throttle mplayer, if we remove -benchmark and pass -fps. delay = scheduler.next(self.config.scheduler.policy) * self.config.scheduler.multiplier if delay: # too much CPU load, slow down yield kaa.delay(delay) try: success = yield self._generate(job) except Exception: success = False if not success: # Something went awry, generate a failed thumbnail file. self.create_failed(job) # Notify client via rpc that this thumbnail job is done. self.notify_client(job)
def add_movie_by_id(self, filename, metadata, id): """ Match movie id to the given filename for future lookups """ if not metadata.get('hash') or not metadata.get('filesize'): yield False # check if we already have that movie in the db data = self._db.query(type='movie', moviedb=id) if not data: # We are limited to 30 requests per 10 seconds. Wait one # second before doing the searches. yield kaa.delay(1) result = yield self._server_call('movie/%s' % id) if result: result['/images'] = yield self._server_call('movie/%s/images' % id) result['/casts'] = yield self._server_call('movie/%s/casts' % id) result['/keywords'] = yield self._server_call( 'movie/%s/keywords' % id) movie = Movie(result, self) if movie.poster and not os.path.isfile(movie.poster): data = yield (yield movie.get_all_posters())[0].fetch() open(movie.poster, 'w').write(data) if movie.image and not os.path.isfile(movie.image): data = yield (yield movie.get_all_images())[0].fetch() open(movie.image, 'w').write(data) self._db.add('movie', moviedb=int(id), name=movie.name, imdb=movie.imdb, data=movie._data) self._db.commit() data = self._db.query(type='movie', moviedb=id) if data: self._db.add('hash', moviedb=id, value=u'%s|%s' % (metadata.get('hash'), metadata.filesize)) self._db.commit() yield True
def connect(self): """ Connect to the thumbnail server """ start = time.time() while True: try: channel = kaa.rpc.connect('thumb/socket') channel.register(self) self.rpc = channel.rpc yield kaa.inprogress(channel) yield None except Exception, e: # FIXME: rather than this kludge, catch only the exceptions likely to happen # if connection to thumbnail server fails. if isinstance(e, GeneratorExit): raise if start + 3 < time.time(): # start time is up, something is wrong here raise RuntimeError('unable to connect to thumbnail server') yield kaa.delay(0.01)
def select(self, path, **attributes): if self.application and self.application.name == 'menu': menu = self.application.current if path.lower() == 'back': self.application.back_one_menu() elif path.lower() == 'home': self.application.back_to_menu(self.application[0]) elif path.lower() == 'submenu': pass else: menu.select(menu.choices[int(path)]) self.application.refresh() yield kaa.delay(0.2) if menu.selected.type == 'video': items = menu.selected.subitems self.application.pushmenu(freevo.Menu(menu.selected.name, items, type='submenu')) else: actions = menu.selected._get_actions() if actions: actions[0]() yield {}
def select(self, path, **attributes): if self.application and self.application.name == 'menu': menu = self.application.current if path.lower() == 'back': self.application.back_one_menu() elif path.lower() == 'home': self.application.back_to_menu(self.application[0]) elif path.lower() == 'submenu': pass else: menu.select(menu.choices[int(path)]) self.application.refresh() yield kaa.delay(0.2) if menu.selected.type == 'video': items = menu.selected.subitems self.application.pushmenu( freevo.Menu(menu.selected.name, items, type='submenu')) else: actions = menu.selected._get_actions() if actions: actions[0]() yield {}
def main(): feed, items = yield load_feed('beach') # this is the context for the flickr widget context = dict(title=feed.feed.title, items=items) # remove the wait label (it is safe to remove something from the stage in the # mainloop) and add the flickr container based on the context. stage.remove(label) container = candy.container.flickr(context=context) stage.add(container) print 'take a look' yield kaa.delay(1) print 'scroll down' grid = container.get_widget('items') grid.scroll_by((0, 2), 1) yield kaa.delay(2) print 'scroll right' grid.scroll_by((2, 0), 4) yield kaa.delay(2) print 'scroll up very fast, more than possible' grid.scroll_by((0,-15), 0.5) yield kaa.delay(2) print 'and down again' grid.scroll_by((1,1), 0.8) yield kaa.delay(0.7) print 'and left again while the animation is still running' grid.scroll_by((-1, 0), 0.8) yield kaa.delay(2) print 'go home (0,0)' grid.scroll_to((0, 0), 0.8) yield kaa.delay(2) print 'load more' # create new context and replace it feed, items = yield load_feed('sunset') context = dict(title=feed.feed.title, items=items) # set context container.context = context
def _wait_for_idle(self, timeout=120): """ Waits until XBMC is idle (i.e. not scanning library). :returns: True if XBMC is idle, False if it isn't (due to timeout), or None if JSON-RPC isn't working. """ if not self._rpcsock.connected: # No RPC support yield None if self._rpcver >= 3: check_scanning_args = 'XBMC.GetInfoBooleans', {'booleans': ['library.isscanning']} else: check_scanning_args = 'System.GetInfoBooleans', ['library.isscanning'] t0 = time.time() while time.time() - t0 < timeout: result = yield self._jsonrpc(*check_scanning_args) if not result or result.get('library.isscanning') != True: yield True log.debug2('XBMC busy scanning, waiting') yield kaa.delay(5) yield False
def main(): query = yield (yield kaa.beacon.get(sys.argv[1])).list() # this is the context for the images widget context = kaa.candy.Context(title=os.path.basename(sys.argv[1]), items=query) group = candy.group.thumbnails(context=context) stage.add(group) grid = group.get_widget('items') # if 1: # # add effects and hide selection rectangle # grid.behave('opacity', 80, 255).behave('scale', (1, 1), (1.1, 1.1)) # grid.selection.opacity = 0 # if 0: # # add effects and hide selection rectangle # grid.behave('scale', (1, 1), (1.5, 1.5)) yield kaa.delay(0.5) # now we move the selection print 'move selection to the right' grid.select((2, 0), 1) yield kaa.delay(1.5) print 'move selection down' grid.select((2, 2), 1) yield kaa.delay(1.5) print 'move selection down and scroll at the same time to make it look' print 'like the selection is standing still.' grid.select((2, 4), 1) grid.scroll_by((0, 2), 1) yield kaa.delay(1.5) print 'move selection down fast' grid.select((2, 5), 0.3) yield kaa.delay(1.5) print 'move selection and start scrolling with a different speed' grid.select((5, 5), 1) yield kaa.delay(0.3) grid.scroll_by((4, 0), 4) yield kaa.delay(2) grid.select((5, 3), 1) yield kaa.delay(2) print 'move selection very slowly' grid.select((7, 3), 3) yield kaa.delay(3.5) print 'scroll to get selection to the left side' grid.scroll_by((3, 0), 1) yield kaa.delay(2) print 'move selection fast to the right' grid.select((12, 3), 0.8) yield kaa.delay(1) print 'and back' grid.select((7, 3), 1) yield kaa.delay(0.3) print 'and revert while moving' grid.select((12, 3), 1) yield kaa.delay(1) print 'and back again very fast' grid.select((7, 3), 0.3) yield kaa.delay(0.5) print 'left again and start scrolling' grid.select((16, 3), 0.8) yield kaa.delay(0.3) grid.scroll_by((4, 0), 0.5) yield kaa.delay(1.0) print 'change col and row' grid.select((11, 6), 1)
def search(self, filename, metadata): """ Search for possible movie information for the given filename """ if not os.path.exists(filename): yield [] # We are limited to 30 requests per 10 seconds. Wait one # second before doing some searches. yield kaa.delay(1) result = [] nfo = os.path.splitext(filename)[0] + '.nfo' if os.path.exists(nfo) and not result: match = IMDB_REGEXP.search(open(nfo).read()) if match: result = yield self._server_call('movie/tt%s' % match.groups()[0]) if result: movie = Movie(result, self) movie.likely = True result = [movie] if not result: # try guessing title and year m = TITLE_REGEXP.match(os.path.basename(filename)) data = None if m: name, year = m.groups() if int(year) > 1900 and int(year) <= time.localtime().tm_year: # valid year name = name.lower().replace('.', ' ').replace('-', ' ').replace( '_', ' ') data = yield self._server_call('search/movie', query=name, year=year) if not data or not data.get('results', None) and name.find('3d') > 0: name = name[:name.find('3d')] data = yield self._server_call('search/movie', query=name, year=year) # guess by kaa.metadata title if not data or not data.get('results', None): metadata = kaa.metadata.parse(filename) if metadata and metadata.title: name = metadata.title else: name = os.path.basename(filename) name = name.lower().replace('.', ' ').replace('-', ' ').replace( '_', ' ') data = yield self._server_call('search/movie', query=name) if not data or not data.get('results', None) and name.find('3d') > 0: name = name[:name.find('3d')] data = yield self._server_call('search/movie', query=name) if data and data.get('results', None): result = [] for r in data.get('results'): movie = Movie(r, self) # mark the best matches if movie.name.lower().replace('.', ' ').replace( '-', ' ').replace('_', ' ') == name: movie.likely = True else: movie.likely = False result.append(movie) yield result
def fake_download(progress, result, outfile, episode): for i in range(100): progress.set(i*1*1024, 100*1024, 2048) print progress.get_progressbar(), progress.speed yield kaa.delay(1)
# now that we have data run set_metadata again self.set_metadata(filename, attributes) self.guessing_failed.append(series) yield None if not attributes.get('length') or attributes.get('length') < 60 * 60: # less than an hour does not look like a movie; mark file # as guessed attributes['webmetadata'] = filename yield None # we use the movie hash here. Therefore, the file should # be finished downloading or copying. This slows us down, # but it is the guessing part that runs in the background # anyway. try: filesize = os.path.getsize(filename) yield kaa.delay(5) if filesize != os.path.getsize(filename): # still growing, we do not want to handle this # file. Beacon will catch it again and we will be # here again. yield None except OSError: # file is deleted while we were checking yield None # check the movie database log.info('guess %s', filename) try: result = yield kaa.webmetadata.movie.search(filename, attributes) except Exception, e: # something went wrong, maybe we have more luck next time log.exception('kaa.webmetadata.movie.search')