Dynamite-plugin
Inhaltsverzeichnis |
Beschreibung
Autor: Lars Hanisch
Mit Hilfe dieses Plugins lassen sich Empfangsgeräte dem vdr entziehen bzw. hinzufügen, während dieser läuft. Dies ist z.B. für USB-Geräte interessant, die zur Auflösung von zu vielen Timer-Konflikten temporär in den Wohnzimmer-vdr gestöpselt werden. Oder auch für Geräte, die eine lange Initialisierungsphase haben und somit den Start des vdr stark verzögern. Mit der internen, schneller initialisierten PCI DVB-Karte kann dann schon mal ferngesehen werden, während so nach und nach die anderen Geräte "aufwachen" und ihre Arbeit aufnehmen.
Weiterhin lassen sich auch "wildgewordene" Treiber wieder reanimieren - kurz das Geräte "aushängen", Treiber neu laden und wieder "einhängen". Dadurch werden Aufnahmen auf anderen Geräten nicht beeinflusst (wenn die natürlich einen anderen Treiber benutzen) und alle sind glücklich...
Ich versuche, das README in den Plugin-Sourcen so aktuell wie möglich zu halten, also solltest du das auf alle Fälle lesen, bevor du dynamite "blind" ausprobierst. Dort sind z.B. auch alle SVDRP-Befehle und die vdr-interne Service-Schnittstelle erklärt.
Wie es funktioniert
Das dynamite-Plugin enthält eine von cDevice abgeleitete Klasse (cDynamicDevice), die sich ähnlich wie das dummydevice als stumpf-dummes Empfangsgerät ausgibt - es kann rein gar nichts empfangen. Durch den Patch wurde cDevice selbst u.a. durch zwei Felder erweitert: parentDevice und subDevice. Diese werden nun von cDynamicDevice dazu genutzt, etwas zu "lernen". Wird z.B. ein neues DVB-Gerät am System angesteckt (z.B. per USB), reagiert dynamite auf das entsprechende udev-Event, sobald das Frontend registriert wird. Danach wird dann die Liste der cDvbDeviceProbe-Objekte abgeklappert, bis sich einer verantwortlich fühlt und ein cDvbDevice o.ä. erstellt hat. Dieses Objekt wird dann als "subDevice" in ein vorhandenes, freies cDynamicDevice eingehängt. Und ab diesem Zeitpunkt kann dieses dann alles empfangen, was sein SubDevice empfangen kann.
Dazu muss cDynamicDevice alle virtuellen Methoden von cDevice überladen und bei vorhandenem SubDevice einfach durchreichen - oder eben den Standardwert aus cDevice zurückgeben. Zusätzlich ist es auch nötig, das einige nicht-virtuelle Methoden angepasst werden und je nach dem, was sie tun, mal die entsprechende Methode des SubDevice bzw. des ParentDevice aufrufen müssen. Ruft z.B. ein als SubDevice eingehängtes Objekt "StartSectionHandler" auf, würde innerhalb dieses Objekts zwar der SectionHandler gestartet werden, aber der vdr würde nichts davon mitbekommen, da dieser nur die cDynamicDevice-Objekte in seinem "device"-Array sieht.
Wird dynamite nun mit anderen Patches oder Plugins kombiniert, muss es also eventuell angepasst werden.
Wie andere Plugins was davon haben
Damit andere Plugins von der HotPlug-Funktionalität profitieren können, wurde ein ähnliches Konstrukt wie cDvbDeviceProbe eingeführt: cDynamicDeviceProbe (siehe gepatchtes device.h)
Wird nun dynamite z.B. über einen SVDRP-Befehl angewiesen, ein Gerät einzuhängen, dass auf den Namen "/dev/video0" hört (svdrpsend plug dynamite attachdevice /dev/video0), wird diese Liste durchgegangen, bis ein von cDevice abgeleitetes Objekt zurückgegeben wird. In diesem Beispiel wird dann pvrinput reagieren und ein Objekt der Klasse cPvrDevice instantiieren. Dieses wird von dynamite dann eingehängt und schon kann das gute, alte Analog-Fernsehen empfangen werden (wenn es denn ein von pvrinput unterstütztes Gerät ist).
Genauso kann dann über "svdrpsend plug dynamite detachdevice /dev/video0" dieses Objekt wieder zerstört werden. Deshalb ist es wichtig, dass diese Klasse im Destruktor auch schön hinter sich aufräumt und alle offenen Handles schließt usw..
Um das Ganze dann auch noch etwas komfortabler zu machen, bietet dynamite die Möglichkeit, auf bestimmte udev-Ereignisse zu reagieren. pvrinput z.B. ruft die entsprechende Service-Schnittstelle "dynamite-AddUdevMonitor-v0.1" von dynamite auf (falls dieses geladen ist) und übergibt die Parameter "video4linux /dev/video". Daraufhin kreiert dynamite einen udev-Monitor für das Subsystem "video4linux". Sollte dort dann ein "add"-Ereignis vorbeikommen, dessen Devnode mit "/dev/video" beginnt, wird der komplette Devnode-String an die oben erwähnte cDynamicDeviceProbe-Liste übergeben. Und wenn pvrinput sich dann dazu in der Lage fühlt, dieses Gerät zu unterstützen, erzeugt es ein cPvrDevice-Objekt dazu und alles geht seinen Weg.
Da der vdr immer mit der Klasse cDvbDevice ausgeliefert wird, läuft standardmäßig schon ein udev-Monitor auf dem Subsystem "dvb", der auf Frontends reagiert, um dann die cDvbDeviceProbe-Liste abzuklappern.
Ladereihenfolge der Plugins
dynamite erstellt so viele cDynamicDevice-Objekte, bis das interne Array des vdr, in dem alle Geräte verwaltet werden, bis zum Rand gefüllt ist. Das macht es deshalb, damit es auch mit Plugins zurecht kommt, die sich in cDvbDeviceProbe einhängen. Deshalb ist es wichtig, dass alle Plugins, die keine von dynamite zu verwaltenen Geräte verwenden, vor dynamite geladen werden. Dazu gehören Ausgabe-Plugins, aber auch streamdev-client, iptv usw.
Ist ein Plugin "dynamite-aware", ist es im Prinzip egal, wann es geladen wird. Es wird dann nämlich in seiner Instantiate-Phase nicht wie bisher seine cDevice-Objekte erstellen, sondern mit der Hilfsfunktion "cDynamicDeviceProbe::QueueDynamicDeviceCommand(ddpcAttach, ...)" einen entsprechenden String an dynamite senden, so dass es später dann von dynamite dazu gebracht wird, das Objekt zu erzeugen.
Softwareanforderungen
- libudev-dev
Entwicklerversion
oder bei github.com bzw.
# von den vdr-Sourcen aus cd PLUGINS/src # wenn Sourcen noch nie geholt: git clone git://projects.vdr-developer.org/vdr-plugin-dynamite.git dynamite # ansonsten cd dynamite ; git pull ; cd .. # danach dann cd ../.. # wenn der Patch noch nicht angewendet wurde patch -n1 < PLUGINS/src/dynamite/vdr-<passende Version>-dynamite.patch # und übersetzen... make plugins