Der X-Server wird über die Systemd-Unit x@vt7.service gestartet, die als Abhängigkeit der Unit xlogin@vdr.service aufgerufen wird. xlogin startet eine Systemd-User Session (die nötigen Units stammen aus dem Paket dbus-user-session). Im Autostat des Window Manager/Desktop-Manager wird die Unit yavdr-frontend.service gestartet. Das Skript yavdr-frontend dient dazu den Start des VDR-Frontend, einem Mediacenter wie KODI und weitere Anwendungen zu koordinieren, und den Wechsel zwischen diesen zu ermöglichen. Es kann über DBus gesteuert werden, so dass seine Aktionen leicht durch Skripte, irexec, Hotkeys des Window-Manager usw. ausgelöst werden können.
yavdr-frontend startet beim Start das konfigurierte Frontend. Das kann ein VDR-Frontend, ein Mediacenter wie KODI oder eine andere Systemd-Unit bzw. Anwendung sein.
main:
# start with the choosen frontend type: vdr|mediacenter|app
primary_frontend = vdr
secondary_frontend = mediacenter
Folgende Umgebungsvariablen werden genutz, um Optionen für die Frontends festzulegen:
Variable | Vorgabewert | Beschreibung |
---|---|---|
DISPLAY | :0 | Bildschirm für das primäre Frontend |
ALSA_DEVICE | hw:0,0 | Gerät für die PCM-Ausgabe über ALSA |
ALSA_AC3_DEVICE | Gerät für die Passthrough-Ausgabe über ALSA | |
AE_SINK | Soundausgabe für KODI (ALSA oder PULSE) |
yavdr-frontend legt auf dem SystemBus unter dem Namen de.yavdr.frontend ein Objekt an, das unter dem Pfad **/frontend** die folgenden Funktionen bietet:
- start
- starte das momentan gewählte Frontend
- stop
- stoppe das momentan aktive Frontend
- toggle
- starte das Frontend, wenn es inaktiv ist, stoppe es, wenn es aktiv ist
- switch
- wechlse zum anderen Frontend
- switchTo string:”FRONTEND NAME”
- wechsle zum Frontend mit dem angegebenen Namen
- setDisplay string:”DISPLAY”
- setze das Display, auf dem das primäre Frontend angezeigt werden soll, also z.B. “:0” oder “:0.1”
- setNext string:”FRONTEND NAME”
- setze das nächste Frontend, aber wechsle nicht sofort
- switchBetween string:”FRONTEND A” string:”FRONTEND B”
- wechsle zu Frontend A, wenn dieses aktuell nicht gewählt ist, sonst zu Frontend B
Mit dem Hilfsskript frontend-dbus-send können diese Befehle leicht in einem Skript genutzt werden, z.B. um zum Mediacenter (oder zum zuletzt genutzten Frontend zurück) zu wechseln:
frontend-dbus-send switchBetween string:vdr string:mediacenter
yavdr-frontend initialisiert ein Objekt der Klasse VDRFrontend. Dieses wartet auf den Start des VDR und fragt über das dbus2vdr-Plugin die vom VDR geladenen Plugins ab. Dann sucht es unter Berücksichtigung der Reihenfolge der Einträge im Abschnitt [VDR-Frontends] in seiner Konfigurationsdatei ein passendes Frontend-Objekt heraus. Das Frontend kann im einfachsten Fall eine .desktop-Datei sein, alternativ kann auch eine Systemd-Unit oder ein Python-Modul genutzt werden. In den beiden erstgenannten Fällen wird ein Python-Wrapper genutzt, um die benötigten Methoden (start(), stop(), on_stopped()) zu implementieren.
In der Konfigurationsdatei wird einem VDR-Ausgabeplugin ein entsprechendes Frontend zugewiesen:
vdr:
frontends:
# <plugin name> = <type> <path> [<object>]
# type can be one of:
# module (Python-Module)
# unit (Systemd Unit)
# app (.desktop file)
softhddevice:
module_name: frontends.softhddevice
class_name: Softhddevice
xineliboutput:
app: vdr-sxfe.desktop
xine:
unit xine.service
rpihddevice:
module_name: frontends.rpihddevice
class_name: RPIHDDevice
Ob das Frontend beim Start sofort gestartet wird oder in dem Fall, dass der VDR für eine Aufnahme gestartet wurde erst nachträglich durch den Benutzer (z.B. per Tastendruck auf der Fernbedienung) aktiviert wird, kann über die Konfigurationsdatei festgelegt werden:
vdr:
# allowed values for attach_frontend:
# auto: attach only on manual start
# never: never start the frontend autmatically
# always: always start frontend
attach_frontend = auto
Anstatt wie bei früheren yaVDR-Version fest auf XBMC/KODI zu setzen, soll das bei yaVDR 0.7 generischer gelöst werden, so dass es möglich wird z.B. Plex oder andere Programme als Mediacenter zu nutzen. Vor dem Wechsel zum Mediacenter wird ein laufendes VDR-Frontend oder eine andere Standalone-Anwendung automatisch gestoppt.
Die Syntax entspricht der für die VDR-Frontends. Der Abschnitt in der Konfigurationsdatei sieht z.B. so aus:
applications:
mediacenter:
name: kodi.service
Für KODI genügt es nicht den normalen Starter aus der KODI.desktop zu nutzen, da es nicht sauber auf ein SIGTERM-Signal reagiert (bleibt z.B. mitunter beim Beenden hängen). Daher wird es in der Unit kodi.service gezielt über seine RPC-API beendet und dann wird darauf gewartet, dass der Prozess tatsächlich beendet wurde (und damit alle Ressourcen wieder freigegeben wurden), da es sonst zu Folgeproblemen wie noch belegten Soundkarten für das nachfolgende Frontend kommen kann.
Das vdr-plugin-desktop stellt die vorhandenen .desktop-Dateien in einer Menü-Struktur dar und ruft ein externes Skript mit dem Pfad der .desktop-Datei auf, wenn der Benutzer eine Anwendung ausgewählt hat. Das Skript wird vom Plugin in /var/lib/vdr/plugins/desktop/starter erwartet. Ein Beispielskript ist im Quellcode des Plugins zu finden: [starter][]
[starter]: https://github.com/flensrocker/vdr-plugin-desktop/blob/master/examples/starter
Das starter-Skript gibt die .desktop-Datei über die DBus-API an yavdr-frontend weiter.
Daneben könnte man z.B. eine angepasste Version von adeskbar oder einen anderen Programmstarter nutzen, der sich ähnlich verhält.
Um Programme in der Session aufzurufen, benötigen wir ein Hilfsskript, dem die .desktop-Dateien übergeben werden und das den Pfad an yavdr-frontend weiterreicht, das den Start der Anwendung übernimmt.
In der User-Session kann pulseaudio genutzt werden, so dass auch moderne Programme ohne Alsa-Unterstützung Ton ausgeben können. Wenn ein Programm nur alsa-Unterstützung bietet oder direkten Zugriff auf die Hardware benötigt (z.B. für bestimmte Passthrough-Formate), kann es mittels pasuspender oder yavdr-pasuspend pulseaudio dazu veranlassen seine Ausgabe stummzuschalten und die Audiogeräte freizugeben. pasuspender nimm ein Programm als Argument, das direkten Zugriff auf die Audio-Hardware haben soll, die Ausgabe über pulseaudio wird so lange unterbrochen, bis das Programm beendet wird. yavdr-pasuspend ermöglicht es die pulseaudio-Ausgabe an- und abzuschalten, was z.B. für softhddevice praktisch ist, da das kein eigenständiges Programm ist:
# schalte pulseaudio für ein bestimmtes Programm ab:
pasuspender -- audacity
# schalte pulseaudio bis auf weiteres ab:
yavdr-pasuspend -s
svdrpsend plug softhddevice atta
# und wenn es nicht mehr gebraucht wird:
svdrpsend plug softhddevice deta
yavdr-pasuspend -r
Der direkte Zugriff auf die Audio-Hardware funktioniert nur für den Nutzer, unter dem Pulseaudio läuft (und root).
Ein neues Frontend sollte von der Basis-Klasse BasicFrontend abgeleitet werden. Wird eine eigene __init__()
Funtion genutzt, muss die Controller-Instanz als Argument akzeptiert werden (alle anderen Argumente müssen optional sein):
controller
- die Klasseninstanz, die das Frontend verwaltet
name
- der Name des Frontend
fe_type
- der Typ des Frontends
Diese müssen dann an die __init__()
Methode der Basisklasse weitergegeben werden:
from yavdr_frontend.basicfrontend import BasicFrontend
class MyFrontend(BasicFrontend)
name = "MyFrontend"
fe_type = "CustomFrontend"
def __init__(self, controller):
super().__init__(controller, name, fe_type)
# do other stuff
Darüber hinaus sollte es die folgenden Methoden implementieren (die Basis-Klasse BasicFrontend
fungiert wie ein Dummy-Frontend, das das Interface abbildet, ohne etwas zu tun):
start(self)
- starte das Frontend
started(self)
- setzt die Status-Variable
is_running
auf aktiv, wenn der Start erfolgreich war stop(self)
- stoppt das Frontend
stopped(self)
- wenn das Frontend gestoppt wurde, muss es die on_stopped() Methode des Controller aufrufen und den Status
is_running
zu false ändern