HOW-TO:Script addon: Difference between revisions

From Official Kodi Wiki
Jump to navigation Jump to search
No edit summary
(22 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{mininav|[[Development]]|[[Add-on development]]}}
{{mininav|[[Development]]|[[Add-on development]]}}


This page will outline the basics of creating your first Python script for Kodi. It assumes you're at least familiar with the basics of Python.
This page will outline the basics of creating your first Python script for Kodi. It assumes you're at least familiar with the basics of Python.<br />
If not, we recommend visiting the [http://docs.python.org/2/tutorial/ Python tutorial] first, and then returning here.
If not, we recommend visiting the [http://docs.python.org/2/tutorial/ Python tutorial] first, and then returning here.


Line 9: Line 9:
{{See also|Add-on structure}}
{{See also|Add-on structure}}


The first step to making an add-on is to put the basic structure in place.  
The first step to making an add-on is to put the basic structure in place.<br />
Make sure your directory is properly named, e.g. <code>script.my-addon</code>, this should be the same as your addon id.
Make sure your directory is properly named, e.g. <code>script.my-addon</code>, this should be the same as your addon id.<br />
Once these are done, you can get started writing the actual code for your add-on!
Once these are done, you can get started writing the actual code for your add-on!


The structure of our addon will look like this:
The structure of our addon will look like this:


[[File:Script_testwindow.jpg]]
[[File:script_testwindow_structure.jpg]]
 


= The addon.xml file =
= The addon.xml file =
{{See also|Addon.xml}}
{{See also|Addon.xml}}


In the addon.xml file you define the (unique) id of your addon and the name of the addon.
In the addon.xml file you define the (unique) id of your addon and the name of the addon.<br />
It will also tell Kodi what type of addon it is. Since we're going to create a script type addon, we need to set our extension point to 'xbmc.python.script'.
It will also tell Kodi what type of addon it is. Since we're going to create a script type addon, we need to set our extension point to 'xbmc.python.script'.<br />
Also define your python file in the 'library' field. This is the file Kodi will execute when you run your script.
Also define your python file in the 'library' field. This is the file Kodi will execute when you run your script.


This is what your addon.xml will need to look like (the bare minimum):
This is what your addon.xml will need to look like (the bare minimum):
<syntaxhighlight lang="xml" enclose="div">
<syntaxhighlight lang=xml enclose="div">
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.testwindow" name="test window" version="0.0.1" provider-name="me">
<addon id="script.testwindow" name="test window" version="0.0.1" provider-name="me">
Line 47: Line 48:
:''See also: [https://codedocs.xyz/xbmc/xbmc/group__python.html '''kodi python api''']''
:''See also: [https://codedocs.xyz/xbmc/xbmc/group__python.html '''kodi python api''']''


Your python code will look like this, please see the in-line comments for a full explanation of what each line does.
Your python code will look like this, please see the in-line comments for a full explanation of what each line does.<br />
Remember these are just the bare basics to get you started, many more options are available to enhance your window.
Remember these are just the bare basics to get you started, many more options are available to enhance your window.


<syntaxhighlight lang="python" enclose="div">
<syntaxhighlight lang=python enclose="div">
# import the kodi python modules we are going to use
# import the kodi python modules we are going to use
# see the kodi api docs to find out what functionality each module provides
# see the kodi api docs to find out what functionality each module provides
Line 61: Line 62:
# get the full path to your addon, decode it to unicode to handle special (non-ascii) characters in the path
# get the full path to your addon, decode it to unicode to handle special (non-ascii) characters in the path
CWD = ADDON.getAddonInfo('path').decode('utf-8')
CWD = ADDON.getAddonInfo('path').decode('utf-8')
#CWD = ADDON.getAddonInfo('path') # for kodi 19 and up..


# add a class to create your xml based window
# add a class to create your xml based window
Line 71: Line 73:
     # until now we have a blank window, the onInit function will parse your xml file
     # until now we have a blank window, the onInit function will parse your xml file
     def onInit(self):
     def onInit(self):
        # select a view mode, '50' in our case, as defined in the skin file
        xbmc.executebuiltin('Container.SetViewMode(50)')
         # define a temporary list where we are going to add all the listitems to
         # define a temporary list where we are going to add all the listitems to
         listitems = []
         listitems = []
Line 81: Line 85:
         # and add it to the temporary list as well
         # and add it to the temporary list as well
         listitems.append(listitem2)
         listitems.append(listitem2)
         # now we are going to add all the items we have defined to the container
        # by default the built-in container already contains one item, the 'up' (..) item, let's remove that one
        self.clearList()
         # now we are going to add all the items we have defined to the (built-in) container
         self.addItems(listitems)
         self.addItems(listitems)
         # give kodi a bit of (processing) time to add all items to the list
         # give kodi a bit of (processing) time to add all items to the container
         xbmc.sleep(100)
         xbmc.sleep(100)
         # this puts the focus on the top item of the container
         # this puts the focus on the top item of the container
Line 90: Line 96:
# this is the entry point of your addon, execution of your script will start here
# this is the entry point of your addon, execution of your script will start here
if (__name__ == '__main__'):
if (__name__ == '__main__'):
     # define your xml window and pass these five (or six or more - optional) arguments:
     # define your xml window and pass these four (kodi 17) or five (kodi 18) arguments (more optional items can be passed as well):
     # 1 'the name of the xml file for this window',  
     # 1 'the name of the xml file for this window',  
     # 2 'the path to your addon',
     # 2 'the path to your addon',
     # 3 'the name of the folder that contains the skin',
     # 3 'the name of the folder that contains the skin',
     # 4 'the name of the folder that contains the skin xml files'
     # 4 'the name of the folder that contains the skin xml files'
     # 5 'set to True for a media window (a window that will list music / videos / pictures), set to False otherwise
     # 5 [kodi 18] set to True for a media window (a window that will list music / videos / pictures), set to False otherwise
     # 6 [optional] if you need to pass additional items to your window, simply add them (as many as you need) to the list
     # 6 [optional] if you need to pass additional data to your window, simply add them to the list
     ui = GUI('script-testwindow.xml', CWD, 'default', '1080p', True, optional1='some data')
    # you'll have to add them as key=value pairs: key1=value1, key2=value2, etc...
     ui = GUI('script-testwindow.xml', CWD, 'default', '1080i', True, optional1='some data') # for kodi 18 and up..
#    ui = GUI('script-testwindow.xml', CWD, 'default', '1080i', optional1='some data') # use this line instead for kodi 17 and earlier
     # now open your window. the window will be shown until you close your addon
     # now open your window. the window will be shown until you close your addon
     ui.doModal()
     ui.doModal()
     # window closed, now cleanup a bit: delete your window before the fully script exits
     # window closed, now cleanup a bit: delete your window before the script fully exits
     del ui
     del ui


Line 114: Line 122:
The subject of skinning is outside of the scope of this tutorial, so please refer for the kodi skinning manual for details.
The subject of skinning is outside of the scope of this tutorial, so please refer for the kodi skinning manual for details.


<syntaxhighlight lang="xml" enclose="div">
<syntaxhighlight lang=xml enclose="div">
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<window>
<window>
Line 157: Line 165:
</window>
</window>
</syntaxhighlight>
</syntaxhighlight>
= Other options =
I'm sure you're familiar with the 'all roads lead to Rome' saying and, as such, there is another way to handle containers in your window.<br />
But, if you're happy with the way above... you can stop reading now.
Each python window has a built-in container (the one we used in the example above) but it is not mandatory to use the built-in container.<br />
you can also define your own container, and as many of them as you need.
Here's is an example of a window with two custom containers (only commenting on the differences to the example above):
<syntaxhighlight lang=python enclose="div">
import xbmc
import xbmcgui
import xbmcaddon
ADDON = xbmcaddon.Addon()
CWD = ADDON.getAddonInfo('path').decode('utf-8')
class GUI(xbmcgui.WindowXML):
    def onInit(self):
        # define two temporary lists where we are going to add our the listitems to
        list1 = []
        list2 = []
        # create and add some items to the first temporary list
        listitem1 = xbmcgui.ListItem('my first item')
        list1.append(listitem1)
        listitem2 = xbmcgui.ListItem('my second item')
        list1.append(listitem2)
        # create and add some items to the second temporary list
        listitem3 = xbmcgui.ListItem('this is one item')
        list2.append(listitem3)
        listitem4 = xbmcgui.ListItem('this is another item')
        list2.append(listitem4)
        # now define your two containers, the id's refer to the container id's you use in your xml file
        self.cont1 = self.getControl(100)
        self.cont2 = self.getControl(200)
        # add all the items in the first list to container 1
        self.cont1.addItems(list1)
        # and the items in the second list to container 2
        self.cont2.addItems(list2)
        xbmc.sleep(100)
        # this puts the focus on the first listitem in the first container
        self.setFocus(self.cont1)
if (__name__ == '__main__'):
    # [kodi 18] media windows use the built-in container by default, so do not set the fifth argument (it defaults to False) as we are not going to use it
    ui = GUI('script-testwindow.xml', CWD, 'default', '1080p')
    ui.doModal()
    del ui
</syntaxhighlight>
The xml code you need for two containers looks like this:
<syntaxhighlight lang=xml enclose="div">
<?xml version="1.0" encoding="UTF-8"?>
<window>
<controls>
<control type="list" id="100">
...
</control>
<control type="list" id="200">
...
</control>
</controls>
</window>
</syntaxhighlight>
= Download =
You can download this test addon here: <br />
[https://gitlab.com/ronie/script.testwindow script.testwindow]

Revision as of 20:54, 14 October 2019

Home icon grey.png   ▶ Development ▶ Add-on development ▶ HOW-TO:Script addon

This page will outline the basics of creating your first Python script for Kodi. It assumes you're at least familiar with the basics of Python.
If not, we recommend visiting the Python tutorial first, and then returning here.

While a python script can do many things, this tutorial is aimed at creating a window in Kodi.

Before we get started

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. script.my-addon, this should be the same as your addon id.
Once these are done, you can get started writing the actual code for your add-on!

The structure of our addon will look like this:

Script testwindow structure.jpg


The addon.xml file

In the addon.xml file you define the (unique) id of your addon and the name of the addon.
It will also tell Kodi what type of addon it is. Since we're going to create a script type addon, we need to set our extension point to 'xbmc.python.script'.
Also define your python file in the 'library' field. This is the file Kodi will execute when you run your script.

This is what your addon.xml will need to look like (the bare minimum):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.testwindow" name="test window" version="0.0.1" provider-name="me">
	<requires>
		<import addon="xbmc.python" version="2.25.0"/>
	</requires>
	<extension point="xbmc.python.script" library="default.py">
		<provides>executable</provides>
	</extension>
	<extension point="xbmc.addon.metadata">
		<summary lang="en_GB">window demo script</summary>
		<description lang="en_GB">a demo script to create a window</description>
		<language></language>
		<platform>all</platform>
	</extension>
</addon>


Your default.py file

See also: kodi python api

Your python code will look like this, please see the in-line comments for a full explanation of what each line does.
Remember these are just the bare basics to get you started, many more options are available to enhance your window.

# import the kodi python modules we are going to use
# see the kodi api docs to find out what functionality each module provides
import xbmc
import xbmcgui
import xbmcaddon

# create a class for your addon, we need this to get info about your addon
ADDON = xbmcaddon.Addon()
# get the full path to your addon, decode it to unicode to handle special (non-ascii) characters in the path
CWD = ADDON.getAddonInfo('path').decode('utf-8')
#CWD = ADDON.getAddonInfo('path') # for kodi 19 and up..

# add a class to create your xml based window
class GUI(xbmcgui.WindowXML):
    # [optional] this function is only needed of you are passing optional data to your window
    def __init__(self, *args, **kwargs):
        # get the optional data and add it to a variable you can use elsewhere in your script
        self.data = kwargs['optional1']

    # until now we have a blank window, the onInit function will parse your xml file
    def onInit(self):
        # select a view mode, '50' in our case, as defined in the skin file
        xbmc.executebuiltin('Container.SetViewMode(50)')
        # define a temporary list where we are going to add all the listitems to
        listitems = []
        # this will be the first item in the list. 'my first item' will be the label that is shown in the list
        listitem1 = xbmcgui.ListItem('my first item')
        # add this item to our temporary list
        listitems.append(listitem1)
        # let's create another item
        listitem2 = xbmcgui.ListItem('my second item')
        # and add it to the temporary list as well
        listitems.append(listitem2)
        # by default the built-in container already contains one item, the 'up' (..) item, let's remove that one
        self.clearList()
        # now we are going to add all the items we have defined to the (built-in) container
        self.addItems(listitems)
        # give kodi a bit of (processing) time to add all items to the container
        xbmc.sleep(100)
        # this puts the focus on the top item of the container
        self.setFocusId(self.getCurrentContainerId())

# this is the entry point of your addon, execution of your script will start here
if (__name__ == '__main__'):
    # define your xml window and pass these four (kodi 17) or five (kodi 18) arguments (more optional items can be passed as well):
    # 1 'the name of the xml file for this window', 
    # 2 'the path to your addon',
    # 3 'the name of the folder that contains the skin',
    # 4 'the name of the folder that contains the skin xml files'
    # 5 [kodi 18] set to True for a media window (a window that will list music / videos / pictures), set to False otherwise
    # 6 [optional] if you need to pass additional data to your window, simply add them to the list
    # you'll have to add them as key=value pairs: key1=value1, key2=value2, etc...
    ui = GUI('script-testwindow.xml', CWD, 'default', '1080i', True, optional1='some data') # for kodi 18 and up..
#    ui = GUI('script-testwindow.xml', CWD, 'default', '1080i', optional1='some data') # use this line instead for kodi 17 and earlier
    # now open your window. the window will be shown until you close your addon
    ui.doModal()
    # window closed, now cleanup a bit: delete your window before the script fully exits
    del ui

# the end!

Your script-testwindow.xml file

This is the xml code for the window your script will open. Basically all you need to define is a container (list) which your script will fill with listitems.
If you are using images in your xml file, put the inside the 'media' folder of your addon.

The subject of skinning is outside of the scope of this tutorial, so please refer for the kodi skinning manual for details.

<?xml version="1.0" encoding="UTF-8"?>
<window>
	<views>50</views>
	<controls>
		<control type="list" id="50">
			<left>500</left>
			<top>200</top>
			<width>1000</width>
			<height>500</height>
			<viewtype label="535">list</viewtype>
			<itemlayout height="100" width="1000">
				<control type="label">
					<left>20</left>
					<top>0</top>
					<height>50</height>
					<width>960</width>
					<font>font13</font>
					<label>$INFO[ListItem.Label]</label>
				</control>
			</itemlayout>
			<focusedlayout height="100" width="1000">
				<control type="image">
					<left>0</left>
					<top>0</top>
					<width>1000</width>
					<height>50</height>
					<texture>testwindow-focus.png</texture>
				</control>
				<control type="label">
					<left>20</left>
					<top>0</top>
					<height>50</height>
					<width>960</width>
					<font>font13</font>
					<label>$INFO[ListItem.Label]</label>
					<textcolor>orange</textcolor>
				</control>
			</focusedlayout>
		</control>
	</controls>
</window>


Other options

I'm sure you're familiar with the 'all roads lead to Rome' saying and, as such, there is another way to handle containers in your window.
But, if you're happy with the way above... you can stop reading now.

Each python window has a built-in container (the one we used in the example above) but it is not mandatory to use the built-in container.
you can also define your own container, and as many of them as you need.

Here's is an example of a window with two custom containers (only commenting on the differences to the example above):

import xbmc
import xbmcgui
import xbmcaddon

ADDON = xbmcaddon.Addon()
CWD = ADDON.getAddonInfo('path').decode('utf-8')

class GUI(xbmcgui.WindowXML):
    def onInit(self):
        # define two temporary lists where we are going to add our the listitems to
        list1 = []
        list2 = []
        # create and add some items to the first temporary list
        listitem1 = xbmcgui.ListItem('my first item')
        list1.append(listitem1)
        listitem2 = xbmcgui.ListItem('my second item')
        list1.append(listitem2)
        # create and add some items to the second temporary list
        listitem3 = xbmcgui.ListItem('this is one item')
        list2.append(listitem3)
        listitem4 = xbmcgui.ListItem('this is another item')
        list2.append(listitem4)
        # now define your two containers, the id's refer to the container id's you use in your xml file
        self.cont1 = self.getControl(100)
        self.cont2 = self.getControl(200)
        # add all the items in the first list to container 1
        self.cont1.addItems(list1)
        # and the items in the second list to container 2
        self.cont2.addItems(list2)
        xbmc.sleep(100)
        # this puts the focus on the first listitem in the first container
        self.setFocus(self.cont1)

if (__name__ == '__main__'):
    # [kodi 18] media windows use the built-in container by default, so do not set the fifth argument (it defaults to False) as we are not going to use it
    ui = GUI('script-testwindow.xml', CWD, 'default', '1080p')
    ui.doModal()
    del ui


The xml code you need for two containers looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<window>
	<controls>
		<control type="list" id="100">
			...
		</control>
		<control type="list" id="200">
			...
		</control>
	</controls>
</window>


Download

You can download this test addon here:
script.testwindow