]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Get preferred audio and subtitle languages from vdr including subtitle status and...
[vompclient.git] / vdr.cc
1 /*
2     Copyright 2004-2008 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "vdr.h"
22
23 #include "recman.h"
24 #include "tcp.h"
25 #include "log.h"
26 #include "recinfo.h"
27 #include "dsock.h"
28 #include "channel.h"
29 #include "event.h"
30 #include "wol.h"
31 #include "vdrrequestpacket.h"
32 #include "vdrresponsepacket.h"
33 #include "command.h"
34 #ifdef VOMP_MEDIAPLAYER
35 #include "media.h"
36 #include "mediaprovider.h"
37 #include "mediaproviderids.h"
38 #endif
39 #include "vdrcommand.h"
40 #include "video.h"
41 #include "osd.h"
42 #include "movieinfo.h"
43 #include "seriesinfo.h"
44 #include "osdvector.h"
45 #include "tvmedia.h"
46
47 #define VOMP_PROTOCOLL_VERSION 0x00000302
48
49 VDR* VDR::instance = NULL;
50 #ifdef VOMP_MEDIAPLAYER
51 //prepare a request
52 //will create a request package from a command variable and fill this
53 //caller has to destroy buffer
54 static SerializeBuffer * prepareRequest(VDR_Command *cmd) {
55   SerializeBuffer *buf=new SerializeBuffer(512,false,true);
56   if (cmd->serialize(buf) != 0) {
57     delete buf;
58     return NULL;
59   }
60   return buf;
61 }
62
63 //handle request/response
64 //TODO avoid copy of buffer (needs extension of requestpacket)
65 //TODO avoid command 2x (needs some more restructuring)
66 SerializeBuffer * VDR::doRequestResponse(SerializeBuffer *rq,int cmd) {
67   VDR_RequestPacket *rt=new VDR_RequestPacket;
68   if (! rt) {
69     delete rq;
70     return NULL;
71   }
72   if (! rt->init(cmd,true,rq->getCurrent()-rq->getStart())) {
73     delete rq;
74     delete rt;
75     return NULL;
76   }
77   if (! rt->copyin(rq->getStart(),(ULONG)(rq->getCurrent()-rq->getStart()))) {
78     delete rq;
79     delete rt;
80     return NULL;
81   }
82   delete rq;
83   VDR_ResponsePacket *rp=RequestResponse(rt);
84   logger->log("doRequestResponse",Log::DEBUG,"got response %p",rp);
85   if ( !rp) {
86     delete rt;
87     return NULL;
88   }
89   SerializeBuffer *buf=new SerializeBuffer(rp->getUserData(),rp->getUserDataLength(),true,true,false);
90   delete rp;
91   return buf;
92 }
93
94
95
96 //deserialize a received response
97 //delete the package
98 //return !=0 on error
99 static int decodeResponse(SerializeBuffer *rp,VDR_Command *c) {
100   ULONG expected=c->command;
101   if (c->deserialize(rp) != 0) {
102     delete rp;
103     Log::getInstance()->log("VDR", Log::ERR, "decodeResponse unable to deserialize for command %lu",expected);
104     return -1;
105   }
106   delete rp;
107   if (c->command != expected) {
108    Log::getInstance()->log("VDR", Log::ERR, "decodeResponse unexpected response received 0x%lx, expected 0x%lx",c->command,expected);
109     return -1;
110   }
111   Log::getInstance()->log("VDR", Log::DEBUG, "decodeResponse successfully decoded command 0x%lx",expected);
112   return 0;
113 }
114
115 #endif
116
117 VDR::VDR()
118 {
119   if (instance) return;
120   instance = this;
121   initted = 0;
122   findingServer = 0;
123   tcp = NULL;
124   connected = false;
125   maxChannelNumber = 0;
126   channelNumberWidth = 1;
127   doVDRShutdown = false;
128   TEMP_SINGLE_VDR_PR = NULL;
129 #ifdef VOMP_MEDIAPLAYER
130   providerId=MPROVIDERID_VDR;
131   subRange=MPROVIDERRANGE_VDR;
132   MediaPlayerRegister::getInstance()->registerMediaProvider(this,MPROVIDERID_VDR,MPROVIDERRANGE_VDR);
133 #endif
134 }
135
136 VDR::~VDR()
137 {
138   instance = NULL;
139   if (initted) shutdown();
140 }
141
142 VDR* VDR::getInstance()
143 {
144   return instance;
145 }
146
147 int VDR::init(int tport)
148 {
149   if (initted) return 0;
150   initted = 1;
151   port = tport;
152   logger = Log::getInstance();
153   return 1;
154 }
155
156 int VDR::shutdown()
157 {
158   if (!initted) return 0;
159   initted = 0;
160   disconnect();
161   return 1;
162 }
163
164 void VDR::findServers(vector<VDRServer>& servers)
165 {
166   Wol* wol = Wol::getInstance();
167   findingServer = 1;
168   char message[15];
169   memset(message, 0, 15);
170   strcpy(message, "VDP-0001");
171   /*tcp->getMAC(&message[9]); put mac here when TCP modified to do this*/
172
173   DatagramSocket ds(0);
174   int haveAtLeastOne = 0;
175   int retval;
176   int waitType = 1;
177   bool firstloop = true;
178   while(findingServer)
179   {
180     if (waitType == 1)
181     {
182       ds.shutdown();
183       ds.init();
184       logger->log("VDR", Log::NOTICE, "Broadcasting for server");
185       ds.send("255.255.255.255", 51051, message, 15);
186       ds.send("255.255.255.255", 51052, message, 15);
187       ds.send("255.255.255.255", 51053, message, 15);
188       ds.send("255.255.255.255", 51054, message, 15);
189       ds.send("255.255.255.255", 51055, message, 15);
190       if(!firstloop) wol->doWakeUp();
191     }
192     retval = ds.waitforMessage(waitType);
193
194     if (retval == 2) // we got a reply
195     {
196       waitType = 2;
197       
198       char* vdpreply = ds.getData();
199       if ((ds.getDataLength() >= 24) && !strncmp(vdpreply, "VDP-0002", 8))
200       {
201         VDRServer newServer;
202         // FIXME upgrade this to look for a return IP in the reply packet
203         newServer.ip = new char[16];
204         strcpy(newServer.ip, ds.getFromIPA());
205
206         USHORT newServerPort;
207         memcpy(&newServerPort, &vdpreply[26], 2);
208         newServer.port = ntohs(newServerPort);
209
210         ULONG newServerVersion;
211         memcpy(&newServerVersion, &vdpreply[28], 4);
212         newServer.version = ntohl(newServerVersion);
213
214         int newServerNameLength = ds.getDataLength() - 32;
215         newServer.name = new char[newServerNameLength];
216         strcpy(newServer.name, &vdpreply[32]);
217
218         servers.push_back(newServer);
219         haveAtLeastOne = 1;
220       }
221     }
222     else
223     {
224       if (haveAtLeastOne) break;
225       waitType = 1;
226       firstloop = false;
227 /* For DEBUGGING *
228       { VDRServer newServer;
229       newServer.ip = new char[16];
230       strcpy(newServer.ip, "192.168.1.7");
231       newServer.name = new char[6];
232       strcpy(newServer.name,"debug");
233       servers.push_back(newServer);
234       waitType = 2;
235       haveAtLeastOne = 1;}/ * */
236
237
238
239     }
240   }
241   logger->log("VDR", Log::NOTICE, "END loop");
242   sort(servers.begin(), servers.end(), ServerSorter());
243 }
244
245 void VDR::cancelFindingServer()
246 {
247   findingServer = 0;
248 }
249
250 void VDR::setServerIP(char* newIP)
251 {
252   strcpy(serverIP, newIP);
253 }
254
255 void VDR::setServerPort(USHORT newPort)
256 {
257   serverPort = newPort;
258 }
259
260 int VDR::connect()
261 {
262   maxChannelNumber = 0;
263   channelNumberWidth = 1;
264
265   if (tcp) delete tcp;
266   tcp = new TCP();
267   if (tcp->connectTo(serverIP, serverPort))
268   {
269     connected = true;
270     threadStart();
271     return 1;
272   }
273   else
274   {
275     return 0;
276   }
277 }
278
279 void VDR::disconnect()
280 {
281   threadCancel();
282   if (tcp) delete tcp;
283   tcp = NULL;
284   connected = false;
285   logger->log("VDR", Log::DEBUG, "Disconnect");
286 }
287
288 void VDR::setReceiveWindow(size_t size)
289 {
290   if (connected && size) tcp->setReceiveWindow(size);
291 }
292
293 ///////////////////////////////////////////////////////
294
295 void VDR::threadMethod()
296 {
297   logger->log("VDR", Log::DEBUG, "VDR RUN");  
298
299   threadSetKillable(); // FIXME - change this to deal with the EDRs
300   
301   ULONG channelID;
302   
303   ULONG requestID;
304   ULONG userDataLength;
305   UCHAR* userData;
306
307   ULONG streamID;
308   ULONG flag;
309
310   VDR_ResponsePacket* vresp;
311   
312   ULONG timeNow = 0;
313   ULONG lastKAsent = 0;
314   ULONG lastKArecv = time(NULL);
315   int readSuccess;
316
317   while(1)
318   {
319     timeNow = time(NULL);
320     
321     readSuccess = tcp->readData((UCHAR*)&channelID, sizeof(ULONG));  // 2s timeout atm
322
323     if (!readSuccess)
324     {
325       //logger->log("VDR", Log::DEBUG, "Net read timeout");
326       if (!tcp->isConnected()) { connectionDied(); return; } // return to stop this thread
327     }
328       
329     // Error or timeout.
330
331     if (!lastKAsent) // have not sent a KA
332     {
333       if (lastKArecv < (timeNow - 5))
334       {
335         logger->log("VDR", Log::DEBUG, "Sending KA packet");
336         if (!sendKA(timeNow))
337         {
338           logger->log("VDR", Log::DEBUG, "Could not send KA, calling connectionDied");
339           connectionDied();
340           return;
341         }
342         lastKAsent = timeNow;
343       }
344     }
345     else
346     {
347       if (lastKAsent <= (timeNow - 10))
348       {
349         logger->log("VDR", Log::DEBUG, "lastKA over 10s ago, calling connectionDied");
350         connectionDied();
351         return;
352       }    
353     }
354
355     if (!readSuccess) continue; // no data was read but the connection is ok.
356     
357     // Data was read
358             
359     channelID = ntohl(channelID);
360
361     if (channelID == CHANNEL_REQUEST_RESPONSE)
362     {
363       if (!tcp->readData((UCHAR*)&requestID, sizeof(ULONG))) break;
364       requestID = ntohl(requestID);
365       if (!tcp->readData((UCHAR*)&userDataLength, sizeof(ULONG))) break;
366       userDataLength = ntohl(userDataLength);
367       if (userDataLength > 5000000) break; // how big can these packets get?
368       userData = NULL;
369       if (userDataLength > 0)
370       {
371         userData = (UCHAR*)malloc(userDataLength);
372         if (!userData) break;
373         if (!tcp->readData(userData, userDataLength)) break;
374       }
375
376       vresp = new VDR_ResponsePacket();  
377       vresp->setResponse(requestID, userData, userDataLength);
378       logger->log("VDR", Log::DEBUG, "Rxd a response packet, requestID=%lu, len=%lu", requestID, userDataLength);
379
380       if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
381       {
382         // If edFindAndCall returns true, edr was called and vresp was handed off.
383         // else, delete vresp here.
384         delete vresp;
385       }
386     }
387     else if (channelID == CHANNEL_STREAM || channelID == CHANNEL_TVMEDIA)
388     {
389       if (!tcp->readData((UCHAR*)&streamID, sizeof(ULONG))) break;
390       streamID = ntohl(streamID);
391
392       if (!tcp->readData((UCHAR*)&flag, sizeof(ULONG))) break;
393       flag = ntohl(flag);
394
395       if (!tcp->readData((UCHAR*)&userDataLength, sizeof(ULONG))) break; 
396       userDataLength = ntohl(userDataLength);
397       userData = NULL;
398       if (userDataLength > 0)
399       {
400         userData = (UCHAR*)malloc(userDataLength);
401         if (!userData) break;
402         if (!tcp->readData(userData, userDataLength)) break;
403       }
404
405       vresp = new VDR_ResponsePacket();    
406       vresp->setStream(streamID, flag, userData, userDataLength, channelID);
407       //logger->log("VDR", Log::DEBUG, "Rxd a stream packet, streamID=%lu, flag=%lu, len=%lu", streamID, flag, userDataLength);
408
409       if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
410       {
411         // If edFindAndCall returns true, edr was called and vresp was handed off.
412         // else, delete vresp here.
413         delete vresp;
414       }
415     }
416     else if (channelID == CHANNEL_KEEPALIVE)
417     {
418       ULONG KAreply = 0;
419       if (!tcp->readData((UCHAR*)&KAreply, sizeof(ULONG))) break;
420       KAreply = (ULONG)ntohl(KAreply);
421       if (KAreply == lastKAsent) // successful KA response
422       {
423         lastKAsent = 0;
424         lastKArecv = KAreply;
425         logger->log("VDR", Log::DEBUG, "Rxd correct KA reply");
426       }
427     }
428     else
429     {
430       logger->log("VDR", Log::ERR, "Rxd a response packet on channel %lu !!", channelID);
431       break;
432     }
433     threadCheckExit();
434
435
436     // Who deletes vresp?
437     // If RR, the individual protocol functions must delete vresp.
438     // If stream, the data and length is taken out in ed_cb_call and vresp is deleted there.
439   }
440  
441   connectionDied();
442 }
443
444 void VDR::connectionDied()
445 {
446   // Called from within threadMethod to do cleanup if it decides the connection has died
447
448   connected = false; // though actually it could still be connected until someone calls vdr->disconnect
449
450   // Need to wake up any waiting channel 1 request-response threads
451   // Normally this is done by a packet coming in with channelid and requestid      
452   // Instead, go through the list and for each channel 1 edr, make an empty vresp
453   // An empty vresp will have userData == NULL, which means vresp->noResponse() == true
454
455   // If it's a stream receiver, generate a stream packet with flag == connection_lost
456
457   edLock();
458   VDR_PacketReceiver* vdrpr;
459   VDR_ResponsePacket* vresp;
460   while(receivers.size())
461   {
462     vdrpr = (VDR_PacketReceiver*) *(receivers.begin());
463     if (vdrpr->receiverChannel == CHANNEL_REQUEST_RESPONSE)
464     {
465       vresp = new VDR_ResponsePacket();
466       vresp->setResponse(vdrpr->requestSerialNumber, NULL, 0);
467       logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for request serial %lu", vdrpr->requestSerialNumber);
468       edUnlock();
469       if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
470       {
471         // If edFindAndCall returns true, edr was called and vresp was handed off.
472         // else, delete vresp here.
473         logger->log("VDR", Log::ERR, "Timeouts: no waiting thread found for request serial %lu !!!", vdrpr->requestSerialNumber);
474         delete vresp;
475       }
476       edLock();
477     }
478     else if (vdrpr->receiverChannel == CHANNEL_STREAM || vdrpr->receiverChannel == CHANNEL_TVMEDIA)
479     {
480       vresp = new VDR_ResponsePacket();
481       vresp->setStream(vdrpr->streamID, 2 /* connection-lost flag */ , NULL, 0, vdrpr->receiverChannel);
482       logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for streamid %lu", vdrpr->streamID);
483       edUnlock();
484       if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
485       {
486         // If edFindAndCall returns true, edr was called and vresp was handed off.
487         // else, delete vresp here.
488         logger->log("VDR", Log::ERR, "Timeouts: no waiting stream receiver found for streamid %lu !!!", vdrpr->streamID);
489         delete vresp;
490       }
491       edLock();
492       
493       for(EDRL::iterator i = receivers.begin(); i != receivers.end(); i++)
494         if ((VDR_PacketReceiver*)*i == vdrpr) { receivers.erase(i); break; }
495     }
496   }
497   edUnlock();
498   // Ok, all event receviers should be dealt with. just in case there weren't any, inform command
499   logger->log("VDR", Log::DEBUG, "edUnlock at end of connectionDied");
500
501   Command::getInstance()->connectionLost();
502 }
503
504 bool VDR::ed_cb_find(EDReceiver* edr, void* userTag)
505 {
506   // edr is a VDR_PacketReceiver object made in VDR::RequestResponse
507   // userTag is a VDR_ResponsePacket made in threadMethod
508
509   VDR_PacketReceiver* vdrpr = (VDR_PacketReceiver*)edr;
510   VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag;
511   
512   // Is vresp for vdrpr ?
513   
514   ULONG packetChannel = vresp->getChannelID();
515   //logger->log("VDR", Log::DEBUG, "TVMedia debug %d %d %x", vdrpr->receiverChannel,packetChannel,vdrpr);
516   if (vdrpr->receiverChannel != packetChannel) return false;
517
518   if (packetChannel == CHANNEL_REQUEST_RESPONSE)
519   {
520     if (vdrpr->requestSerialNumber == vresp->getRequestID()) return true;
521   }
522   else if (packetChannel == CHANNEL_STREAM)
523   {
524     if (vdrpr->streamID == vresp->getStreamID()) return true;
525   } else  if (packetChannel == CHANNEL_TVMEDIA)
526   { //We want them all
527     return true;
528   }
529  
530   return false;
531 }
532
533 VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp)
534 {
535   //logger->log("VDR", Log::DEBUG, "RR %lu", vrp->getOpcode());
536
537   if (!connected)
538   {
539     logger->log("VDR", Log::DEBUG, "RR when !connected");
540     VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
541     return vresp; // "no-response" return
542   }
543
544   // ED make new VDR and register
545   // make a VDR_PacketReceiver
546   // - init with serial number of request packet
547
548   VDR_PacketReceiver vdrpr;
549 //  vdrpr.requestTime = time(NULL);
550   vdrpr.receiverChannel = VDR::CHANNEL_REQUEST_RESPONSE;
551   vdrpr.requestSerialNumber = vrp->getSerial();
552
553   edRegister(&vdrpr);
554    
555   edLock();  
556
557   if ((ULONG)tcp->sendData(vrp->getPtr(), vrp->getLen()) != vrp->getLen())
558   {
559     edUnlock();
560     edUnregister(&vdrpr);
561     VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
562     return vresp; // "no-response" return
563   }
564
565   // Sleep and block this thread. The sleep unlocks the mutex
566   logger->log("VDR", Log::DEBUG, "RR sleep - opcode %lu", vrp->getOpcode());
567   edSleepThisReceiver(&vdrpr);
568   logger->log("VDR", Log::DEBUG, "RR unsleep");
569     
570   // Woken because a response packet has arrived, mutex will be locked
571   logger->log("VDR", Log::DEBUG, "Packet delivered to me, requestID: %lu", vdrpr.save_vresp->getRequestID());
572   
573   edUnlock();
574   return vdrpr.save_vresp;
575 }
576
577 bool VDR::sendKA(ULONG timeStamp)
578 {
579   char buffer[8];
580
581   int pos=0;
582   ULONG ul=CHANNEL_KEEPALIVE;
583   buffer[pos++]=(ul>>24)&0xff;
584   buffer[pos++]=(ul>>16)&0xff;
585   buffer[pos++]=(ul>>8)&0xff;
586   buffer[pos++]=ul &0xff;
587   ul=timeStamp;
588   buffer[pos++]=(ul>>24)&0xff;
589   buffer[pos++]=(ul>>16)&0xff;
590   buffer[pos++]=(ul>>8)&0xff;
591   buffer[pos++]=ul &0xff;
592   if ((ULONG)tcp->sendData(buffer, 8) != 8) return false;
593   return true;
594 }
595
596 /////////////////////////////////////////////////////////////////////////////
597
598 // Here VDR takes a break for the VDR_PacketReceiver helper class
599
600 bool VDR_PacketReceiver::call(void* userTag, bool & deleteme)
601 {
602   if (receiverChannel == VDR::CHANNEL_REQUEST_RESPONSE)
603   {
604     // It's a RR. Save vresp and, signal the waiting thread and return.
605     // VDR::RequestResponse will be blocking waiting for this to happen.
606     // That function has a pointer to this object and can read save_vresp.
607     save_vresp = (VDR_ResponsePacket*)userTag;
608     deleteme=false;
609     return true; // Signals ED to remove edr from receivers and wake up edr thread
610   }
611   
612   if (receiverChannel == VDR::CHANNEL_STREAM)
613   {
614     // It's a stream packet.
615     VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag;
616     streamReceiver->streamReceive(vresp->getFlag(), vresp->getUserData(), vresp->getUserDataLength());
617     delete vresp;
618     deleteme=false;
619     return false;
620   }
621   if (receiverChannel == VDR::CHANNEL_TVMEDIA)
622   {
623           // It's TVMedia
624           VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag;
625           Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia Pictures arrived VDR %x",vresp->getStreamID());
626           OsdVector *osd=dynamic_cast<OsdVector*>(Osd::getInstance());
627           if (osd) osd->getPictReader()->receivePicture(vresp);
628           else delete vresp; //nonsense
629           deleteme=false;
630           return true;
631   }
632
633
634   abort(); // unknown receiverChannel, should not happen
635 }
636
637 /////////////////////////////////////////////////////////////////////////////
638
639 int VDR::doLogin(unsigned int* v_server_min, unsigned int* v_server_max, unsigned int* v_client,
640                 ASLPrefList& list, int &subtitles)
641 {
642   VDR_RequestPacket vrp;
643   if (!vrp.init(VDR_LOGIN, true, 6)) return 0;
644
645   char* mactemp[6];
646   tcp->getMAC((char*)mactemp);
647   if (!vrp.copyin((UCHAR*)mactemp, 6)) return 0;
648
649   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
650   if (vresp->noResponse()) { delete vresp; return 0; }
651
652   ULONG vdrTime = vresp->extractULONG();
653   logger->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
654   long vdrTimeOffset = vresp->extractLONG();
655   logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
656
657   unsigned int version_min=vresp->extractULONG();
658
659   *v_server_min=version_min;
660   unsigned int version_max=vresp->extractULONG();
661   *v_server_max=version_max;
662   *v_client=VOMP_PROTOCOLL_VERSION;
663
664   unsigned int numlangcodes = vresp->extractULONG();
665   subtitles = vresp->extractULONG();
666   list.clear();
667   for (int i=0; i<numlangcodes; i++) {
668           ASLPref newpref;
669           newpref.audiopref = vresp->extractLONG();
670           newpref.subtitlepref = vresp->extractLONG();
671           newpref.langcode = vresp->extractStdString();
672           //logger->log("VDR", Log::DEBUG, "Langpref %s %d %d", newpref.langcode.c_str(),  newpref.audiopref,  newpref.subtitlepref);
673           list.push_back(newpref);
674   }
675
676
677   delete vresp;
678
679   if ((version_min > VOMP_PROTOCOLL_VERSION)
680                   || (version_max < VOMP_PROTOCOLL_VERSION) ) {
681
682           return 0;
683
684   }
685
686   // Set the time and zone on the MVP only
687
688 #if !defined(WIN32) && !defined(__ANDROID__)
689   struct timespec currentTime;
690   currentTime.tv_sec = vdrTime;
691   currentTime.tv_nsec = 0;
692
693   int b = clock_settime(CLOCK_REALTIME, &currentTime);
694
695   logger->log("VDR", Log::DEBUG, "set clock = %u", b);
696
697   // now make a TZ variable and set it
698   char sign;
699   int hours;
700   int minutes;
701   if (vdrTimeOffset > 0) sign = '-';
702   else sign = '+';
703
704   vdrTimeOffset = abs(vdrTimeOffset);
705
706   hours = (int)vdrTimeOffset / 3600;
707   minutes = vdrTimeOffset % 3600;
708
709   logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
710
711   minutes = (int)minutes / 60;
712
713   logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
714
715   char newTZ[30];
716   sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
717   setenv("TZ", newTZ, 1);
718
719   logger->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
720 #endif
721
722   setCharset(Osd::getInstance()->charSet());
723
724   return 1;
725 }
726
727 bool VDR::LogExtern(const char* logString)
728 {
729   if (!connected) return false;
730   int stringLength = strlen(logString);
731   int packetLength = stringLength + 8;
732   char *buffer=new char[packetLength + 1];
733   int pos=0;
734   ULONG ul=CHANNEL_NETLOG;
735   buffer[pos++]=(ul>>24)&0xff;
736   buffer[pos++]=(ul>>16)&0xff;
737   buffer[pos++]=(ul>>8)&0xff;
738   buffer[pos++]=ul &0xff;
739   ul=stringLength;
740   buffer[pos++]=(ul>>24)&0xff;
741   buffer[pos++]=(ul>>16)&0xff;
742   buffer[pos++]=(ul>>8)&0xff;
743   buffer[pos++]=ul &0xff;
744
745   strcpy(&buffer[8], logString);
746   
747   if (tcp->sendData(buffer, packetLength) != packetLength)
748   {
749     connected = false; // stop the rest of the connection  
750     delete [] buffer;
751     return false;
752   }
753   delete [] buffer;
754   return true;
755 }
756
757 bool VDR::setCharset(int charset)
758 {
759   VDR_RequestPacket vrp;
760   if (!vrp.init(VDR_SETCHARSET, true, sizeof(ULONG))) return false;
761   if (!vrp.addULONG(charset)) return false;
762
763   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
764   if (vresp->noResponse()) { delete vresp; return false; }
765
766   ULONG success = vresp->extractULONG();
767   delete vresp;
768
769   if (!success) return false;
770
771   return true;
772 }
773
774 bool VDR::getRecordingsList(RecMan* recman)
775 {
776   VDR_RequestPacket vrp;
777   if (!vrp.init(VDR_GETRECORDINGLIST, true, 0)) return false;
778
779   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
780   if (vresp->noResponse()) { delete vresp; return false; }
781
782   ULONG totalSpace = vresp->extractULONG();
783   ULONG freeSpace = vresp->extractULONG();
784   ULONG percent = vresp->extractULONG();
785
786   recman->setStats(totalSpace, freeSpace, percent);
787
788   ULONG start;
789   UCHAR isNew;
790   char* name;
791   char* fileName;
792
793   while (!vresp->end())
794   {
795     start = vresp->extractULONG();
796     isNew = vresp->extractUCHAR();
797     name = vresp->extractString();
798     fileName = vresp->extractString();
799     recman->addEntry(isNew, start, name, fileName);
800     delete[] name;
801     delete[] fileName;
802   }
803   delete vresp;
804
805   return true;
806 }
807
808 int VDR::deleteRecording(char* fileName)
809 {
810   VDR_RequestPacket vrp;
811   if (!vrp.init(VDR_DELETERECORDING, true, strlen(fileName) + 1)) return 0;
812   if (!vrp.addString(fileName)) return 0;
813   
814   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
815   if (vresp->noResponse()) { delete vresp; return 0; }
816   
817   int toReturn = (int)vresp->extractULONG();
818   delete vresp;
819
820   return toReturn;
821 }
822
823 char* VDR::moveRecording(char* fileName, char* newPath)
824 {
825   VDR_RequestPacket vrp;
826   if (!vrp.init(VDR_MOVERECORDING, true, strlen(fileName) + 1 + strlen(newPath) + 1)) return NULL;
827   if (!vrp.addString(fileName)) return NULL;
828   if (!vrp.addString(newPath)) return NULL;
829   
830   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
831   if (vresp->noResponse()) { delete vresp; return NULL; }
832   
833   char* toReturn = NULL;
834   int success = (int)vresp->extractULONG();
835   if (success == 1)
836   {
837     toReturn = vresp->extractString();
838   }
839
840   delete vresp;
841
842   return toReturn;
843 }
844
845 ChannelList* VDR::getChannelsList(ULONG type)
846 {
847   VDR_RequestPacket vrp;
848   if (!vrp.init(VDR_GETCHANNELLIST, true, 0)) return NULL;
849
850   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
851   if (vresp->noResponse()) { delete vresp; return NULL; }
852   
853   ChannelList* chanList = new ChannelList();
854
855   bool h264support=Video::getInstance()->supportsh264();
856   bool mpeg2support=Video::getInstance()->supportsmpeg2();
857
858   while (!vresp->end())
859   {
860     Channel* chan = new Channel();
861     chan->number = vresp->extractULONG();
862     chan->type = vresp->extractULONG();
863     chan->name = vresp->extractString();
864     chan->vstreamtype = vresp->extractULONG();
865
866     if (chan->type == type && ((chan->vstreamtype==0x1b && h264support)|| (chan->vstreamtype!=0x1b &&mpeg2support)) )
867     {
868       chanList->push_back(chan);
869       logger->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
870       if (chan->number > maxChannelNumber) maxChannelNumber = chan->number;
871     }
872     else
873     {
874       delete chan;
875     }
876   }
877
878   delete vresp;
879
880   if (maxChannelNumber > 99999)
881     channelNumberWidth = 6;
882   else if (maxChannelNumber > 9999)
883     channelNumberWidth = 5;
884   else if (maxChannelNumber > 999)
885     channelNumberWidth = 4;
886   else if (maxChannelNumber > 99)
887     channelNumberWidth = 3;
888   else if (maxChannelNumber > 9)
889     channelNumberWidth = 2;
890   else
891     channelNumberWidth = 1;
892
893   return chanList;
894 }
895
896 int VDR::streamChannel(ULONG number, StreamReceiver* tstreamReceiver)
897 {
898   VDR_RequestPacket vrp;
899   if (!vrp.init(VDR_STREAMCHANNEL, true, sizeof(ULONG))) return 0;
900   if (!vrp.addULONG(number)) return 0;
901   
902   
903   VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
904   vdrpr->receiverChannel = VDR::CHANNEL_STREAM;
905   vdrpr->streamID = vrp.getSerial();
906   vdrpr->streamReceiver = tstreamReceiver;
907   edRegister(vdrpr);
908   TEMP_SINGLE_VDR_PR = vdrpr;
909   
910   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
911   if (vresp->noResponse())
912   {
913     delete vresp;
914     edUnregister(vdrpr);
915     delete vdrpr;
916     return 0;
917   }
918   
919   int toReturn = (int)vresp->extractULONG();
920   logger->log("VDR", Log::DEBUG, "VDR said %lu to start streaming request", toReturn);
921   delete vresp;
922
923   return toReturn;
924 }
925
926 int VDR::stopStreaming()
927 {
928   VDR_RequestPacket vrp;
929   if (!vrp.init(VDR_STOPSTREAMING, true, 0)) return 0;
930
931   if (TEMP_SINGLE_VDR_PR) // this block only needs to be done if it was a live stream
932                           // TEMP_SINGLE_VDR_PR will not be set unless we are streaming a channel
933   {
934     edUnregister(TEMP_SINGLE_VDR_PR);
935     delete TEMP_SINGLE_VDR_PR;
936     TEMP_SINGLE_VDR_PR = NULL;
937   }
938
939   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
940   if (vresp->noResponse()) { delete vresp; return 0; }
941   
942   int toReturn = (int)vresp->extractULONG();
943   delete vresp;
944
945   return toReturn;
946 }
947
948 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
949 {
950   VDR_RequestPacket vrp;
951   if (!vrp.init(VDR_GETBLOCK, true, sizeof(ULLONG) + sizeof(ULONG))) return NULL;
952   if (!vrp.addULLONG(position)) return NULL;
953   if (!vrp.addULONG(maxAmount)) return NULL;
954
955   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
956   if (vresp->noResponse()) { delete vresp; return NULL; }
957
958   if (vresp->serverError())
959   {
960     logger->log("VDR", Log::DEBUG, "Detected getblock 0");
961     delete vresp;
962     return NULL;
963   }
964
965   // Special handling for getblock
966   UCHAR* toReturn = vresp->getUserData();
967   *amountReceived = vresp->getUserDataLength();
968   
969   delete vresp;
970   
971   return toReturn;
972 }
973
974 ULLONG VDR::streamRecording(char* fileName, ULONG* totalFrames, bool* IsPesRecording)
975 {
976   VDR_RequestPacket vrp;
977   if (!vrp.init(VDR_STREAMRECORDING, true, strlen(fileName) + 1)) return 0;
978   if (!vrp.addString(fileName)) return 0;
979
980   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
981   if (vresp->noResponse()) { delete vresp; return 0; }
982   
983   ULLONG lengthBytes = vresp->extractULLONG();
984   ULONG lengthFrames = vresp->extractULONG();
985   UCHAR isPesRecording = vresp->extractUCHAR();
986   delete vresp;
987
988   *totalFrames = lengthFrames;
989   *IsPesRecording = (isPesRecording);//convert Uchar to bool
990
991   logger->log("VDR", Log::DEBUG, "VDR said length is: %llu %lu, IsPesRecording %x", lengthBytes, lengthFrames, *IsPesRecording);
992
993   return lengthBytes;
994 }
995
996 ULLONG VDR::positionFromFrameNumber(ULONG frameNumber)
997 {
998   VDR_RequestPacket vrp;
999   if (!vrp.init(VDR_POSFROMFRAME, true, sizeof(ULONG))) return 0;
1000   if (!vrp.addULONG(frameNumber)) return 0;
1001
1002   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1003   if (vresp->noResponse()) { delete vresp; return 0; }
1004   
1005   ULLONG position = vresp->extractULLONG();
1006   delete vresp;
1007   
1008   logger->log("VDR", Log::DEBUG, "VDR said new position is: %llu", position);
1009
1010   return position;
1011 }
1012
1013 ULONG VDR::frameNumberFromPosition(ULLONG position)
1014 {
1015   VDR_RequestPacket vrp;
1016   if (!vrp.init(VDR_FRAMEFROMPOS, true, sizeof(ULLONG))) return 0;
1017   if (!vrp.addULLONG(position)) return 0;
1018
1019   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1020   if (vresp->noResponse()) { delete vresp; return 0; }
1021   
1022   ULONG framenumber = vresp->extractULONG();
1023   delete vresp;
1024   
1025   logger->log("VDR", Log::DEBUG, "VDR said new framenumber is: %u", framenumber);
1026
1027   return framenumber;
1028 }
1029
1030 bool VDR::getNextIFrame(ULONG frameNumber, ULONG direction, ULLONG* rfilePosition, ULONG* rframeNumber, ULONG* rframeLength)
1031 {
1032   VDR_RequestPacket vrp;
1033   if (!vrp.init(VDR_GETNEXTIFRAME, true, sizeof(ULONG)*2)) return false;
1034   if (!vrp.addULONG(frameNumber)) return false;
1035   if (!vrp.addULONG(direction)) return false;
1036
1037   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1038   if (vresp->noResponse()) { delete vresp; return false; }
1039   
1040   if (vresp->serverError())
1041   {
1042     logger->log("VDR", Log::DEBUG, "Detected getNextIFrame error");
1043     delete vresp;
1044     return false;
1045   }
1046
1047   *rfilePosition = vresp->extractULLONG();
1048   *rframeNumber = vresp->extractULONG();
1049   *rframeLength = vresp->extractULONG();
1050
1051   delete vresp;
1052
1053   logger->log("VDR", Log::DEBUG, "VDR GNIF said %llu %lu %lu", *rfilePosition, *rframeNumber, *rframeLength);
1054
1055   return true;
1056 }
1057
1058 EventList* VDR::getChannelSchedule(ULONG number)
1059 {
1060   time_t now;
1061   time(&now);
1062   return getChannelSchedule(number, now, 24 * 60 * 60);
1063 }
1064
1065 EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
1066 {
1067 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
1068
1069   VDR_RequestPacket vrp;
1070   if (!vrp.init(VDR_GETCHANNELSCHEDULE, true, sizeof(ULONG)*3)) return NULL;
1071   if (!vrp.addULONG(number)) return NULL;
1072   if (!vrp.addULONG(start)) return NULL;
1073   if (!vrp.addULONG(duration)) return NULL;
1074
1075   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1076   if (vresp->noResponse()) { delete vresp; return NULL; }
1077
1078   // received a ulong(0) - schedules error in the plugin
1079   if (vresp->serverError())
1080   {
1081     delete vresp;
1082     return NULL;
1083   }
1084
1085   EventList* eventList = new EventList();
1086
1087   while (!vresp->end())
1088   {
1089     Event* event = new Event();
1090     event->id = vresp->extractULONG();
1091     event->time = vresp->extractULONG();
1092     event->duration = vresp->extractULONG();
1093     event->title = vresp->extractString();
1094     event->subtitle = vresp->extractString();
1095     event->description = vresp->extractString();
1096     eventList->push_back(event);
1097   }
1098
1099   delete vresp;
1100
1101   logger->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
1102   return eventList;
1103 }
1104
1105 int VDR::configSave(const char* section, const char* key, const char* value)
1106 {
1107   VDR_RequestPacket vrp;
1108   if (!vrp.init(VDR_CONFIGSAVE, false, 0)) return 0;
1109   if (!vrp.addString(section)) return 0;
1110   if (!vrp.addString(key)) return 0;
1111   if (!vrp.addString(value)) return 0;
1112
1113   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1114   if (vresp->noResponse()) { delete vresp; return 0; }
1115
1116   int toReturn = (int)vresp->extractULONG();
1117   delete vresp;
1118
1119   return toReturn;
1120 }
1121
1122 char* VDR::configLoad(const char* section, const char* key)
1123 {
1124   VDR_RequestPacket vrp;
1125   if (!vrp.init(VDR_CONFIGLOAD, false, 0)) return NULL;
1126   if (!vrp.addString(section)) return NULL;
1127   if (!vrp.addString(key)) return NULL;
1128
1129   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1130   if (vresp->noResponse()) { delete vresp; return NULL; }
1131   
1132   char* toReturn = vresp->extractString();
1133   delete vresp;
1134
1135   return toReturn;
1136 }
1137
1138 RecTimerList* VDR::getRecTimersList()
1139 {
1140   VDR_RequestPacket vrp;
1141   if (!vrp.init(VDR_GETTIMERS, true, 0)) return NULL;
1142
1143   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1144   if (vresp->noResponse()) { delete vresp; return NULL; }
1145
1146   RecTimerList* recTimerList = new RecTimerList();
1147
1148   ULONG numTimers = vresp->extractULONG();
1149   if (numTimers > 0)
1150   {
1151     RecTimer* newRecTimer;
1152     char* tempString;
1153
1154     while (!vresp->end())
1155     {
1156       newRecTimer = new RecTimer();
1157       newRecTimer->active = vresp->extractULONG();
1158       newRecTimer->recording = vresp->extractULONG();
1159       newRecTimer->pending = vresp->extractULONG();
1160       newRecTimer->priority = vresp->extractULONG();
1161       newRecTimer->lifeTime = vresp->extractULONG();
1162       newRecTimer->channelNumber = vresp->extractULONG();
1163       newRecTimer->startTime = vresp->extractULONG();
1164       newRecTimer->stopTime = vresp->extractULONG();
1165       newRecTimer->day = vresp->extractULONG();
1166       newRecTimer->weekDays = vresp->extractULONG();
1167
1168       tempString = vresp->extractString();
1169       newRecTimer->setFile(tempString);
1170       delete[] tempString;
1171
1172       recTimerList->push_back(newRecTimer);
1173       logger->log("VDR", Log::DEBUG, "TL: %lu %lu %lu %lu %lu %lu %lu %lu %s",
1174         newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
1175         newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
1176     }
1177   }
1178
1179   delete vresp;
1180
1181   sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
1182
1183   return recTimerList;
1184 }
1185
1186 ULONG VDR::setEventTimer(char* timerString)
1187 {
1188   VDR_RequestPacket vrp;
1189   if (!vrp.init(VDR_SETTIMER, true, strlen(timerString) + 1)) return 0;
1190   if (!vrp.addString(timerString)) return 0;
1191
1192   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1193   if (vresp->noResponse()) { delete vresp; return 0; }
1194   
1195   ULONG toReturn = vresp->extractULONG();
1196   delete vresp;
1197
1198   return toReturn;
1199 }
1200
1201 RecInfo* VDR::getRecInfo(char* fileName)
1202 {
1203   VDR_RequestPacket vrp;
1204   if (!vrp.init(VDR_GETRECINFO, true, strlen(fileName) + 1)) return NULL;
1205   if (!vrp.addString(fileName)) return NULL;
1206   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1207
1208   if (vresp->noResponse()) { delete vresp; return NULL; }
1209
1210   if (vresp->serverError())
1211   {
1212     logger->log("VDR", Log::DEBUG, "Could not get rec info");
1213     delete vresp;
1214     return NULL;
1215   }
1216
1217   RecInfo* recInfo = new RecInfo();
1218
1219   recInfo->timerStart = vresp->extractULONG();
1220   recInfo->timerEnd = vresp->extractULONG();
1221   recInfo->resumePoint = vresp->extractULONG();
1222   recInfo->summary = vresp->extractString();
1223
1224   ULONG numComponents = vresp->extractULONG();
1225   if (numComponents)
1226   {
1227     recInfo->setNumComponents(numComponents);
1228     for (ULONG i = 0; i < numComponents; i++)
1229     {
1230       recInfo->streams[i] = vresp->extractUCHAR();
1231       recInfo->types[i] = vresp->extractUCHAR();
1232       recInfo->languages[i] = vresp->extractString();
1233       recInfo->descriptions[i] = vresp->extractString();
1234     }
1235   }
1236   recInfo->fps=vresp->extractdouble();
1237   recInfo->title=vresp->extractString();
1238   
1239
1240   recInfo->print();
1241
1242   delete vresp;
1243   return recInfo;
1244 }
1245
1246 // FIXME obselete
1247 ULLONG VDR::rescanRecording(ULONG* totalFrames)
1248 {
1249   VDR_RequestPacket vrp;
1250   if (!vrp.init(VDR_RESCANRECORDING, true, 0)) return 0;
1251
1252   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1253   if (vresp->noResponse()) { delete vresp; return 0; }
1254   
1255   ULLONG lengthBytes = vresp->extractULLONG();
1256   ULONG lengthFrames = vresp->extractULONG();
1257   delete vresp;
1258   
1259   logger->log("VDR", Log::DEBUG, "VDR said length is: %llu %lu", lengthBytes, lengthFrames);
1260
1261   *totalFrames = lengthFrames;
1262   return lengthBytes;
1263 }
1264
1265 MarkList* VDR::getMarks(char* fileName)
1266 {
1267   VDR_RequestPacket vrp;
1268   if (!vrp.init(VDR_GETMARKS, true, strlen(fileName) + 1)) return NULL;
1269   if (!vrp.addString(fileName)) return NULL;
1270
1271   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1272   if (vresp->noResponse()) { delete vresp; return NULL; }
1273   
1274   if (vresp->serverError())
1275   {
1276     delete vresp;
1277     return NULL;
1278   }
1279
1280   MarkList* markList = new MarkList();
1281
1282   while (!vresp->end())
1283   {
1284     Mark* mark = new Mark();
1285     mark->pos = vresp->extractULONG();
1286
1287     markList->push_back(mark);
1288     logger->log("VDR", Log::DEBUG, "Have added a mark to list. %lu", mark->pos);
1289   }
1290
1291   delete vresp;
1292   
1293   return markList;
1294 }
1295
1296 void VDR::getChannelPids(Channel* channel)
1297 {
1298   VDR_RequestPacket vrp;
1299   if (!vrp.init(VDR_GETCHANNELPIDS, true, sizeof(ULONG))) return ;
1300   if (!vrp.addULONG(channel->number)) return ;
1301
1302   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1303   if (vresp->noResponse()) { delete vresp; return ; }
1304   
1305   // Format of response
1306   // vpid
1307   // number of apids
1308   // {
1309   //    apid
1310   //    lang string
1311   // }
1312
1313   channel->vpid = vresp->extractULONG();
1314   channel->vstreamtype = vresp->extractULONG();
1315   channel->numAPids = vresp->extractULONG();
1316
1317   for (ULONG i = 0; i < channel->numAPids; i++)
1318   {
1319     apid newapid;
1320     newapid.pid = vresp->extractULONG();
1321     char * name=vresp->extractString();
1322     strncpy(newapid.desc,name,9);
1323     delete [] name;
1324     channel->apids.push_back(newapid);
1325   }
1326
1327   channel->numDPids = vresp->extractULONG();
1328
1329   for (ULONG i = 0; i < channel->numDPids; i++)
1330   {
1331     apid newdpid;
1332     newdpid.pid = vresp->extractULONG();
1333     char * name=vresp->extractString();
1334     strncpy(newdpid.desc,name,9);
1335     delete [] name;
1336     channel->dpids.push_back(newdpid);
1337   }
1338
1339   channel->numSPids = vresp->extractULONG();
1340
1341   for (ULONG i = 0; i < channel->numSPids; i++)
1342   {
1343     apid newspid;
1344     newspid.pid = vresp->extractULONG();
1345     char * name=vresp->extractString();
1346     strncpy(newspid.desc,name,9);
1347     delete [] name;
1348     channel->spids.push_back(newspid);
1349   }
1350   channel->tpid = vresp->extractULONG();
1351   // extension
1352   for (ULONG i = 0; i < channel->numAPids; i++)
1353   {
1354           channel->apids[i].type = vresp->extractULONG();
1355   }
1356   for (ULONG i = 0; i < channel->numDPids; i++)
1357   {
1358           channel->dpids[i].type = vresp->extractULONG();
1359   }
1360   for (ULONG i = 0; i < channel->numSPids; i++)
1361   {
1362           channel->spids[i].type = vresp->extractULONG();
1363           channel->spids[i].data1 = vresp->extractULONG();
1364           channel->spids[i].data2 = vresp->extractULONG();
1365   }
1366
1367   delete vresp;
1368   
1369   return ;
1370 }
1371
1372 #ifdef VOMP_MEDIAPLAYER
1373 MediaList * VDR::getRootList() {
1374   return getMediaList(NULL);
1375 }
1376 /**
1377   * media List Request:
1378   * mediaURI
1379   * Media List response:
1380   * mediaList
1381 */
1382 MediaList* VDR::getMediaList(const MediaURI * root)
1383 {
1384   logger->log("VDR", Log::DEBUG, "getMediaList %s,d=%s, prov=%d", (root?root->getName():"NULL"), 
1385       ((root && root->hasDisplayName())?root->getDisplayName():"NULL"),
1386       (root?root->getProvider():providerId));
1387   MediaURI remoteURI(root);
1388   VDR_GetMediaListRequest request(&remoteURI);
1389   SerializeBuffer *vrp=prepareRequest(&request);
1390   if (!vrp) {
1391     logger->log("VDR", Log::ERR, "getMediaList unable to create command");
1392     return NULL;
1393   }
1394     
1395   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1396   if (!vresp) {
1397     Command::getInstance()->connectionLost();
1398     return NULL;
1399   }
1400   
1401   MediaList *rt=new MediaList(NULL);
1402   ULONG rtflags=0;
1403   VDR_GetMediaListResponse resp(&rtflags,rt);
1404   if (decodeResponse(vresp,&resp) != 0) {
1405     return NULL;
1406   }
1407   return rt;
1408 }
1409
1410 /**
1411   * get image Request:
1412   * uri,x,y, channel
1413   * get media response:
1414   * 4 flags
1415   * 8 len of image
1416 */
1417 int VDR::openMedium(ULONG channel,const MediaURI *uri,  ULLONG * size, ULONG x, ULONG y)
1418 {
1419   MediaURI remoteURI(uri);
1420   VDR_OpenMediumRequest request(&channel,&remoteURI,&x,&y);
1421   *size=0;
1422   SerializeBuffer *vrp=prepareRequest(&request);
1423   if (!vrp) {
1424     logger->log("VDR", Log::ERR, "openMedium unable to create command");
1425     return -1;
1426   }
1427   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1428   if (!vresp) {
1429     Command::getInstance()->connectionLost();
1430     return -1;
1431   }
1432   ULONG flags=0;
1433   VDR_OpenMediumResponse response(&flags,size);
1434   if (decodeResponse(vresp,&response) != 0) {
1435     return -1;
1436   }
1437   logger->log("VDR", Log::DEBUG, "openMedia len=%llu", *size);
1438   return 0;
1439 }
1440
1441 /**
1442   * getMediaBlock - no separate response class - simple data block
1443   * resp
1444   * packet
1445   */
1446 int VDR::getMediaBlock(ULONG channel, ULLONG position, ULONG maxAmount, ULONG* amountReceived, unsigned char **buffer)
1447 {
1448   *amountReceived=0;
1449   VDR_GetMediaBlockRequest request(&channel,&position,&maxAmount);
1450   SerializeBuffer *vrp=prepareRequest(&request);
1451   if (!vrp) {
1452     logger->log("VDR", Log::ERR, "getMediaBlock unable to create command");
1453     return -1;
1454   }
1455   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1456   if (!vresp) {
1457     Command::getInstance()->connectionLost();
1458     return -1;
1459   }
1460   
1461   // Special handling for getblock
1462   *amountReceived = (ULONG)(vresp->getEnd()-vresp->getStart());
1463   *buffer = vresp->steelBuffer();
1464   delete vresp;
1465   return 0;
1466 }
1467
1468 /**
1469   * VDR_GETMEDIAINFO
1470   * channel
1471   * rt
1472   * flags
1473   * info
1474   */
1475
1476 int VDR::getMediaInfo(ULONG channel, MediaInfo * result) {
1477   if (! result) return -1;
1478   VDR_GetMediaInfoRequest request(&channel);
1479   SerializeBuffer *vrp=prepareRequest(&request);
1480   if (!vrp) {
1481     logger->log("VDR", Log::ERR, "getMediaInfo unable to create command");
1482     return -1;
1483   }
1484   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1485   if (!vresp) {
1486     Command::getInstance()->connectionLost();
1487     return -1;
1488   }
1489
1490   ULONG flags=0;
1491   VDR_GetMediaInfoResponse response(&flags,result);
1492   if (decodeResponse(vresp,&response) != 0) {
1493     return -1;
1494   }
1495   return 0;
1496 }
1497
1498 /**
1499   * VDR_CLOSECHANNEL
1500   * channel
1501   * rt
1502   * flags
1503   */
1504
1505 int VDR::closeMediaChannel(ULONG channel) {
1506   VDR_CloseMediaChannelRequest request(&channel);
1507   SerializeBuffer *vrp=prepareRequest(&request);
1508   if (!vrp) {
1509     logger->log("VDR", Log::ERR, "closeMediaChannel unable to create command");
1510     return -1;
1511   }
1512   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1513   if (!vresp) {
1514     Command::getInstance()->connectionLost();
1515     return -1;
1516   }
1517   ULONG flags;
1518   VDR_CloseMediaChannelResponse response(&flags);
1519   if (decodeResponse(vresp,&response) != 0) return -1;
1520   return (flags != 0)?-1:0;
1521 }
1522
1523 #endif
1524
1525
1526 int VDR::deleteTimer(RecTimer* delTimer)
1527 {
1528   logger->log("VDR", Log::DEBUG, "Delete timer called");
1529   
1530   VDR_RequestPacket vrp;
1531   if (!vrp.init(VDR_DELETETIMER, false, 0)) return 0;
1532   if (!vrp.addULONG(delTimer->channelNumber)) return 0;
1533   if (!vrp.addULONG(delTimer->weekDays)) return 0;    
1534   if (!vrp.addULONG(delTimer->day)) return 0;
1535   if (!vrp.addULONG(delTimer->startTime)) return 0;  
1536   if (!vrp.addULONG(delTimer->stopTime)) return 0; 
1537    
1538   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1539   if (vresp->noResponse()) { delete vresp; return 0; }
1540   
1541   int toReturn = (int)vresp->extractULONG();
1542   delete vresp;
1543
1544   return toReturn;
1545 }
1546
1547 I18n::lang_code_list VDR::getLanguageList()
1548 {
1549   I18n::lang_code_list CodeList;
1550   CodeList["en"] = "English"; // Default entry
1551   VDR_RequestPacket vrp;
1552   if (!vrp.init(VDR_GETLANGUAGELIST, false, 0)) return CodeList;
1553   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1554   if (vresp->noResponse() || vresp->end())
1555   {
1556     delete vresp;
1557     return CodeList;
1558   }
1559   CodeList.clear();
1560   while (!vresp->end())
1561   {
1562     char* c_code = vresp->extractString();
1563     char* c_name = vresp->extractString();
1564     string code = c_code;
1565     string name = c_name;
1566     CodeList[code] = name;
1567     delete[] c_code;
1568     delete[] c_name;
1569   }
1570   delete vresp;
1571   return CodeList;
1572 }
1573
1574 int VDR::getLanguageContent(const std::string code, I18n::trans_table& texts)
1575 {
1576   VDR_RequestPacket vrp;
1577   if (!vrp.init(VDR_GETLANGUAGECONTENT, false, 0)) return 0;
1578   if (!vrp.addString(code.c_str())) return 0;
1579   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1580   if (vresp->noResponse()) { delete vresp; return 0; }
1581   texts.clear();
1582   while (!vresp->end())
1583   {
1584     char* c_key = vresp->extractString();
1585     char* c_text = vresp->extractString();
1586     string key = c_key;
1587     string text = c_text;
1588     texts[key] = text;
1589     delete[] c_key;
1590     delete[] c_text;
1591   }
1592   delete vresp;
1593   return 1;
1594 }
1595
1596 void VDR::shutdownVDR()
1597 {
1598   if(doVDRShutdown)
1599     logger->log("VDR", Log::DEBUG, "Shutting down vdr");
1600   else
1601     logger->log("VDR", Log::DEBUG, "Shutting down vomp only");
1602
1603   if(!doVDRShutdown || !connected)
1604     return;
1605
1606   VDR_RequestPacket vrp;
1607   logger->log("VDR", Log::DEBUG, "Sending shutdown");
1608   if (!vrp.init(VDR_SHUTDOWN, false, 0)) return;
1609   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1610   delete vresp;
1611
1612   logger->log("VDR", Log::DEBUG, "VDR shutdown");
1613 }
1614
1615 void VDR::getScraperEventType(char * fileName, int & movieID,
1616                 int & seriesID, int & episodeID)
1617 {
1618         movieID = 0;
1619         seriesID = 0;
1620         episodeID = 0;
1621         VDR_RequestPacket vrp;
1622         if (!vrp.init(VDR_GETRECSCRAPEREVENTTYPE, true, strlen(fileName) + 1)) return;
1623         if (!vrp.addString(fileName)) return ;
1624         Log::getInstance()->log("Recording", Log::DEBUG, "Before Response ");
1625         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1626         Log::getInstance()->log("Recording", Log::DEBUG, "After Response ");
1627         if (vresp->noResponse()) { delete vresp; return ; }
1628         int type = vresp->extractUCHAR();
1629         if (type == 0) //serie
1630         {
1631                 seriesID = vresp->extractLONG();
1632                 episodeID = vresp->extractLONG();
1633         } else if (type == 1) //movie
1634         {
1635                 movieID = vresp->extractLONG();
1636         }
1637         delete vresp;
1638
1639 }
1640
1641 void VDR::getScraperEventType(UINT channelid, UINT eventid, int & movieID,
1642                 int & seriesID, int & episodeID, int & epgImage )
1643 {
1644         movieID = 0;
1645         seriesID = 0;
1646         episodeID = 0;
1647         epgImage = 0;
1648         VDR_RequestPacket vrp;
1649         if (!vrp.init(VDR_GETEVENTSCRAPEREVENTTYPE, false, 0)) return;
1650         if (!vrp.addULONG(channelid)) return ;
1651         if (!vrp.addULONG(eventid)) return ;
1652         Log::getInstance()->log("Recording", Log::DEBUG, "Before Response ");
1653         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1654         Log::getInstance()->log("Recording", Log::DEBUG, "After Response ");
1655         if (vresp->noResponse()) { delete vresp; return ; }
1656         int type = vresp->extractUCHAR();
1657         if (type == 0) //serie
1658         {
1659                 seriesID = vresp->extractLONG();
1660                 episodeID = vresp->extractLONG();
1661         } else if (type == 1) //movie
1662         {
1663                 movieID = vresp->extractLONG();
1664         }
1665         epgImage = vresp->extractLONG();
1666         delete vresp;
1667
1668 }
1669
1670 MovieInfo *VDR::getScraperMovieInfo(int movieID)
1671 {
1672         VDR_RequestPacket vrp;
1673         if (!vrp.init(VDR_GETSCRAPERMOVIEINFO, false, 0)) return NULL;
1674         if (!vrp.addULONG(movieID)) return NULL;
1675         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1676         if (vresp->noResponse()) { delete vresp; return NULL; }
1677         MovieInfo * movieinf= new MovieInfo();
1678
1679         movieinf->id=movieID;
1680         movieinf->title = vresp->extractStdString();
1681         movieinf->originalTitle = vresp->extractStdString();
1682         movieinf->tagline = vresp->extractStdString();
1683         movieinf->overview = vresp->extractStdString();
1684         movieinf->adult = vresp->extractUCHAR();
1685         movieinf->collectionName = vresp->extractStdString();
1686
1687         movieinf->budget = vresp->extractLONG();
1688         movieinf->revenue = vresp->extractLONG();
1689         movieinf->genres = vresp->extractStdString();
1690         movieinf->homepage = vresp->extractStdString();
1691         movieinf->releaseDate = vresp->extractStdString();
1692         movieinf->runtime = vresp->extractLONG();
1693         movieinf->popularity = vresp->extractdouble();
1694         movieinf->voteAverage = vresp->extractdouble();
1695         movieinf->poster.width = vresp->extractULONG();
1696         movieinf->poster.height = vresp->extractULONG();
1697         movieinf->poster.info.setMovieInfo(movieinf);
1698         movieinf->poster.info.setElement(0,0);
1699         movieinf->fanart.width = vresp->extractULONG();
1700         movieinf->fanart.height = vresp->extractULONG();
1701         movieinf->fanart.info.setMovieInfo(movieinf);
1702         movieinf->fanart.info.setElement(1,0);
1703         movieinf->collectionPoster.width = vresp->extractULONG();
1704         movieinf->collectionPoster.height = vresp->extractULONG();
1705         movieinf->collectionPoster.info.setMovieInfo(movieinf);
1706         movieinf->collectionPoster.info.setElement(2,0);
1707         movieinf->collectionFanart.width = vresp->extractULONG();
1708         movieinf->collectionFanart.height = vresp->extractULONG();
1709         movieinf->collectionFanart.info.setMovieInfo(movieinf);
1710         movieinf->collectionFanart.info.setElement(3,0);
1711         ULONG num_actors =  vresp->extractULONG();
1712         movieinf->actors.clear();
1713         movieinf->actors.reserve(num_actors);
1714         for (ULONG acty=0; acty < num_actors; acty++) {
1715                 Actor new_act;
1716                 new_act.name =  vresp->extractStdString();
1717                 new_act.role =  vresp->extractStdString();
1718                 new_act.thumb.width = vresp->extractULONG();
1719                 new_act.thumb.height = vresp->extractULONG();
1720                 new_act.thumb.info.setMovieInfo(movieinf);
1721                 new_act.thumb.info.setElement(4,acty);
1722                 movieinf->actors.push_back(new_act);
1723         }
1724
1725
1726         delete vresp;
1727         return movieinf;
1728
1729 }
1730
1731 SeriesInfo *VDR::getScraperSeriesInfo(int seriesID, int episodeID)
1732 {
1733         VDR_RequestPacket vrp;
1734         if (!vrp.init(VDR_GETSCRAPERSERIESINFO, false, 0)) return NULL;
1735         if (!vrp.addULONG(seriesID)) return NULL;
1736         if (!vrp.addULONG(episodeID)) return NULL;
1737
1738         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1739         if (vresp->noResponse()) { delete vresp; return 0; }
1740         SeriesInfo * seriesinf= new SeriesInfo();
1741
1742         seriesinf->id=seriesID;
1743
1744
1745         seriesinf->name = vresp->extractStdString();
1746         seriesinf->overview = vresp->extractStdString();
1747         seriesinf->firstAired = vresp->extractStdString();
1748         seriesinf->network = vresp->extractStdString();
1749         seriesinf->genre = vresp->extractStdString();
1750         seriesinf->rating =  vresp->extractdouble();
1751         seriesinf->status = vresp->extractStdString();
1752
1753
1754         seriesinf->episode.episodeid=episodeID;
1755         seriesinf->episode.number = vresp->extractLONG();
1756         seriesinf->episode.season = vresp->extractLONG();
1757         seriesinf->episode.name =  vresp->extractStdString();
1758         seriesinf->episode.firstAired =  vresp->extractStdString();
1759         seriesinf->episode.guestStars =  vresp->extractStdString();
1760         seriesinf->episode.overview =  vresp->extractStdString();
1761         seriesinf->episode.rating = vresp->extractdouble();
1762         seriesinf->episode.image.width =  vresp->extractULONG();
1763         seriesinf->episode.image.height =  vresp->extractULONG();
1764         seriesinf->episode.image.info.setSeriesInfo(seriesinf);
1765         seriesinf->episode.image.info.setElement(0,0);
1766
1767
1768         ULONG num_actors =  vresp->extractULONG();
1769         seriesinf->actors.clear();
1770         seriesinf->actors.reserve(num_actors);
1771         for (ULONG acty=0; acty < num_actors; acty++) {
1772                 Actor new_act;
1773                 new_act.name =  vresp->extractStdString();
1774                 new_act.role =  vresp->extractStdString();
1775                 new_act.thumb.width = vresp->extractULONG();
1776                 new_act.thumb.height = vresp->extractULONG();
1777                 new_act.thumb.info.setSeriesInfo(seriesinf);
1778                 new_act.thumb.info.setElement(1,acty);
1779                 seriesinf->actors.push_back(new_act);
1780         }
1781         ULONG num_posters =  vresp->extractULONG();
1782         for (ULONG medias = 0; medias < num_posters; medias++ ) {
1783                 TVMedia media;
1784                 media.info.setSeriesInfo(seriesinf);
1785                 media.info.setElement(2,medias);
1786                 media.width =  vresp->extractULONG();
1787                 media.height = vresp->extractULONG();
1788                 seriesinf->posters.push_back(media);
1789         }
1790
1791         ULONG num_banners =  vresp->extractULONG();
1792         for (ULONG medias = 0; medias < num_banners; medias++ ) {
1793                 TVMedia media;
1794                 media.info.setSeriesInfo(seriesinf);
1795                 media.info.setElement(3,medias);
1796                 media.width =  vresp->extractULONG();
1797                 media.height = vresp->extractULONG();
1798                 seriesinf->banners.push_back(media);
1799         }
1800         ULONG num_fanarts =  vresp->extractULONG();
1801         for (ULONG medias = 0; medias < num_fanarts; medias++ ) {
1802                 TVMedia media;
1803                 media.info.setSeriesInfo(seriesinf);
1804                 media.info.setElement(4,medias);
1805                 media.width =  vresp->extractULONG();
1806                 media.height = vresp->extractULONG();
1807                 seriesinf->fanart.push_back(media);
1808         }
1809         seriesinf->seasonposter.width = vresp->extractULONG();
1810         seriesinf->seasonposter.height = vresp->extractULONG();
1811         seriesinf->seasonposter.info.setSeriesInfo(seriesinf);
1812         seriesinf->seasonposter.info.setElement(5,0);
1813
1814         delete vresp;
1815         return seriesinf;
1816
1817 }
1818
1819 ULONG VDR::loadTVMedia(TVMediaInfo& tvmedia)
1820 {
1821
1822         VDR_RequestPacket vrp;
1823
1824         if (!vrp.init(VDR_LOADTVMEDIA, false, 0)) return -1;
1825         if (!vrp.addULONG(tvmedia.type)) return -1;
1826         if (!vrp.addULONG(tvmedia.primary_id)) return -1;
1827         if (!vrp.addULONG(tvmedia.secondary_id)) return -1;
1828         if (!vrp.addULONG(tvmedia.type_pict)) return -1;
1829         if (!vrp.addULONG(tvmedia.container)) return -1;
1830         if (!vrp.addULONG(tvmedia.container_member)) return -1;
1831 /*      Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia with ID %d %d; %d %d %d %d;%d",
1832                         tvmedia.primary_id,tvmedia.secondary_id,tvmedia.type,tvmedia.type_pict,
1833                         tvmedia.container,tvmedia.container_member,vrp.getSerial());*/
1834
1835
1836         VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1837         vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1838         vdrpr->streamID = vrp.getSerial();
1839         vdrpr->streamReceiver = NULL;
1840         edRegister(vdrpr);
1841
1842
1843         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1844         //if (vresp->noResponse()) { delete vresp; return -1; }
1845         delete vresp;
1846
1847         return vrp.getSerial();
1848 }
1849
1850 ULONG VDR::loadTVMediaRecThumb(TVMediaInfo & media)
1851 {
1852
1853         VDR_RequestPacket vrp;
1854
1855         if (!vrp.init(VDR_LOADTVMEDIARECTHUMB, false, 0)) return -1;
1856         if (!vrp.addString(media.primary_name.c_str())) return NULL;
1857
1858         VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1859         vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1860         vdrpr->streamID = vrp.getSerial();
1861         vdrpr->streamReceiver = NULL;
1862         edRegister(vdrpr);
1863
1864
1865         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1866         //if (vresp->noResponse()) { delete vresp; return -1; }
1867         delete vresp;
1868
1869         return vrp.getSerial();
1870 }
1871
1872 ULONG VDR::loadTVMediaEventThumb(TVMediaInfo & media)
1873 {
1874
1875         VDR_RequestPacket vrp;
1876
1877         if (!vrp.init(VDR_LOADTVMEDIAEVENTTHUMB, false, 0)) return -1;
1878         if (!vrp.addULONG(media.primary_id)) return NULL;
1879         if (!vrp.addULONG(media.secondary_id)) return NULL;
1880
1881         VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1882         vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1883         vdrpr->streamID = vrp.getSerial();
1884         vdrpr->streamReceiver = NULL;
1885         edRegister(vdrpr);
1886
1887
1888         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1889         //if (vresp->noResponse()) { delete vresp; return -1; }
1890         delete vresp;
1891
1892         return vrp.getSerial();
1893 }
1894
1895 ULONG VDR::loadChannelLogo(TVMediaInfo & media)
1896 {
1897
1898         VDR_RequestPacket vrp;
1899
1900         if (!vrp.init(VDR_LOADCHANNELLOGO, false, 0)) return -1;
1901         if (!vrp.addULONG(media.primary_id)) return NULL;
1902
1903         VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1904         vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1905         vdrpr->streamID = vrp.getSerial();
1906         vdrpr->streamReceiver = NULL;
1907         edRegister(vdrpr);
1908
1909
1910         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1911         //if (vresp->noResponse()) { delete vresp; return -1; }
1912         delete vresp;
1913
1914 //      Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia Channel Logo %d %x",
1915 //                              media.primary_id,vrp.getSerial());
1916
1917         return vrp.getSerial();
1918 }