Eigene Plugins für XBMC schreiben

Aus LinuxUser 04/2013

Eigene Plugins für XBMC schreiben

© maxkrasnov, 123RF

Organisch erweitern

Nicht immer findet sich in XBMC ein passendes Addon für die eigenen Wünsche. Kein Problem: Ein maßgeschneidertes Plugin haben Sie schnell erstellt.

Das Mediencenter XBMC hat sich zu einem machtvollen Instrument mit einer Vielzahl an Komponenten entwickelt. Je nachdem, welche Funktionalität von XBMC Sie erweitern möchten, bietet sich jeweils ein andere Sorte von Addon dazu an. Zunächst lassen sich grob die vier Hauptkategorien Plugin, Skript, Skin und Repository unterscheiden (siehe Kasten “XBMC: Addon-Typen”).

Neben Skins erfreuen sich vor allem Plugins unter XBMC-Anwendern besonderer Beliebtheit. Die meisten dieser Erweiterungen bedienen Sie wie ein virtuelles Dateisystem: Sie navigieren durch Verzeichnisse und wählen Medien zum Abspielen aus. Oft liegen diese tatsächlich aber weder lokal noch als Datei innerhalb einer Hierarchie vor: Stattdessen handelt es sich vielleicht um Livestreams von Fernsehsendern, um Fotos, welche das Plugin über die API eines Bilderdienstes abruft, oder um Videos, deren Links aus einer HTML-Seite herausgefiltert (“gescraped”) wurden.

Unabhängig davon, wie das Plugin an die Mediendaten gelangt: Der Nutzer bekommt von solchen Abläufen im Hintergrund nichts mit. Er bedient das Mediencenter weiter über die gewohnte Verzeichnis/Datei-Struktur. Auf diese Weise lassen sich selbst die ungewöhnlichsten Erweiterungen ohne Einlernzeit sofort nutzen.

XBMC: Addon-Typen

Plugins erweitern das Mediencenter um Funktionen, die der Benutzer direkt über ein entsprechendes Untermenü aufrufen kann. Ein Beispiel hierfür wäre etwa die Erweiterung plugin.video.youtube. Haben Sie diese installiert, erscheint sie unterhalb des Hauptmenüs im Punkt Videos. Andere Medientypen verfügen ebenfalls über entsprechende Erweiterungsmöglichkeiten, hier heißen die Subkategorien entsprechend plugin.audio.*, plugin.picture.* und plugin.weather.*.

Skripte spezialisieren sich hingegen nicht auf das Bereitstellen und Wiedergeben bestimmter Medien. Oft bieten sie dem Benutzer über den Hauptmenüpunkt Programme Funktionen an, die nicht in das Hauptanwendungsgebiet eines Mediencenters fallen, aber einen netten Zusatz darstellen – etwa ein Foren-Browser für den Fernseher oder das Starten eines externen Programms. Gelegentlich bleiben sie aber für den Benutzer unsichtbar: Die Unterkategorie script.module.* besitzt dann nur für Autoren anderer Addons Relevanz und sie stellt etwa Bibliotheken mit Funktionen bereit. Spezielleren Anwendungszwecken dient script.service.*: Solche Skripten führt XBMC beim Start aus, wo sie entweder einmalige Aktionen (wie etwa das Aktualisieren der Datenbank) vornehmen oder auf Wunsch auch regelmäßig getriggert werden.

Skins passen das Aussehen der Oberfläche an. Dabei kann der Nutzer das Äußere und die Bedienung von XBMC komplett auf den Kopf stellen. Statt den Vorgaben des Standard-Skins “Confluence” zu folgen, passen Sie Schriftart, Texte und Bilder so an, dass diese Ihrem Geschmack entsprechen. Selbst ein komplettes Verändern des Haupt- und der Untermenüs ist möglich. Soll XBMC etwa die Bedienerführung eines Apple-TV imitieren, weil etwa die Familienmitglieder noch an dessen Nutzerführung gewohnt sind, realisieren Sie das mit einem eigenen Skin.

Etwas ungewöhnlich wirkt auf den ersten Blick, dass auch Paketquellen (englisch: “repositories”) zu den Addons zählen. Dies liegt daran, dass XBMC in der Standardeinstellung erstmal nur auf die eine offizielle Paketquelle der Community zurückgreift. Die weist zwar einen beträchtlichen Umfang auf, nimmt jedoch nicht jedes Addon auf. Es fehlen etwa solche, die der Ersteller nicht unter einer Open-Source-Lizenz gestellt hat oder in deren Metadaten ein englischer Beschreibungstext fehlt. Aufgrund seiner offenen Philosophie erlaubt XBMC auch fremde Paketquellen, aus denen sich Fremdpakete genauso leicht nachinstallieren lassen wie aus dem Standard-Repository.

Planung

Für unser Beispiel nehmen wir an, Sie hätten von der Deutschen Telekom einen “Entertain”-Telefonanschluss, über den die gängigsten deutschen Sender per IPTV-Multicast übertragen werden. Zwar versieht der Telefonanbieter die privaten Fernsehstationen dabei mit einer proprietären Verschlüsselung, alle öffentlich-rechtliche Sender lassen sich barrierefrei als Stream abrufen. Was liegt da näher, als dafür auf dem XBMC-Mediencenter einen eigenen Menüpunkt einzurichten?

Die hierfür nötigen Streaming-URLs finden sich bei ARD  [1] und ZDF [2]. Ein Blick in die offizielle XBMC-Paketquelle verrät jedoch, dass für die Entertain-Streams bisher kein Plugin existiert. Kein Problem: Dann schreiben wir eben unser eigenes. Gerade bei Entertain fällt das aufgrund der geringen Komplexität der Anbindung recht leicht – und ermöglicht eine übersichtliche Einführung in die Grundstruktur und den Aufbau eines Plugins. Dies ist auch der Grund für die Wahl dieses Beispiels.

Das Endprodukt soll wie folgt aussehen: Zuerst erscheint ein Hauptmenü, in dem Sie entscheiden, ob Sie ein lokales Fernsehprogramm (also eines der Dritten) oder eines mit bundesweitem Schwerpunkt anschauen möchten. Entscheiden Sie sich für Letzteres, stehen ARD, ZDF, Phoenix und der Kinderkanal zur Wahl. Bei den lokalen Sendern soll XBMC die verschiedenen Regionalfenstern des WDR anbieten (Abbildung 1). In dieser Auflistung fehlen einige öffentlich-rechtliche Fernsehstationen, wie etwa Eins Plus, Arte und zahlreiche Dritte Programme: Die Vielzahl weiterer Streaming-URLs würde hier die Listings nur aufblasen, ohne zusätzlich zum Lernziel dieses Artikels beizutragen.

Abbildung 1: Das Hauptmenü unseres Plugins offeriert die Wahl zwischen den bundesweit empfangbaren öffentlich-rechtlichen Sendern und deren lokalen Ablegern. Je nach Auswahl des Menüpunkts verzweigt die Auswahl dann zu den Haupt- beziehungsweise Regionalsendern.

Abbildung 1: Das Hauptmenü unseres Plugins offeriert die Wahl zwischen den bundesweit empfangbaren öffentlich-rechtlichen Sendern und deren lokalen Ablegern. Je nach Auswahl des Menüpunkts verzweigt die Auswahl dann zu den Haupt- beziehungsweise Regionalsendern.

Plugins für XBMC schreibt man üblicherweise in Python. Dabei gilt es zu beachten, dass XBMC einen internen Python-Interpreter der Version 2.4 verwendet. Sie können also keinen Python-Code mit der Syntax der neueren Python-3.x-Versionen verwenden.

Grundlagen

Im ersten Schritt müssen Sie die benötigte Mindeststruktur an Verzeichnissen und Dateien erstellen. Wechseln sie dazu in das Unterverzeichnis ~/User/.xbmc/addons. Dort erstellen Sie den Ordner plugin.video.Plugin-Name, in diesem Fall also plugin.video.entertain. Innerhalb dieses Verzeichnisses benötigt XBMC wiederum die in Abbildung 2 gezeigte minimale Datei- und Verzeichnisstruktur.

Abbildung 2: Für das Erstellen eines XBMC-Plugins benötigen Sie als Grundlage die hier gezeigte Verzeichnisstruktur innerhalb des Home-Verzeichnisses.

Abbildung 2: Für das Erstellen eines XBMC-Plugins benötigen Sie als Grundlage die hier gezeigte Verzeichnisstruktur innerhalb des Home-Verzeichnisses.

TIPP

Unter OpenELEC lautet der XBMC-Nutzername schlicht openelec, bei RaspBMC ist es der Nutzer Pi. Soll das Plugin später auf einem Raspberry Pi laufen, kann es sinnvoll sein, dieses erst einmal auf schnellerer Hardware zu entwickeln und erst das Endprodukt auf dem Kleinrechner zu nutzen.

In addon.xml definieren Sie ein paar grundlegende Meta-Informationen wie zum Beispiel Name und Beschreibung des Plugins. Zusammen mit dem 256×256 Pixel messenden Vorschaubild icon.png zeigt XBMC diese Informationen später im Plugin-Auswahlmenü (Abbildung 3). Eigentlich liegt es in unserem Beispiel nahe, als Icon das Telekom-Logo einzusetzen, was jedoch rechtlich problematisch sein könnte. Also behelfen wir uns mit einer lizenzfreien Grafik eines Fernsehers und fügen dieser mit Gimp noch den Schriftzug Entertain-Streams hinzu. Das eigentlich Python-Skript wird XBMC später in entertain.py vorfinden.

Abbildung 3: Diese Meta-Informationen zu unserem Plugin stammen aus der Datei <code srcset=

addon.xml.” width=”300″ height=”169″ /> Abbildung 3: Diese Meta-Informationen zu unserem Plugin stammen aus der Datei addon.xml.

Auf dieser Verzeichnisebene können noch zwei weitere Dateien lagern, die aber technisch nicht zwingend notwendig sind. Die changelog.txt, die der Nutzer bei der Installation zu sehen bekommt, enthält eine Liste der Veränderungen gegenüber der letzten Version. In der fanart.jpg lagert ein Bild, welches das Plugin automatisch im Hintergrund seiner Menüs anzeigt.

Das Unterverzeichnis /resources/lib/ enthält eventuell benötigte Zusatzmodule, die XBMC nicht automatisiert über die Standard-Paketquelle beziehen kann – eine solche eine Konstellation kommt jedoch eher selten vor. Die Datei strings.xml ermöglicht mehrsprachige Plugins: Hier weist der Programmierer für jede unterstützte Sprache Strings einer Nummer zu, wobei das Python-Skript später nur die Nummer als Platzhalter für Textausgaben verwendet.

Im brandneuen XBMC 12 “Frodo” haben die Entwickler die strings.xml durch eine Datei namens strings.po ersetzt. In unserem Beispiel spielt Mehrsprachigkeit aber ohnehin keine Rolle, so dass wir in die strings.xml nur den Namen des Plugins hineinschreiben (Listing 1).

Listing 1

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<strings>
  <!--<string id="30000">Entertain-Streams</string>-->
</strings>

Die Metadaten in der Datei addon.xml (Listing 2) fallen zum Großteil selbsterklärend aus. Den Wert bei provider-name in Zeile 2 zeigt XBMC später in der Plugin-Übersicht als Autorenname an. Selbst in den Erweiterungen der offiziellen Paketquelle steht dort manchmal nur ein Pseudonym anstatt eines Realnamens. Die Angaben summary und description können Sie optional auch für verschiedene Sprachen mehrfach anlegen. Zeile 5 signalisiert, dass wir die Funktionen der praktischen Bibliothek parsedom verwenden möchten – dazu später mehr.

Listing 2

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.entertain" name="Entertain" version="1.0" provider-name="Ich">
  <requires>
    <import addon="xbmc.python" version="2.0"/>
    <import addon="script.module.parsedom" version="0.9.1"/>
  </requires>
  <extension point="xbmc.python.pluginsource" library="entertain.py">
    <provides>video</provides>
  </extension>
  <extension point="xbmc.addon.metadata">
    <language>de</language>
    <platform>all</platform>
    <summary lang="de">IPTV für Telekom Entertain</summary>
    <description lang="de">Eine subjektive Auswahl öffentlich-rechtlicher Livestreams. Dieses Plugin funktioniert nur an Telekom-Entertain-Anschlüssen.</description>
  </extension>
</addon>

Der Plugin-Code

Nun geht es an das Herzstück unseres Addons, das Skript entertain.py (Listing 3). Die Zeilen 4 bis 6 importieren alle benötigten Module. CommonFunctions verweist dabei auf das Modul parsedom. Man kann es beispielsweise dafür nutzen, um den DOM-Baum eines XML-Dokuments zu parsen. Für unseren Fall dient es jedoch dazu, um in Zeile 42 intern übergebene Parameter zu parsen. Falls wir uns beispielsweise in XBMC derzeit im Unterordner Lokalprogramme befinden, liefert ein Aufruf von sys.argv[2] den String

?url=%2Flokalfernsehen%2F&mode=2&name=Lokalfernsehen

Für den weiteren Programmablauf gilt es die Parameter url, mode und name aus dieser Zeichenkette herauszufiltern und in eigenen Variablen abzuspeichern. Das ließe sich über entsprechende String-Funktionen vornehmen. Noch einfacher klappt es über die Methode common.getParameters(sys.argv[2]), die passende Schlüssel/Wert-Paare liefert.

Die Zeilen 44 bis 51 fangen den Fall ab, dass der Benutzer sich im Hauptmenü des Plugins befindet: Dann ist nämlich der Parameterstring leer, und es gilt zu verhindern, dass dies zu einem Fehler führt. Anhand der Variable mode testet das Skript, welches Untermenü aktiv ist, und ruft dazu passende Funktionen auf (Zeilen 63 bis 67). Nachdem letztere das aktuelle Menü mit Punkten befüllt haben, schließt Zeile 69 die Auswahlseite ab.

Hier terminiert das Skript fürs Erste. Wenn der Nutzer nun innerhalb des von XBMC dargestellten Menüs wieder ein unter- oder übergeordnetes virtuelles Verzeichnis auswählt, startet das Skript mit den entsprechenden Parametern erneut und generiert wieder eine dazu passende Auswahl.

Listing 3

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib, urllib2
import xbmcplugin, xbmcgui, xbmc
import CommonFunctions
common = CommonFunctions
def addDir(name,url,mode,iconimage):
    u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
    ok=True
    liz=xbmcgui.ListItem(name, iconImage="DefaultFolder.png", thumbnailImage=iconimage)
    liz.setInfo( type="Video", infoLabels={ "Title": name } )
    ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
    return ok
def addLink(name,url,iconimage):
    ok=True
    liz=xbmcgui.ListItem(name, iconImage="DefaultVideo.png", thumbnailImage=iconimage)
    liz.setInfo( type="Video", infoLabels={ "Title": name } )
    ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz)
    return ok
def hauptmenue():
    addDir("Hauptprogramme", '/hauptprogramme/', 1, "")
    addDir("Lokalfernsehen", '/lokalfernsehen/', 2, "")
def menueHauptsenderWaehlen():
    addLink("ARD","rtp://@239.35.10.4:10000", "")
    addLink("ZDF","rtp://@239.35.10.5:10000", "")
    addLink("Phoenix","rtp://@239.35.10.22:10000", "")
    addLink("KiKa","rtp://@239.35.10.19:10000", "")
def lokalprogrammWaehlen():
    addLink("WDR Köln","rtp://@239.35.10.18:10000","")
    addLink("WDR Bonn","rtp://@239.35.10.37:10000","")
    addLink("WDR Dortmund","rtp://@239.35.10.38:10000","")
    addLink("WDR Duisburg","rtp://@239.35.10.39:10000","")
params = common.getParameters(sys.argv[2])
try:
    mode = int(params['mode'])
except:
    mode = None
try:
    name = params['name']
except:
    name = None
try:
    url = params['url']
except:
    url = None
if mode == None:
        hauptmenue()
elif mode == 1:
        menueHauptsenderWaehlen()
elif mode == 2:
        lokalprogrammWaehlen()
xbmcplugin.endOfDirectory(int(sys.argv[1]))

Unterprogramme

Das Unterprogramm hauptmenue() ruft für die beiden Menüpunkte jeweils addDir() auf. Dabei übergibt es:

  • die Werte für den Namen der jeweiligen Menüpunkte,
  • die interne (frei gewählte) URL für den fiktiven Unterordner,
  • den mode-Wert, der als Hilfswert speichert, in welchem Menü der Nutzer sich befindet, und
  • einen leeren Wert für die Thumbnail-Grafik, was bewirkt, dass der Nutzer die Standard-Grafik für Ordner zu sehen bekommt.

Die Funktion addDir() macht dabei nichts anderes, als die Variablen zu einem Parameterstring zusammenzusetzen, damit das Skript diese bis zu seinem nächsten Aufruf mittransportiert (Zeilen 11 und 15 ), sowie über die passenden XBMC-internen Funktionen die benötigten Werte zu setzen. Ähnlich läuft der Funktionsaufruf von addLink() ab. Da hier aber der Nutzer nach dem Abspielen eines Videos in die derzeit aktuelle Verzeichnishierarchie zurückkehrt und diese nicht wechselt, muss kein neuer mode-Wert übermittelt werden. Außerdem setzt dieses Unterprogramm den Wert isFolder logischerweise nicht wie addDir() auf True.

Die Funktionen addDir() und addLink() stammen ursprünglich aus der XBMC-Dokumentation, finden sich jedoch aufgrund Ihrer einfachen Anwendbarkeit in vielen kleineren Plugins wieder. Wollen Sie Videolinks aus einer Webseite herausscrapen? Dann extrahieren Sie die Links entweder mittels diverser Stringfunktionen (oder ressourcenaufwändiger mittels eines regulären Ausdrucks und dem Modul re) und stellen diese anschließend über addDir() und addLink() dem Nutzer zur Verfügung.

Falls Sie die API eines Webdienstes nutzen, um URLs zu Mediendateien zu erhalten, bietet sich oft ein anderes Vorgehen an. Handelt es sich beispielsweise um Youtube-Links, so können Sie sich Funktionen anderer Addons zunutze machen. Für Youtube existiert beispielsweise bereits ein Plugin. Geben Sie dann die Abhängigkeit dazu in der addon.xml mittels des Strings <import addon=”plugin.video.youtube”/> an. Nun spielt die Plugin-URL

plugin://plugin.video.youtube/?path=/root/video&action=play_video&videoid=VideoID

das angegebene Video des fraglichen Anbieters ab, wenn Sie sie als Ziel von addDirectory() angeben.

Komplexere Plugins

Je weniger statische Daten Ihr Script nutzt und je komplizierter die verwendeten Datenstrukturen ausfallen, desto eher sollten Sie von der oben dargestellten Struktur abweichen.

Für komplexere Plugins lohnt es sich oft, XBMCSwift2 [4] einzubinden. Das erleichtert zunächst einmal das Debugging. Die einfachste Form der Fehlersuche besteht in XBMC-Addons normalerweise darin, mehrere Variablenwerte über den Print-Befehl auszugeben. Diese Werte schreibt der Medienserver dann in die Datei ~/.xbmc/temp/xbmc.log. XBMCSwift2 geht ökonomischer vor: Es führt zum Entwanzen Plugins auf der Kommandozeile aus, wobei es eine XBMC-Ersatzbibliothek zwischenschaltet, die als Text ausgibt, was die Erweiterung jetzt innerhalb der XBMC-Struktur tun würde.

Daneben enthält XBMCSwift2 weitere interessante Ansätze, wie etwa die Möglichkeit, interne Plugin-URLs auf komfortablere Weise an bestimmte Unterprogramme zu “binden”. Allerdings weist dieses Framework auch Nachteile auf: Auf der Kommandozeile ausgeführt, können die Ersatzbibliotheken das Verhalten von XBMC nicht in jedem Fall richtig nachstellen. Auch zwingt XBMCSwift den Coding-Stil des Plugin-Schreibers in ein enges Korsett, was nicht jeder mag.

Ausblick

Wir konnten hier nur auf einen kleine Auswahl der vorhandenen Möglichkeiten eingehen und dabei wurden auch nur Plugins genauer betrachten, obwohl – wie anfangs dargestellt – auch noch andere Addon-Arten existieren. Besonders einfach definieren Sie auch eigene Skins, indem Sie das Aussehen des Mediencenters über XML-Definitionen anpassen [5]. Es kann sich daneben auch anbieten, mehrere selbsterstellte Addons miteinander zu kombinieren: Durch solche Verkettungen ergeben sich vielerlei neue Möglichkeiten für XBMC. 

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 04/2013 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

1 Kommentar
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
monika
6 Jahre her

Hallo, es wäre schön wenn dieser Artikel mal ein update bekommen würde. Eigene video Plugins für Kodi 18.4 schreiben.
vielen dank

Nach oben