]> git.vomp.tv Git - vompclient.git/blob - src/vdr.cc
Type change: UCHAR -> u1
[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   struct timespec currentTime;
687   currentTime.tv_sec = vdrTime;
688   currentTime.tv_nsec = 0;
689
690   int b = clock_settime(CLOCK_REALTIME, &currentTime);
691
692   logger->debug(TAG, "set clock = {}", b);
693
694   // now make a TZ variable and set it
695   char sign;
696   int hours;
697   int minutes;
698   if (vdrTimeOffset > 0) sign = '-';
699   else sign = '+';
700
701   vdrTimeOffset = abs(vdrTimeOffset);
702
703   hours = (int)vdrTimeOffset / 3600;
704   minutes = vdrTimeOffset % 3600;
705
706   logger->debug(TAG, "{} {} {}", sign, hours, minutes);
707
708   minutes = (int)minutes / 60;
709
710   logger->debug(TAG, "{} {} {}", sign, hours, minutes);
711
712   char newTZ[30];
713   sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
714   setenv("TZ", newTZ, 1);
715
716   logger->debug(TAG, "Timezone data: {}", newTZ);
717 #endif
718
719   setCharset(Osd::getInstance()->charSet());
720
721   return true;
722 }
723
724 bool VDR::LogExtern(const char* logString)
725 {
726   if (!connected || disconnecting) return false;
727   int stringLength = strlen(logString);
728   int packetLength = stringLength + 8;
729   char *buffer=new char[packetLength + 1];
730   int pos=0;
731   u4 ul=CHANNEL_NETLOG;
732   buffer[pos++]=(ul>>24)&0xff;
733   buffer[pos++]=(ul>>16)&0xff;
734   buffer[pos++]=(ul>>8)&0xff;
735   buffer[pos++]=ul &0xff;
736   ul=stringLength;
737   buffer[pos++]=(ul>>24)&0xff;
738   buffer[pos++]=(ul>>16)&0xff;
739   buffer[pos++]=(ul>>8)&0xff;
740   buffer[pos++]=ul &0xff;
741
742   strcpy(&buffer[8], logString);
743   
744   if (!tcp.write(buffer, packetLength))
745   {
746     delete [] buffer;
747     disconnecting = true; // stop the rest of the connection
748     Control::getInstance()->connectionLost();
749     return false;
750   }
751   delete [] buffer;
752   return true;
753 }
754
755 bool VDR::setCharset(int charset)
756 {
757   VDR_RequestPacket vrp;
758   if (!vrp.init(VDR_SETCHARSET, true, sizeof(u4))) return false;
759   if (!vrp.addu4(charset)) return false;
760
761   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
762   if (vresp->noResponse()) { delete vresp; return false; }
763
764   u4 success = vresp->extractu4();
765   delete vresp;
766
767   if (!success) return false;
768
769   return true;
770 }
771
772 bool VDR::getRecordingsList(RecMan* recman)
773 {
774   VDR_RequestPacket vrp;
775   if (!vrp.init(VDR_GETRECORDINGLIST, true, 0)) return false;
776
777   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
778   if (vresp->noResponse()) { delete vresp; return false; }
779
780   u4 totalSpace = vresp->extractu4();
781   u4 freeSpace = vresp->extractu4();
782   u4 percent = vresp->extractu4();
783
784   recman->setStats(totalSpace, freeSpace, percent);
785
786   u4 start;
787   u1 isNew;
788   char* name;
789   char* fileName;
790
791   while (!vresp->end())
792   {
793     start = vresp->extractu4();
794     isNew = vresp->extractu1();
795     name = vresp->extractString();
796     fileName = vresp->extractString();
797     recman->addEntry(isNew, start, name, fileName);
798     delete[] name;
799     delete[] fileName;
800   }
801   delete vresp;
802
803   return true;
804 }
805
806 int VDR::deleteRecording(char* fileName)
807 {
808   VDR_RequestPacket vrp;
809   if (!vrp.init(VDR_DELETERECORDING, true, strlen(fileName) + 1)) return 0;
810   if (!vrp.addString(fileName)) return 0;
811   
812   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
813   if (vresp->noResponse()) { delete vresp; return 0; }
814   
815   int toReturn = toi4(vresp->extractu4());
816   delete vresp;
817
818   return toReturn;
819 }
820
821 int VDR::deleteRecResume(char* fileName)
822 {
823   VDR_RequestPacket vrp;
824   if (!vrp.init(VDR_DELETERECRESUME, true, strlen(fileName) + 1)) return 0;
825   if (!vrp.addString(fileName)) return 0;
826
827   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
828   if (vresp->noResponse()) { delete vresp; return 0; }
829
830   int toReturn = toi4(vresp->extractu4());
831   delete vresp;
832
833   return toReturn;
834 }
835
836 char* VDR::moveRecording(char* fileName, char* newPath)
837 {
838   VDR_RequestPacket vrp;
839   if (!vrp.init(VDR_MOVERECORDING, true, strlen(fileName) + 1 + strlen(newPath) + 1)) return NULL;
840   if (!vrp.addString(fileName)) return NULL;
841   if (!vrp.addString(newPath)) return NULL;
842   
843   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
844   if (vresp->noResponse()) { delete vresp; return NULL; }
845   
846   char* toReturn = NULL;
847   int success = toi4(vresp->extractu4());
848   if (success == 1)
849   {
850     toReturn = vresp->extractString();
851   }
852
853   delete vresp;
854
855   return toReturn;
856 }
857
858 std::shared_ptr<ChannelList> VDR::getChannelsList(u4 type)
859 {
860   VDR_RequestPacket vrp;
861   if (!vrp.init(VDR_GETCHANNELLIST, true, 0)) return NULL;
862
863   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
864   if (vresp->noResponse()) { delete vresp; return NULL; }
865   
866   // shared_ptr for a ChannelList (std::vector<Channel*>) with custom deleter to delete all the Channel* objects
867   std::shared_ptr<ChannelList> chanList(new ChannelList(),
868     [] (ChannelList* cl) { for (Channel* p : *cl) delete p; });
869
870   bool h264support=Video::getInstance()->supportsh264();
871   bool mpeg2support=Video::getInstance()->supportsmpeg2();
872
873   while (!vresp->end())
874   {
875     Channel* chan = new Channel();
876     chan->number = vresp->extractu4();
877     chan->type = vresp->extractu4();
878     chan->name = vresp->extractString();
879     chan->vstreamtype = static_cast<u1>(vresp->extractu4());
880
881     if (chan->type == type && ((chan->vstreamtype==0x1b && h264support)|| (chan->vstreamtype!=0x1b &&mpeg2support)) )
882     {
883       chanList->push_back(chan);
884       logger->debug(TAG, "Have added a channel to list. {} {} {}", chan->number, chan->type, chan->name);
885       if (chan->number > maxChannelNumber) maxChannelNumber = chan->number;
886     }
887     else
888     {
889       delete chan;
890     }
891   }
892
893   delete vresp;
894
895   if (maxChannelNumber > 99999)
896     channelNumberWidth = 6;
897   else if (maxChannelNumber > 9999)
898     channelNumberWidth = 5;
899   else if (maxChannelNumber > 999)
900     channelNumberWidth = 4;
901   else if (maxChannelNumber > 99)
902     channelNumberWidth = 3;
903   else if (maxChannelNumber > 9)
904     channelNumberWidth = 2;
905   else
906     channelNumberWidth = 1;
907
908   return chanList;
909 }
910
911 int VDR::streamChannel(u4 number, StreamReceiver* tstreamReceiver)
912 {
913   VDR_RequestPacket vrp;
914   if (!vrp.init(VDR_STREAMCHANNEL, true, sizeof(u4))) return 0;
915   if (!vrp.addu4(number)) return 0;
916   
917   
918   VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
919   vdrpr->receiverChannel = VDR::CHANNEL_STREAM;
920   vdrpr->streamID = vrp.getSerial();
921   vdrpr->streamReceiver = tstreamReceiver;
922   edRegister(vdrpr);
923   TEMP_SINGLE_VDR_PR = vdrpr;
924   
925   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
926   if (vresp->noResponse())
927   {
928     delete vresp;
929     edUnregister(vdrpr);
930     delete vdrpr;
931     return 0;
932   }
933   
934   int toReturn = toi4(vresp->extractu4());
935   logger->debug(TAG, "VDR said {} to start streaming request", toReturn);
936   delete vresp;
937
938   return toReturn;
939 }
940
941 int VDR::stopStreaming()
942 {
943   VDR_RequestPacket vrp;
944   if (!vrp.init(VDR_STOPSTREAMING, true, 0)) return 0;
945
946   if (TEMP_SINGLE_VDR_PR) // this block only needs to be done if it was a live stream
947                           // TEMP_SINGLE_VDR_PR will not be set unless we are streaming a channel
948   {
949     edUnregister(TEMP_SINGLE_VDR_PR);
950     delete TEMP_SINGLE_VDR_PR;
951     TEMP_SINGLE_VDR_PR = NULL;
952   }
953
954   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
955   if (vresp->noResponse()) { delete vresp; return 0; }
956   
957   int toReturn = toi4(vresp->extractu4());
958   delete vresp;
959
960   return toReturn;
961 }
962
963 u1* VDR::getBlock(u8 position, u4 maxAmount, u4* amountReceived)
964 {
965   VDR_RequestPacket vrp;
966   if (!vrp.init(VDR_GETBLOCK, true, sizeof(u8) + sizeof(u4))) return NULL;
967   if (!vrp.addu8(position)) return NULL;
968   if (!vrp.addu4(maxAmount)) return NULL;
969
970   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
971   if (vresp->noResponse()) { delete vresp; return NULL; }
972
973   if (vresp->serverError())
974   {
975     logger->debug(TAG, "Detected getblock 0");
976     *amountReceived = 0;
977     delete vresp;
978     return NULL;
979   }
980
981   // Special handling for getblock
982   u1* toReturn = vresp->getUserData();
983   *amountReceived = vresp->getUserDataLength();
984   
985   delete vresp;
986   
987   return toReturn;
988 }
989
990 u8 VDR::streamRecording(char* fileName, u4* totalFrames, bool* IsPesRecording)
991 {
992   VDR_RequestPacket vrp;
993   if (!vrp.init(VDR_STREAMRECORDING, true, strlen(fileName) + 1)) return 0;
994   if (!vrp.addString(fileName)) return 0;
995
996   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
997   if (vresp->noResponse()) { delete vresp; return 0; }
998   
999   u8 lengthBytes = vresp->extractu8();
1000   u4 lengthFrames = vresp->extractu4();
1001   u1 isPesRecording = vresp->extractu1();
1002   delete vresp;
1003
1004   *totalFrames = lengthFrames;
1005   *IsPesRecording = (isPesRecording);//convert Uchar to bool
1006
1007   logger->debug(TAG, "VDR said length is: {} {}, IsPesRecording {:#x}", lengthBytes, lengthFrames, *IsPesRecording);
1008
1009   return lengthBytes;
1010 }
1011
1012 u8 VDR::positionFromFrameNumber(u4 frameNumber)
1013 {
1014   VDR_RequestPacket vrp;
1015   if (!vrp.init(VDR_POSFROMFRAME, true, sizeof(u4))) return 0;
1016   if (!vrp.addu4(frameNumber)) return 0;
1017
1018   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1019   if (vresp->noResponse()) { delete vresp; return 0; }
1020   
1021   u8 position = vresp->extractu8();
1022   delete vresp;
1023   
1024   logger->debug(TAG, "VDR said new position is: {}", position);
1025
1026   return position;
1027 }
1028
1029 u4 VDR::frameNumberFromPosition(u8 position)
1030 {
1031   VDR_RequestPacket vrp;
1032   if (!vrp.init(VDR_FRAMEFROMPOS, true, sizeof(u8))) return 0;
1033   if (!vrp.addu8(position)) return 0;
1034
1035   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1036   if (vresp->noResponse()) { delete vresp; return 0; }
1037   
1038   u4 framenumber = vresp->extractu4();
1039   delete vresp;
1040   
1041   logger->debug(TAG, "VDR said new framenumber is: {}", framenumber);
1042
1043   return framenumber;
1044 }
1045
1046 bool VDR::getNextIFrame(u4 frameNumber, u4 direction, u8* rfilePosition, u4* rframeNumber, u4* rframeLength)
1047 {
1048   VDR_RequestPacket vrp;
1049   if (!vrp.init(VDR_GETNEXTIFRAME, true, sizeof(u4)*2)) return false;
1050   if (!vrp.addu4(frameNumber)) return false;
1051   if (!vrp.addu4(direction)) return false;
1052
1053   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1054   if (vresp->noResponse()) { delete vresp; return false; }
1055   
1056   if (vresp->serverError())
1057   {
1058     logger->debug(TAG, "Detected getNextIFrame error");
1059     delete vresp;
1060     return false;
1061   }
1062
1063   *rfilePosition = vresp->extractu8();
1064   *rframeNumber = vresp->extractu4();
1065   *rframeLength = vresp->extractu4();
1066
1067   delete vresp;
1068
1069   logger->debug(TAG, "VDR GNIF said {} {} {}", *rfilePosition, *rframeNumber, *rframeLength);
1070
1071   return true;
1072 }
1073
1074 EventList* VDR::getChannelSchedule(u4 number)
1075 {
1076   time_t now;
1077   time(&now);
1078   return getChannelSchedule(number, now, 24 * 60 * 60);
1079 }
1080
1081 EventList* VDR::getChannelSchedule(u4 number, time_t start, u4 duration)
1082 {
1083 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
1084
1085   VDR_RequestPacket vrp;
1086   if (!vrp.init(VDR_GETCHANNELSCHEDULE, true, sizeof(u4)*3)) return NULL;
1087   if (!vrp.addu4(number)) return NULL;
1088   if (!vrp.addu4(start)) return NULL;
1089   if (!vrp.addu4(duration)) return NULL;
1090
1091   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1092   if (vresp->noResponse()) { delete vresp; return NULL; }
1093
1094   // received a ulong(0) - schedules error in the plugin
1095   if (vresp->serverError())
1096   {
1097     delete vresp;
1098     return NULL;
1099   }
1100
1101   EventList* eventList = new EventList();
1102
1103   while (!vresp->end())
1104   {
1105     Event* event = new Event();
1106     event->id = vresp->extractu4();
1107     event->time = vresp->extractu4();
1108     event->duration = vresp->extractu4();
1109     event->title = vresp->extractString();
1110     event->subtitle = vresp->extractString();
1111     event->description = vresp->extractString();
1112     eventList->push_back(event);
1113   }
1114
1115   delete vresp;
1116
1117   logger->debug(TAG, "Success got to end of getChannelSchedule");
1118   return eventList;
1119 }
1120
1121 int VDR::configSave(const char* section, const char* key, const char* value)
1122 {
1123   VDR_RequestPacket vrp;
1124   if (!vrp.init(VDR_CONFIGSAVE, false, 0)) return 0;
1125   if (!vrp.addString(section)) return 0;
1126   if (!vrp.addString(key)) return 0;
1127   if (!vrp.addString(value)) return 0;
1128
1129   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1130   if (vresp->noResponse()) { delete vresp; return 0; }
1131
1132   int toReturn = toi4(vresp->extractu4());
1133   delete vresp;
1134
1135   return toReturn;
1136 }
1137
1138 char* VDR::configLoad(const char* section, const char* key)
1139 {
1140   VDR_RequestPacket vrp;
1141   if (!vrp.init(VDR_CONFIGLOAD, false, 0)) return NULL;
1142   if (!vrp.addString(section)) return NULL;
1143   if (!vrp.addString(key)) return NULL;
1144
1145   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1146   if (vresp->noResponse()) { delete vresp; return NULL; }
1147   
1148   char* toReturn = vresp->extractString();
1149   delete vresp;
1150
1151   return toReturn;
1152 }
1153
1154 RecTimerList* VDR::getRecTimersList()
1155 {
1156   VDR_RequestPacket vrp;
1157   if (!vrp.init(VDR_GETTIMERS, true, 0)) return NULL;
1158
1159   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1160   if (vresp->noResponse()) { delete vresp; return NULL; }
1161
1162   RecTimerList* recTimerList = new RecTimerList();
1163
1164   u4 numTimers = vresp->extractu4();
1165   if (numTimers > 0)
1166   {
1167     RecTimer* newRecTimer;
1168     char* tempString;
1169
1170     while (!vresp->end())
1171     {
1172       newRecTimer = new RecTimer();
1173       newRecTimer->active = vresp->extractu4();
1174       newRecTimer->recording = vresp->extractu4();
1175       newRecTimer->pending = vresp->extractu4();
1176       newRecTimer->priority = vresp->extractu4();
1177       newRecTimer->lifeTime = vresp->extractu4();
1178       newRecTimer->channelNumber = vresp->extractu4();
1179       newRecTimer->startTime = vresp->extractu4();
1180       newRecTimer->stopTime = vresp->extractu4();
1181       newRecTimer->day = vresp->extractu4();
1182       newRecTimer->weekDays = vresp->extractu4();
1183
1184       tempString = vresp->extractString();
1185       newRecTimer->setFile(tempString);
1186       delete[] tempString;
1187
1188       recTimerList->push_back(newRecTimer);
1189       logger->debug(TAG, "TL: {} {} {} {} {} {} {} {} {}",
1190         newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
1191         newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
1192     }
1193   }
1194
1195   delete vresp;
1196
1197   sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
1198
1199   return recTimerList;
1200 }
1201
1202 u4 VDR::setEventTimer(char* timerString)
1203 {
1204   VDR_RequestPacket vrp;
1205   if (!vrp.init(VDR_SETTIMER, true, strlen(timerString) + 1)) return 0;
1206   if (!vrp.addString(timerString)) return 0;
1207
1208   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1209   if (vresp->noResponse()) { delete vresp; return 0; }
1210   
1211   u4 toReturn = vresp->extractu4();
1212   delete vresp;
1213
1214   return toReturn;
1215 }
1216
1217 RecInfo* VDR::getRecInfo(char* fileName)
1218 {
1219   VDR_RequestPacket vrp;
1220   if (!vrp.init(VDR_GETRECINFO2, true, strlen(fileName) + 1)) return NULL;
1221   if (!vrp.addString(fileName)) return NULL;
1222   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1223
1224   if (vresp->noResponse()) { delete vresp; return NULL; }
1225
1226   if (vresp->serverError())
1227   {
1228     logger->debug(TAG, "Could not get rec info");
1229     delete vresp;
1230     return NULL;
1231   }
1232
1233   RecInfo* recInfo = new RecInfo();
1234
1235   recInfo->timerStart = vresp->extractu4();
1236   recInfo->timerEnd = vresp->extractu4();
1237   recInfo->resumePoint = vresp->extractu4();
1238   recInfo->summary = vresp->extractString();
1239
1240   u4 numComponents = vresp->extractu4();
1241   if (numComponents)
1242   {
1243     recInfo->setNumComponents(numComponents);
1244     for (u4 i = 0; i < numComponents; i++)
1245     {
1246       recInfo->streams[i] = vresp->extractu1();
1247       recInfo->types[i] = vresp->extractu1();
1248       recInfo->languages[i] = vresp->extractString();
1249       recInfo->descriptions[i] = vresp->extractString();
1250     }
1251   }
1252   recInfo->fps=vresp->extractdouble();
1253   recInfo->title=vresp->extractString();
1254   
1255   // New stuff
1256   recInfo->channelName = vresp->extractString();
1257   recInfo->duration = vresp->extractu4();
1258   recInfo->fileSize = vresp->extractu4();
1259   recInfo->priority = vresp->extractu4();
1260   recInfo->lifetime = vresp->extractu4();
1261
1262   recInfo->print();
1263
1264   delete vresp;
1265   return recInfo;
1266 }
1267
1268 // FIXME obselete
1269 u8 VDR::rescanRecording(u4* totalFrames)
1270 {
1271   VDR_RequestPacket vrp;
1272   if (!vrp.init(VDR_RESCANRECORDING, true, 0)) return 0;
1273
1274   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1275   if (vresp->noResponse()) { delete vresp; return 0; }
1276   
1277   u8 lengthBytes = vresp->extractu8();
1278   u4 lengthFrames = vresp->extractu4();
1279   delete vresp;
1280   
1281   logger->debug(TAG, "VDR said length is: {} {}", lengthBytes, lengthFrames);
1282
1283   *totalFrames = lengthFrames;
1284   return lengthBytes;
1285 }
1286
1287 MarkList* VDR::getMarks(char* fileName)
1288 {
1289   VDR_RequestPacket vrp;
1290   if (!vrp.init(VDR_GETMARKS, true, strlen(fileName) + 1)) return NULL;
1291   if (!vrp.addString(fileName)) return NULL;
1292
1293   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1294   if (vresp->noResponse()) { delete vresp; return NULL; }
1295   
1296   if (vresp->serverError())
1297   {
1298     delete vresp;
1299     return NULL;
1300   }
1301
1302   MarkList* markList = new MarkList();
1303
1304   while (!vresp->end())
1305   {
1306     Mark* mark = new Mark();
1307     mark->pos = vresp->extractu4();
1308
1309     markList->push_back(mark);
1310     logger->debug(TAG, "Have added a mark to list. {}", mark->pos);
1311   }
1312
1313   delete vresp;
1314   
1315   return markList;
1316 }
1317
1318 void VDR::getChannelPids(Channel* channel)
1319 {
1320   VDR_RequestPacket vrp;
1321   if (!vrp.init(VDR_GETCHANNELPIDS, true, sizeof(u4))) return ;
1322   if (!vrp.addu4(channel->number)) return ;
1323
1324   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1325   if (vresp->noResponse()) { delete vresp; return ; }
1326   
1327   // Format of response
1328   // vpid
1329   // number of apids
1330   // {
1331   //    apid
1332   //    lang string
1333   // }
1334
1335   channel->vpid = vresp->extractu4();
1336   channel->vstreamtype = static_cast<u1>(vresp->extractu4());
1337   channel->numAPids = vresp->extractu4();
1338
1339   for (u4 i = 0; i < channel->numAPids; i++)
1340   {
1341     apid newapid;
1342     newapid.pid = vresp->extractu4();
1343     char * name=vresp->extractString();
1344     strncpy(newapid.desc,name,9);
1345     delete [] name;
1346     channel->apids.push_back(newapid);
1347   }
1348
1349   channel->numDPids = vresp->extractu4();
1350
1351   for (u4 i = 0; i < channel->numDPids; i++)
1352   {
1353     apid newdpid;
1354     newdpid.pid = vresp->extractu4();
1355     char * name=vresp->extractString();
1356     strncpy(newdpid.desc,name,9);
1357     delete [] name;
1358     channel->dpids.push_back(newdpid);
1359   }
1360
1361   channel->numSPids = vresp->extractu4();
1362
1363   for (u4 i = 0; i < channel->numSPids; i++)
1364   {
1365     apid newspid;
1366     newspid.pid = vresp->extractu4();
1367     char * name=vresp->extractString();
1368     strncpy(newspid.desc,name,9);
1369     delete [] name;
1370     channel->spids.push_back(newspid);
1371   }
1372   channel->tpid = vresp->extractu4();
1373   // extension
1374   for (u4 i = 0; i < channel->numAPids; i++)
1375   {
1376           channel->apids[i].type = vresp->extractu4();
1377   }
1378   for (u4 i = 0; i < channel->numDPids; i++)
1379   {
1380           channel->dpids[i].type = vresp->extractu4();
1381   }
1382   for (u4 i = 0; i < channel->numSPids; i++)
1383   {
1384           channel->spids[i].type = vresp->extractu4();
1385           channel->spids[i].data1 = vresp->extractu4();
1386           channel->spids[i].data2 = vresp->extractu4();
1387   }
1388
1389   delete vresp;
1390   
1391   return ;
1392 }
1393
1394 #ifdef VOMP_MEDIAPLAYER
1395 MediaList * VDR::getRootList() {
1396   return getMediaList(NULL);
1397 }
1398 /**
1399   * media List Request:
1400   * mediaURI
1401   * Media List response:
1402   * mediaList
1403 */
1404 MediaList* VDR::getMediaList(const MediaURI * root)
1405 {
1406   logger->debug(TAG, "getMediaList {},d={}, prov={}", (root?root->getName():"NULL"),
1407       ((root && root->hasDisplayName())?root->getDisplayName():"NULL"),
1408       (root?root->getProvider():providerId));
1409   MediaURI remoteURI(root);
1410   VDR_GetMediaListRequest request(&remoteURI);
1411   SerializeBuffer *vrp=prepareRequest(&request);
1412   if (!vrp) {
1413     logger->log("VDR", Log::ERR, "getMediaList unable to create command");
1414     return NULL;
1415   }
1416     
1417   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1418   if (!vresp) {
1419     Control::getInstance()->connectionLost();
1420     return NULL;
1421   }
1422   
1423   MediaList *rt=new MediaList(NULL);
1424   u4 rtflags=0;
1425   VDR_GetMediaListResponse resp(&rtflags,rt);
1426   if (decodeResponse(vresp,&resp) != 0) {
1427     return NULL;
1428   }
1429   return rt;
1430 }
1431
1432 /**
1433   * get image Request:
1434   * uri,x,y, channel
1435   * get media response:
1436   * 4 flags
1437   * 8 len of image
1438 */
1439 int VDR::openMedium(u4 channel,const MediaURI *uri,  u8 * size, u4 x, u4 y)
1440 {
1441   MediaURI remoteURI(uri);
1442   VDR_OpenMediumRequest request(&channel,&remoteURI,&x,&y);
1443   *size=0;
1444   SerializeBuffer *vrp=prepareRequest(&request);
1445   if (!vrp) {
1446     logger->log("VDR", Log::ERR, "openMedium unable to create command");
1447     return -1;
1448   }
1449   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1450   if (!vresp) {
1451     Control::getInstance()->connectionLost();
1452     return -1;
1453   }
1454   u4 flags=0;
1455   VDR_OpenMediumResponse response(&flags,size);
1456   if (decodeResponse(vresp,&response) != 0) {
1457     return -1;
1458   }
1459   logger->debug(TAG, "openMedia len={}", *size);
1460   return 0;
1461 }
1462
1463 /**
1464   * getMediaBlock - no separate response class - simple data block
1465   * resp
1466   * packet
1467   */
1468 int VDR::getMediaBlock(u4 channel, u8 position, u4 maxAmount, u4* amountReceived, unsigned char **buffer)
1469 {
1470   *amountReceived=0;
1471   VDR_GetMediaBlockRequest request(&channel,&position,&maxAmount);
1472   SerializeBuffer *vrp=prepareRequest(&request);
1473   if (!vrp) {
1474     logger->log("VDR", Log::ERR, "getMediaBlock unable to create command");
1475     return -1;
1476   }
1477   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1478   if (!vresp) {
1479     Control::getInstance()->connectionLost();
1480     return -1;
1481   }
1482   
1483   // Special handling for getblock
1484   *amountReceived = (u4)(vresp->getEnd()-vresp->getStart());
1485   *buffer = vresp->steelBuffer();
1486   delete vresp;
1487   return 0;
1488 }
1489
1490 /**
1491   * VDR_GETMEDIAINFO
1492   * channel
1493   * rt
1494   * flags
1495   * info
1496   */
1497
1498 int VDR::getMediaInfo(u4 channel, MediaInfo * result) {
1499   if (! result) return -1;
1500   VDR_GetMediaInfoRequest request(&channel);
1501   SerializeBuffer *vrp=prepareRequest(&request);
1502   if (!vrp) {
1503     logger->log("VDR", Log::ERR, "getMediaInfo unable to create command");
1504     return -1;
1505   }
1506   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1507   if (!vresp) {
1508     Control::getInstance()->connectionLost();
1509     return -1;
1510   }
1511
1512   u4 flags=0;
1513   VDR_GetMediaInfoResponse response(&flags,result);
1514   if (decodeResponse(vresp,&response) != 0) {
1515     return -1;
1516   }
1517   return 0;
1518 }
1519
1520 /**
1521   * VDR_CLOSECHANNEL
1522   * channel
1523   * rt
1524   * flags
1525   */
1526
1527 int VDR::closeMediaChannel(u4 channel) {
1528   VDR_CloseMediaChannelRequest request(&channel);
1529   SerializeBuffer *vrp=prepareRequest(&request);
1530   if (!vrp) {
1531     logger->log("VDR", Log::ERR, "closeMediaChannel unable to create command");
1532     return -1;
1533   }
1534   SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1535   if (!vresp) {
1536     Control::getInstance()->connectionLost();
1537     return -1;
1538   }
1539   u4 flags;
1540   VDR_CloseMediaChannelResponse response(&flags);
1541   if (decodeResponse(vresp,&response) != 0) return -1;
1542   return (flags != 0)?-1:0;
1543 }
1544
1545 #endif
1546
1547
1548 int VDR::deleteTimer(RecTimer* delTimer)
1549 {
1550   logger->debug(TAG, "Delete timer called");
1551   
1552   VDR_RequestPacket vrp;
1553   if (!vrp.init(VDR_DELETETIMER, false, 0)) return 0;
1554   if (!vrp.addu4(delTimer->channelNumber)) return 0;
1555   if (!vrp.addu4(delTimer->weekDays)) return 0;
1556   if (!vrp.addu4(delTimer->day)) return 0;
1557   if (!vrp.addu4(delTimer->startTime)) return 0;
1558   if (!vrp.addu4(delTimer->stopTime)) return 0;
1559    
1560   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1561   if (vresp->noResponse()) { delete vresp; return 0; }
1562   
1563   int toReturn = toi4(vresp->extractu4());
1564   delete vresp;
1565
1566   return toReturn;
1567 }
1568
1569 I18n::lang_code_list VDR::getLanguageList()
1570 {
1571   I18n::lang_code_list CodeList;
1572   CodeList["en"] = "English"; // Default entry
1573   VDR_RequestPacket vrp;
1574   if (!vrp.init(VDR_GETLANGUAGELIST, false, 0)) return CodeList;
1575   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1576   if (vresp->noResponse() || vresp->end())
1577   {
1578     delete vresp;
1579     return CodeList;
1580   }
1581   CodeList.clear();
1582   while (!vresp->end())
1583   {
1584     char* c_code = vresp->extractString();
1585     char* c_name = vresp->extractString();
1586     std::string code = c_code;
1587     std::string name = c_name;
1588     CodeList[code] = name;
1589     delete[] c_code;
1590     delete[] c_name;
1591   }
1592   delete vresp;
1593   return CodeList;
1594 }
1595
1596 int VDR::getLanguageContent(const std::string code, I18n::trans_table& texts)
1597 {
1598   VDR_RequestPacket vrp;
1599   if (!vrp.init(VDR_GETLANGUAGECONTENT, false, 0)) return 0;
1600   if (!vrp.addString(code.c_str())) return 0;
1601   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1602   if (vresp->noResponse()) { delete vresp; return 0; }
1603   texts.clear();
1604   while (!vresp->end())
1605   {
1606     char* c_key = vresp->extractString();
1607     char* c_text = vresp->extractString();
1608     std::string key = c_key;
1609     std::string text = c_text;
1610     texts[key] = text;
1611     delete[] c_key;
1612     delete[] c_text;
1613   }
1614   delete vresp;
1615   return 1;
1616 }
1617
1618 void VDR::shutdownVDR()
1619 {
1620   if(doVDRShutdown)
1621     logger->debug(TAG, "Shutting down vdr");
1622   else
1623     logger->debug(TAG, "Shutting down vomp only");
1624
1625   if(!doVDRShutdown || !connected || disconnecting)
1626     return;
1627
1628   VDR_RequestPacket vrp;
1629   logger->debug(TAG, "Sending shutdown");
1630   if (!vrp.init(VDR_SHUTDOWN, false, 0)) return;
1631   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1632   delete vresp;
1633
1634   logger->debug(TAG, "VDR shutdown");
1635 }
1636
1637 void VDR::getScraperEventType(char * fileName, int & movieID,
1638                 int & seriesID, int & episodeID)
1639 {
1640         movieID = 0;
1641         seriesID = 0;
1642         episodeID = 0;
1643         VDR_RequestPacket vrp;
1644         if (!vrp.init(VDR_GETRECSCRAPEREVENTTYPE, true, strlen(fileName) + 1)) return;
1645         if (!vrp.addString(fileName)) return ;
1646         logger->debug(TAG, "Before response");
1647         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1648         logger->debug(TAG, "After response");
1649         if (vresp->noResponse()) { delete vresp; return ; }
1650         int type = vresp->extractu1();
1651         if (type == 0) //serie
1652         {
1653                 seriesID = vresp->extractLONG();
1654                 episodeID = vresp->extractLONG();
1655         } else if (type == 1) //movie
1656         {
1657                 movieID = vresp->extractLONG();
1658         }
1659         delete vresp;
1660
1661 }
1662
1663 void VDR::getScraperEventType(u4 channelid, u4 eventid, int & movieID,
1664                 int & seriesID, int & episodeID, int & epgImage )
1665 {
1666         movieID = 0;
1667         seriesID = 0;
1668         episodeID = 0;
1669         epgImage = 0;
1670         VDR_RequestPacket vrp;
1671         if (!vrp.init(VDR_GETEVENTSCRAPEREVENTTYPE, false, 0)) return;
1672         if (!vrp.addu4(channelid)) return ;
1673         if (!vrp.addu4(eventid)) return ;
1674         logger->debug(TAG, "Before response");
1675         VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1676         logger->debug(TAG, "After response");
1677         if (vresp->noResponse()) { delete vresp; return ; }
1678         int type = vresp->extractu1();
1679         if (type == 0) //serie
1680         {
1681                 seriesID = vresp->extractLONG();
1682                 episodeID = vresp->extractLONG();
1683         } else if (type == 1) //movie
1684         {
1685                 movieID = vresp->extractLONG();
1686         }
1687         epgImage = vresp->extractLONG();
1688         delete vresp;
1689
1690 }
1691
1692 MovieInfo *VDR::getScraperMovieInfo(int movieID)
1693 {
1694   ImageLoader* imageLoader = ImageLoader::getInstance();
1695
1696   VDR_RequestPacket vrp;
1697   if (!vrp.init(VDR_GETSCRAPERMOVIEINFO, false, 0)) return NULL;
1698   if (!vrp.addu4(movieID)) return NULL;
1699   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1700   if (vresp->noResponse()) { delete vresp; return NULL; }
1701   MovieInfo* movieinf = new MovieInfo;
1702
1703   ImageGeneric imageGeneric1 = imageLoader->createGeneric();
1704   movieinf->poster.image = imageGeneric1;
1705
1706   ImageGeneric imageGeneric2 = imageLoader->createGeneric();
1707   movieinf->fanart.image = imageGeneric2;
1708
1709   ImageGeneric imageGeneric3 = imageLoader->createGeneric();
1710   movieinf->collectionPoster.image = imageGeneric3;
1711
1712   ImageGeneric imageGeneric4 = imageLoader->createGeneric();
1713   movieinf->collectionFanart.image = imageGeneric4;
1714
1715   movieinf->id=movieID;
1716   movieinf->title = vresp->extractStdString();
1717   movieinf->originalTitle = vresp->extractStdString();
1718   movieinf->tagline = vresp->extractStdString();
1719   movieinf->overview = vresp->extractStdString();
1720   movieinf->adult = vresp->extractu1();
1721   movieinf->collectionName = vresp->extractStdString();
1722
1723   movieinf->budget = vresp->extractLONG();
1724   movieinf->revenue = vresp->extractLONG();
1725   movieinf->genres = vresp->extractStdString();
1726   movieinf->homepage = vresp->extractStdString();
1727   movieinf->releaseDate = vresp->extractStdString();
1728   movieinf->runtime = vresp->extractLONG();
1729   movieinf->popularity = vresp->extractdouble();
1730   movieinf->voteAverage = vresp->extractdouble();
1731   movieinf->poster.width = vresp->extractu4();
1732   movieinf->poster.height = vresp->extractu4();
1733   imageGeneric1->setMovieInfo(movieinf);
1734   imageGeneric1->setElement(0,0);
1735   movieinf->fanart.width = vresp->extractu4();
1736   movieinf->fanart.height = vresp->extractu4();
1737   imageGeneric2->setMovieInfo(movieinf);
1738   imageGeneric2->setElement(1,0);
1739   movieinf->collectionPoster.width = vresp->extractu4();
1740   movieinf->collectionPoster.height = vresp->extractu4();
1741   imageGeneric3->setMovieInfo(movieinf);
1742   imageGeneric3->setElement(2,0);
1743   movieinf->collectionFanart.width = vresp->extractu4();
1744   movieinf->collectionFanart.height = vresp->extractu4();
1745   imageGeneric4->setMovieInfo(movieinf);
1746   imageGeneric4->setElement(3,0);
1747   u4 num_actors =  vresp->extractu4();
1748   movieinf->actors.clear();
1749   movieinf->actors.reserve(num_actors);
1750   for (u4 acty=0; acty < num_actors; acty++)
1751   {
1752     Actor new_act;
1753     ImageGeneric newActImageGeneric = imageLoader->createGeneric();
1754     new_act.thumb.image = newActImageGeneric;
1755
1756     new_act.name =  vresp->extractStdString();
1757     new_act.role =  vresp->extractStdString();
1758     new_act.thumb.width = vresp->extractu4();
1759     new_act.thumb.height = vresp->extractu4();
1760     newActImageGeneric->setMovieInfo(movieinf);
1761     newActImageGeneric->setElement(4,acty);
1762     movieinf->actors.push_back(new_act);
1763     imageLoader->ensureLoaded(newActImageGeneric);
1764   }
1765
1766   imageLoader->ensureLoaded(imageGeneric1);
1767   imageLoader->ensureLoaded(imageGeneric2);
1768   imageLoader->ensureLoaded(imageGeneric3);
1769   imageLoader->ensureLoaded(imageGeneric4);
1770
1771   delete vresp;
1772   return movieinf;
1773 }
1774
1775 SeriesInfo* VDR::getScraperSeriesInfo(int seriesID, int episodeID)
1776 {
1777   ImageLoader* imageLoader = ImageLoader::getInstance();
1778
1779   VDR_RequestPacket vrp;
1780   if (!vrp.init(VDR_GETSCRAPERSERIESINFO, false, 0)) return NULL;
1781   if (!vrp.addu4(seriesID)) return NULL;
1782   if (!vrp.addu4(episodeID)) return NULL;
1783
1784   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1785   if (vresp->noResponse()) { delete vresp; return 0; }
1786   SeriesInfo* seriesinf = new SeriesInfo();
1787
1788   ImageGeneric imageGeneric1 = imageLoader->createGeneric();
1789   Image imageBase1 = imageGeneric1;
1790   seriesinf->episode.image.image = imageBase1;
1791
1792   ImageGeneric imageGeneric2 = imageLoader->createGeneric();
1793   Image imageBase2 = imageGeneric2;
1794   seriesinf->seasonposter.image = imageBase2;
1795
1796   seriesinf->id = seriesID;
1797
1798   seriesinf->name = vresp->extractStdString();
1799   seriesinf->overview = vresp->extractStdString();
1800   seriesinf->firstAired = vresp->extractStdString();
1801   seriesinf->network = vresp->extractStdString();
1802   seriesinf->genre = vresp->extractStdString();
1803   seriesinf->rating =  vresp->extractdouble();
1804   seriesinf->status = vresp->extractStdString();
1805
1806
1807   seriesinf->episode.episodeid=episodeID;
1808   seriesinf->episode.number = vresp->extractLONG();
1809   seriesinf->episode.season = vresp->extractLONG();
1810   seriesinf->episode.name =  vresp->extractStdString();
1811   seriesinf->episode.firstAired =  vresp->extractStdString();
1812   seriesinf->episode.guestStars =  vresp->extractStdString();
1813   seriesinf->episode.overview =  vresp->extractStdString();
1814   seriesinf->episode.rating = vresp->extractdouble();
1815   seriesinf->episode.image.width =  vresp->extractu4();
1816   seriesinf->episode.image.height =  vresp->extractu4();
1817   imageGeneric1->setSeriesInfo(seriesinf);
1818   imageGeneric1->setElement(0,0);
1819
1820
1821   u4 num_actors =  vresp->extractu4();
1822   seriesinf->actors.clear();
1823   seriesinf->actors.reserve(num_actors);
1824   for (u4 acty=0; acty < num_actors; acty++) {
1825       Actor new_act;
1826       new_act.name =  vresp->extractStdString();
1827       new_act.role =  vresp->extractStdString();
1828       new_act.thumb.width = vresp->extractu4();
1829       new_act.thumb.height = vresp->extractu4();
1830
1831       ImageGeneric actorIG = imageLoader->createGeneric();
1832       new_act.thumb.image = actorIG;
1833       actorIG->setSeriesInfo(seriesinf);
1834       actorIG->setElement(1,acty);
1835       seriesinf->actors.push_back(new_act);
1836
1837       imageLoader->ensureLoaded(actorIG);
1838   }
1839   u4 num_posters =  vresp->extractu4();
1840   for (u4 medias = 0; medias < num_posters; medias++ ) {
1841       TVMediaStruct media;
1842       ImageGeneric mediaIG = imageLoader->createGeneric();
1843       media.image = mediaIG;
1844       mediaIG->setSeriesInfo(seriesinf);
1845       mediaIG->setElement(2, medias);
1846       media.width =  vresp->extractu4();
1847       media.height = vresp->extractu4();
1848       seriesinf->posters.push_back(media);
1849
1850       imageLoader->ensureLoaded(mediaIG);
1851   }
1852
1853   u4 num_banners =  vresp->extractu4();
1854   for (u4 medias = 0; medias < num_banners; medias++ ) {
1855       TVMediaStruct media;
1856       ImageGeneric mediaIG = imageLoader->createGeneric();
1857       media.image = mediaIG;
1858       mediaIG->setSeriesInfo(seriesinf);
1859       mediaIG->setElement(3,medias);
1860       media.width =  vresp->extractu4();
1861       media.height = vresp->extractu4();
1862       seriesinf->banners.push_back(media);
1863
1864       imageLoader->ensureLoaded(mediaIG);
1865   }
1866   u4 num_fanarts =  vresp->extractu4();
1867   for (u4 medias = 0; medias < num_fanarts; medias++ ) {
1868       TVMediaStruct media;
1869       ImageGeneric mediaIG = imageLoader->createGeneric();
1870       media.image = mediaIG;
1871       mediaIG->setSeriesInfo(seriesinf);
1872       mediaIG->setElement(4,medias);
1873       media.width =  vresp->extractu4();
1874       media.height = vresp->extractu4();
1875       seriesinf->fanart.push_back(media);
1876
1877       imageLoader->ensureLoaded(mediaIG);
1878   }
1879   seriesinf->seasonposter.width = vresp->extractu4();
1880   seriesinf->seasonposter.height = vresp->extractu4();
1881   imageGeneric2->setSeriesInfo(seriesinf);
1882   imageGeneric2->setElement(5,0);
1883
1884   imageLoader->ensureLoaded(imageGeneric1);
1885   imageLoader->ensureLoaded(imageGeneric2);
1886
1887   delete vresp;
1888   return seriesinf;
1889 }
1890
1891 bool VDR::loadImageGeneric(ImageGeneric& image)
1892 {
1893   VDR_RequestPacket vrp;
1894
1895   if (!vrp.init(VDR_LOADTVMEDIA, false, 0)) return false;
1896   if (!vrp.addu4(image->getType())) return false;
1897   if (!vrp.addu4(image->primary_id)) return false;
1898   if (!vrp.addu4(image->secondary_id)) return false;
1899   if (!vrp.addu4(image->type_pict)) return false;
1900   if (!vrp.addu4(image->container)) return false;
1901   if (!vrp.addu4(image->container_member)) return false;
1902   logger->debug(TAG, "Image with ID {} {}; {} {} {} {};{}",
1903           image->primary_id,image->secondary_id,image->type,image->type_pict,
1904           image->container,image->container_member,vrp.getSerial());
1905
1906 // FIXME - ImageLoader should register itself as a permenant stream receiver instead of making temporary ones like this
1907   VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1908   vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1909   vdrpr->streamID = vrp.getSerial();
1910   vdrpr->streamReceiver = NULL;
1911   edRegister(vdrpr);
1912
1913   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1914   bool ret = !vresp->noResponse();
1915   delete vresp;
1916   return ret;
1917 }
1918
1919 bool VDR::loadImageRecThumb(ImageRecThumb& image) // FIXME convert return to bool
1920 {
1921   VDR_RequestPacket vrp;
1922
1923   if (!vrp.init(VDR_LOADTVMEDIARECTHUMB, false, 0)) return false;
1924   if (!vrp.addString(image->getFileName())) return false;
1925   image->setServerLoadingRef(vrp.getSerial());
1926
1927   VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1928   vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1929   vdrpr->streamID = vrp.getSerial();
1930   vdrpr->streamReceiver = NULL;
1931   edRegister(vdrpr);
1932
1933   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1934   bool ret = !vresp->noResponse();
1935   delete vresp;
1936   return ret;
1937 }
1938
1939 bool VDR::loadImageEventThumb(ImageEventThumb& image)
1940 {
1941   VDR_RequestPacket vrp;
1942
1943   if (!vrp.init(VDR_LOADTVMEDIAEVENTTHUMB, false, 0)) return false;
1944   if (!vrp.addu4(image->getChannel())) return false;
1945   if (!vrp.addu4(image->getEvent())) return false;
1946   image->setServerLoadingRef(vrp.getSerial());
1947
1948   VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1949   vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1950   vdrpr->streamID = vrp.getSerial();
1951   vdrpr->streamReceiver = NULL;
1952   edRegister(vdrpr);
1953
1954   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1955   bool ret = !vresp->noResponse();
1956   delete vresp;
1957   return ret;
1958 }
1959
1960 bool VDR::loadImageChannelLogo(ImageChannelLogo& image)
1961 {
1962   VDR_RequestPacket vrp;
1963
1964   if (!vrp.init(VDR_LOADCHANNELLOGO, false, 0)) return false;
1965   if (!vrp.addu4(image->getChannelID())) return false;
1966   image->setServerLoadingRef(vrp.getSerial());
1967
1968   VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1969   vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1970   vdrpr->streamID = vrp.getSerial();
1971   vdrpr->streamReceiver = NULL;
1972   edRegister(vdrpr);
1973
1974   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1975   bool ret = !vresp->noResponse();
1976   delete vresp;
1977   return ret;
1978 }