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