def menu_albums(params): # get connection connection = get_connection() if connection == False: return listing = [] menus = { 'albums_newest': { 'name': Addon().get_localized_string(30023), 'thumb': None, 'args': { "ltype": "newest" } }, 'albums_frequent': { 'name': Addon().get_localized_string(30024), 'thumb': None, 'args': { "ltype": "frequent" } }, 'albums_recent': { 'name': Addon().get_localized_string(30025), 'thumb': None, 'args': { "ltype": "recent" } }, 'albums_random': { 'name': Addon().get_localized_string(30026), 'thumb': None, 'args': { "ltype": "random" } } } # Iterate through albums for menu_id in menus: menu = menus.get(menu_id) # image if 'thumb' in menu: thumb = menu.get('thumb') listing.append({ 'label': menu.get('name'), 'thumb': menu.get('thumb'), # Item thumbnail 'fanart': menu.get('thumb'), # Item thumbnail 'url': plugin.get_url(action='list_albums', page=1, query_args=json.dumps(menu.get('args')), menu_id=menu_id) }) # Item label add_directory_items(create_listing(listing, ))
def download_tracks(ids): #popup is fired before, in download_item download_folder = Addon().get_setting('download_folder') if not download_folder: return if not ids: return False #make list if not isinstance(ids, list) or isinstance(ids, tuple): ids = [ids] ids_count = len(ids) #check if empty if ids_count == 0: return False plugin.log('download_tracks IDs:') plugin.log(json.dumps(ids)) # get connection connection = get_connection() if connection is False: return #progress... pc_step = 100 / ids_count pc_progress = 0 ids_parsed = 0 progressdialog = xbmcgui.DialogProgress() progressdialog.create("Downloading tracks...") #Title for id in ids: if (progressdialog.iscanceled()): return False # debug plugin.log('Trying to download track #' + str(id)) # get track infos response = connection.getSong(id) track = response.get('song') plugin.log('Track info :') plugin.log(track) # progress bar pc_progress = ids_parsed * pc_step progressdialog.update(pc_progress, 'Getting track informations...', get_entry_track_label(track)) track_path_relative = track.get("path", None).encode( 'utf8', 'replace') # 'Radiohead/Kid A/Idioteque.mp3' track_path = os.path.join( download_folder, track_path_relative ) # 'C:/users/.../Radiohead/Kid A/Idioteque.mp3' track_directory = os.path.dirname( os.path.abspath(track_path)) # 'C:/users/.../Radiohead/Kid A' #check if file exists if os.path.isfile(track_path): progressdialog.update(pc_progress, 'Track has already been downloaded!') plugin.log("File '%s' already exists" % (id)) else: progressdialog.update(pc_progress, "Downloading track...", track_path) try: #get remote file (file-object like) file_obj = connection.download(id) #create directory if it does not exists if not os.path.exists(track_directory): os.makedirs(track_directory) #create blank file file = open( track_path, 'a' ) #create a new file but don't erase the existing one if it exists #fill blank file shutil.copyfileobj(file_obj, file) file.close() except: popup("Error while downloading track #%s" % (id)) plugin.log("Error while downloading track #%s" % (id)) pass ids_parsed += 1 progressdialog.update(100, "Done !", "Enjoy !") xbmc.sleep(1000) progressdialog.close()
# coding: utf-8 # Created on: 24.03.2016 # Author: Roman Miroshnychenko aka Roman V.M. ([email protected]) import os import re import cPickle as pickle from traceback import format_exc from requests import post from simpleplugin import Addon from torrent_info import get_torrents, OrderedDict, check_proper addon = Addon('plugin.video.rk.tv') yatp_addon = Addon('plugin.video.yatp') filters_file = os.path.join(addon.config_dir, 'filters.pcl') json_rpc_url = 'http://127.0.0.1:{0}/json-rpc'.format(yatp_addon.server_port) def download_torrent(torrent, save_path): """ Download torrent via YATP """ post(json_rpc_url, json={ 'method': 'add_torrent', 'params': { 'torrent': torrent, 'save_path': save_path, 'paused': False }
def test_addon_instance_creation(self): addon = Addon('test.addon') self.assertEqual(addon.id, 'test.addon') self.assertTrue(os.path.exists(os.path.join(cwd, 'config')))
def star_item(params): ids = params.get('ids') #can be single or lists of IDs unstar = params.get('unstar', False) unstar = (unstar) and (unstar != 'None') and (unstar != 'False' ) #TO FIX better statement ? type = params.get('type') sids = albumIds = artistIds = None #validate type if type == 'track': sids = ids elif type == 'artist': artistIds = ids elif type == 'album': albumIds = ids #validate capability if not can_star(type, ids): return #validate IDs if (not sids and not artistIds and not albumIds): return # get connection connection = get_connection() if connection is False: return ### did_action = False try: if unstar: request = connection.unstar(sids, albumIds, artistIds) else: request = connection.star(sids, albumIds, artistIds) if request['status'] == 'ok': did_action = True except: pass ### if did_action: if unstar: message = Addon().get_localized_string(30091) plugin.log('Unstarred %s #%s' % (type, json.dumps(ids))) else: #star message = Addon().get_localized_string(30092) plugin.log('Starred %s #%s' % (type, json.dumps(ids))) stars_cache_update(ids, unstar) popup(message) #TO FIX clear starred lists caches ? #TO FIX refresh current list after star set ? else: if unstar: plugin.log_error('Unable to unstar %s #%s' % (type, json.dumps(ids))) else: plugin.log_error('Unable to star %s #%s' % (type, json.dumps(ids))) return did_action
# coding: utf-8 # Module: json_requests # Created on: 17.07.2015 # Author: Roman Miroshnychenko aka Roman V.M. ([email protected]) # Licence: GPL v.3: http://www.gnu.org/copyleft/gpl.html """ JSON-RPC requests to the Torrent Server """ from requests import post from simpleplugin import Addon addon = Addon('plugin.video.yatp') json_rpc_url = 'http://127.0.0.1:{0}/json-rpc'.format(addon.server_port) def _request(data): """ Send JSON-RPC request :param data: JSON request as dict :return: """ reply = post(json_rpc_url, json=data).json() try: return reply['result'] except KeyError: raise RuntimeError('JSON-RPC returned error:\n{0}'.format( reply['error']))
def menu_albums(params): # get connection connection = get_connection() if connection is False: return listing = [] menus = { 'albums_newest': { 'name': Addon().get_localized_string(30023), 'thumb': None, 'args': { "ltype": "newest" } }, 'albums_frequent': { 'name': Addon().get_localized_string(30024), 'thumb': None, 'args': { "ltype": "frequent" } }, 'albums_recent': { 'name': Addon().get_localized_string(30025), 'thumb': None, 'args': { "ltype": "recent" } }, 'albums_random': { 'name': Addon().get_localized_string(30026), 'thumb': None, 'args': { "ltype": "random" } } } # Iterate through categories for menu_id in menus: menu = menus.get(menu_id) # image if 'thumb' in menu: thumb = menu.get('thumb') listing.append({ 'label': menu.get('name'), 'thumb': menu.get('thumb'), # Item thumbnail 'fanart': menu.get('thumb'), # Item thumbnail 'url': plugin.get_url(action='list_albums', page=1, query_args=json.dumps(menu.get('args')), menu_id=menu_id) }) # Item label return plugin.create_listing( listing, #succeeded = True, #if False Kodi won’t open a new listing and stays on the current level. #update_listing = False, #if True, Kodi won’t open a sub-listing but refresh the current one. #cache_to_disk = True, #cache this view to disk. #sort_methods = None, #he list of integer constants representing virtual folder sort methods. #view_mode = None, #a numeric code for a skin view mode. View mode codes are different in different skins except for 50 (basic listing). #content = None #string - current plugin content, e.g. ‘movies’ or ‘episodes’. )
def list_tracks(params): menu_id = params.get('menu_id') listing = [] #query query_args = {} try: query_args_json = params['query_args'] query_args = json.loads(query_args_json) except: pass #size tracks_per_page = int(Addon().get_setting('tracks_per_page')) query_args["size"] = tracks_per_page #offset offset = int(params.get('page', 1)) - 1 if offset > 0: query_args["offset"] = offset * tracks_per_page #debug query_args_json = json.dumps(query_args) plugin.log('list_tracks with args:' + query_args_json) # get connection connection = get_connection() if connection is False: return # Album if 'album_id' in params: generator = connection.walk_album(params['album_id']) # Playlist elif 'playlist_id' in params: generator = connection.walk_playlist(params['playlist_id']) ##########TO FIX # tracknumber = 0 # for item in items: # tracknumber += 1 # items[item]['tracknumber'] = tracknumber # Top tracks elif menu_id == 'tracks_top': generator = connection.walk_tracks_top(query_args['artist']) # Starred elif menu_id == 'tracks_starred': generator = connection.walk_tracks_starred() # Random elif menu_id == 'tracks_random': generator = connection.walk_tracks_random(**query_args) #make a list out of the generator so we can iterate it several times items = list(generator) #check if there is only one artist for this album (and then hide it) artists = [item.get('artist', None) for item in items] if len(artists) <= 1: params['hide_artist'] = True #update stars if menu_id == 'tracks_starred': ids_list = [item.get('id') for item in items] stars_cache_update(ids_list) # Iterate through items key = 0 for item in items: track = get_entry_track(item, params) listing.append(track) key += 1 ######TO FIX # Pagination if we've not reached the end of the list # if type(items) != type(True): TO FIX #link_next = navigate_next(params) #listing.append(link_next) return plugin.create_listing(listing, cache_to_disk=False, sort_methods=get_sort_methods( 'tracks', params), view_mode=Addon().get_setting('view_song'), content='songs')
def download_media(params): from slugify import slugify #validate path download_folder = Addon().get_setting('download_folder') if not download_folder: common.popup( "Veuillez configurer un répertoire de téléchargement dans les paramètres du plugin" ) common.plugin.log_error("download_media: No directory set") return False #get media details mid = int(params.get('media_id', None)) media = api.get_media_details(mid) media_title = media.get('title') media_subtitle = media.get('subtitle') #media URL stream_node = media.get('url_streaming') if stream_node: media_url = stream_node.get('url', '').encode('utf-8').strip() if not media_url: common.plugin.log_error("unable to get a downloadable stream URL.") common.popup("Impossible de trouver un flux media téléchargeable") return False #filename remote_path = urlparse.urlparse(media_url).path #full path remote_file = media_url.rsplit('/', 1)[-1] #only what's after the last '/' remote_filename = os.path.splitext(remote_file)[0] remote_ext = os.path.splitext(remote_file)[1] if media_subtitle: file_title = "%s - %s" % (media_title, media_subtitle) else: file_title = media_title file_title = slugify(file_title) file_name = file_title + remote_ext file_path = xbmc.makeLegalFilename(os.path.join(download_folder, file_name)) file_path = urllib2.unquote(file_path) common.plugin.log("download_media #{0} - filename:{1} - from:{2}".format( mid, file_name, media_url)) # Overwrite existing file? if os.path.isfile(file_path): do_override = common.ask( 'Le fichier [B]%s[/B] existe déjà. Écraser ?' % (file_name)) if not do_override: return # Download size = 1024 * 1024 start = time.clock() f = open(file_path, 'wb') u = urllib2.urlopen(media_url) bytes_so_far = 0 error = False # Get file size try: total_size = u.info().getheader('Content-Length').strip() total_size = int(total_size) except AttributeError: total_size = 0 # a response doesn't always include the "Content-Length" header if total_size < 1: common.popup( "Erreur lors du téléchargement: Impossible de déterminer la taille du fichier." ) return False # Progress dialog progressdialog = xbmcgui.DialogProgress() progressdialog.create("Téléchargement du média...") #Title while True: # Aborded by user if progressdialog.iscanceled(): error = True break try: buff = u.read(size) if not buff: break else: bytes_so_far += len(buff) f.write(buff) percent = min(100 * bytes_so_far / total_size, 100) speed_str = str( int((bytes_so_far / 1024) / (time.clock() - start))) + ' KB/s' percent_str = str(percent) + '%' progressdialog.update(percent, file_name, percent_str, speed_str) except Exception, e: error = True break
def media_to_kodi_item(media): #common.plugin.log(json.dumps(media)) context_actions = [] #context menu actions #MEDIA mid = media.get('id') media_type = media.get('type') is_livevideo = (media_type == 'livevideo') kodi_type = utils.get_kodi_media_type(media) has_drm = media.get('drm') #build label title = media.get('title', '').encode('utf-8').strip() subtitle = media.get('subtitle', '').encode('utf-8').strip() channel_node = media.get('channel') if channel_node: channel = channel_node.get('label', '').encode('utf-8').strip() title = "[B]{0}[/B] - {1}".format(channel, title) if subtitle: title = "{0} - [I]{1}[/I]".format(title, subtitle) #Add 'DRM' prefix if has_drm and Addon().get_setting('drm_title_prefix'): title = "[COLOR red]DRM[/COLOR] " + title #live video if is_livevideo: if utils.media_is_streaming(media): title += ' [COLOR yellow]direct[/COLOR]' else: stream_start = utils.get_stream_start_date_formatted( media.get('start_date', None)) title += ' [COLOR red]' + stream_start + '[/COLOR]' #MEDIA INFOS #http://romanvm.github.io/script.module.simpleplugin/_actions/vf.html #http://kodi.wiki/view/InfoLabels#ListItem infos = {} info_details = { #'date': utils.datetime_W3C_to_kodi(media.get('date_publish_from')), #file date 'count': media.get( 'id' ), #can be used to store an id for later, or for sorting purposes 'duration': utils.get_kodi_media_duration(media), } if kodi_type == 'video': video_infos = { 'aired': utils.datetime_W3C_to_kodi(media.get('date_publish_from')), 'genre': media.get('category', {}).get('label', '').encode('utf-8'), 'plot': media.get('description', '').encode('utf-8'), #Long Description 'plotoutline': media.get('description', '').encode('utf-8'), #Short Description } #parse args info_details = utils.parse_dict_args(info_details, video_infos) infos = {'video': info_details} elif kodi_type == 'music': music_infos = { 'genre': media.get('category', {}).get('label').encode('utf-8'), } #parse args info_details = utils.parse_dict_args(info_details, music_infos) infos = {'music': info_details} #download context menu if not is_livevideo and not has_drm: download_action = ( 'Télécharger', 'XBMC.RunPlugin(%s)' % common.plugin.get_url(action='download_media', media_id=mid)) context_actions.append(download_action) li = { 'label': title, 'label2': subtitle, 'thumb': media.get('images', {}).get('cover', {}).get('1x1', {}).get('370x370', '').encode('utf-8').strip(), 'fanart': media.get('images', {}).get('illustration', {}).get('16x9', {}).get('1920x1080', '').encode('utf-8').strip(), 'url': common.plugin.get_url(action='play_media', media_id=mid, livevideo=is_livevideo), 'info': infos, 'is_playable': True, 'context_menu': context_actions } return li
def root(params): # get connection connection = get_connection() if connection == False: return listing = [] menus = { 'folders': { 'name': Addon().get_localized_string(30038), 'callback': 'browse_folders', 'thumb': None }, 'library': { 'name': Addon().get_localized_string(30019), 'callback': 'browse_library', 'thumb': None }, 'albums': { 'name': Addon().get_localized_string(30020), 'callback': 'menu_albums', 'thumb': None }, 'tracks': { 'name': Addon().get_localized_string(30021), 'callback': 'menu_tracks', 'thumb': None }, 'playlists': { 'name': Addon().get_localized_string(30022), 'callback': 'list_playlists', 'thumb': None }, 'search': { 'name': Addon().get_localized_string(30039), 'callback': 'search', 'thumb': None }, } # Iterate through categories for mid in menus: # image if 'thumb' in menus[mid]: thumb = menus[mid]['thumb'] listing.append({ 'label': menus[mid]['name'], 'thumb': thumb, # Item thumbnail 'fanart': thumb, # Item thumbnail 'url': plugin.get_url(action=menus[mid]['callback'], menu_id=mid) }) # Item label add_directory_items(create_listing( listing, sort_methods=None, ))
def list_tracks(params): menu_id = params.get('menu_id') listing = [] #query query_args = {} try: query_args_json = params['query_args'] query_args = json.loads(query_args_json) except: pass #size tracks_per_page = int(Addon().get_setting('tracks_per_page')) query_args["size"] = tracks_per_page #offset offset = int(params.get('page', 1)) - 1 if offset > 0: query_args["offset"] = offset * tracks_per_page #debug query_args_json = json.dumps(query_args) plugin.log('list_tracks with args:' + query_args_json) # get connection connection = get_connection() if connection == False: return # Album if 'album_id' in params: generator = walk_album(params['album_id']) # Playlist elif 'playlist_id' in params: generator = walk_playlist(params['playlist_id']) #TO FIX #tracknumber = 0 #for item in items: # tracknumber += 1 # items[item]['tracknumber'] = tracknumber # Starred elif menu_id == 'tracks_starred': generator = walk_tracks_starred() # Random elif menu_id == 'tracks_random': generator = walk_tracks_random(**query_args) # Filters #else: #TO WORK #make a list out of the generator so we can iterate it several times items = list(generator) #check if there==only one artist for this album (and then hide it) artists = [item.get('artist', None) for item in items] if len(artists) <= 1: params['hide_artist'] = True #update stars if menu_id == 'tracks_starred': ids_list = [item.get('id') for item in items] #stars_local_update(ids_list) cache_refresh(True) # Iterate through items key = 0 for item in items: track = get_entry_track(item, params) listing.append(track) key += 1 # Root menu #link_root = navigate_root() #listing.append(link_root) # Pagination if we've not reached the end of the lsit # if type(items) != type(True): TO FIX #link_next = navigate_next(params) #listing.append(link_next) add_directory_items( create_listing( listing, sort_methods=get_sort_methods('tracks', params), content= 'songs' #string - current plugin content, e.g. ‘movies’ or ‘episodes’. ))
def list_albums(params): """ List albums from the library (ID3 tags) """ listing = [] # get connection connection = get_connection() if connection == False: return #query query_args = {} try: query_args_json = params['query_args'] query_args = json.loads(query_args_json) except: pass #size albums_per_page = int(Addon().get_setting('albums_per_page')) query_args["size"] = albums_per_page #offset offset = int(params.get('page', 1)) - 1 if offset > 0: query_args["offset"] = offset * albums_per_page #debug query_args_json = json.dumps(query_args) plugin.log('list_albums with args:' + query_args_json) #Get items if 'artist_id' in params: generator = walk_artist(params.get('artist_id')) else: generator = walk_albums(**query_args) #make a list out of the generator so we can iterate it several times items = list(generator) #check if there==only one artist for this album (and then hide it) artists = [item.get('artist', None) for item in items] if len(artists) <= 1: params['hide_artist'] = True # Iterate through items for item in items: album = get_entry_album(item, params) listing.append(album) # Root menu link_root = navigate_root() listing.append(link_root) if not 'artist_id' in params: # Pagination if we've not reached the end of the lsit # if type(items) != type(True): TO FIX link_next = navigate_next(params) listing.append(link_next) add_directory_items( create_listing( listing, cache_to_disk=True, #cache this view to disk. sort_methods=get_sort_methods('albums', params), content= 'albums' #string - current plugin content, e.g. ‘movies’ or ‘episodes’. ))
def list_directory(params): connection = get_connection() if connection is False: return listing = [] # Get items id = params.get('id') items = connection.walk_directory_nonrecursive(id) dircount = 0 songcount = 0 # Iterate through items for item in items: genre_setting = item.get('genre') if ( Addon().get_setting('view_genre')) else None # Is a directory if (item.get('isDir') == True): dircount += 1 entry = { 'label': item.get('title'), 'url': plugin.get_url(action='list_directory', id=item.get('id'), menu_id=params.get('menu_id')), 'thumb': connection.getCoverArtUrl(item.get('coverArt')), 'icon': 'DefaultMusicAlbums.png', 'info': { 'music': { 'mediatype': 'album', 'year': item.get('year'), 'artist': item.get('artist'), 'rating': item.get('starred'), 'genre': genre_setting } } } listing.append(entry) # Songs or a combination of both else: songcount += 1 entry = get_entry_track(item, params) listing.append(entry) # Set view, sort and content if (dircount == 0): view_mode_setting = Addon().get_setting('view_song') sort_mode = get_sort_methods('tracks', params) content_mode = 'songs' if (songcount == 0): view_mode_setting = Addon().get_setting('view_album') sort_mode = get_sort_methods('albums', params) content_mode = 'albums' else: view_mode_setting = Addon().get_setting('view_song') sort_mode = get_sort_methods('tracks', params) content_mode = 'songs' # Only show in artist directory, maybe check results first? if (songcount == 0) and params.get('menu_id') == 'folders': topsongs = { 'label': item.get('artist') + '\'s top songs', 'url': plugin.get_url( action='list_tracks', query_args=json.dumps({ 'artist': item.get('artist'), 'count': Addon().get_setting('tracks_per_page'), }), menu_id='tracks_top', ), 'thumb': 'DefaultMusicTop100.png', 'info': { 'music': { 'mediatype': 'album', 'artist': item.get('artist'), } } } listing.append(topsongs) """ artist_radio = { 'label': item.get('artist') + ' radio', 'url': plugin.get_url( action= 'list_tracks', id= item.get('id'), menu_id= 'artist_radio' ), 'thumb': 'DefaultMusicCompilations.png', 'info': { 'music': { 'mediatype': 'album', 'artist': item.get('artist'), } } } listing.append(artist_radio) """ return plugin.create_listing( listing, cache_to_disk=True, sort_methods=sort_mode, view_mode=view_mode_setting, content=content_mode, )
def root(params): # get connection connection = get_connection() if connection is False: return listing = [] menus = { 'folders': { 'name': Addon().get_localized_string(30038), 'callback': 'browse_folders', 'thumb': None }, 'library': { 'name': Addon().get_localized_string(30019), 'callback': 'browse_library', 'thumb': None }, 'albums': { 'name': Addon().get_localized_string(30020), 'callback': 'menu_albums', 'thumb': None }, 'tracks': { 'name': Addon().get_localized_string(30021), 'callback': 'menu_tracks', 'thumb': None }, 'playlists': { 'name': Addon().get_localized_string(30022), 'callback': 'list_playlists', 'thumb': None }, 'search': { 'name': Addon().get_localized_string(30039), 'callback': 'search', 'thumb': None }, } # Iterate through categories for mid in menus: # image if 'thumb' in menus[mid]: thumb = menus[mid]['thumb'] listing.append({ 'label': menus[mid]['name'], 'thumb': thumb, # Item thumbnail 'fanart': thumb, # Item thumbnail 'url': plugin.get_url(action=menus[mid]['callback'], menu_id=mid) }) # Item label return plugin.create_listing( listing, #succeeded = True, #if False Kodi won’t open a new listing and stays on the current level. #update_listing = False, #if True, Kodi won’t open a sub-listing but refresh the current one. #cache_to_disk = True, #cache this view to disk. sort_methods= None, #he list of integer constants representing virtual folder sort methods. #view_mode = None, #a numeric code for a skin view mode. View mode codes are different in different skins except for 50 (basic listing). #content = None #string - current plugin content, e.g. ‘movies’ or ‘episodes’. )
def list_albums(params): #List albums from the library (ID3 tags) listing = [] connection = get_connection() if connection is False: return #query query_args = {} try: query_args_json = params['query_args'] query_args = json.loads(query_args_json) except: pass #Size, defined in settings albums_per_page = int(Addon().get_setting('albums_per_page')) query_args["size"] = albums_per_page #offset offset = int(params.get('page', 1)) - 1 if offset > 0: query_args["offset"] = offset * albums_per_page #debug query_args_json = json.dumps(query_args) plugin.log('list_albums with args:' + query_args_json) #Get items if 'artist_id' in params: generator = connection.walk_artist(params.get('artist_id')) else: generator = connection.walk_albums(**query_args) #make a list out of the generator so we can iterate it several times items = list(generator) #coverart first in random album list if setting is true if Addon().get_setting('coverart_first') and params.get( 'menu_id') == 'albums_random': items = coverart_first(items) #check if there is only one artist for this album (and then hide it) artists = [item.get('artist', None) for item in items] if len(artists) <= 1: params['hide_artist'] = True # Iterate through items for item in items: album = get_entry_album(item, params) listing.append(album) if not 'artist_id' in params: ####TO FIX Pagination if we've not reached the end of the lsit ########### if type(items) != type(True): TO FIX link_next = navigate_next(params) listing.append(link_next) return plugin.create_listing(listing, cache_to_disk=True, sort_methods=get_sort_methods( 'albums', params), view_mode=Addon().get_setting('view_album'), content='albums')
xbmcaddon.Addon("plugin.audio.subsonic").getAddonInfo("path"), "lib"))) import libsonic_extra #TO FIX - we should get rid of this and use only libsonic from simpleplugin import Plugin from simpleplugin import Addon # Create plugin instance plugin = Plugin() # initialize_gettext #_ = plugin.initialize_gettext() connection = None cachetime = int(Addon().get_setting('cachetime')) def popup(text, time=5000, image=None): title = plugin.addon.getAddonInfo('name') icon = plugin.addon.getAddonInfo('icon') xbmc.executebuiltin('Notification(%s, %s, %d, %s)' % (title, text, time, icon)) def get_connection(): global connection if connection is None: connected = False
def get_search_results(params): # get connection connection = get_connection() if connection is False: return query_args = json.loads(params['query_args']) maxitems = int( Addon().get_setting('tracks_per_page' if query_args['type'] == "track" else 'albums_per_page')) # Get items # This uses the same maximum amount for all types, but since we only use the one we're interested in that's ok. items = connection.search2(query=query_args['query'], artistCount=maxitems, artistOffset=maxitems * params['page'], albumCount=maxitems, albumOffset=maxitems * params['page'], songCount=maxitems, songOffset=maxitems * params['page'], musicFolderId=None) itemfunc = { "get_entry_artist": get_entry_artist, "get_entry_album": get_entry_album, "get_entry_track": get_entry_track, } listing = [] # Maybe we should refactor "track" functions to "song" some day to stay in line with subsonic API lingo type = "song" if query_args['type'] == "track" else query_args['type'] # Iterate through items if type in items['searchResult2']: for item in items.get('searchResult2').get(type): entry = itemfunc['get_entry_{0}'.format(query_args['type'])]( item, params) listing.append(entry) prev = navigate_prev(params) if prev: listing.append(prev) maxitems += 1 # TODO: check that there are actually more results available if len(listing) == maxitems: listing.append(navigate_next(params)) else: d = xbmcgui.Dialog().ok( Addon().get_localized_string(30062), # Search Addon().get_localized_string(30088) # No items found ) return if query_args['type'] == "track": content = 'songs' view_mode_setting = Addon().get_setting('view_song') elif query_args['type'] == "album": content = 'albums' view_mode_setting = Addon().get_setting('view_album') else: content = 'artists' view_mode_setting = Addon().get_setting('view_artist') return plugin.create_listing( listing, update_listing=not params.get('firstEntry', False), view_mode=view_mode_setting, content=content, )
def list_albums(params): listing = [] # get connection connection = get_connection() if connection is False: return #query query_args = {} try: query_args_json = params['query_args'] query_args = json.loads(query_args_json) except: pass #size albums_per_page = int(Addon().get_setting('albums_per_page')) query_args["size"] = albums_per_page #offset offset = int(params.get('page', 1)) - 1 if offset > 0: query_args["offset"] = offset * albums_per_page #debug query_args_json = json.dumps(query_args) plugin.log('list_albums with args:' + query_args_json) #Get items if 'artist_id' in params: generator = connection.walk_artist(params.get('artist_id')) else: generator = connection.walk_albums(**query_args) #make a list out of the generator so we can iterate it several times items = list(generator) #check if there is only one artist for this album (and then hide it) artists = [item.get('artist', None) for item in items] if len(artists) <= 1: params['hide_artist'] = True # Iterate through items for item in items: album = get_entry_album(item, params) listing.append(album) # Root menu link_root = navigate_root() listing.append(link_root) if not 'artist_id' in params: # Pagination if we've not reached the end of the lsit # if type(items) != type(True): TO FIX link_next = navigate_next(params) listing.append(link_next) return plugin.create_listing( listing, #succeeded = True, #if False Kodi won’t open a new listing and stays on the current level. #update_listing = False, #if True, Kodi won’t open a sub-listing but refresh the current one. cache_to_disk=True, #cache this view to disk. sort_methods=get_sort_methods('albums', params), #view_mode = None, #a numeric code for a skin view mode. View mode codes are different in different skins except for 50 (basic listing). content= 'albums' #string - current plugin content, e.g. ‘movies’ or ‘episodes’. )
def root(params): # get connection connection = get_connection() if connection is False: return listing = [] if Addon().get_setting('merge_folders') == True: mediafolders = Addon().get_localized_string(30060) thumbnail = 'DefaultMusicArtists.png' else: mediafolders = Addon().get_localized_string(30059) thumbnail = None menus = { 'folders': { 'name': mediafolders, 'callback': 'browse_folders', 'thumb': thumbnail, 'fanart': None, }, 'playlists': { 'name': Addon().get_localized_string(30061), 'callback': 'list_playlists', 'thumb': 'DefaultMusicPlaylists.png', 'fanart': None, }, 'search': { 'name': Addon().get_localized_string(30062), 'callback': 'search', 'thumb': 'DefaultAddonsSearch.png', 'fanart': None, }, } # Iterate through categories for mid in menus: if 'thumb' in menus[mid]: thumb = menus[mid]['thumb'] listing.append({ 'label': menus[mid]['name'], 'thumb': thumb, 'fanart': None, 'url': plugin.get_url(action=menus[mid]['callback'], menu_id=mid) }) menus = { 'albums_newest': { 'name': Addon().get_localized_string(30070), 'thumb': 'DefaultMusicRecentlyAdded.png', 'args': { "ltype": "newest" }, 'fanart': None, }, 'albums_frequent': { 'name': Addon().get_localized_string(30071), 'thumb': 'DefaultMusicTop100Albums.png', 'args': { "ltype": "frequent" }, 'fanart': None, }, 'albums_recent': { 'name': Addon().get_localized_string(30072), 'thumb': 'DefaultMusicRecentlyPlayed.png', 'args': { "ltype": "recent" }, 'fanart': None, }, 'albums_random': { 'name': Addon().get_localized_string(30073), 'thumb': 'DefaultMusicAlbums.png', 'args': { "ltype": "random" }, 'fanart': None, } } # Iterate through albums for menu_id in menus: menu = menus.get(menu_id) if 'thumb' in menu: thumb = menu.get('thumb') listing.append({ 'label': menu.get('name'), 'thumb': menu.get('thumb'), 'url': plugin.get_url(action='list_albums', page=1, query_args=json.dumps(menu.get('args')), menu_id=menu_id) }) menus = { 'tracks_starred': { 'name': Addon().get_localized_string(30080), 'thumb': 'DefaultMusicTop100Songs.png', 'fanart': None, }, 'tracks_random': { 'name': Addon().get_localized_string(30081), 'thumb': 'DefaultMusicSongs.png', 'fanart': None, } } # Iterate through tracks for menu_id in menus: menu = menus.get(menu_id) if 'thumb' in menu: thumb = menu.get('thumb') listing.append({ 'label': menu.get('name'), 'thumb': menu.get('thumb'), 'url': plugin.get_url(action='list_tracks', menu_id=menu_id) }) return plugin.create_listing( listing, cache_to_disk=True, sort_methods=None, view_mode=None, content='mixed', )
def list_tracks(params): menu_id = params.get('menu_id') listing = [] #query query_args = {} try: query_args_json = params['query_args'] query_args = json.loads(query_args_json) except: pass #size tracks_per_page = int(Addon().get_setting('tracks_per_page')) query_args["size"] = tracks_per_page #offset offset = int(params.get('page', 1)) - 1 if offset > 0: query_args["offset"] = offset * tracks_per_page #debug query_args_json = json.dumps(query_args) plugin.log('list_tracks with args:' + query_args_json) # get connection connection = get_connection() if connection is False: return # Album if 'album_id' in params: generator = connection.walk_album(params['album_id']) # Playlist elif 'playlist_id' in params: generator = connection.walk_playlist(params['playlist_id']) #TO FIX #tracknumber = 0 #for item in items: # tracknumber += 1 # items[item]['tracknumber'] = tracknumber # Starred # Starred elif menu_id == 'tracks_starred': generator = connection.walk_tracks_starred() # Random elif menu_id == 'tracks_random': generator = connection.walk_tracks_random(**query_args) # Filters #else: #TO WORK #make a list out of the generator so we can iterate it several times items = list(generator) #check if there is only one artist for this album (and then hide it) artists = [item.get('artist', None) for item in items] if len(artists) <= 1: params['hide_artist'] = True #update stars if menu_id == 'tracks_starred': ids_list = [item.get('id') for item in items] stars_cache_update(ids_list) # Iterate through items key = 0 for item in items: track = get_entry_track(item, params) listing.append(track) key += 1 # Root menu #link_root = navigate_root() #listing.append(link_root) # Pagination if we've not reached the end of the lsit # if type(items) != type(True): TO FIX #link_next = navigate_next(params) #listing.append(link_next) return plugin.create_listing( listing, #succeeded = True, #if False Kodi won’t open a new listing and stays on the current level. #update_listing = False, #if True, Kodi won’t open a sub-listing but refresh the current one. #cache_to_disk = True, #cache this view to disk. sort_methods=get_sort_methods('tracks', params), #view_mode = None, #a numeric code for a skin view mode. View mode codes are different in different skins except for 50 (basic listing). content= 'songs' #string - current plugin content, e.g. ‘movies’ or ‘episodes’. )
def test_gettext_initialized(self): addon = Addon() _ = addon.initialize_gettext() self.assertEqual(_('Hello World!'), u'Привет, мир!') self.assertEqual(_('I love you.'), u'Я тебя люблю.') self.assertRaises(SimplePluginError, _, 'Foo Bar')
def navigate_root(): return { 'label': Addon().get_localized_string(30030), 'url': plugin.get_url(action='root') }
# Author: Roman V.M. # Created on: 12.05.2015 # License: GPL v.3 https://www.gnu.org/copyleft/gpl.html """ Buffering torrent """ import os from urllib import quote import xbmc import xbmcgui import json_requests as jsonrq from simpleplugin import Addon addon = Addon() _ = addon.initialize_gettext() media_url = 'http://127.0.0.1:{0}/stream/'.format(addon.server_port) MEDIAFILES = ('.avi', '.mkv', '.mp4', '.ts', '.m2ts', '.mov', '.m4v', '.wmv') def get_videofiles(files): """ Get a sorted list of videofiles from all files in a torrent :param files: :return: the sorted list of 3-item tuples (file_index, file_name, file_size) """ videofiles = [] for file_index, file_ in enumerate(files): if os.path.splitext(file_[0].lower())[1] in MEDIAFILES:
def context_action_download(type, id): label = Addon().get_localized_string(30095) return (label, 'XBMC.RunPlugin(%s)' % plugin.get_url(action='download_item', type=type, id=id))
def test_gettext_not_initialized(self): addon = Addon() self.assertRaises(SimplePluginError, addon.gettext, 'Hello World!')
def download_media(params): from slugify import slugify title= params.get('title'); url= params.get('url'); #validate path download_folder = Addon().get_setting('download_folder') if not download_folder: common.popup("Veuillez configurer un répertoire de téléchargement dans les paramètres du plugin") common.plugin.log_error("download_media: No directory set") return False if not url: common.popup("Impossible de télécharger ce média") plugin.log_error("download_media: Missing URL") return False #filename remote_path = urlparse.urlparse(url).path #full path remote_file = url.rsplit('/', 1)[-1] #only what's after the last '/' remote_filename = os.path.splitext(remote_file)[0] remote_ext = os.path.splitext(remote_file)[1] file_name = slugify(title) + remote_ext file_path = xbmc.makeLegalFilename(os.path.join(download_folder, file_name)) file_path = urllib2.unquote(file_path) common.plugin.log('download_media - filename: %s from %s' % (file_name,url)) # Overwrite existing file? if os.path.isfile(file_path): do_override = common.ask('Le fichier [B]%s[/B] existe déjà. Écraser ?' % (file_name)) if not do_override: return # Download size = 1024 * 1024 start = time.clock() f = open(file_path, 'wb') u = urllib2.urlopen(url) bytes_so_far = 0 error = False # Get file size try: total_size = u.info().getheader('Content-Length').strip() total_size = int(total_size) except AttributeError: total_size = 0 # a response doesn't always include the "Content-Length" header if total_size < 1: common.popup("Erreur lors du téléchargement: Impossible de déterminer la taille du fichier.") return False # Progress dialog progressdialog = xbmcgui.DialogProgress() progressdialog.create("Téléchargement du média...") #Title while True: # Aborded by user if (progressdialog.iscanceled()): error = True break try: buff = u.read(size) if not buff: break else: bytes_so_far += len(buff) f.write(buff) percent = min(100 * bytes_so_far / total_size, 100) speed_str = str(int((bytes_so_far / 1024) / (time.clock() - start))) + ' KB/s' percent_str = str(percent) + '%' progressdialog.update(percent, file_name,percent_str,speed_str) except Exception, e: error = True break