Notes on creating Kodi addons

Development gotchas for the popular open-source media center software.

Screenshot for the Kodi addon

This is an ideal continuation of this great post by Johan Zietsman. So you are encouraged to read his post first then come back here.

Addons vs. plugins

Without any doubt plugins are easier to start with. It's because Kodi gives you a more obvious framework to build on your application, but this easiness come with the price you won't be able to customize your UI too much. Want to add a secondary label below each main container list item label? Sorry, no luck.

On the other hand addons let you do much more, like creating new full screen windows and populate them programmatically or by loading a XML skin file from your addon resources folder.

An ode to simpleplugin

Roman Miroshnychenko's simpleplugin, now maintaned by Vladimir Maksimenko, is a great little module incapsulating a lot of common helpers. It covers the creation of both addons and plugins. Jump on the develop branch and you will find version 3.

To use it simply extend it and start rocking:

import simpleplugin
  
class MyAddon(simpleplugin.Addon):

  def __init__(self):
    super(MyAddon, self).__init__()
    # Do your initialisation here

  def run(self):
    # Open your first window here

if __name__ == '__main__':    
  addon = MyAddon()
  addon.run()           

Note: API changed significally between version 2 and 3 so don't be fooled by the outdated documentation you find online.

Subclass isn't

Suppose your addon needs to create several custom XML windows, possibly handling their own events. Also each window has its XML skin file, so it makes sense to couple such information within the window creation.

So you diligently subclass WindowXML class and write this piece of code which overrides parent class __init__ method:

import xbmcgui

class MyWindow(xbmcgui.WindowXML):
  def __init__(self, *args, **kwargs):
    self.foo = kwargs['foo'] 
    super(MyWindow, self).__init__('custom-skin.xml', ...) 

  def onInit(self):     
    # Do your initialisation here

window = MyWindow(foo="bar")

However, at runtime this throws an exception. So what's going on here?

After some failed attempts to fix the error I've come to the conclusion that there must be some weird interaction between Python and Kodi core classes, since standard Python inheritance doesn't behave as expected.

A common workaround is to use a factory function which incapsulates the creation of the XML window:


class MyWindow(xbmcgui.WindowXML):

  def __init__(self, *args, **kwargs):
    self.foo = kwargs['foo']   
      
  def onInit(self):     
    # Do your initialisation here
    
def showMyWindow():
    window = MyWindow('custom-skin.xml', ..., foo="bar") 
    window.doModal()
    del window
        

Watch your resolution

If your addon UI appears with wrong proportions (tiny fonts, elements too spaced out, images which get cut, etc.) check your resolution folder: you might have copied files from a skin designed to be used at 720p while you have put files into 1080i folder (or the other way around).

No new include files

To my knowledge an addon cannot define new <include> files. If you do you are likely to see a Skin has invalid include warning on the Kodi log file.

The unpleasant workaround is to copy-paste common UI controls from a XML file to another.

 

Comments for this article are closed, thank you.