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