2 Copyright 2004-2020 Chris Tallon
4 This file is part of VOMP.
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.
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.
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/>.
26 #include "vdrrequestpacket.h"
27 #include "vdrresponsepacket.h"
29 #ifdef VOMP_MEDIAPLAYER
31 #include "mediaprovider.h"
32 #include "mediaproviderids.h"
34 #include "vdrcommand.h"
37 #include "movieinfo.h"
38 #include "seriesinfo.h"
39 #include "osdvector.h"
41 #include "imageloader.h"
45 static const char* TAG = "VDR";
47 #define VOMP_PROTOCOL_VERSION 0x00000500
49 VDR* VDR::instance = NULL;
50 #ifdef VOMP_MEDIAPLAYER
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) {
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;
72 if (! rt->init(cmd,true,rq->getCurrent()-rq->getStart())) {
77 if (! rt->copyin(rq->getStart(),(u4)(rq->getCurrent()-rq->getStart()))) {
83 VDR_ResponsePacket *rp=RequestResponse(rt);
84 logger->debug(TAG, "Got response {}", (void*)rp);
89 SerializeBuffer *buf=new SerializeBuffer(rp->getUserData(),rp->getUserDataLength(),true,true,false);
94 //deserialize a received response
97 static int decodeResponse(SerializeBuffer *rp,VDR_Command *c) {
98 u4 expected=c->command;
99 if (c->deserialize(rp) != 0) {
101 Log::getInstance()->error(TAG, "decodeResponse unable to deserialize for command {}", expected);
105 if (c->command != expected) {
106 Log::getInstance()->error(TAG, "decodeResponse unexpected response received {:#x}, expected {:#x}", c->command, expected);
109 Log::getInstance()->error(TAG, "decodeResponse successfully decoded command {:#x}", expected);
117 if (instance) return;
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);
131 if (initted) shutdown();
134 VDR* VDR::getInstance()
141 if (initted) return 0;
143 logger = LogNT::getInstance();
150 if (!initted) return 0;
156 void VDR::setServerIP(const char* newIP)
158 strcpy(serverIP, newIP);
161 void VDR::setServerPort(u2 newPort)
163 serverPort = newPort;
169 maxChannelNumber = 0;
170 channelNumberWidth = 1;
172 connectStateMutex.lock();
173 if (connecting || connected) return true;
175 connectStateMutex.unlock(); // now I have connecting
177 bool connectResult = tcp.connect(serverIP, serverPort);
179 connectStateMutex.lock(); // connected = false, connecting = true, babortConnect = ?
184 if (connectResult) tcp.shutdown();
185 babortConnect = false;
186 connectStateMutex.unlock();
194 threadStartProtect.lock();
195 vdrThread = std::thread( [this]
197 threadStartProtect.lock();
198 threadStartProtect.unlock();
201 threadStartProtect.unlock();
203 connectStateMutex.unlock();
208 connectStateMutex.unlock();
213 void VDR::abortConnect() // If there is one, force a running connect call to abort
215 connectStateMutex.lock();
219 babortConnect = true;
223 connectStateMutex.unlock();
226 void VDR::disconnect()
228 std::lock_guard<std::mutex> lg(connectStateMutex);
230 if (!connected) return;
232 if (vdrThread.joinable())
234 threadReqStop = true;
237 threadReqStop = false;
242 disconnecting = false;
244 logger->debug(TAG, "Disconnect");
247 void VDR::setReceiveWindow(size_t /*size*/)
249 //if (connected && size) tcpold->setReceiveWindow(size);
252 ///////////////////////////////////////////////////////
254 void VDR::threadMethod()
256 logger->debug(TAG, "VDR RUN");
267 VDR_ResponsePacket* vresp;
271 u4 lastKArecv = time(NULL);
276 readSuccess = tcp.read(&channelID, sizeof(u4));
277 if (threadReqStop) return;
278 timeNow = time(NULL);
282 //logger->debug(TAG, "Net read timeout");
283 if (!tcp.status()) { connectionDied(); return; } // return to stop this thread
286 if (!lastKAsent) // have not sent a KA
288 if (lastKArecv < (timeNow - 5))
290 //logger->debug(TAG, "Sending KA packet");
291 if (!sendKA(timeNow))
293 logger->debug(TAG, "Could not send KA, calling connectionDied");
297 lastKAsent = timeNow;
299 if (threadReqStop) return;
304 if (lastKAsent <= (timeNow - 10))
306 logger->debug(TAG, "lastKA over 10s ago, calling connectionDied");
312 if (!readSuccess) continue; // no data was read but the connection is ok.
316 channelID = ntohl(channelID);
318 if (channelID == CHANNEL_REQUEST_RESPONSE)
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?
328 if (userDataLength > 0)
330 userData = malloc(userDataLength);
331 if (!userData) break;
332 if (!tcp.read(userData, userDataLength))
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);
350 if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
352 // If edFindAndCall returns true, edr was called and vresp was handed off.
353 // else, delete vresp here.
356 if (threadReqStop) return;
358 else if (channelID == CHANNEL_STREAM || channelID == CHANNEL_TVMEDIA)
360 if (!tcp.read(&streamID, sizeof(u4))) break;
361 if (threadReqStop) return;
362 streamID = ntohl(streamID);
364 if (!tcp.read(&flag, sizeof(u4))) break;
365 if (threadReqStop) return;
368 if (!tcp.read(&userDataLength, sizeof(u4))) break;
369 if (threadReqStop) return;
370 userDataLength = ntohl(userDataLength);
372 if (userDataLength > 0)
374 userData = malloc(userDataLength);
375 if (!userData) break;
376 if (!tcp.read(userData, userDataLength))
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);
393 if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
395 // If edFindAndCall returns true, edr was called and vresp was handed off.
396 // else, delete vresp here.
400 if (threadReqStop) return;
402 else if (channelID == CHANNEL_KEEPALIVE)
405 if (!tcp.read(&KAreply, sizeof(u4))) break;
406 if (threadReqStop) return;
407 KAreply = ntohl(KAreply);
408 if (KAreply == lastKAsent) // successful KA response
411 lastKArecv = KAreply;
412 //logger->debug(TAG, "Rxd correct KA reply");
417 logger->error(TAG, "Rxd a response packet on channel {} !!", channelID);
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.
429 void VDR::connectionDied()
431 // Called from within threadMethod to do cleanup if it decides the connection has died
433 disconnecting = true;
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
440 // If it's a stream receiver, generate a stream packet with flag == connection_lost
443 VDR_PacketReceiver* vdrpr;
444 VDR_ResponsePacket* vresp;
445 while(receivers.size())
447 vdrpr = dynamic_cast<VDR_PacketReceiver*>(*(receivers.begin()));
448 if (vdrpr->receiverChannel == CHANNEL_REQUEST_RESPONSE)
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);
454 if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
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);
463 else if (vdrpr->receiverChannel == CHANNEL_STREAM || vdrpr->receiverChannel == CHANNEL_TVMEDIA)
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);
469 if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
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);
478 for(EDRL::iterator i = receivers.begin(); i != receivers.end(); i++)
479 if (dynamic_cast<VDR_PacketReceiver*>(*i) == vdrpr) { receivers.erase(i); break; }
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");
486 Control::getInstance()->connectionLost();
489 bool VDR::ed_cb_find(EDReceiver* edr, void* userTag)
491 // edr is a VDR_PacketReceiver object made in VDR::RequestResponse
492 // userTag is a VDR_ResponsePacket made in threadMethod
494 VDR_PacketReceiver* vdrpr = dynamic_cast<VDR_PacketReceiver*>(edr);
495 VDR_ResponsePacket* vresp = reinterpret_cast<VDR_ResponsePacket*>(userTag);
497 // Is vresp for vdrpr ?
499 u4 packetChannel = vresp->getChannelID();
500 //logger->debug(TAG, "Image debug {} {} {:#x}", vdrpr->receiverChannel,packetChannel,vdrpr);
501 if (vdrpr->receiverChannel != packetChannel) return false;
503 if (packetChannel == CHANNEL_REQUEST_RESPONSE)
505 if (vdrpr->requestSerialNumber == vresp->getRequestID()) return true;
507 else if (packetChannel == CHANNEL_STREAM)
509 if (vdrpr->streamID == vresp->getStreamID()) return true;
511 else if (packetChannel == CHANNEL_TVMEDIA)
513 if (vdrpr->streamID == vresp->getStreamID()) return true;
519 VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp)
521 //logger->debug(TAG, "RR {}", vrp->getOpcode());
523 if (!connected || disconnecting)
525 logger->debug(TAG, "RR when !connected || disconnecting");
526 VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
527 return vresp; // "no-response" return
530 // ED make new VDR and register
531 // make a VDR_PacketReceiver
532 // - init with serial number of request packet
534 VDR_PacketReceiver vdrpr;
535 // vdrpr.requestTime = time(NULL);
536 vdrpr.receiverChannel = VDR::CHANNEL_REQUEST_RESPONSE;
537 vdrpr.requestSerialNumber = vrp->getSerial();
544 if (!tcp.write(vrp->getPtr(), vrp->getLen()))
547 edUnregister(&vdrpr);
548 VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
549 return vresp; // "no-response" return
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");
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());
561 return vdrpr.save_vresp;
564 bool VDR::sendKA(u4 timeStamp)
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;
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);
582 /////////////////////////////////////////////////////////////////////////////
584 // Here VDR takes a break for the VDR_PacketReceiver helper class
586 void VDR_PacketReceiver::call(void* userTag, bool& r_deregisterEDR, bool& r_wakeThread, bool& r_deleteEDR)
588 if (receiverChannel == VDR::CHANNEL_REQUEST_RESPONSE)
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);
595 r_deregisterEDR = true;
599 else if (receiverChannel == VDR::CHANNEL_STREAM)
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());
607 r_deregisterEDR = false;
608 r_wakeThread = false;
611 else if (receiverChannel == VDR::CHANNEL_TVMEDIA)
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
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.
626 r_deregisterEDR = true;
627 r_wakeThread = false;
630 else abort(); // unknown receiverChannel, should not happen
633 /////////////////////////////////////////////////////////////////////////////
635 bool VDR::doLogin(unsigned int* v_server_min, unsigned int* v_server_max, unsigned int* v_client,
636 ASLPrefList& list, int &subtitles)
638 VDR_RequestPacket vrp;
639 if (!vrp.init(VDR_LOGIN, true, 6)) return false;
641 MACAddress myMAC = tcp.getMAC();
642 if (!vrp.copyin(reinterpret_cast<u1*>(&myMAC), 6)) return false;
644 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
645 if (vresp->noResponse()) { delete vresp; return false; }
647 u4 vdrTime = vresp->extractu4();
648 logger->debug(TAG, "vdrtime = {}", vdrTime);
649 long vdrTimeOffset = vresp->extractLONG();
650 logger->debug(TAG, "offset = {}", vdrTimeOffset);
652 unsigned int version_min=vresp->extractu4();
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;
659 if (0x00000302 <= version_max) {
660 unsigned int numlangcodes = vresp->extractu4();
661 subtitles = vresp->extractu4();
663 for (unsigned int i=0; i<numlangcodes; i++) {
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);
676 if ((version_min > VOMP_PROTOCOL_VERSION)
677 || (version_max < VOMP_PROTOCOL_VERSION) ) {
683 // Set the time and zone on the MVP only
685 #if !defined(WIN32) && !defined(__ANDROID__)
687 /* FIXME make this a config option
688 struct timespec currentTime;
689 currentTime.tv_sec = vdrTime;
690 currentTime.tv_nsec = 0;
691 int b = clock_settime(CLOCK_REALTIME, ¤tTime);
692 logger->debug(TAG, "set clock = {}", b);
696 // now make a TZ variable and set it
700 if (vdrTimeOffset > 0) sign = '-';
703 vdrTimeOffset = abs(vdrTimeOffset);
705 hours = (int)vdrTimeOffset / 3600;
706 minutes = vdrTimeOffset % 3600;
708 logger->debug(TAG, "{} {} {}", sign, hours, minutes);
710 minutes = (int)minutes / 60;
712 logger->debug(TAG, "{} {} {}", sign, hours, minutes);
715 sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
716 setenv("TZ", newTZ, 1);
718 logger->debug(TAG, "Timezone data: {}", newTZ);
722 setCharset(Osd::getInstance()->charSet());
727 bool VDR::LogExtern(const char* logString)
729 if (!connected || disconnecting) return false;
730 int stringLength = strlen(logString);
731 int packetLength = stringLength + 8;
732 char *buffer=new char[packetLength + 1];
734 u4 ul=CHANNEL_NETLOG;
735 buffer[pos++]=(ul>>24)&0xff;
736 buffer[pos++]=(ul>>16)&0xff;
737 buffer[pos++]=(ul>>8)&0xff;
738 buffer[pos++]=ul &0xff;
740 buffer[pos++]=(ul>>24)&0xff;
741 buffer[pos++]=(ul>>16)&0xff;
742 buffer[pos++]=(ul>>8)&0xff;
743 buffer[pos++]=ul &0xff;
745 strcpy(&buffer[8], logString);
747 if (!tcp.write(buffer, packetLength))
750 disconnecting = true; // stop the rest of the connection
751 Control::getInstance()->connectionLost();
758 bool VDR::setCharset(int charset)
760 VDR_RequestPacket vrp;
761 if (!vrp.init(VDR_SETCHARSET, true, sizeof(u4))) return false;
762 if (!vrp.addu4(charset)) return false;
764 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
765 if (vresp->noResponse()) { delete vresp; return false; }
767 u4 success = vresp->extractu4();
770 if (!success) return false;
775 bool VDR::getRecordingsList(RecMan* recman)
777 VDR_RequestPacket vrp;
778 if (!vrp.init(VDR_GETRECORDINGLIST, true, 0)) return false;
780 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
781 if (vresp->noResponse()) { delete vresp; return false; }
783 u4 totalSpace = vresp->extractu4();
784 u4 freeSpace = vresp->extractu4();
785 u4 percent = vresp->extractu4();
787 recman->setStats(totalSpace, freeSpace, percent);
794 while (!vresp->end())
796 start = vresp->extractu4();
797 isNew = vresp->extractu1();
798 name = vresp->extractString();
799 fileName = vresp->extractString();
800 recman->addEntry(isNew, start, name, fileName);
809 int VDR::deleteRecording(char* fileName)
811 VDR_RequestPacket vrp;
812 if (!vrp.init(VDR_DELETERECORDING, true, strlen(fileName) + 1)) return 0;
813 if (!vrp.addString(fileName)) return 0;
815 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
816 if (vresp->noResponse()) { delete vresp; return 0; }
818 int toReturn = toi4(vresp->extractu4());
824 int VDR::deleteRecResume(char* fileName)
826 VDR_RequestPacket vrp;
827 if (!vrp.init(VDR_DELETERECRESUME, true, strlen(fileName) + 1)) return 0;
828 if (!vrp.addString(fileName)) return 0;
830 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
831 if (vresp->noResponse()) { delete vresp; return 0; }
833 int toReturn = toi4(vresp->extractu4());
839 char* VDR::moveRecording(char* fileName, char* newPath)
841 VDR_RequestPacket vrp;
842 if (!vrp.init(VDR_MOVERECORDING, true, strlen(fileName) + 1 + strlen(newPath) + 1)) return NULL;
843 if (!vrp.addString(fileName)) return NULL;
844 if (!vrp.addString(newPath)) return NULL;
846 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
847 if (vresp->noResponse()) { delete vresp; return NULL; }
849 char* toReturn = NULL;
850 int success = toi4(vresp->extractu4());
853 toReturn = vresp->extractString();
861 std::shared_ptr<ChannelList> VDR::getChannelsList(u4 type)
863 VDR_RequestPacket vrp;
864 if (!vrp.init(VDR_GETCHANNELLIST, true, 0)) return NULL;
866 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
867 if (vresp->noResponse()) { delete vresp; return NULL; }
869 // shared_ptr for a ChannelList (std::vector<Channel*>) with custom deleter to delete all the Channel* objects
870 std::shared_ptr<ChannelList> chanList(new ChannelList(),
871 [] (ChannelList* cl) { for (Channel* p : *cl) delete p; });
873 bool h264support=Video::getInstance()->supportsh264();
874 bool mpeg2support=Video::getInstance()->supportsmpeg2();
876 while (!vresp->end())
878 Channel* chan = new Channel();
879 chan->number = vresp->extractu4();
880 chan->type = vresp->extractu4();
881 chan->name = vresp->extractString();
882 chan->vstreamtype = static_cast<u1>(vresp->extractu4());
884 if (chan->type == type && ((chan->vstreamtype==0x1b && h264support)|| (chan->vstreamtype!=0x1b &&mpeg2support)) )
886 chanList->push_back(chan);
887 logger->debug(TAG, "Have added a channel to list. {} {} {}", chan->number, chan->type, chan->name);
888 if (chan->number > maxChannelNumber) maxChannelNumber = chan->number;
898 if (maxChannelNumber > 99999)
899 channelNumberWidth = 6;
900 else if (maxChannelNumber > 9999)
901 channelNumberWidth = 5;
902 else if (maxChannelNumber > 999)
903 channelNumberWidth = 4;
904 else if (maxChannelNumber > 99)
905 channelNumberWidth = 3;
906 else if (maxChannelNumber > 9)
907 channelNumberWidth = 2;
909 channelNumberWidth = 1;
914 int VDR::streamChannel(u4 number, StreamReceiver* tstreamReceiver)
916 VDR_RequestPacket vrp;
917 if (!vrp.init(VDR_STREAMCHANNEL, true, sizeof(u4))) return 0;
918 if (!vrp.addu4(number)) return 0;
921 VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
922 vdrpr->receiverChannel = VDR::CHANNEL_STREAM;
923 vdrpr->streamID = vrp.getSerial();
924 vdrpr->streamReceiver = tstreamReceiver;
926 TEMP_SINGLE_VDR_PR = vdrpr;
928 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
929 if (vresp->noResponse())
937 int toReturn = toi4(vresp->extractu4());
938 logger->debug(TAG, "VDR said {} to start streaming request", toReturn);
944 int VDR::stopStreaming()
946 VDR_RequestPacket vrp;
947 if (!vrp.init(VDR_STOPSTREAMING, true, 0)) return 0;
949 if (TEMP_SINGLE_VDR_PR) // this block only needs to be done if it was a live stream
950 // TEMP_SINGLE_VDR_PR will not be set unless we are streaming a channel
952 edUnregister(TEMP_SINGLE_VDR_PR);
953 delete TEMP_SINGLE_VDR_PR;
954 TEMP_SINGLE_VDR_PR = NULL;
957 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
958 if (vresp->noResponse()) { delete vresp; return 0; }
960 int toReturn = toi4(vresp->extractu4());
966 u1* VDR::getBlock(u8 position, u4 maxAmount, u4* amountReceived)
968 VDR_RequestPacket vrp;
969 if (!vrp.init(VDR_GETBLOCK, true, sizeof(u8) + sizeof(u4))) return NULL;
970 if (!vrp.addu8(position)) return NULL;
971 if (!vrp.addu4(maxAmount)) return NULL;
973 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
974 if (vresp->noResponse()) { delete vresp; return NULL; }
976 if (vresp->serverError())
978 logger->debug(TAG, "Detected getblock 0");
984 // Special handling for getblock
985 u1* toReturn = vresp->getUserData();
986 *amountReceived = vresp->getUserDataLength();
993 u8 VDR::streamRecording(char* fileName, u4* totalFrames, bool* IsPesRecording)
995 VDR_RequestPacket vrp;
996 if (!vrp.init(VDR_STREAMRECORDING, true, strlen(fileName) + 1)) return 0;
997 if (!vrp.addString(fileName)) return 0;
999 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1000 if (vresp->noResponse()) { delete vresp; return 0; }
1002 u8 lengthBytes = vresp->extractu8();
1003 u4 lengthFrames = vresp->extractu4();
1004 u1 isPesRecording = vresp->extractu1();
1007 *totalFrames = lengthFrames;
1008 *IsPesRecording = (isPesRecording);//convert Uchar to bool
1010 logger->debug(TAG, "VDR said length is: {} {}, IsPesRecording {:#x}", lengthBytes, lengthFrames, *IsPesRecording);
1015 u8 VDR::positionFromFrameNumber(u4 frameNumber)
1017 VDR_RequestPacket vrp;
1018 if (!vrp.init(VDR_POSFROMFRAME, true, sizeof(u4))) return 0;
1019 if (!vrp.addu4(frameNumber)) return 0;
1021 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1022 if (vresp->noResponse()) { delete vresp; return 0; }
1024 u8 position = vresp->extractu8();
1027 logger->debug(TAG, "VDR said new position is: {}", position);
1032 u4 VDR::frameNumberFromPosition(u8 position)
1034 VDR_RequestPacket vrp;
1035 if (!vrp.init(VDR_FRAMEFROMPOS, true, sizeof(u8))) return 0;
1036 if (!vrp.addu8(position)) return 0;
1038 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1039 if (vresp->noResponse()) { delete vresp; return 0; }
1041 u4 framenumber = vresp->extractu4();
1044 logger->debug(TAG, "VDR said new framenumber is: {}", framenumber);
1049 bool VDR::getNextIFrame(u4 frameNumber, u4 direction, u8* rfilePosition, u4* rframeNumber, u4* rframeLength)
1051 VDR_RequestPacket vrp;
1052 if (!vrp.init(VDR_GETNEXTIFRAME, true, sizeof(u4)*2)) return false;
1053 if (!vrp.addu4(frameNumber)) return false;
1054 if (!vrp.addu4(direction)) return false;
1056 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1057 if (vresp->noResponse()) { delete vresp; return false; }
1059 if (vresp->serverError())
1061 logger->debug(TAG, "Detected getNextIFrame error");
1066 *rfilePosition = vresp->extractu8();
1067 *rframeNumber = vresp->extractu4();
1068 *rframeLength = vresp->extractu4();
1072 logger->debug(TAG, "VDR GNIF said {} {} {}", *rfilePosition, *rframeNumber, *rframeLength);
1077 EventList* VDR::getChannelSchedule(u4 number)
1081 return getChannelSchedule(number, now, 24 * 60 * 60);
1084 EventList* VDR::getChannelSchedule(u4 number, time_t start, u4 duration)
1086 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
1088 VDR_RequestPacket vrp;
1089 if (!vrp.init(VDR_GETCHANNELSCHEDULE, true, sizeof(u4)*3)) return NULL;
1090 if (!vrp.addu4(number)) return NULL;
1091 if (!vrp.addu4(start)) return NULL;
1092 if (!vrp.addu4(duration)) return NULL;
1094 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1095 if (vresp->noResponse()) { delete vresp; return NULL; }
1097 // received a ulong(0) - schedules error in the plugin
1098 if (vresp->serverError())
1104 EventList* eventList = new EventList();
1106 while (!vresp->end())
1108 Event* event = new Event();
1109 event->id = vresp->extractu4();
1110 event->time = vresp->extractu4();
1111 event->duration = vresp->extractu4();
1112 event->title = vresp->extractString();
1113 event->subtitle = vresp->extractString();
1114 event->description = vresp->extractString();
1115 eventList->push_back(event);
1120 logger->debug(TAG, "Success got to end of getChannelSchedule");
1124 int VDR::configSave(const char* section, const char* key, const char* value)
1126 VDR_RequestPacket vrp;
1127 if (!vrp.init(VDR_CONFIGSAVE, false, 0)) return 0;
1128 if (!vrp.addString(section)) return 0;
1129 if (!vrp.addString(key)) return 0;
1130 if (!vrp.addString(value)) return 0;
1132 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1133 if (vresp->noResponse()) { delete vresp; return 0; }
1135 int toReturn = toi4(vresp->extractu4());
1141 char* VDR::configLoad(const char* section, const char* key)
1143 VDR_RequestPacket vrp;
1144 if (!vrp.init(VDR_CONFIGLOAD, false, 0)) return NULL;
1145 if (!vrp.addString(section)) return NULL;
1146 if (!vrp.addString(key)) return NULL;
1148 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1149 if (vresp->noResponse()) { delete vresp; return NULL; }
1151 char* toReturn = vresp->extractString();
1157 RecTimerList* VDR::getRecTimersList()
1159 VDR_RequestPacket vrp;
1160 if (!vrp.init(VDR_GETTIMERS, true, 0)) return NULL;
1162 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1163 if (vresp->noResponse()) { delete vresp; return NULL; }
1165 RecTimerList* recTimerList = new RecTimerList();
1167 u4 numTimers = vresp->extractu4();
1170 RecTimer* newRecTimer;
1173 while (!vresp->end())
1175 newRecTimer = new RecTimer();
1176 newRecTimer->active = vresp->extractu4();
1177 newRecTimer->recording = vresp->extractu4();
1178 newRecTimer->pending = vresp->extractu4();
1179 newRecTimer->priority = vresp->extractu4();
1180 newRecTimer->lifeTime = vresp->extractu4();
1181 newRecTimer->channelNumber = vresp->extractu4();
1182 newRecTimer->startTime = vresp->extractu4();
1183 newRecTimer->stopTime = vresp->extractu4();
1184 newRecTimer->day = vresp->extractu4();
1185 newRecTimer->weekDays = vresp->extractu4();
1187 tempString = vresp->extractString();
1188 newRecTimer->setFile(tempString);
1189 delete[] tempString;
1191 recTimerList->push_back(newRecTimer);
1192 logger->debug(TAG, "TL: {} {} {} {} {} {} {} {} {}",
1193 newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
1194 newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
1200 sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
1202 return recTimerList;
1205 u4 VDR::setEventTimer(char* timerString)
1207 VDR_RequestPacket vrp;
1208 if (!vrp.init(VDR_SETTIMER, true, strlen(timerString) + 1)) return 0;
1209 if (!vrp.addString(timerString)) return 0;
1211 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1212 if (vresp->noResponse()) { delete vresp; return 0; }
1214 u4 toReturn = vresp->extractu4();
1220 RecInfo* VDR::getRecInfo(char* fileName)
1222 VDR_RequestPacket vrp;
1223 if (!vrp.init(VDR_GETRECINFO2, true, strlen(fileName) + 1)) return NULL;
1224 if (!vrp.addString(fileName)) return NULL;
1225 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1227 if (vresp->noResponse()) { delete vresp; return NULL; }
1229 if (vresp->serverError())
1231 logger->debug(TAG, "Could not get rec info");
1236 RecInfo* recInfo = new RecInfo();
1238 recInfo->timerStart = vresp->extractu4();
1239 recInfo->timerEnd = vresp->extractu4();
1240 recInfo->resumePoint = vresp->extractu4();
1241 recInfo->summary = vresp->extractString();
1243 u4 numComponents = vresp->extractu4();
1246 recInfo->setNumComponents(numComponents);
1247 for (u4 i = 0; i < numComponents; i++)
1249 recInfo->streams[i] = vresp->extractu1();
1250 recInfo->types[i] = vresp->extractu1();
1251 recInfo->languages[i] = vresp->extractString();
1252 recInfo->descriptions[i] = vresp->extractString();
1255 recInfo->fps=vresp->extractdouble();
1256 recInfo->title=vresp->extractString();
1259 recInfo->channelName = vresp->extractString();
1260 recInfo->duration = vresp->extractu4();
1261 recInfo->fileSize = vresp->extractu4();
1262 recInfo->priority = vresp->extractu4();
1263 recInfo->lifetime = vresp->extractu4();
1272 u8 VDR::rescanRecording(u4* totalFrames)
1274 VDR_RequestPacket vrp;
1275 if (!vrp.init(VDR_RESCANRECORDING, true, 0)) return 0;
1277 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1278 if (vresp->noResponse()) { delete vresp; return 0; }
1280 u8 lengthBytes = vresp->extractu8();
1281 u4 lengthFrames = vresp->extractu4();
1284 logger->debug(TAG, "VDR said length is: {} {}", lengthBytes, lengthFrames);
1286 *totalFrames = lengthFrames;
1290 MarkList* VDR::getMarks(char* fileName)
1292 VDR_RequestPacket vrp;
1293 if (!vrp.init(VDR_GETMARKS, true, strlen(fileName) + 1)) return NULL;
1294 if (!vrp.addString(fileName)) return NULL;
1296 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1297 if (vresp->noResponse()) { delete vresp; return NULL; }
1299 if (vresp->serverError())
1305 MarkList* markList = new MarkList();
1307 while (!vresp->end())
1309 Mark* mark = new Mark();
1310 mark->pos = vresp->extractu4();
1312 markList->push_back(mark);
1313 logger->debug(TAG, "Have added a mark to list. {}", mark->pos);
1321 void VDR::getChannelPids(Channel* channel)
1323 VDR_RequestPacket vrp;
1324 if (!vrp.init(VDR_GETCHANNELPIDS, true, sizeof(u4))) return ;
1325 if (!vrp.addu4(channel->number)) return ;
1327 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1328 if (vresp->noResponse()) { delete vresp; return ; }
1330 // Format of response
1338 channel->vpid = vresp->extractu4();
1339 channel->vstreamtype = static_cast<u1>(vresp->extractu4());
1340 channel->numAPids = vresp->extractu4();
1342 for (u4 i = 0; i < channel->numAPids; i++)
1345 newapid.pid = vresp->extractu4();
1346 char * name=vresp->extractString();
1347 strncpy(newapid.desc,name,9);
1349 channel->apids.push_back(newapid);
1352 channel->numDPids = vresp->extractu4();
1354 for (u4 i = 0; i < channel->numDPids; i++)
1357 newdpid.pid = vresp->extractu4();
1358 char * name=vresp->extractString();
1359 strncpy(newdpid.desc,name,9);
1361 channel->dpids.push_back(newdpid);
1364 channel->numSPids = vresp->extractu4();
1366 for (u4 i = 0; i < channel->numSPids; i++)
1369 newspid.pid = vresp->extractu4();
1370 char * name=vresp->extractString();
1371 strncpy(newspid.desc,name,9);
1373 channel->spids.push_back(newspid);
1375 channel->tpid = vresp->extractu4();
1377 for (u4 i = 0; i < channel->numAPids; i++)
1379 channel->apids[i].type = vresp->extractu4();
1381 for (u4 i = 0; i < channel->numDPids; i++)
1383 channel->dpids[i].type = vresp->extractu4();
1385 for (u4 i = 0; i < channel->numSPids; i++)
1387 channel->spids[i].type = vresp->extractu4();
1388 channel->spids[i].data1 = vresp->extractu4();
1389 channel->spids[i].data2 = vresp->extractu4();
1397 #ifdef VOMP_MEDIAPLAYER
1398 MediaList * VDR::getRootList() {
1399 return getMediaList(NULL);
1402 * media List Request:
1404 * Media List response:
1407 MediaList* VDR::getMediaList(const MediaURI * root)
1409 logger->debug(TAG, "getMediaList {},d={}, prov={}", (root?root->getName():"NULL"),
1410 ((root && root->hasDisplayName())?root->getDisplayName():"NULL"),
1411 (root?root->getProvider():providerId));
1412 MediaURI remoteURI(root);
1413 VDR_GetMediaListRequest request(&remoteURI);
1414 SerializeBuffer *vrp=prepareRequest(&request);
1416 logger->log("VDR", Log::ERR, "getMediaList unable to create command");
1420 SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1422 Control::getInstance()->connectionLost();
1426 MediaList *rt=new MediaList(NULL);
1428 VDR_GetMediaListResponse resp(&rtflags,rt);
1429 if (decodeResponse(vresp,&resp) != 0) {
1436 * get image Request:
1438 * get media response:
1442 int VDR::openMedium(u4 channel,const MediaURI *uri, u8 * size, u4 x, u4 y)
1444 MediaURI remoteURI(uri);
1445 VDR_OpenMediumRequest request(&channel,&remoteURI,&x,&y);
1447 SerializeBuffer *vrp=prepareRequest(&request);
1449 logger->log("VDR", Log::ERR, "openMedium unable to create command");
1452 SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1454 Control::getInstance()->connectionLost();
1458 VDR_OpenMediumResponse response(&flags,size);
1459 if (decodeResponse(vresp,&response) != 0) {
1462 logger->debug(TAG, "openMedia len={}", *size);
1467 * getMediaBlock - no separate response class - simple data block
1471 int VDR::getMediaBlock(u4 channel, u8 position, u4 maxAmount, u4* amountReceived, unsigned char **buffer)
1474 VDR_GetMediaBlockRequest request(&channel,&position,&maxAmount);
1475 SerializeBuffer *vrp=prepareRequest(&request);
1477 logger->log("VDR", Log::ERR, "getMediaBlock unable to create command");
1480 SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1482 Control::getInstance()->connectionLost();
1486 // Special handling for getblock
1487 *amountReceived = (u4)(vresp->getEnd()-vresp->getStart());
1488 *buffer = vresp->steelBuffer();
1501 int VDR::getMediaInfo(u4 channel, MediaInfo * result) {
1502 if (! result) return -1;
1503 VDR_GetMediaInfoRequest request(&channel);
1504 SerializeBuffer *vrp=prepareRequest(&request);
1506 logger->log("VDR", Log::ERR, "getMediaInfo unable to create command");
1509 SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1511 Control::getInstance()->connectionLost();
1516 VDR_GetMediaInfoResponse response(&flags,result);
1517 if (decodeResponse(vresp,&response) != 0) {
1530 int VDR::closeMediaChannel(u4 channel) {
1531 VDR_CloseMediaChannelRequest request(&channel);
1532 SerializeBuffer *vrp=prepareRequest(&request);
1534 logger->log("VDR", Log::ERR, "closeMediaChannel unable to create command");
1537 SerializeBuffer* vresp = doRequestResponse(vrp,request.command);
1539 Control::getInstance()->connectionLost();
1543 VDR_CloseMediaChannelResponse response(&flags);
1544 if (decodeResponse(vresp,&response) != 0) return -1;
1545 return (flags != 0)?-1:0;
1551 int VDR::deleteTimer(RecTimer* delTimer)
1553 logger->debug(TAG, "Delete timer called");
1555 VDR_RequestPacket vrp;
1556 if (!vrp.init(VDR_DELETETIMER, false, 0)) return 0;
1557 if (!vrp.addu4(delTimer->channelNumber)) return 0;
1558 if (!vrp.addu4(delTimer->weekDays)) return 0;
1559 if (!vrp.addu4(delTimer->day)) return 0;
1560 if (!vrp.addu4(delTimer->startTime)) return 0;
1561 if (!vrp.addu4(delTimer->stopTime)) return 0;
1563 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1564 if (vresp->noResponse()) { delete vresp; return 0; }
1566 int toReturn = toi4(vresp->extractu4());
1572 I18n::lang_code_list VDR::getLanguageList()
1574 I18n::lang_code_list CodeList;
1575 CodeList["en"] = "English"; // Default entry
1576 VDR_RequestPacket vrp;
1577 if (!vrp.init(VDR_GETLANGUAGELIST, false, 0)) return CodeList;
1578 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1579 if (vresp->noResponse() || vresp->end())
1585 while (!vresp->end())
1587 char* c_code = vresp->extractString();
1588 char* c_name = vresp->extractString();
1589 std::string code = c_code;
1590 std::string name = c_name;
1591 CodeList[code] = name;
1599 int VDR::getLanguageContent(const std::string code, I18n::trans_table& texts)
1601 VDR_RequestPacket vrp;
1602 if (!vrp.init(VDR_GETLANGUAGECONTENT, false, 0)) return 0;
1603 if (!vrp.addString(code.c_str())) return 0;
1604 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1605 if (vresp->noResponse()) { delete vresp; return 0; }
1607 while (!vresp->end())
1609 char* c_key = vresp->extractString();
1610 char* c_text = vresp->extractString();
1611 std::string key = c_key;
1612 std::string text = c_text;
1621 void VDR::shutdownVDR()
1624 logger->debug(TAG, "Shutting down vdr");
1626 logger->debug(TAG, "Shutting down vomp only");
1628 if(!doVDRShutdown || !connected || disconnecting)
1631 VDR_RequestPacket vrp;
1632 logger->debug(TAG, "Sending shutdown");
1633 if (!vrp.init(VDR_SHUTDOWN, false, 0)) return;
1634 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1637 logger->debug(TAG, "VDR shutdown");
1640 void VDR::getScraperEventType(char * fileName, int & movieID,
1641 int & seriesID, int & episodeID)
1646 VDR_RequestPacket vrp;
1647 if (!vrp.init(VDR_GETRECSCRAPEREVENTTYPE, true, strlen(fileName) + 1)) return;
1648 if (!vrp.addString(fileName)) return ;
1649 logger->debug(TAG, "Before response");
1650 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1651 logger->debug(TAG, "After response");
1652 if (vresp->noResponse()) { delete vresp; return ; }
1653 int type = vresp->extractu1();
1654 if (type == 0) //serie
1656 seriesID = vresp->extractLONG();
1657 episodeID = vresp->extractLONG();
1658 } else if (type == 1) //movie
1660 movieID = vresp->extractLONG();
1666 void VDR::getScraperEventType(u4 channelid, u4 eventid, int & movieID,
1667 int & seriesID, int & episodeID, int & epgImage )
1673 VDR_RequestPacket vrp;
1674 if (!vrp.init(VDR_GETEVENTSCRAPEREVENTTYPE, false, 0)) return;
1675 if (!vrp.addu4(channelid)) return ;
1676 if (!vrp.addu4(eventid)) return ;
1677 logger->debug(TAG, "Before response");
1678 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1679 logger->debug(TAG, "After response");
1680 if (vresp->noResponse()) { delete vresp; return ; }
1681 int type = vresp->extractu1();
1682 if (type == 0) //serie
1684 seriesID = vresp->extractLONG();
1685 episodeID = vresp->extractLONG();
1686 } else if (type == 1) //movie
1688 movieID = vresp->extractLONG();
1690 epgImage = vresp->extractLONG();
1695 MovieInfo *VDR::getScraperMovieInfo(int movieID)
1697 ImageLoader* imageLoader = ImageLoader::getInstance();
1699 VDR_RequestPacket vrp;
1700 if (!vrp.init(VDR_GETSCRAPERMOVIEINFO, false, 0)) return NULL;
1701 if (!vrp.addu4(movieID)) return NULL;
1702 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1703 if (vresp->noResponse()) { delete vresp; return NULL; }
1704 MovieInfo* movieinf = new MovieInfo;
1706 ImageGeneric imageGeneric1 = imageLoader->createGeneric();
1707 movieinf->poster.image = imageGeneric1;
1709 ImageGeneric imageGeneric2 = imageLoader->createGeneric();
1710 movieinf->fanart.image = imageGeneric2;
1712 ImageGeneric imageGeneric3 = imageLoader->createGeneric();
1713 movieinf->collectionPoster.image = imageGeneric3;
1715 ImageGeneric imageGeneric4 = imageLoader->createGeneric();
1716 movieinf->collectionFanart.image = imageGeneric4;
1718 movieinf->id=movieID;
1719 movieinf->title = vresp->extractStdString();
1720 movieinf->originalTitle = vresp->extractStdString();
1721 movieinf->tagline = vresp->extractStdString();
1722 movieinf->overview = vresp->extractStdString();
1723 movieinf->adult = vresp->extractu1();
1724 movieinf->collectionName = vresp->extractStdString();
1726 movieinf->budget = vresp->extractLONG();
1727 movieinf->revenue = vresp->extractLONG();
1728 movieinf->genres = vresp->extractStdString();
1729 movieinf->homepage = vresp->extractStdString();
1730 movieinf->releaseDate = vresp->extractStdString();
1731 movieinf->runtime = vresp->extractLONG();
1732 movieinf->popularity = vresp->extractdouble();
1733 movieinf->voteAverage = vresp->extractdouble();
1734 movieinf->poster.width = vresp->extractu4();
1735 movieinf->poster.height = vresp->extractu4();
1736 imageGeneric1->setMovieInfo(movieinf);
1737 imageGeneric1->setElement(0,0);
1738 movieinf->fanart.width = vresp->extractu4();
1739 movieinf->fanart.height = vresp->extractu4();
1740 imageGeneric2->setMovieInfo(movieinf);
1741 imageGeneric2->setElement(1,0);
1742 movieinf->collectionPoster.width = vresp->extractu4();
1743 movieinf->collectionPoster.height = vresp->extractu4();
1744 imageGeneric3->setMovieInfo(movieinf);
1745 imageGeneric3->setElement(2,0);
1746 movieinf->collectionFanart.width = vresp->extractu4();
1747 movieinf->collectionFanart.height = vresp->extractu4();
1748 imageGeneric4->setMovieInfo(movieinf);
1749 imageGeneric4->setElement(3,0);
1750 u4 num_actors = vresp->extractu4();
1751 movieinf->actors.clear();
1752 movieinf->actors.reserve(num_actors);
1753 for (u4 acty=0; acty < num_actors; acty++)
1756 ImageGeneric newActImageGeneric = imageLoader->createGeneric();
1757 new_act.thumb.image = newActImageGeneric;
1759 new_act.name = vresp->extractStdString();
1760 new_act.role = vresp->extractStdString();
1761 new_act.thumb.width = vresp->extractu4();
1762 new_act.thumb.height = vresp->extractu4();
1763 newActImageGeneric->setMovieInfo(movieinf);
1764 newActImageGeneric->setElement(4,acty);
1765 movieinf->actors.push_back(new_act);
1766 imageLoader->ensureLoaded(newActImageGeneric);
1769 imageLoader->ensureLoaded(imageGeneric1);
1770 imageLoader->ensureLoaded(imageGeneric2);
1771 imageLoader->ensureLoaded(imageGeneric3);
1772 imageLoader->ensureLoaded(imageGeneric4);
1778 SeriesInfo* VDR::getScraperSeriesInfo(int seriesID, int episodeID)
1780 ImageLoader* imageLoader = ImageLoader::getInstance();
1782 VDR_RequestPacket vrp;
1783 if (!vrp.init(VDR_GETSCRAPERSERIESINFO, false, 0)) return NULL;
1784 if (!vrp.addu4(seriesID)) return NULL;
1785 if (!vrp.addu4(episodeID)) return NULL;
1787 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1788 if (vresp->noResponse()) { delete vresp; return 0; }
1789 SeriesInfo* seriesinf = new SeriesInfo();
1791 ImageGeneric imageGeneric1 = imageLoader->createGeneric();
1792 Image imageBase1 = imageGeneric1;
1793 seriesinf->episode.image.image = imageBase1;
1795 ImageGeneric imageGeneric2 = imageLoader->createGeneric();
1796 Image imageBase2 = imageGeneric2;
1797 seriesinf->seasonposter.image = imageBase2;
1799 seriesinf->id = seriesID;
1801 seriesinf->name = vresp->extractStdString();
1802 seriesinf->overview = vresp->extractStdString();
1803 seriesinf->firstAired = vresp->extractStdString();
1804 seriesinf->network = vresp->extractStdString();
1805 seriesinf->genre = vresp->extractStdString();
1806 seriesinf->rating = vresp->extractdouble();
1807 seriesinf->status = vresp->extractStdString();
1810 seriesinf->episode.episodeid=episodeID;
1811 seriesinf->episode.number = vresp->extractLONG();
1812 seriesinf->episode.season = vresp->extractLONG();
1813 seriesinf->episode.name = vresp->extractStdString();
1814 seriesinf->episode.firstAired = vresp->extractStdString();
1815 seriesinf->episode.guestStars = vresp->extractStdString();
1816 seriesinf->episode.overview = vresp->extractStdString();
1817 seriesinf->episode.rating = vresp->extractdouble();
1818 seriesinf->episode.image.width = vresp->extractu4();
1819 seriesinf->episode.image.height = vresp->extractu4();
1820 imageGeneric1->setSeriesInfo(seriesinf);
1821 imageGeneric1->setElement(0,0);
1824 u4 num_actors = vresp->extractu4();
1825 seriesinf->actors.clear();
1826 seriesinf->actors.reserve(num_actors);
1827 for (u4 acty=0; acty < num_actors; acty++) {
1829 new_act.name = vresp->extractStdString();
1830 new_act.role = vresp->extractStdString();
1831 new_act.thumb.width = vresp->extractu4();
1832 new_act.thumb.height = vresp->extractu4();
1834 ImageGeneric actorIG = imageLoader->createGeneric();
1835 new_act.thumb.image = actorIG;
1836 actorIG->setSeriesInfo(seriesinf);
1837 actorIG->setElement(1,acty);
1838 seriesinf->actors.push_back(new_act);
1840 imageLoader->ensureLoaded(actorIG);
1842 u4 num_posters = vresp->extractu4();
1843 for (u4 medias = 0; medias < num_posters; medias++ ) {
1844 TVMediaStruct media;
1845 ImageGeneric mediaIG = imageLoader->createGeneric();
1846 media.image = mediaIG;
1847 mediaIG->setSeriesInfo(seriesinf);
1848 mediaIG->setElement(2, medias);
1849 media.width = vresp->extractu4();
1850 media.height = vresp->extractu4();
1851 seriesinf->posters.push_back(media);
1853 imageLoader->ensureLoaded(mediaIG);
1856 u4 num_banners = vresp->extractu4();
1857 for (u4 medias = 0; medias < num_banners; medias++ ) {
1858 TVMediaStruct media;
1859 ImageGeneric mediaIG = imageLoader->createGeneric();
1860 media.image = mediaIG;
1861 mediaIG->setSeriesInfo(seriesinf);
1862 mediaIG->setElement(3,medias);
1863 media.width = vresp->extractu4();
1864 media.height = vresp->extractu4();
1865 seriesinf->banners.push_back(media);
1867 imageLoader->ensureLoaded(mediaIG);
1869 u4 num_fanarts = vresp->extractu4();
1870 for (u4 medias = 0; medias < num_fanarts; medias++ ) {
1871 TVMediaStruct media;
1872 ImageGeneric mediaIG = imageLoader->createGeneric();
1873 media.image = mediaIG;
1874 mediaIG->setSeriesInfo(seriesinf);
1875 mediaIG->setElement(4,medias);
1876 media.width = vresp->extractu4();
1877 media.height = vresp->extractu4();
1878 seriesinf->fanart.push_back(media);
1880 imageLoader->ensureLoaded(mediaIG);
1882 seriesinf->seasonposter.width = vresp->extractu4();
1883 seriesinf->seasonposter.height = vresp->extractu4();
1884 imageGeneric2->setSeriesInfo(seriesinf);
1885 imageGeneric2->setElement(5,0);
1887 imageLoader->ensureLoaded(imageGeneric1);
1888 imageLoader->ensureLoaded(imageGeneric2);
1894 bool VDR::loadImageGeneric(ImageGeneric& image)
1896 VDR_RequestPacket vrp;
1898 if (!vrp.init(VDR_LOADTVMEDIA, false, 0)) return false;
1899 if (!vrp.addu4(image->getType())) return false;
1900 if (!vrp.addu4(image->primary_id)) return false;
1901 if (!vrp.addu4(image->secondary_id)) return false;
1902 if (!vrp.addu4(image->type_pict)) return false;
1903 if (!vrp.addu4(image->container)) return false;
1904 if (!vrp.addu4(image->container_member)) return false;
1905 logger->debug(TAG, "Image with ID {} {}; {} {} {} {};{}",
1906 image->primary_id,image->secondary_id,image->type,image->type_pict,
1907 image->container,image->container_member,vrp.getSerial());
1909 // FIXME - ImageLoader should register itself as a permenant stream receiver instead of making temporary ones like this
1910 VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1911 vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1912 vdrpr->streamID = vrp.getSerial();
1913 vdrpr->streamReceiver = NULL;
1916 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1917 bool ret = !vresp->noResponse();
1922 bool VDR::loadImageRecThumb(ImageRecThumb& image) // FIXME convert return to bool
1924 VDR_RequestPacket vrp;
1926 if (!vrp.init(VDR_LOADTVMEDIARECTHUMB, false, 0)) return false;
1927 if (!vrp.addString(image->getFileName())) return false;
1928 image->setServerLoadingRef(vrp.getSerial());
1930 VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1931 vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1932 vdrpr->streamID = vrp.getSerial();
1933 vdrpr->streamReceiver = NULL;
1936 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1937 bool ret = !vresp->noResponse();
1942 bool VDR::loadImageEventThumb(ImageEventThumb& image)
1944 VDR_RequestPacket vrp;
1946 if (!vrp.init(VDR_LOADTVMEDIAEVENTTHUMB, false, 0)) return false;
1947 if (!vrp.addu4(image->getChannel())) return false;
1948 if (!vrp.addu4(image->getEvent())) return false;
1949 image->setServerLoadingRef(vrp.getSerial());
1951 VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1952 vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1953 vdrpr->streamID = vrp.getSerial();
1954 vdrpr->streamReceiver = NULL;
1957 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1958 bool ret = !vresp->noResponse();
1963 bool VDR::loadImageChannelLogo(ImageChannelLogo& image)
1965 VDR_RequestPacket vrp;
1967 if (!vrp.init(VDR_LOADCHANNELLOGO, false, 0)) return false;
1968 if (!vrp.addu4(image->getChannelID())) return false;
1969 image->setServerLoadingRef(vrp.getSerial());
1971 VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
1972 vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
1973 vdrpr->streamID = vrp.getSerial();
1974 vdrpr->streamReceiver = NULL;
1977 VDR_ResponsePacket* vresp = RequestResponse(&vrp);
1978 bool ret = !vresp->noResponse();