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