Use the cached_route() decorator instead of the normal route decorator. This will cache the results of your view for 24 hours.
NOTE: You must be returning a list of plain dictionaries from your view and cannot return plugin.finish(). This is due to a current limitation in the cache which doesn’t keep track of side effects such as a call to plugin.finish. If you need to call plugin.finish() because you are passing non-default arguments, then see the next example which uses plugin.cached().
@plugin.cached_route('/subjects/', options={'url': full_url('subjects')})
def show_subjects(url):
'''Lists available subjects found on the website'''
html = htmlify(url)
subjects = html.findAll('a', {'class': 'subj-links'})
items = [{
'label': subject.div.string.strip(),
'path': plugin.url_for('show_topics', url=full_url(subject['href'])),
} for subject in subjects]
return items
To cache the results of any function call, simply use the cached() decorator. Keep in mind that the function name along with the args and kwargs used to call the function are used as the cache key. If your function depends on any variables in outer scope which could affect the return value, you should pass in those variables explictly as args to ensure a different cache entry is created.
@plugin.cached()
def get_api_data():
return download_data()
You can always create your own persistent storage using get_storage(). The returned storage acts like a dictionary, however it is automatically persisted to disk.
storage = plugin.get_storage('people')
storage['jon'] = {'vehicle': 'bike'}
storage['dave'] # Throws KeyError
storage.get('dave') # Returns None
storage.clear() # Clears all items from the storage
If you are scraping a website that uses pagination, it’s possible to present the same interface in XBMC without having to scrape all of the pages up front. To accomplish this, we are going to create our own Next and Previous list items which go the next and previous page of results respectively. We’re also going to take advantage of a parameter option that gets passed to XBMC, updateListing. If we pass True for this parameter, then every time the use clicks the Next item, the URL won’t be added to history. This enables the ”..” list item to go to the correct parent directory, instead of the previous page.
Some example code:
@plugin.route('/videos/<page>')
def show_videos(page='1'):
page = int(page) # all url params are strings by default
videos, next_page = get_videos(page)
items = [make_item(video) for video in videos]
if next_page:
items.insert(0, {
'label': 'Next >>',
'path': plugin.url_for('show_videos', page=str(page + 1))
})
if page > 1:
items.insert(0, {
'label': '<< Previous',
'path': plugin.url_for('show_videos', page=str(page - 1))
})
return plugin.finish(items, update_listing=True)
The first thing to notice about our view, is that it takes a page number as a URL parameter. We then pass the page number to the API call, get_videos(), to return the correct data based on the current page. Then we create our own previous/next list items depending on the current page. Lastly, we are returning the result of the call to plugin.finish(). By default, when you normally return a list of dicts, plugin.finish() is called for you. However, in this case we need to pass the update_listing=True parameter so we must call it explictly.
Setting update_listing to True, notifies XBMC that we are paginating, and that every new page should not be a new entry in the history.
It is possible to decorate views with more than one route. This becomes useful if you are parsing different URLs that share the same parsing code. In order to unambiguously use url_for(), you need to pass a value for the name keyword argument. When calling url_for, you pass this specified name instead of the name of the actual function.
If the decorated method requires arguments, it is possible to pass these as default keyword arguments to the route decorator. Also, the function itself can use python’s default argument syntax.
@plugin.route('/movies/', name='show_movie_genres')
@plugin.route('/silents/', name='show_silent_genres', options={'path': 'index.php/silent-films-menu'})
@plugin.route('/serials/', name='show_serials', options={'path': 'index.php/serials'})
def show_genres(path='movies'):
pass
Sort methods enable the user to sort a directory listing in different ways. You can see the available sort methods here, or by doing dir(xbmcswift2.SortMethod). The simplest way to add sort methods to your views is to call plugin.finish() with a sort_methods argument and return the result from your view (this is what xbmcswift2 does behind the scenes normally).
@plugin.route('/movies')
def show_movies():
movies = api.get_movies()
items = [create_item(movie) for movie in movies]
return plugin.finish(items, sort_methods=['playlist_order', 'title', 'date'])
See xbmcswift2.Plugin.finish() for more information.
If we need to play an RTMP url, we can use xbmcswift.Plugin.play_video().
@plugin.route('/live/')
def watch_live():
item = {
'label': 'AlJazeera Live',
'path': 'rtmp://aljazeeraflashlivefs.fplive.net:1935/aljazeeraflashlive-live/aljazeera_english_1 live=true',
}
return plugin.play_video(item)
how to use settings
When calling xbmcswift.Plugin.url_for(), any keyword arguments passed that are not required for the specified view function will be added as query string arguments.
A dict of query string parameters can be accessed from plugin.request.args.
Any arguments that are not instances of basestring will attempt to be preserved by pickling them before being encoded into the query string. This functionality isn’t fully tested however, and XBMC does limit the length of URLs. If you need to preserve python objects between function calls, see the Caching patterns.
Modules are meant to be mini-addons. They have some basic functionality that is separate from the main plugin. In order to be used, they must be registered with a plugin.
Creating an add to favorites plugin:
from xbmcswift import Module
playlist = Module(__name__)
@playlist.route('/add/')
def add_to_playlist():
items = [playlist.qs_args]
return playlist._plugin.add_to_playlist(items)
- add to favorites
- report to google form
How to test with nose