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