Пишем плагин для XBMC с собственным интерфейсом: часть III — API и микро-фреймворк

в 19:40, , рубрики: HTPC, plugin, python, XBMC, домашний кинотеатр, медиацентр, разработка

Вступление

Это III часть цикла статей, посвященных написанию плагинов для XBMC с собственным интерфейсом. В предыдущих частях (часть I и часть II) я рассказал об основных принципах создания интерфейса плагинов XBMC и дал несколько простых примеров. В этой части я хочу совсем кратко рассказать о различных API для взаимодействия с XBMC, продемонстрировать написанный мною микро-фреймворк, упрощающий компоновку интерфейса.

Дополнение от 3.11.14: во время написания первых двух частей я пообещал вскоре написать 3-ю часть статьи. Но, к сожалению, жизнь вносит свои коррективы, и написание 3-й части пришлось отложить до лучших времен. Теперь я постараюсь исполнить обещанное, хоть и не в полной мере: рассказ о микро-фреймворке будет несколько упрощенным.

API

Рассказ о написании плагинов для XBMC был бы неполным без хотя бы краткого рассказа о различных API, обеспечивающих взаимодействие плагинов с XBMC. До сих пор в статьях речь шла об API для создания интерфейса, но ведь плагинам нужно выполнять и другие задачи: получение информации о медиафайлах, управление проигрыванием и т. п. Для выполнения этих задач в XBMC существует 3 основных API: Python API, встроенные функции (built-ins) и протокол JSON-RPC. Далее совсем кратко поговорим о каждом из них.

Python API

Набор из 5 модулей Python: xbmc, xbmcgui, xbmcplugin, xbmcaddon, xbmcvfs для взаимодействия с XBMC. Модули написаны на C++, используя Python-C API (SWIG). Ниже их краткий обзор:
xbmc — общее взаимодействие с XBMC;
xbmcgui — взаимодействие с GUI;
xbmcplugin — организация плагинов-источников контента;
xbmcaddon — доступ к различным параметрам плагинов (настройки, языковые файлы и т. п.);
xbmcvfs — работа с файловой системой.

Встроенные функции (builtins)

Набор команд для управления XBMC. Для вызова встроенных функций не обязательно писать программный код: их можно, к примеру, привязать к кнопке пульта или клавиатуры путем редактирования соответствующего конфигурационного файла. Перечень встроенных функций можно найти здесь.
Для вызова встроенных функций из скриптов на Питоне существует функция xbmc.executebuiltin().

Протокол JSON-RPC

Протокол для локального и удаленного управления XBMC на базе JSON-RPC. Обеспечивает широкие возможности взаимодействия с XBMC, включая двухсторонний обмен информацией. В последнем примере данной статьи протокол JSON-RPC используется для получения информации о последних добавленных в медиатеку фильмах. Подробнее о протоколе JSON-RPC в XBMC можно почитать здесь.
Для локального управления и обмена информацией по протоколу JSON-RPC используется функция xbmc.executeJSONRPC(). Кроме того, в состав стандартной библиотеки Питона входит модуль json, упрощающий обработку строк JSON.
Удаленное взаимодействие с XBMC на других компьютерах можно осуществлять при помощи модуля urllib2 стандартной библиотеки.

Возможности этих API частично пересекаются, и одну и ту же операцию нередко можно выполнить разными способами.

Примечание: вплоть до версии 11.0 в XBMC также был Web-API, который позволял управлять XBMC при помощи команд в URL-encoded нотации. Однако, начиная с версии 12.0, он был убран в силу избыточности, поскольку JSON-RPC обеспечивает намного большие возможности.

PyXBMCt — микрофреймворк для упрощения компоновки интерфейса плагинов

Как видно из предыдущих частей данного цикла статей, API для создания интерфейса плагинов на базе классов Window/WindowDialog и потомков класса Control не очень удобен: приходится оперировать абсолютными координатами, и графическое оформление интерфейса полностью возлагается на разработчика.

Идея создания микро-фреймоврка, который бы упростил создание интефейса плагинов (естественно, в пределах возможностей XBMC Python API), родилась у меня в ходе написания собственного плагина для закачки субтитров. В XBMC до версии 13.0 плагины субтитров были полностью автономными скриптами, и создание интерфейса возлагалось на разработчика. К слову, в версии 13.0 архитектуру плагинов субтитров полностью поменяли, и теперь они работают аналогично плагинам-источникам контента, а за интерфейс отвечает базовый код XBMC (кстати, с 14-й версии медиацентр будет называться Kodi).
Чтобы не возиться с абсолютными координатами элементов интерфейса, я написал wrapper вокруг классов Window/WindowDialog/Control, реализующий подобие менеджера геометрии Grid, и украсил всё это дело текстурами, взятыми с дефолтного скина XBMC — Confluence. Получилось неплохо, и я решил сделать на базе этого полноценный микро-фреймворк. В качестве образца был взят PyQt, поэтому фреймоврк получил название PyXBMCt.

Фреймворк предлагает 4 базовых класса-контерйнера и 9 готовых к использованию виджетов, или, как они называются в XBMC, контролов. За размещение контролов на экране отвечает менеджер геометрии Grid, и интерактивные контролы связываются с с функциями/методами аналогично механизму сигналов-слотов в PyQt. Те, кто знаком с PyQt/PySide, должны освоить PyXBMCt в два счета.

Для наглядности рассмотрим совсем простой пример.
Микро-фреймворк PyXBMCt присутствует в официальном репозитории XBMC/Kodi, поэтому, чтобы воспользоваться им, нужно добавить в раздел файла addon.xml вашего плагина (подробнее об архитектуре плагинов см. здесь) следующую строку:

<import addon="script.module.pyxbmct" version="1.1.4"/>

Теперь при установке вашего плагина из репозитория или файла ZIP микро-фреймворк подтянется из официального репозитория автоматически. Кроме того, в Kodi 14.0 «Helix» наконец-то появилась возможность устанавливать служебные плагины вручную, и плагин PyXBMCt можно установить заранее самому.
В качестве простейшего примера, естественно, возьмем «Hello World»:

Hello World

# -*- coding: utf-8 -*-
# Импортируем модуль PyXBMCt.
import pyxbmct.addonwindow as pyxbmct


class MyWindow(pyxbmct.AddonDialogWindow):

    def __init__(self, title=''):
        # Вызываем конструктор базового класса.
        super(MyWindow, self).__init__(title)
        # Устанавливаем ширину и высоту окна, а также разрешение сетки (Grid):
        # 2 строки и 3 столбца.
        self.setGeometry(350, 150, 2, 3)
        # Создаем текстовую надпись.
        label = pyxbmct.Label('This is a PyXBMCt window.', alignment=pyxbmct.ALIGN_CENTER)
        # Помещаем надпись в сетку.
        self.placeControl(label, 0, 0, columnspan=3)
        # Создаем кнопку.
        button = pyxbmct.Button('Close')
        # Помещаем кнопку в сетку.
        self.placeControl(button, 1, 1)
        # Устанавливаем начальный фокус на кнопку.
        self.setFocus(button)
        # Связываем кнопку с методом.
        self.connect(button, self.close)
        # Связываем клавиатурное действие с методом.
        self.connect(pyxbmct.ACTION_NAV_BACK, self.close)


# Создаем экземпляр окна.
window = MyWindow('Hello, World!')
# Выводим созданное окно.
window.doModal()
# Принудительно удаляем экземпляр окна после использования.
del window

Если всё сделано правильно, на экране появится такое окошко с кнопкой:
Пишем плагин для XBMC с собственным интерфейсом: часть III — API и микро фреймворк

Теперь, подробный разбор. Для отображения номеров строк используйте текстовый редактор с соответствующей функцией, например Notepad++. Думаю, те, кто знаком с PyQt/PySide или с другими «взрослыми» GUI-фреймворками, сразу поймут, что к чему, поэтому очевидные вещи пропускаю.

Строка 13: метод self.setGeometry() задает ширину и высоту окна, а также разрешение координатной сетки родительского окна, в которой размещаются контролы. Принцип полностью аналогичен компоновщику QtGui.QGridLayout. По умолчанию окно помещается в центр экрана, но при желании можно задать точные координаты окна в виде дополнительных параметров этого метода.

Строка 17: метод self.placeControl() помещает выбранный контрол в координатную сетку. Как и в настоящем QtGui.QGridLayout, контрол может занимать несколько строк и столбцов.

Строка 23: метод setFocus() устанавливает начальный фокус на выбранный контрол. При наличии любых интерактивных контролов этот метод является обязательным, иначе вы просто не сможете управлять своим плагином с клавиатуры/пульта.
При наличии нескольких интерактивных контролов также нужно настроить правила навигации между ними (см. предыдущие части).

Строки 25 и 27: метод self.connect() связывает контрол или числовой код клавиатурного события с функцией/методом. Естественно, здесь используется ссылка на функцию (без круглых скобок ()), а не вызов функции. Также здесь можно использовать lambda — всё как в настоящем PyQt.
Связать можно только те контролы, которые генерируют событие при их активации: это Button, RadioButton и List. Другие контролы не генерируют событий, и связывать их бесполезно.
Числовые коды событий, генерируемых органами управления (клавиатурой, мышью, джойстиком и т. п.) можно найти здесь. PyXBMCt включает символьные имена для часто используемых событий.
Числовой код ACTION_PREVIOUS_MENU или 10 (по умолчанию — клавиша ESC на клавиатуре) всегда связан с методом close(), закрывающим окно, и переназначить его нельзя. Это сделано для того, чтобы окно плагина всегда можно было закрыть.

Строка 35: после использования экземпляр окна принудительно удаляется (вызывается деструктор экземпляра окна и всех объектов, связанных с ним). Дело здесь в том, что Garbage Collector почему-то не удаляет объекты классов xbmcgui после завершения работы плагина, что может приводить к утечкам памяти. Поэтому открытые окна на базе xbmcgui/PyXBMCt нужно удалять из памяти принудительно.

Практический пример использования PyXBMCt можно увидеть в моем плагине ex.ua.alternative, где микро-фреймворк используется для создания окна входа на сайт:

Окно входа на ex.ua

Пишем плагин для XBMC с собственным интерфейсом: часть III — API и микро фреймворк

Подробнее с PyXBMCt можно познакомиться по ссылкам ниже (английский язык).

PyXBMCt QuickStart Guide.

Автоматически сгенерированная документация по классам и методам PyXBMCt.

Репозиторий PyXBMCt на Github.

Тема на официальном форуме XBMC (Kodi).

Плагин, демонстрирующий возможности PyXBMCt (скриншот под спойлером ниже).

Скриншот PyXBMCt Demo

Пишем плагин для XBMC с собственным интерфейсом: часть III — API и микро фреймворк

Конечно, интерфейс плагина, созданный на базе PyXBMCt, уступает по возможностям и «украшательствам» интерфейсу на базе XML-скина. Однако во многих случаях его возможностей вполне достаточно, и те, кто знакомы с «настольными» GUI-фреймворками, в частности PyQt/PySide, могут освоить PyXBMCt очень быстро.

Заключение

На этом я заканчиваю цикл статей, посвященных написанию плагинов для XBMC (Kodi). К сожалению, в силу ряда обстоятельств 3-я часть выходит со значительным запозданием, но, как говорится, «лучше поздно, чем никогда».

Предыдущие статьи

Подробная анатомия простого плагина для XBMC.
Пишем плагин для XBMC с собственным интерфейсом: часть I — теория и простейший пример.
Пишем плагин для XBMC с собственным интерфейсом: часть II — диалоги и украшателства.

Автор: Roman_V_M

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js