Introduction
This is part III of a series of articles on writing plug-ins for XBMC with its own interface. In the previous sections (
Part I and
Part II ) I talked about the basic principles of creating an interface for XBMC plug-ins and gave some simple examples. In this part, I want to briefly describe the various APIs for interacting with XBMC, to demonstrate the micro-framework written by me, which simplifies the layout of the interface.
Update as of November 3, 2014: while writing the first two parts, I promised to write the 3rd part of the article soon. But, unfortunately, life makes its own adjustments, and the writing of the third part had to be postponed until better times. Now I will try to fulfill the promise, although not fully: the story of the micro-framework will be somewhat simplified.
API
A story about writing plugins for XBMC would be incomplete without at least a short story about various APIs that allow plug-ins to interact with XBMC. Until now, the articles dealt with the API for creating an interface, but after all, plug-ins need to perform other tasks: obtaining information about media files, managing playback, etc. To perform these tasks, XBMC has 4 main APIs: Python API, built-in functions (built-ins), JSON-RPC protocol and Infolabels. Further, quite briefly talk about each of them.
')
Python API
A set of 5 Python modules: xbmc, xbmcgui, xbmcplugin, xbmcaddon, xbmcvfs for interacting with XBMC. Modules are written in C ++ using the Python-C API (SWIG). Below is a brief overview:
xbmc - general interaction with XBMC;
xbmcgui - interaction with the GUI;
xbmcplugin - organization of plug-in sources of content;
xbmcaddon - access to various plug-in parameters (settings, language files, etc.);
xbmcvfs - work with the file system.
Built-in functions (builtins)
A set of commands to control XBMC. To call built-in functions, it is not necessary to write program code: they can, for example, be tied to a keypad or keyboard button by editing the corresponding configuration file. A list of built-in functions can be found
here .
To call built-in functions from Python scripts, there is a function xbmc.executebuiltin ().
JSON-RPC protocol
A protocol for local and remote control of XBMC based on JSON-RPC. Provides extensive interoperability with XBMC, including two-way communication. Read more about the JSON-RPC protocol in XBMC
here .
For local control and information exchange via the JSON-RPC protocol, the xbmc.executeJSONRPC () function is used. In addition, the standard Python library includes the json module, which simplifies the handling of JSON strings.
Remote interaction with XBMC on other computers can be performed using the standard library's urllib2 module.
Infolabels
API for getting various info from XBMC. A list of all available infolabels can be found
here .
To request information, use the xbmc.getInfoLabel () function.
The capabilities of these APIs overlap, and the same operation can often be performed in different ways.
Note: Up to version 11.0, XBMC also had a Web API, which allowed XBMC to be controlled using commands in URL-encoded notation. However, starting with version 12.0, it was removed due to redundancy, since JSON-RPC provides much more features.
PyXBMCt - microform to simplify the layout of the plug-in interface
As can be seen from the previous parts of this series of articles, the API for creating plug-in interfaces based on the Window / WindowDialog classes and the descendants of the Control class is not very convenient: you have to operate with absolute coordinates, and the graphical design of the interface is completely left to the developer.
The idea of ​​creating a micro-framework that would simplify the creation of an interface of plug-ins (of course, within the capabilities of the XBMC Python API), was born during my writing of my own plug-in for downloading subtitles. In XBMC before version 13.0, subtitle plugins were fully autonomous scripts, and the creation of the interface was assigned to the developer. By the way, in version 13.0, the subtitle plug-in architecture was completely changed, and now they work similarly to
content-source plug-ins , and the base code XBMC is responsible for the interface (by the way, from the 14th version the media center will be called Kodi).
In order not to tinker with the absolute coordinates of the interface elements, I wrote a wrapper around the Window / WindowDialog / Control classes, implementing the similarity of the Grid geometry manager, and decorated the whole thing with textures taken from the default XBMC skin - Confluence. It turned out well, and I decided to make on the basis of this a full-fledged micro-framework. PyQt was taken as a sample, so the framework was called PyXBMCt.
The framework offers 4 base container classes and 9 ready-to-use widgets, or, as they are called in XBMC, controls. The Grid geometry manager is responsible for placing controls on the screen, and interactive controls are associated with functions / methods similarly to the signal-slot mechanism in PyQt. Those familiar with PyQt / PySide should master PyXBMCt in two accounts.
For clarity, we consider a very simple example.
The PyXBMCt micro framework is present in the official XBMC / Kodi repository, so in order to use it, you need to add the following line to the addon.xml section of your plugin (for more information about the plug-in architecture
here ):
<import addon="script.module.pyxbmct" version="1.1.4"/>
Now when you install your plug-in from the repository or ZIP file, the micro-framework will be pulled from the official repository automatically. In addition, Kodi 14.0 "Helix" finally got the opportunity to install service plugins manually, and you can install the PyXBMCt plugin yourself.
As the simplest example, of course, take “Hello World”:
If everything is done correctly, this window will appear on the screen with the button:

Now, a detailed analysis. To display line numbers, use a text editor with the appropriate function, such as Notepad ++. I think those who are familiar with PyQt / PySide or with other “adult” GUI frameworks will immediately understand what is happening, so I’m missing obvious things.
Line 13: the self.setGeometry () method sets the width and height of the window, as well as the resolution of the coordinate grid of the parent window in which the controls are placed. The principle is completely analogous to the QtGui.QGridLayout linker. By default, the window is placed in the center of the screen, but if you wish, you can specify the exact coordinates of the window as additional parameters of this method.
Line 17: The self.placeControl () method places the selected control into a grid. As in the present QtGui.QGridLayout, a control can occupy several rows and columns.
Attention! Any methods of the instance of the control (for example, setLabel () to change the text of the label) must be called only after this control is added to the window using placeControl (). Otherwise, various glitches are possible, funny and not so.
Line 23: The setFocus () method sets the initial focus to the selected control. If there are any interactive controls, this method is
mandatory , otherwise you simply cannot control your plugin from the keyboard / remote.
If there are several interactive controls, you also need to set up navigation rules between them (see the previous parts).
Lines 25 and 27: the self.connect () method associates a control or numeric key of a keyboard event with a function / method. Naturally, a function reference is used here (without parentheses
() ), and not a function call. Also here you can use
lambda - all as in the present PyQt.
You can link only those controls that generate an event when they are activated: these are
Button ,
RadioButton and
List . Other controls do not generate events, and linking them is useless.
The numeric event codes generated by the controls (keyboard, mouse, joystick, etc.) can be found
here . PyXBMCt includes symbolic names for frequently used events.
A numeric code
ACTION_PREVIOUS_MENU or
10 (by default, the ESC key on the keyboard) is always associated with the close () method that closes the window and cannot be reassigned. This is done so that the plug-in window can always be closed.
Line 35: after use, the window instance is forcibly deleted (the destructor of the window instance and all objects associated with it is called). The point here is that the Garbage Collector for some reason does not remove the objects of the xbmcgui classes after the plug-in is completed, which can lead to memory leaks. Therefore, open windows based on xbmcgui / PyXBMCt must be removed from memory forcibly.
A practical example of using PyXBMCt can be seen in
my ex.ua.alternative plugin , where a micro-framework is used to create a login box for a website:
More information about PyXBMCt can be found at the links below (English).
PyXBMCt QuickStart Guide .
Automatically generated documentation on PyXBMCt classes and methods .
The PyXBMCt repository on Github .
Subject on the official forum XBMC (Kodi) .
Plugin demonstrating the features of PyXBMCt (screenshot below is the spoiler).
Of course, the plugin interface created on the basis of PyXBMCt is inferior in its capabilities and “embellishments” to the interface based on the XML-skin. However, in many cases, its capabilities are quite sufficient, and those who are familiar with “desktop” GUI frameworks, in particular PyQt / PySide, can learn PyXBMCt very quickly.
Conclusion
This concludes the series of articles on writing plugins for XBMC (Kodi). Unfortunately, due to a number of circumstances, the third part comes out with a considerable delay, but, as they say, "better late than never."
PS Added info about InfoLabels.
Previous articles
Detailed anatomy of a simple XBMC plugin .
We write a plugin for XBMC with its own interface: Part I - the theory and the simplest example .
We are writing a plugin for XBMC with its own interface: Part II - dialogues and embellishments .