def attach_context_menu(self, item, menu): colorCaution = getSetting('item_caution_color') login = getSetting('username') isOwner = True cmd = containerUpdate(self.make_url(nt=Flag.USERPLAYLISTS, id='', mode=Mode.VIEW)) menu.add(path='playlist', pos = 1, label="Playlist", cmd=cmd, mode=Mode.VIEW) if login != self.get_property('owner/name'): isOwner = False if isOwner: url = self.make_url(nt=Flag.PLAYLIST, mode=Mode.VIEW, nm='set_as_current') menu.add(path='playlist/set_as_current', label=lang(39007), cmd=containerUpdate(url)) url = self.make_url(nt=Flag.PLAYLIST, nm='gui_rename') menu.add(path='playlist/rename', label=lang(39009), cmd=runPlugin(url)) else: url = self.make_url(nt=Flag.PLAYLIST, nm='subscribe') menu.add(path='playlist/subscribe', label=lang(39012), cmd=runPlugin(url)) url = self.make_url(nt=Flag.PLAYLIST, nm='gui_remove') menu.add(path='playlist/remove', label=lang(39010), cmd=runPlugin(url), color=colorCaution) ''' Calling base class ''' super(Node_playlist, self).attach_context_menu(item, menu)
def makeListItem(self, replaceItems=False): colorItem = getSetting('item_default_color') colorPl = getSetting('item_section_color') label = self.get_label() image = self.get_image() owner = self.get_owner() url = self.make_url() if not self.is_my_playlist: label = '%s - %s' % (color(colorItem,owner), label) if self.b_is_current: label = '-o] %s [o-' % (color(colorPl, label)) #label = color(colorPl, label) item = xbmcgui.ListItem(label, owner, image, image, url) if not item: warn(self, "Error: Cannot make xbmc list item") return None item.setPath(url) ctxMenu = contextMenu() self.attach_context_menu(item, ctxMenu) item.addContextMenuItems(ctxMenu.getTuples(), replaceItems) return item
def get_ttl(self, key, *a, **ka): if len(a) > 0: if a[0] == '/track/getFileUrl': return 60*15 if 'user_id' in ka: return getSetting('cache_duration_middle', isInt=True) * 60 return getSetting('cache_duration_long', isInt=True) * 60
def get_ttl(self, key, *a, **ka): if len(a) > 0: if a[0] == '/track/getFileUrl': return 60 * 15 if 'user_id' in ka: return getSetting('cache_duration_middle', isInt=True) * 60 return getSetting('cache_duration_long', isInt=True) * 60
def __init__(self): self.data = {} self.defaultSection = 'qobuz' self.color_default = getSetting('item_default_color') self.color_section = getSetting('item_section_color') formatStr = getSetting('item_section_format') try: test = formatStr % ('plop') except: formatStr = '[ %s ]' self.format_section = formatStr
def bootstrap_registry(self): from api import api cache.base_path = qobuz.path.cache api.stream_format = 6 if getSetting('streamtype') == 'flac' else 5 if not api.login(getSetting('username'), getSetting('password')): dialogLoginFailure() #@TODO sys.exit killing XBMC? FRODO BUG ? # sys.exit(1) containerRefresh() raise QobuzXbmcError( who=self, what='invalid_login', additional=None)
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit', isInt=True) self.data = None query = self.query if not query: from gui.util import Keyboard k = Keyboard('', 'My %s' % self.search_type) k.doModal() if not k.isConfirmed(): return False query = k.getText() query.strip() info(self, 'search_type: %s, query: %s' % (self.search_type, query)) source = self.source kwargs = { 'query': query, 'limit': limit, } if source is not None: kwargs['source'] = source data = None self.data = data if self.search_type == 'albums': data = api.get('/collection/getAlbums', **kwargs) elif self.search_type == 'artists': data = api.get('/collection/getArtists', **kwargs) elif self.search_type == 'tracks': data = api.get('/collection/getTracks', **kwargs) # try: # self.data = data['items'] # return True # except Exception as e: # warn(self, 'Exception: %s' % e) self.data = data return False
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit', isInt=True) self.data = None query = self.query if not query: from gui.util import Keyboard k = Keyboard('', 'My %s' % self.search_type) k.doModal() if not k.isConfirmed(): return False query = k.getText() query.strip() info(self, 'search_type: %s, query: %s' % (self.search_type, query)) source = self.source kwargs = {'query': query, 'limit': limit, } if source is not None: kwargs['source'] = source data = None self.data = data if self.search_type == 'albums': data = api.get('/collection/getAlbums', **kwargs) elif self.search_type == 'artists': data = api.get('/collection/getArtists', **kwargs) elif self.search_type == 'tracks': data = api.get('/collection/getTracks', **kwargs) # try: # self.data = data['items'] # return True # except Exception as e: # warn(self, 'Exception: %s' % e) self.data = data return False
def _delete_cache(self): limit = getSetting('pagination_limit') key = cache.make_key('/favorite/getUserFavorites', user_id=api.user_id, limit=limit, offset=self.offset) return cache.delete(key)
def __init__(self, parent, params): super(Node_album, self).__init__(parent, params) self.nt = Flag.ALBUM self.image = getImage('album') self.content_type = 'songs' self.is_special_purchase = False self.offset = None self.imageDefaultSize = 'large' self.label = 'Album' try: self.imageDefaultSize = getSetting('image_default_size') except: pass @property def nid(self): return self._nid @nid.getter # @IgnorePep8 def nid(self): return self._nid @nid.setter # @IgnorePep8 def nid(self, value): self._id = value if value in SPECIAL_PURCHASES: self.is_special_purchase = True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') stype = self.search_type query = self.get_parameter('query', unQuote=True) if not query: from gui.util import Keyboard k = Keyboard('', stype) k.doModal() if not k.isConfirmed(): return False query = k.getText() query.strip() data = api.get('/search/getResults', query=query, type=stype, limit=limit, offset=self.offset) if not data: warn(self, "Search return no data") return False if data[stype]['total'] == 0: return False if not 'items' in data[stype]: return False self.set_parameter('query', query, quote=True) self.data = data return True
def __init__(self, parent, params): super(Node_album, self).__init__(parent, params) self.nt = Flag.ALBUM self.image = getImage('album') self.content_type = 'songs' self.is_special_purchase = False self.offset = None self.imageDefaultSize = 'large' self.label = 'Album' try: self.imageDefaultSize = getSetting('image_default_size') except: pass @property def nid(self): return self._nid @nid.getter def nid(self): return self._nid @nid.setter def nid(self, value): self._id = value if value in SPECIAL_PURCHASES: self.is_special_purchase = True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/artist/getSimilarArtists', artist_id=self.nid, offset=self.offset, limit=limit) if not data: return False self.data = data return len(data['artists']['items'])
def __getFileUrl(self): format_id = 6 if getSetting('streamtype') == 'flac' else 5 data = api.get('/track/getFileUrl', format_id=format_id, track_id=self.nid, user_id=api.user_id) if not data: warn(self, "Cannot get stream type for track (network problem?)") return None return data
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting("pagination_limit") data = api.get("/artist/getSimilarArtist", artist_id=self.nid, limit=limit, offset=self.offset, extra="albums") if not data: warn(self, "Cannot fetch albums for artist: " + self.get_label()) return False self.data = data return True
def delete_cache(self, playlist_id): limit = getSetting('pagination_limit') upkey = cache.make_key('/playlist/getUserPlaylists', limit=limit, offset=self.offset, user_id=api.user_id) pkey = cache.make_key('/playlist/get',playlist_id=playlist_id, offset=self.offset, limit=limit, extra='tracks') cache.delete(upkey) cache.delete(pkey)
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/playlist/getUserPlaylists', limit=limit, offset=self.offset, user_id=api.user_id) if not data: warn(self, "Build-down: Cannot fetch user playlists data") return False self.data = data return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/purchase/getUserPurchases', limit=limit, offset=self.offset, user_id=api.user_id) if not data: warn(self, "Cannot fetch purchases data") return False self.data = data return True
def attach_context_menu(self, item, menu): colorWarn = getSetting("item_caution_color") url = self.make_url() menu.add(path="friend", label=self.name, cmd=containerUpdate(url)) cmd = runPlugin(self.make_url(nt=Flag.FRIEND, nm="remove")) menu.add(path="friend/remove", label="Remove", cmd=cmd, color=colorWarn) """ Calling base class """ super(Node_friend, self).attach_context_menu(item, menu)
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/artist/get', artist_id=self.nid, limit=limit, offset=self.offset, extra='albums') if not data: warn(self, "Build-down: Cannot fetch artist data") return False self.data = data return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting("pagination_limit") data = qobuz.registry.get( name="article_listlastarticles", id=self.nid, rubric_ids=self.nid, offset=self.offset, limit=limit ) if not data: return False self.data = data["data"] return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit', isInt=True) data = api.get('/playlist/get',playlist_id=self.nid, offset=self.offset, limit=limit, extra='tracks') if not data: warn(self, "Build-down: Cannot fetch playlist data") return False self.data = data return True
def gui_remove(self, playlist_id=None): if not playlist_id: playlist_id = self.nid if not playlist_id: notifyH(dialogHeading, 'Invalid playlist %s' % (str(playlist_id))) return False # import xbmcgui # @UnresolvedImport # import xbmc # @UnresolvedImport # cid = self.get_current_playlist() login = getSetting('username') offset = 0 limit = getSetting('pagination_limit') data = api.get('/playlist/get', playlist_id=playlist_id, limit=limit, offset=offset) name = '' if 'name' in data: name = data['name'] ok = xbmcgui.Dialog().yesno(lang(30166), lang(30054), color('FFFF0000', name)) if not ok: info(self, "Deleting playlist aborted...") return False res = False if data['owner']['name'] == login: info(self, "Deleting playlist: " + str(playlist_id)) res = api.playlist_delete(playlist_id=playlist_id) else: info(self, 'Unsuscribe playlist' + str(playlist_id)) res = api.playlist_unsubscribe(playlist_id=playlist_id) if not res: warn(self, "Cannot delete playlist with id " + str(playlist_id)) notifyH(lang(30183), lang(30186) + name, getImage('icon-error-256')) return False self.delete_cache(playlist_id) notifyH(lang(30183), (lang(30184) + "%s" + lang(30185)) % (name)) url = self.make_url(nt=Flag.USERPLAYLISTS, mode=Mode.VIEW, nm='', nid='') executeBuiltin(containerUpdate(url, True)) return False
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = qobuz.registry.get(name='article_listrubrics', id=self.nid, offset=self.offset, limit=limit) if not data: return False self.data = data['data'] return True
def fetch(self, Dir, lvl , whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = qobuz.registry.get( name='article_listrubrics', id=self.nid, offset=self.offset, limit=limit) if not data: return False self.data = data['data'] return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting("pagination_limit") data = api.get("/playlist/getPublicPlaylists", offset=self.offset, limit=limit, type="last-created") if not data: return False # @bug: we use pagination_limit as limit for the search so we don't # need offset... (Fixed if qobuz fix it :p) if not "total" in data["playlists"]: data["playlists"]["total"] = data["playlists"]["limit"] self.data = data return True
def attach_context_menu(self, item, menu): colorWarn = getSetting('item_caution_color') url = self.make_url() menu.add(path='friend', label=self.name, cmd=containerUpdate(url)) cmd = runPlugin(self.make_url(nt=Flag.FRIEND, nm="remove")) menu.add(path='friend/remove', label='Remove', cmd=cmd, color=colorWarn) ''' Calling base class ''' super(Node_friend, self).attach_context_menu(item, menu)
def populate(self, Dir, lvl, whiteFlag, blackFlag): self.add_child(getNode(Flag.USERPLAYLISTS)) if getSetting('show_recommendations', isBool=True): self.add_child(getNode(Flag.RECOMMENDATION)) self.add_child(getNode(Flag.PURCHASES)) self.add_child(getNode(Flag.FAVORITES)) if getSetting('search_enabled', isBool=True): search = getNode(Flag.SEARCH) search.search_type = 'albums' self.add_child(search) search = getNode(Flag.SEARCH) search.search_type = 'tracks' self.add_child(search) search = getNode(Flag.SEARCH) search.search_type = 'artists' self.add_child(search) self.add_child(getNode(Flag.FRIEND_LIST)) self.add_child(getNode(Flag.GENRE)) self.add_child(getNode(Flag.PUBLIC_PLAYLISTS)) return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting("pagination_limit") data = api.get("/genre/list", parent_id=self.nid, offset=self.offset, limit=limit) if not data: self.data = None return True # Nothing returned trigger reco build in build_down self.data = data g = self.data["genres"] if "parent" in g and int(g["parent"]["level"]) > 1: self.populate_reco(Dir, lvl, whiteFlag, blackFlag, g["parent"]["id"]) return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/favorite/getUserFavorites', user_id=api.user_id, limit=limit, offset=self.offset) if not data: warn(self, "Build-down: Cannot fetch favorites data") return False self.data = data return True
def gui_remove(self, playlist_id=None): if not playlist_id: playlist_id = self.nid if not playlist_id: notifyH(dialogHeading, 'Invalid playlist %s' % (str(playlist_id))) return False import xbmcgui import xbmc cid = self.get_current_playlist() login = getSetting('username') offset = 0 limit = getSetting('pagination_limit') data = api.get('/playlist/get', playlist_id=playlist_id, limit=limit, offset=offset) name = '' if 'name' in data: name = data['name'] ok = xbmcgui.Dialog().yesno(lang(39010), lang(30052), color('FFFF0000', name)) if not ok: info(self, "Deleting playlist aborted...") return False res = False if data['owner']['name'] == login: info(self, "Deleting playlist: " + str(playlist_id)) res = api.playlist_delete(playlist_id=playlist_id) else: info(self, 'Unsuscribe playlist' + str(playlist_id)) res = api.playlist_unsubscribe(playlist_id=playlist_id) if not res: warn(self, "Cannot delete playlist with id " + str(playlist_id)) notifyH(lang(42001), lang(42004) + name, getImage('icon-error-256')) return False self.delete_cache(playlist_id) notifyH(lang(42001), (lang(42002) + "%s" + lang(42003)) % (name)) url = self.make_url(nt=Flag.USERPLAYLISTS, mode=Mode.VIEW, nm='', nid='') executeBuiltin(containerUpdate(url, True)) return False
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/playlist/getPublicPlaylists', offset=self.offset, limit=limit, type='last-created') if not data: return False # @bug: we use pagination_limit as limit for the search so we don't # need offset... (Fixed if qobuz fix it :p) if not 'total' in data['playlists']: data['playlists']['total'] = data['playlists']['limit'] self.data = data return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/artist/getSimilarArtist', artist_id=self.nid, limit=limit, offset=self.offset, extra='albums') if not data: warn(self, "Cannot fetch albums for artist: " + self.get_label()) return False self.data = data return True
def __init__(self, parent=None, parameters=None): super(Node_user_playlists, self).__init__(parent, parameters) self.label = lang(30019) self.image = getImage('userplaylists') self.nt = Flag.USERPLAYLISTS self.content_type = 'files' display_by = self.get_parameter('display-by') if not display_by: display_by = 'songs' self.set_display_by(display_by) display_cover = getSetting('userplaylists_display_cover', isBool=True) self.display_product_cover = display_cover self.offset = self.get_parameter('offset') or 0
def populate(self, Dir, lvl, whiteFlag, blackFlag): self.add_child(getNode(Flag.USERPLAYLISTS)) if getSetting('show_recommendations', isBool=True): self.add_child(getNode(Flag.RECOMMENDATION)) self.add_child(getNode(Flag.PURCHASES)) self.add_child(getNode(Flag.FAVORITES)) if getSetting('search_enabled', isBool=True): search = getNode(Flag.SEARCH) search.search_type = 'albums' self.add_child(search) search = getNode(Flag.SEARCH) search.search_type = 'tracks' self.add_child(search) search = getNode(Flag.SEARCH) search.search_type = 'artists' self.add_child(search) collections = getNode(Flag.COLLECTIONS) self.add_child(collections) self.add_child(getNode(Flag.FRIENDS)) self.add_child(getNode(Flag.GENRE)) self.add_child(getNode(Flag.PUBLIC_PLAYLISTS)) return True
def populate(self, xbmc_directory, lvl, whiteFlag, blackFlag): offset = self.get_parameter('offset') or 0 #@bug: Qobuz service seam do don't return total so pagination is broken limit = getSetting('pagination_limit') data = api.get('/label/list', limit=limit, offset=offset) if not data: warn(self, "No label data") return False for item in data['labels']['items']: node = Node_label() node.data = item self.add_child(node) return True
def fetch(self, Dir, lvl , whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/genre/list', parent_id=self.nid, offset=self.offset, limit=limit) if not data: self.data = None return True # Nothing return trigger reco build in build_down self.data = data g = self.data['genres'] if 'parent' in g and int(g['parent']['level']) > 1: self.populate_reco(Dir, lvl, whiteFlag, blackFlag, g['parent']['id']) return True
def populate(self, Dir, lvl, whiteFlag, blackFlag): login = getSetting('username') cid = self.get_current_playlist_id() for data in self.data['playlists']['items']: node = getNode(Flag.PLAYLIST, {'offset': 0}) node.data = data if self.display_product_cover: pass if (cid and cid == node.nid): node.set_is_current(True) if node.get_owner() == login: node.set_is_my_playlist(True) self.add_child(node) return True
def attach_context_menu(self, item, menu): if self.parent and (self.parent.nt & Flag.PLAYLIST == Flag.PLAYLIST): colorCaution = getSetting('item_caution_color') url = self.parent.make_url(nt=Flag.PLAYLIST, id=self.parent.nid, qid=self.get_playlist_track_id(), nm='gui_remove_track', mode=Mode.VIEW) menu.add(path='playlist/remove', label=lang(30075), cmd=runPlugin(url), color=colorCaution) ''' Calling base class ''' super(Node_track, self).attach_context_menu(item, menu)
def fetch(self, Dir, lvl, whiteFlag, blackFlag): if not (self.genre_type and self.genre_id): return True offset = self.offset or 0 limit = getSetting('pagination_limit') data = api.get('/album/getFeatured', type=RECOS_TYPE_IDS[int(self.genre_type)], genre_id=self.genre_id, limit=limit, offset=offset) if not data: warn(self, "Cannot fetch data for recommendation") return False self.data = data return True
def fetch(self, Dir, lvl, whiteFlag, blackFlag): limit = getSetting('pagination_limit') data = api.get('/genre/list', parent_id=self.nid, offset=self.offset, limit=limit) if not data: self.data = None return True # Nothing return trigger reco build in build_down self.data = data g = self.data['genres'] if 'parent' in g and int(g['parent']['level']) > 1: self.populate_reco(Dir, lvl, whiteFlag, blackFlag, g['parent']['id']) return True
def run(self): """Building our tree, creating root node based on our node_type """ if not self.set_root_node(): warn(self, ("Cannot set root node (%s, %s)") % (str(self.node_type), str(self.root.get_parameter('nid')))) return False if self.root.hasWidget: return self.root.displayWidget() if self.has_method_parameter(): return self.execute_method_parameter() from gui.directory import Directory Dir = Directory(self.root, self.nodes, withProgress=self.enable_progress) Dir.asList = self.asList Dir.handle = qobuz.boot.handle if getSetting('contextmenu_replaceitems', isBool=True): Dir.replaceItems = True try: ret = self.root.populating(Dir, self.depth, self.whiteFlag, self.blackFlag) except Qerror as e: Dir.end_of_directory(False) Dir = None warn(self, "Error while populating our directory: %s" % (repr(e))) return False if not self.asList: import xbmcplugin Dir.set_content(self.root.content_type) methods = [ xbmcplugin.SORT_METHOD_UNSORTED, xbmcplugin.SORT_METHOD_LABEL, xbmcplugin.SORT_METHOD_DATE, xbmcplugin.SORT_METHOD_TITLE, xbmcplugin.SORT_METHOD_VIDEO_YEAR, xbmcplugin.SORT_METHOD_GENRE, xbmcplugin.SORT_METHOD_ARTIST, xbmcplugin.SORT_METHOD_ALBUM, xbmcplugin.SORT_METHOD_PLAYLIST_ORDER, xbmcplugin.SORT_METHOD_TRACKNUM, ] [ xbmcplugin.addSortMethod(handle=qobuz.boot.handle, sortMethod=method) for method in methods ] return Dir.end_of_directory()