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