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

Вступ

Це 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


Якщо все зроблено правильно, на екрані з'явиться таке віконце кнопки:


Тепер, докладний розбір. Для відображення номерів рядків використовуйте текстовий редактор з відповідною функцією, наприклад 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


Детальніше з PyXBMCt можна познайомитися за посиланням нижче (англійська мова).

PyXBMCt QuickStart Guide.

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

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

Тема на офіційному форумі XBMC (Kodi).

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

Скріншот PyXBMCt Demo


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

Висновок

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

Попередні статті

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

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.