def edit_widget_dialog(widget_id): dialog = xbmcgui.Dialog() updated = False if advanced and not warning_shown: _warn() widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return options = _get_widget_options(widget_def) remove_label = utils.get_string(32025) if widget_id else utils.get_string( 32023) options.append('[COLOR firebrick]{}[/COLOR]'.format(remove_label)) idx = dialog.select(utils.get_string(32048), options) if idx < 0: return elif idx == len(options) - 1: _remove_widget(widget_id) utils.update_container() return else: key = _clean_key(options[idx]) updated = _get_widget_value(widget_def, key) utils.log(updated, xbmc.LOGNOTICE) if updated: convert.save_path_details(widget_def, widget_id) utils.update_container() edit_widget_dialog(widget_id)
def _show_options(group_def, path_def=None, type=''): edit_def = path_def if path_def else group_def options = _get_options(edit_def) remove_label = utils.get_string(32025) if path_def else utils.get_string(32023) options.append(u'[COLOR firebrick]{}[/COLOR]'.format(six.ensure_text(remove_label))) if not type: target = path_def['target'] if path_def else group_def['type'] if target not in ['shortcut', 'widget', 'settings']: main_action = utils.get_string(32140) else: main_action = utils.get_string(32048) if target in ['shortcut', 'settings'] else utils.get_string(32141) else: main_action = utils.get_string(32061) idx = dialog.select(main_action, options) if idx < 0: return elif idx == len(options) - 1: if path_def: _remove_path(path_def['id'], group_def['id']) utils.update_container(group_def['type'] == 'shortcut') else: _remove_group(group_def['id']) utils.update_container(group_def['type'] == 'shortcut') return else: key = _clean_key(options[idx]) return _get_value(edit_def, key)
def update_path(widget_id, target, path=None): widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return stack = widget_def.get("stack", []) if target == "next" and path: utils.log("Next Page selected from {}".format(widget_id), "debug") path_def = manage.get_path_by_id(widget_def["path"], widget_def["group"]) if isinstance(path_def, dict): widget_def["label"] = path_def["label"] stack.append(path) widget_def["stack"] = stack elif target == "back" and widget_def.get("stack"): utils.log("Previous Page selected from {}".format(widget_id), "debug") widget_def["stack"] = widget_def["stack"][:-1] elif target == "reset": if len(stack) > 0: # simple compatibility with pre-3.3.0 widgets if isinstance(stack[0], dict): widget_def["path"] = stack[0].get("id", "") widget_def["stack"] = [] manage.save_path_details(widget_def) _update_strings(widget_def) utils.update_container(True) back_to_top(target)
def _show_options(group_def, path_def=None, type=""): edit_def = path_def if path_def else group_def options = _get_options(edit_def) remove_label = utils.get_string(32025) if path_def else utils.get_string( 32023) options.append(u"[COLOR firebrick]{}[/COLOR]".format( six.ensure_text(remove_label))) if not type: target = path_def["target"] if path_def else group_def["type"] if target not in ["shortcut", "widget", "settings"]: main_action = utils.get_string(32140) else: main_action = (utils.get_string(32048) if target in [ "shortcut", "settings" ] else utils.get_string(32141)) else: main_action = utils.get_string(32061) idx = dialog.select(main_action, options) if idx < 0: return elif idx == len(options) - 1: if path_def: _remove_path(path_def["id"], group_def["id"]) utils.update_container(group_def["type"] == "shortcut") else: _remove_group(group_def["id"]) utils.update_container(group_def["type"] == "shortcut") return else: key = _clean_key(options[idx]) return _get_value(edit_def, key)
def onPlayBackEnded(self): # import ptvsd; ptvsd.enable_attach(address=('127.0.0.1', 5678)); ptvsd.wait_for_attach() utils.log("AutoWidget onPlayBackEnded callback", "notice") # Once a playback ends. # Work out which cached paths are most likely to change based on playback history # Record playback in a history db so we can potentially use this for future predictions. try: tt = self.totalTime tp = self.playingTime pp = int(100 * tp / tt) except RuntimeError: pp = -1 except OverflowError: pp = -1 self.totalTime = -1.0 self.playingTime = 0.0 self.info = {} cache.save_playback_history(self.type, pp) utils.log("recorded playback of {}% {}".format(pp, self.type), "notice") # wait for a bit so scrobing can happen time.sleep(5) for hash, path in cache.widgets_changed_by_watching(self.type): # Queue them for refresh cache.push_cache_queue(path) utils.log("Queued cache update: {}".format(hash[:5]), "notice") utils.update_container(reload=True)
def _reload_settings(self): self.refresh_enabled = utils.get_setting_int('service.refresh_enabled') self.refresh_duration = utils.get_setting_float('service.refresh_duration') self.refresh_notification = utils.get_setting_int('service.refresh_notification') self.refresh_sound = utils.get_setting_bool('service.refresh_sound') utils.update_container(True)
def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) if widget_def["action"] in ["static", "merged"]: return paths current_time = time.time() updated_at = widget_def.get("updated", 0) default_refresh = settings.get_setting_float("service.refresh_duration") refresh_duration = float(widget_def.get("refresh", default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: group_id = widget_def["group"] action = widget_def.get("action") current = int(widget_def.get("current", 0)) widget_def["stack"] = [] if not paths: cycle_paths = widget_def.get("cycle_paths") if cycle_paths is None: cycle_paths = [ p.get("id") for p in manage.find_defined_paths(group_id) ] widget_def["cycle_paths"] = cycle_paths paths = [p for p in cycle_paths] if action: if len(paths) > 0: next = 0 if action == "next": next = (current + 1) % len(paths) elif action == "random": random.shuffle(paths) next = random.randrange(len(paths)) widget_def["current"] = next path_id = paths[next] paths.remove(paths[next]) widget_def["path"] = path_id if widget_def["path"]: path_label = manage.get_path_by_id(path_id, group_id).get( "label", "") widget_def["label"] = path_label widget_def["updated"] = 0 if force else current_time manage.save_path_details(widget_def) _update_strings(widget_def) if single: utils.update_container(True) return paths
def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) if widget_def["action"] in ["static", "merged"]: return paths current_time = time.time() updated_at = widget_def.get("updated", 0) default_refresh = utils.get_setting_float("service.refresh_duration") refresh_duration = float(widget_def.get("refresh", default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: group_id = widget_def["group"] action = widget_def.get("action") current = int(widget_def.get("current", -1)) widget_def["stack"] = [] widget_def["label"] = "" if not paths: paths = manage.find_defined_paths(group_id) if action: if len(paths) > 0: next = 0 if action == "next": next = (current + 1) % len(paths) elif action == "random": random.shuffle(paths) next = random.randrange(len(paths)) elif action == 'randomized': next = manage.get_inactive_path(paths) if next == []: next = current widget_def['current'] = next path_def = paths[next] paths.remove(paths[next]) widget_def["path"] = path_def if widget_def["path"]: widget_def["updated"] = 0 if force else current_time manage.save_path_details(widget_def) _update_strings(widget_def) if single: utils.update_container(True) return paths
def edit_widget_dialog(widget_id): updated = False if advanced and not warning_shown: _warn() widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return updated = _show_widget_options(widget_def) if updated: manage.save_path_details(widget_def) utils.update_container(True) edit_widget_dialog(widget_id)
def _show_widget_options(edit_def): options = _get_widget_options(edit_def) options.append('[COLOR firebrick]{}[/COLOR]'.format(utils.get_string(32116))) idx = dialog.select(utils.get_string(32070), options) if idx < 0: return elif idx == len(options) - 1: remove_widget(edit_def['id']) utils.update_container() return else: key = _clean_key(options[idx]) return _get_widget_value(edit_def, key)
def clear_cache(target=None): if not target: dialog = xbmcgui.Dialog() choice = dialog.yesno("AutoWidget", utils.get_string(30118)) del dialog if choice: for file in [ i for i in os.listdir(_addon_data) if i.split('.')[-1] in ["cache", "history", "queue"] ]: os.remove(os.path.join(_addon_data, file)) else: os.remove(os.path.join(_addon_data, "{}.cache".format(target))) utils.update_container(True)
def refresh_paths(notify=False, force=False): if notify: dialog = xbmcgui.Dialog() dialog.notification('AutoWidget', utils.get_string(32033), sound=utils.get_setting_bool('service.refresh_sound')) for group_def in manage.find_defined_groups(): paths = [] widgets = manage.find_defined_widgets(group_def['id']) for widget_def in widgets: paths = refresh(widget_def['id'], widget_def=widget_def, paths=paths, force=force) utils.update_container(True) return True, 'AutoWidget'
def edit_dialog(group_id, path_id=None, base_key=None): updated = False if advanced and not warning_shown: _warn() group_def = manage.get_group_by_id(group_id) path_def = manage.get_path_by_id(path_id, group_id) if not group_def or path_id and not path_def: return updated = _show_options(group_def, path_def) if updated: manage.write_path(group_def, path_def=path_def, update=path_id) utils.update_container(group_def['type'] == 'shortcut') edit_dialog(group_id, path_id)
def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) if widget_def['action'] in ['static', 'merged']: return paths current_time = time.time() updated_at = widget_def.get('updated', 0) default_refresh = utils.get_setting_float('service.refresh_duration') refresh_duration = float(widget_def.get('refresh', default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: group_id = widget_def['group'] action = widget_def.get('action') current = int(widget_def.get('current', -1)) widget_def['stack'] = [] widget_def['label'] = '' if not paths: paths = manage.find_defined_paths(group_id) if action: if len(paths) > 0: next = 0 if action == 'next': next = (current + 1) % len(paths) elif action == 'random': random.shuffle(paths) next = random.randrange(len(paths)) widget_def['current'] = next path_def = paths[next] paths.remove(paths[next]) widget_def['path'] = path_def if widget_def['path']: widget_def['updated'] = 0 if force else current_time manage.save_path_details(widget_def) _update_strings(widget_def) if single: utils.update_container(True) return paths
def refresh(widget_id, widget_def=None, paths=None, force=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) current_time = time.time() updated_at = widget_def.get('updated', 0) default_refresh = utils.get_setting_float('service.refresh_duration') refresh_duration = float(widget_def.get('refresh', default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: path_def = {} _id = widget_def['id'] group_id = widget_def['group'] action = widget_def.get('action') setting = widget_def.get('path_setting') label_setting = widget_def.get('label_setting') current = int(widget_def.get('current', -1)) if not paths: paths = manage.find_defined_paths(group_id) random.shuffle(paths) if action: if len(paths) > 0: next = 0 if action == 'next': next = (current + 1) % len(paths) elif action == 'random': next = random.randrange(len(paths)) widget_def['current'] = next path_def = paths[next] paths.remove(paths[next]) widget_def['path'] = path_def.get('id') if widget_def['path']: widget_def['updated'] = 0 if force else current_time convert.save_path_details(widget_def, _id) _update_strings(_id, path_def, setting, label_setting) utils.update_container() return paths
def add(labels): _type = _add_as(labels['file']) if not _type: return if _type not in ['clone', 'explode']: labels['target'] = _type group_def = _group_dialog(_type) if group_def: _add_path(group_def, labels) elif _type == 'clone': labels['target'] = 'shortcut' _copy_path(labels) elif _type == 'explode': labels['target'] = 'widget' _copy_path(labels) utils.update_container(_type == 'shortcut')
def add(labels): _type = _add_as(labels["file"]) if not _type: return if _type not in ["clone", "explode"]: labels["target"] = _type group_def = _group_dialog(_type) if group_def: _add_path(group_def, labels) elif _type == "clone": labels["target"] = "shortcut" _copy_path(labels) elif _type == "explode": labels["target"] = "widget" _copy_path(labels) utils.update_container(_type == "shortcut")
def copy_group(group_id, type): old_group_def = manage.get_group_by_id(group_id) new_group_id = add_group(type, old_group_def.get("label")) if not new_group_id: return new_group_def = manage.get_group_by_id(new_group_id) new_group_def["art"] = old_group_def.get("art", {}) new_group_def["content"] = old_group_def.get( "content", new_group_def.get("content", "files")) paths = old_group_def.get("paths", []) new_group_def["paths"] = manage.choose_paths(utils.get_string(30121), paths, indices=False) manage.write_path(new_group_def) utils.update_container()
def _show_widget_options(edit_def): options = _get_widget_options(edit_def) options.append("[COLOR firebrick]{}[/COLOR]".format( utils.get_string(30090))) dialog = xbmcgui.Dialog() idx = dialog.select(utils.get_string(30048), options) del dialog if idx < 0: return elif idx == len(options) - 1: remove_widget(edit_def["id"]) utils.update_container() return else: key = _clean_key(options[idx]) return _get_widget_value(edit_def, key)
def shift_path(group_id, path_id, target): group_def = manage.get_group_by_id(group_id) paths = group_def['paths'] for idx, path_def in enumerate(paths): if path_def['id'] == path_id: if target == 'up' and idx > 0: temp = paths[idx - 1] paths[idx - 1] = path_def paths[idx] = temp elif target == 'down' and idx < len(paths) - 1: temp = paths[idx + 1] paths[idx + 1] = path_def paths[idx] = temp break group_def['paths'] = paths manage.write_path(group_def) utils.update_container(group_def['type'])
def refresh_paths(notify=False, force=False): if notify: dialog = xbmcgui.Dialog() dialog.notification( "AutoWidget", utils.get_string(30020), sound=settings.get_setting_bool("service.refresh_sound"), ) del dialog for group_def in manage.find_defined_groups(): paths = [] widgets = manage.find_defined_widgets(group_def["id"]) for widget_def in widgets: paths = refresh( widget_def["id"], widget_def=widget_def, paths=paths, force=force ) utils.update_container(True) return True, "AutoWidget"
def _show_options(group_def, path_def=None): edit_def = path_def if path_def else group_def options = _get_options(edit_def) remove_label = utils.get_string(32025) if path_def else utils.get_string( 32023) options.append('[COLOR firebrick]{}[/COLOR]'.format(remove_label)) idx = dialog.select(utils.get_string(32048), options) if idx < 0: return elif idx == len(options) - 1: if path_def: _remove_path(path_def['id'], group_def['id']) utils.update_container(group_def['type'] == 'shortcut') else: _remove_group(group_def['id']) utils.update_container(group_def['type'] == 'shortcut') return else: key = _clean_key(options[idx]) return _get_value(edit_def, key)
def refresh_paths(notify=False, force=False): converted = [] current_time = time.time() if force: converted = convert.convert_widgets(notify) if notify: dialog = xbmcgui.Dialog() dialog.notification('AutoWidget', utils.get_string(32033)) for group_def in manage.find_defined_groups(): paths = [] widgets = manage.find_defined_widgets(group_def['id']) for widget_def in widgets: paths = refresh(widget_def['id'], widget_def=widget_def, paths=paths, force=force) utils.update_container(reload=len(converted) > 0 and utils.shortcuts_path)
def shift_path(group_id, path_id, target): group_def = manage.get_group_by_id(group_id) paths = group_def['paths'] for idx, path_def in enumerate(paths): if path_def['id'] == path_id: if target == 'up' and idx >= 0: if idx > 0: temp = paths[idx - 1] paths[idx - 1] = path_def paths[idx] = temp else: paths.append(paths.pop(idx)) elif target == 'down' and idx <= len(paths) - 1: if idx < len(paths) - 1: temp = paths[idx + 1] paths[idx + 1] = path_def paths[idx] = temp else: paths.insert(0, paths.pop()) break group_def['paths'] = paths manage.write_path(group_def) utils.update_container(group_def['type'] == 'shortcut')
def update_path(widget_id, target, path=None): widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return stack = widget_def.get("stack", []) if target == "next" and path: utils.log("Next Page selected from {}".format(widget_id), "debug") path_def = widget_def["path"] if isinstance(path_def, dict): widget_def["label"] = path_def["label"] stack.append(widget_def["path"]) widget_def["stack"] = stack widget_def["path"] = path elif target == "back" and widget_def.get("stack"): utils.log("Previous Page selected from {}".format(widget_id), "debug") widget_def["path"] = widget_def["stack"][-1] widget_def["stack"] = widget_def["stack"][:-1] if len(widget_def["stack"]) == 0: widget_def["label"] = "" elif target == "reset": if len(stack) > 0: widget_def["path"] = widget_def["stack"][0] widget_def["stack"] = [] widget_def["label"] = "" action = widget_def[ "path"] if widget_def["action"] != "merged" else "merged" if isinstance(widget_def["path"], dict): action = widget_def["path"]["file"]["file"] manage.save_path_details(widget_def) _update_strings(widget_def) utils.update_container(True) back_to_top(target)
def update_path(widget_id, target, path=None): widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return stack = widget_def.get('stack', []) if target == 'next' and path: utils.log('Next Page selected from {}'.format(widget_id), 'debug') path_def = widget_def['path'] if isinstance(path_def, dict): widget_def['label'] = path_def['label'] stack.append(widget_def['path']) widget_def['stack'] = stack widget_def['path'] = path elif target == 'back' and widget_def.get('stack'): utils.log('Previous Page selected from {}'.format(widget_id), 'debug') widget_def['path'] = widget_def['stack'][-1] widget_def['stack'] = widget_def['stack'][:-1] if len(widget_def['stack']) == 0: widget_def['label'] = '' elif target == 'reset': if len(stack) > 0: widget_def['path'] = widget_def['stack'][0] widget_def['stack'] = [] widget_def['label'] = '' action = widget_def[ 'path'] if widget_def['action'] != 'merged' else 'merged' if isinstance(widget_def['path'], dict): action = widget_def['path']['file']['file'] manage.save_path_details(widget_def) _update_strings(widget_def) utils.update_container(True) back_to_top(target)
def add_group(target): dialog = xbmcgui.Dialog() group_name = dialog.input(heading=utils.get_string(32037)) group_id = '' if group_name: group_id = utils.get_unique_id(group_name) filename = os.path.join(_addon_path, '{}.group'.format(group_id)) group_def = { 'label': group_name, 'type': target, 'paths': [], 'id': group_id, 'info': {}, 'art': folder_sync if target == 'widget' else folder_shortcut, 'version': _addon_version } utils.write_json(filename, group_def) utils.update_container() else: dialog.notification('AutoWidget', utils.get_string(32038)) return group_id
def _update_widgets(self): self._refresh(True) while not self.abortRequested(): for _ in self.tick(15, 60 * 15): # TODO: somehow delay to all other plugins loaded? unrefreshed_widgets = set() for hash, widget_ids in utils.next_cache_queue(): effected_widgets = cache_and_update(widget_ids) utils.remove_cache_queue( hash ) # Just in queued path's widget defintion has changed and it didn't update this path unrefreshed_widgets = unrefreshed_widgets.union( effected_widgets).difference(set(widget_ids)) # # wait 5s or for the skin to reload the widget # # this should reduce churn at startup where widgets take too long too long show up # before_update = time.time() # TODO: have .access file so we can put above update # while _ in self.tick(1, 10, lambda: utils.last_read(hash) > before_update): # pass # utils.log("paused queue until read {:.2} for {}".format(utils.last_read(hash)-before_update, hash[:5]), 'info') if self.abortRequested(): break for widget_id in unrefreshed_widgets: widget_def = manage.get_widget_by_id(widget_id) if not widget_def: continue _update_strings(widget_def) if (os.path.exists(os.path.join(_addon_data, "refresh.time")) and utils.get_active_window() == "home"): utils.update_container(True) if self.abortRequested(): break if not self._refresh(): continue
def edit_dialog(group_id, path_id=''): dialog = xbmcgui.Dialog() updated = False if advanced and not warning_shown: _warn() group_def = manage.get_group_by_id(group_id) if not group_def: return if path_id: path_def = manage.get_path_by_id(path_id, group_id) if not path_def: return edit_def = path_def if path_id else group_def options = _get_options(edit_def) remove_label = utils.get_string(32025) if path_id else utils.get_string( 32023) options.append('[COLOR firebrick]{}[/COLOR]'.format(remove_label)) idx = dialog.select(utils.get_string(32048), options) if idx < 0: return elif idx == len(options) - 1: if path_id: _remove_path(path_id, group_id) utils.update_container(group_def['type']) else: _remove_group(group_id) utils.update_container(group_def['type']) return else: key = _clean_key(options[idx]) updated = _get_value(edit_def, key) utils.log(updated, xbmc.LOGNOTICE) if updated: if path_id: manage.write_path(group_def, path_def=path_def, update=path_id) else: manage.write_path(group_def) utils.update_container(group_def['type']) edit_dialog(group_id, path_id)
def _update_widgets(self): self._refresh(True) while not self.abortRequested(): for _ in self.tick(step=1, max=60 * 15): # don't process cache queue during video playback if self.player.isPlayingVideo(): continue # TODO: somehow delay till all other plugins loaded? updated = False unrefreshed_widgets = set() queue = list(cache.next_cache_queue()) # class Progress(object): # dialog = None # service = self # done = set() # def __call__(self, groupname, path): # if self.dialog is None: # self.dialog = xbmcgui.DialogProgressBG() # self.dialog.create("AutoWidget", utils.get_string(30141)) # if not self.service.player.isPlayingVideo(): # percent = ( # len(self.done) # / float(len(queue) + len(self.done) + 1) # * 100 # ) # self.dialog.update( # int(percent), "AutoWidget", message=groupname # ) # self.done.add(path) # progress = Progress() while queue: path, cache_data, widget_id = queue.pop(0) hash = cache.path2hash(path) utils.log("Dequeued cache update: {}".format(hash[:5]), "notice") affected_widgets = set( cache.cache_and_update( path, widget_id, cache_data, # notify=progress ) ) if affected_widgets: updated = True unrefreshed_widgets = unrefreshed_widgets.union(affected_widgets) # # wait 5s or for the skin to reload the widget # # this should reduce churn at startup where widgets take too long too long show up # before_update = time.time() # TODO: have .access file so we can put above update # while _ in self.tick(1, 10, lambda: cache.last_read(hash) > before_update): # pass # utils.log("paused queue until read {:.2} for {}".format(cache.last_read(hash)-before_update, hash[:5]), 'info') if self.abortRequested(): break if self.player.isPlayingVideo(): # Video stop will cause another refresh anyway. break queue = list(cache.next_cache_queue()) for widget_id in unrefreshed_widgets: widget_def = manage.get_widget_by_id(widget_id) if not widget_def: continue _update_strings(widget_def) if ( os.path.exists(os.path.join(_addon_data, "refresh.time")) and utils.get_active_window() == "home" ): utils.update_container(True) # if progress.dialog is not None: # progress.dialog.update(100) # progress.dialog.close() if ( updated and self.refresh_enabled == 1 and not self.player.isPlayingVideo() ): dialog = xbmcgui.Dialog() dialog.notification( u"AutoWidget", utils.get_string(30142), sound=False ) if self.abortRequested(): break if not self._refresh(): continue