Hi Andre,
Yes, VDR seems very impressive. It fell below our radar because I don't think it works in the US--our satellite is encryped and their are no PC cards. However, I've done installs in Europe with Myth and our analog cards and it's a total nightmare. Not only the xmltv grabber, but also controlling the satellite box with i/r since every sat box maps channels differently. So, it sounds like VDR is perfect for Europe, and the Americans will probably stick to Myth. Fortunately, it's easy to have both.
First, create a Device Template called 'VDR' in category DCESoftware Wrappers/Media Players. Check that it implements DCE, and check command groups: TV commands and Smart Media Player for now. Add the event 'Playback Info Changed'. Add "This device is controlled via category: Category: Standard Orbiter". This means it's parent device (which spawns it) will be an orbiter. The on screen orbiter will take responsibility for launching VDR in one of our ratpoison windows.
Next, create a Device Template called 'VDR Plug-in'. This will be a plug-in in the router that runs in the same memory space, and manages all the VDR devices. It implements DCE, and check 'Is Plugin'. Also add "This device is controlled via: Device:DCERouter Category: DCE Router". Add the command group 'PVR' plugin.
Now, for both devices run: ./DCEGen -d [DeviceTemplate] from the DCEGen directory within the source tree. That will create the projects in ../VDRxxxx.
For VDR do a: make bin, for VDR Plugin, do a: make so
Put both the resulting binaries in /usr/pluto/bin. In Advanced, Devices, remove teh Myth Plugin from DCE Router, and add VDR Plugin, and remove Myth Player from under OnScreen orbiter, and add VDR.
Now, when you do a 'quick reload router', next time you choose TV it will use VDR instead. So on to the implementation:
You can copy mostly from Myth Plugin/PLayer. Starting with the plugin. Add MediaHandlerBase as a 2nd base class. The Media Plugin will call methods derived in there. Put the ! after the //<-dceag tag (means DCEAuto generated). Otherwise next time you run DCEGen for the plugin it will overwrite your change. ! means 'leave it alone'. Otherwise DCEGen overwrites, because you re-run DCEGen everytime you change the command specs (choose Merge to merge in changes).
//<-dceag-decl-b->!
class MythTV_PlugIn : public MythTV_PlugIn_Command, public MediaHandlerBase
{
//<-dceag-decl-e->
Add the mandatory implementations from Media Handler Base:
/** @brief Each Plugin will create its own instance of MediaStream, so it can create a derived version with extra information */
virtual class MediaStream *CreateMediaStream(class MediaHandlerInfo *pMediaHandlerInfo,vector<class EntertainArea *> &vectEntertainArea,MediaDevice *pMediaDevice,int iPK_Users, deque<MediaFile *> *dequeMediaFile,int StreamID)=0;
virtual bool StartMedia(class MediaStream *pMediaStream)=0;
virtual bool StopMedia(class MediaStream *pMediaStream)=0;
For the moment, just make CreateMediaStream return a new, generic stream. You will likely want to create a more specialized one, like VDR Media Stream which has VDR specific information (like channel, satellite, etc.). That way when VDR Plugin gets a command to move tv from one room to the next you can restore all the settings. But for now just:
return new MediaStream(pMediaHandlerInfo, pMediaDevice, 0, st_RemovableMedia,StreamID);
Then make a simple implementation of StartMedia:
bool VDR_PlugIn::StartMedia(class MediaStream *pMediaStream)
{
DCE::CMD_Start_TV cmd(m_dwPK_Device, pMediaStream->m_pMediaDevice_Source->m_pDeviceData_Router->m_dwPK_Device);
SendCommand(cmd);
DCE:: is a namespace. If you have auto-complete, when you type DCE:: it will give you a list of all commands with the syntax for all the parameters.
In the register function, do this. This find the media plugin, and registers your VDR plugin with it. Since they are both plugins running in the same memory space, they can call each other's methods directly. Normally all pluto devices run as separate programs sending messages over sockets (it's safer). But for media, you normally need a plug-in that will have low-level access to the same classes that media plugin uses:
m_iPriority=DATA_Get_Priority();
/** Get a pointer to the media plugin */
m_pMedia_Plugin=NULL;
ListCommand_Impl *pListCommand_Impl = m_pRouter->m_mapPlugIn_DeviceTemplate_Find(DEVICETEMPLATE_Media_Plugin_CONST);
if( !pListCommand_Impl || pListCommand_Impl->size()!=1 )
{
g_pPlutoLogger->Write(LV_CRITICAL,"VDR plug in cannot find media handler %s",(pListCommand_Impl ? "There were more than 1" : ""));
return false;
}
m_pMedia_Plugin=(Media_Plugin *) pListCommand_Impl->front();
m_pMedia_Plugin->RegisterMediaPlugin(this, this, XXXXX, true);
Note that XXXXX is the device template for VDR. Last thing, add a record to DeviceTemplate_MediaType table in pluto_main database where FK_DeviceTemplate is the VDR, and FK_MediaType is 1 (Live TV). Compile and put your binaries in place. The RegisterMediaPlugin tells Media Plugin that your VDR_Plugin is responsible for managing the VDR devices, which accodring to the database, can handle live tv.
Now do a quick reload DCERouter, either from an orbiter, or send it a reload message: MessageSend localhost 0 -1001 7 1
When you watch the DCERouter logs (/var/log/pluto/DCERouter.newlog) you should see that it registers your VDR Plugin. Also, if you do a screen -ls, a copy of VDR should be running, and you should see it registered in DCERouter's log.
Now hit 'tv' from an orbiter (not the onscreen display on the m/d--use an orbiter on another PC). You should see in the VDR logs:
Need to implement CMD_Start_TV
This means everything is working. And, on the orbiter you should see a pvr remote control. As you tune channels, fast forward, rewind, channel surf, etc. you should see in the VDR logs all these messages.
Eventually we can create a new remote for VDR that has extra VDR-specific buttons. But for now it's best to use the basic one because it's important that VDR implements the same 'smart media player' commands the same way, which is what ensures all remote controls (i/r, phone, tablet, etc.) will work the same way and provide basic control.
If you get stuck, I'll be happy to login and look at the code with you and help. When you're ready, I'll show you how to do a sqlCVS checkin. That will checkin your database changes. And we'll checkin your code into our SVN as well. That way our automated build system will start building your devices.