Hi,
Some friends asked me to modify vdr/write a plugin, because their boxes boot so fast that most of the hardware is not initialized by the time vdr can start. They had to delay it or had to restart vdr when they think the hardware is ready. But since some pci-cards are 'fast enough' they would like to attach the 'slow' cards later while using the 'fast' cards for watching, recording etc. as soon as possible. So 'dynamite' was born (just some kind of wordplay with 'dynamic' and it sounds more 'bombastic' and effective in advertising than 'dyndev' or whatever). :-)
It's clear that this can't be done without patching the device handling inside vdr, so attached is my patch against vdr 1.7.17. It is designed in such a way that the original behaviour of vdr is not changed if the dynamite plugin is not loaded. I know that it is pretty invasive but it is as small as I could to do it. My knowledge of the inner relations of the various classes is certainly limited but I spent hours and hours on reading the source. And it is tested by a brave crew of volunteers. Nonetheless I would like to hear some remarks from the vdr-experts out there.
In the following lines I will try to explain what this patch-plugin-combination is able to do and how it's done. It's a bit lengthy but it's important to me and I know it wouldn't get integrated at all if I don't give a wider overview about the concepts and ideas behind this.
Features: - attach/detach devices While vdr is running you can dynamically attach/detach (unused) receiving devices to/from it. This could be a DVB-USB-stick or a very slow initialising piece of hardware (firmware load etc.).
New devices are detected via udev, detaching should be made manually. If a frontend is in use udev is not sending a corresponding signal, there are just some messages from the usb subsystem, for example. The mapping to the right frontend and detaching it automatically is not trivial (in other words: it's on the TODO list). Also OSD integration is completely missing but will be added in the future.
For attaching/detaching there are SVDRP commands (and Service calls for other plugins): PLUG dynamite ATTD /dev/dvb/adapter0/frontend0 PLUG dynamite DETD /dev/dvb/adapter0/frontend0
For a complete list of commands please read the README[1].
- set device on idle You can set a device to 'idle' mode. It will be ignored by the EIT scanner and closes all its handles. This is handy if you have enough tuners and want so save some power or preserve some frontends from being 'always on'. This is also a 'manual' feature, some kind of automatism is planned (some kind of timeout or similar). Of course it will be 'reanimated' automatically if a recording is starting or someone wants to look live-tv.
- GetTSPacket timeout It is possible to set a 'GetTSPacket' timeout on the devices. If a device delivers no data for some time it can be automatically detached. This is intended for devices which has known unstable drivers. After detaching such a device a script is started so the driver can be reloaded and the device can be attached again to the vdr (this could happen on its own if the created frontend is signaled by udev). It avoids restarts of vdr and interrupting recordings on other devices.
How this all is achieved: The class cDevice is extended by two fields: parentDevice and subDevice. The dynamite plugin provides a class derived from cDevice which passes all calls to its methods to its subDevice if one is attached. Otherwise it returns the appropriate values so vdr does think it can't receive anything (like the dummydevice output-plugin which can play everything). On the other side there are some methods in cDevice which have to be "parentDevice-aware", since they are called from other derived devices or classes inside vdr. Since parentDevice (and subDevice) are always NULL if dynamite isn't loaded, it's easy to preserve the original behaviour.
To get the cDynamicDevice between the vdr and the device-creating plugins dynamite is doing two things: - it registers a cDvbDeviceProbe-object and moves it to the front of the list - the patch adds a second list 'cDynamicDeviceProbe' for 'dynamite-aware' plugins (like pvrinput as an example)
On startup when vdr iterates through the dvb-devices dynamite captures all devices and adds a cDynamicDevice for every one to the global vdr-device-array. It asks all other cDvbDeviceProbes if they would like to create a device and attaches this as a subDevice. If no cDvbDeviceProbe is left it creates a core cDvbDevice on its own. After this it creates enough cDynamicDevice objects to flood the vdr-device-array. This ensures that vdr and other plugins always communicate with the devices through dynamite (like CAM, CI etc.) and so there is enough room for devices which will be attached later. If you use plugins which create (non-dvb-)devices which can't be handled by dynamite (like xine, iptv, streamdev etc.) they have to be loaded *before* dynamite. Actually it's best to load dynamite as the *last* plugin because then it can ensure that its cDvbDeviceProbe will be the first one. The dirtiest part of the patch is the modification of the constructor of cDevice. If the new 'parentDevice' parameter would be made non-optional, I don't have to use this ugly global placeholder... If it really gets integrated in vdr (I don't abandon hope on this), that would definitly gets cleaned up. But that would force changes on many plugins so I chose 'the dirty way'.
Plugins which would like to use the functionallity of dynamite had to alter their device detection in their startup phase: - if dynamite is loaded just register a cDynamicDeviceProbe object and use the helper function QueueDynamicDeviceCommand from cDynamicDeviceProbe to queue the strings it needs to create the device objects. - if dynamite is not present create the devices like before - make sure you close all handles on destruction at the latest
Look at pvrinput[3] as an example (cPvrDevice::Initialize at device.c:269 and at the end of that file) pvrinput uses strings like '/dev/video0' to identify the device it has to create. But these 'attach'-strings doesn't necessarily need to be real device paths. It's just a parameter to the Attach method of your cDynamicDeviceProbe object - so your fantasy limits the possibilities. :-) In the dynamite source you'll find a cDynamiteDeviceProbe which reacts on strings like 'dummydevice0' or 'dummydevice1'. It helped me while developing the SVDRP commands since I had only one DVB-T stick at my dev-vdr. You can activate it with a commandline argument.
There are some caveats if you would like to use other patches together with dynamite if they also extend cDevice. Every new method has to be investigated if it should return its own value or the one of the parentDevice or subDevice (if it's present). And every new virtual method has to be added to cDynamicDevice at the dynamite plugin. If I had 'the power' I would integrate the functionality of cDynamicDevice completly into cDevice and leave the controlling at the plugin - but I'm realistic enough to know, that that would need a lot of convincing for my part... :-) As an example I added a reworked version of the lnb-sharing-patch to my repository[2]. Also I include some methods added by the patches yaVDR uses since this is my preferred distribution.
So, anything left to say? It took me a while to write all this stuff down so for now I don't know if I had forgotten something important or not. I'm looking forward for comments.
Of course I'm never responsible for broken or missed recordings (as no one is)! :-)
Thanks for reading!
Regards, Lars. -- P.S.: If you have a Sundtek stick and are interested in dynamite, please check out the sundtek-plugin[4]. It monitors devices via the libmedia/mediasrv and can even react on unplugging a device which is in use. -- [1] http://projects.vdr-developer.org/projects/plg-dynamite/repository/revisions... [2] git://projects.vdr-developer.org/vdr-plugin-dynamite.git [3] http://projects.vdr-developer.org/projects/plg-pvrinput [4] https://github.com/flensrocker/vdr-plugin-sundtek