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