User:Pline: Difference between revisions

From Official Kodi Wiki
Jump to navigation Jump to search
(Blanking this, since I moved it to Audio/Video tutorial)
 
Line 1: Line 1:
This is a staging area for some rewrites to the Python add-on documentation. Ok, let's go!


= Before we get started =
{{See also|Add-on structure}}
The first step to making an add-on is to put the basic structure in place. Make sure your directory is properly named, e.g. <code>plugin.video.my-addon</code>, and that you have a properly-constructed <code>[[addon.xml]]</code> file. Once these are done, you can get started writing the actual code for your add-on!
= Hello, World! =
The simplest form of Python add-on is one that gets run, adds some list items, and exits to let XBMC take over the navigation; people who have written server-side code for the web should be familiar with how this works. (More complex add-ons can process user input in real-time, but we'll discuss those later.) Let's start by looking at an extremely basic example script:
<source lang="python">
import sys
import xbmcgui
import xbmcplugin
addon_id = int(sys.argv[1])
xbmcplugin.setContent(addon_id, 'movies')
url = 'http://localhost/some_video.mkv'
li = xbmcgui.ListItem('My First Video!', iconImage='DefaultVideo.png')
li.setInfo(type='video')
xbmcplugin.addDirectoryItem(handle=addon_id, url=url, listitem=li)
xbmcplugin.endOfDirectory(addon_id)
</source>
While not particularly exciting, this shows the minimal amount of code you need to get an XBMC add-on up and running in Python. First, we get the add-on's process handle from <code>sys.argv[1]</code>. We need this to tell XBMC who we are. Next, we tell XBMC that we're going to show a list of <code>'movies'</code>. There are other options, like <code>'audio'</code> or <code>'episodes'</code>; these just change some details of how XBMC presents your add-on.
The most important part is that we create an <code>xbmcgui.ListItem</code> with the name and icon we want (<code>'DefaultVideo.png'</code> comes from the XBMC skin), set it to be a video item, and then add it to the directory. Once we're done adding items, we need to be sure to call <code>xbmcplugin.endOfDirectory</code> to let XBMC know we're done!
= Navigating between pages =
While the first example might be enough for extremely simple add-ons, most add-ons will want to have the ability to navigate between different pages. Most add-ons are designed to imitate a folder hierarchy where opening folder items shows a different list of items, and going "up" returns you to the parent folder.
== Retrieving arguments ==
As we saw in the first example, XBMC passes some arguments to us via <code>sys.argv</code>. This is important, since it's what will let us tailor the output on the add-on based on user input. Remember, much like a web site, each folder (or page) in an XBMC add-on is the result of a separate invocation of our script. The arguments available to us are:
{| class="wikitable"
! Index !! Description
|-
| 0 || The base URL of your add-on, e.g. <code>'plugin://plugin.video.myaddon/'</code>
|-
| 1 || The process handle for this add-on, as a numeric string
|-
| 2 || The query string passed to your add-on, e.g. <code>'?foo=bar&baz=quux'</code>
|}
Of particular interest is <code>sys.argv[2]</code>, which is what we'll generally use to show different things in the add-on.
===  Multiple content types ===
{{See also|Addon.xml#<provides> element}}
If your add-on provides multiple content types, e.g. <code>audio</code> and <code>video</code>, when the user invokes your add-on from the add-on list, XBMC will add a <code>content_type</code> parameter to your add-on's query string. For example: <code>'?content_type=audio'</code>. This will allow you to modify the output depending on what context your add-on was invoked in.
== Passing arguments ==
Now that we know how to retrieve the arguments passed to our add-on, we'll have to actually pass some along to it. Generally speaking, this involves creating a folder <code>ListItem</code> with a URL back to your add-on; then the next invocation of the add-on will parse those arguments and do something with them. Let's look at another brief example that adds some folders to let the user navigate between different pages of the add-on:
<source lang="python">
import sys
import urllib
import urlparse
import xbmcgui
import xbmcplugin
base_url = sys.argv[0]
addon_id = int(sys.argv[1])
args = urlparse.parse_qs(sys.argv[2][1:])
xbmcplugin.setContent(addon_id, 'movies')
def build_url(query):
    return base_url + '?' + urllib.encode(query)
mode = args.get('mode', None)
if mode is None:
    url = build_url({'mode': 'folder', 'foldername': 'Folder One'})
    li = xbmcgui.ListItem('Folder One', iconImage='DefaultFolder.png')
    xbmcplugin.addDirectoryItem(handle=addon_id, url=url,
                                listitem=li, isFolder=True)
    url = build_url({'mode': 'folder', 'foldername': 'Folder Two'})
    li = xbmcgui.ListItem('Folder Two', iconImage='DefaultFolder.png')
    xbmcplugin.addDirectoryItem(handle=addon_id, url=url,
                                listitem=li, isFolder=True)
    xbmcplugin.endOfDirectory(addon_id)
elif mode[0] == 'folder':
    foldername = args['foldername'][0]
    url = 'http://localhost/some_video.mkv'
    li = xbmcgui.ListItem(foldername + ' Video', iconImage='DefaultVideo.png')
    li.setInfo(type='video')
    xbmcplugin.addDirectoryItem(handle=addon_id, url=url, listitem=li)
    xbmcplugin.endOfDirectory(addon_id)
</source>
As you can see, many parts of our code are very similar to the first example. There are a few important additions, however. First, we want to respond to the arguments supplied to our script, so we parse the query string with:
<source lang="python">
urlparse.parse_qs(sys.argv[2][1:])
</source>
We skip the first character, since it's always <code>'?'</code>. This will give us a <code>dict</code> of <code>list</code>s; for example, <code>'?foo=bar&foo=baz&quux=spam'</code> would be converted to <code>{'foo': ['bar', 'baz'], 'quux': ['spam']}</code>. With this information, we can tailor the output of our add-on to the supplied arguments.
We also need to be able to create links back to our add-on in order to display related pages (e.g. subfolders). We can do this by creating an <code>xbmc.ListItem</code>, passing <code>isFolder=True</code>, and setting the URL of the item to point back to our add-on. We create the URL in the helper function <code>build_url()</code>, which gives us a URL that looks something like:
plugin://plugin.video.myaddon/?mode=folder&foldername=Folder+One
= Working with user settings =
{{See also|Add-on settings}}
Your add-on may require some configurable options for the user (e.g. login credentials for a service). These can be stored as settings. To use settings with your add-on, you'll need to make a file defining the settings in <code>resources/settings.xml</code>. For example:
<source lang="xml">
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
    <setting id="my_setting" type="bool" default="true" label="My Setting"/>
</settings>
</source>
This will allow the user to open the settings for your add-on and modify this setting as needed. Then, in your add-on, you can retrieve or set this setting with the following code:
<source lang="python">
my_addon = xbmcaddon.Addon('plugin.video.my-addon')
my_setting = my_addon.getSetting('my_setting') # returns the string 'true' or 'false'
my_addon.setSetting('my_setting', 'false')
</source>
= Showing additional metadata =
We've already seen how to show some basic metadata, like the icon image and the type of the item (<code>'video'</code> in our case). However, there are many more pieces of metadata that XBMC understands, and adding them can make life easier on your users. We'll take a look at some of the more important ones. You can also find a full list in the [http://mirrors.xbmc.org/docs/python-docs Python documentation] for <code>[http://mirrors.xbmc.org/docs/python-docs/12.2-frodo/xbmcgui.html#ListItem xbmcgui.ListItem]</code>.
== Icons and thumbnails ==
Our previous examples already showed how to set an icon, but you can also set a larger thumbnail for each list item. Both of these can be set in the <code>ListItem</code> constructor:
<source lang="python">
li = xbmcgui.ListItem(label='My video', iconImage='icon.png', thumbnailImage='thumbnail.png')
</source>
You can also set these ''after'' creating the list item:
<source lang="python">
li.setIconImage('icon.png')
li.setThumbnailImage('thumbnail.png')
</source>
== Fanart ==
Fanart (full-screen background images) are another common thing for add-ons to show. This works a bit differently from icons and thumbnails, but it's still a simple process:
<source lang="python">
li.setProperty('fanart_image', 'fanart.jpg')
</source>
If you'd prefer to show the default fanart from your add-on, you can get the path to that image from the <code>[http://mirrors.xbmc.org/docs/python-docs/12.2-frodo/xbmcaddon.html#Addon xbmcaddon.Addon]</code> object:
<source lang="python">
my_addon = xbmcaddon.Addon('plugin.video.myaddon')
# ...
li.setProperty('fanart_image', my_addon.getAddonInfo('fanart'))
</source>
== Info labels ==
XBMC also lets you add useful information about each list item, like the cast, episode number, play count, and duration. The specific fields available depend on whether your list item is video, audio, or a picture. In all cases though, the format is roughly the same. For example, to add info labels to a movie, you might do the following:
<source lang="python">
li.setInfo('video', { 'genre': 'Horror',
                      'year': 1979,
                      'title': 'Alien' })
</source>
For a full list of the available info labels, consult the documentation for <code>[http://mirrors.xbmc.org/docs/python-docs/12.2-frodo/xbmcgui.html#ListItem-setInfo ListItem.setInfo]</code>.
== Stream info ==
In addition to metadata about the file's contents, you can add information about the audio/video streams themselves. For a video, you might do the following:
<source lang="python">
li.addStreamInfo('video', { 'codec': 'h264', 'aspect': 1.78, 'width': 1280,
                            'height': 720, 'duration': 60 })
li.addStreamInfo('audio', { 'codec': 'dts', 'language': 'en', 'channels': 2 })
li.addStreamInfo('subtitle', { 'language': 'en' })
</source>
For complete documentation about this function, see <code>[http://mirrors.xbmc.org/docs/python-docs/12.2-frodo/xbmcgui.html#ListItem-addStreamInfo ListItem.addStreamInfo]</code>.
= Adding context menus =
In addition to the default action for a list item (e.g. playing the video), your add-on can provide additional actions for an item in the context menu. Note that this only applies to list items in ''your'' add-on. Currently, you're not able to modify the context menu for movies in the user's library. To add a context menu item, you need to give it a label and a [[List of built-in functions|built-in function]] as a string:
<source lang="python">
li.addContextMenuItems([ ('Refresh', 'Container.Refresh'),
                        ('Go up', 'Action(ParentDir)') ])
</source>
You can also elect to show ''only'' your context menu items:
<source lang="python">
li.addContextMenuItems([ ('Refresh', 'Container.Refresh') ], replaceItems=True)
</source>

Latest revision as of 00:33, 18 December 2013