]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Select list upgrade, gui and backend support to move recordings
[vompclient.git] / vdr.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "vdr.h"
22
23 VDR* VDR::instance = NULL;
24
25 #ifndef WIN32
26 #define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex)
27 #define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex)
28 #else
29 #define MUTEX_LOCK(mutex) WaitForSingleObject(*(mutex), INFINITE )
30 #define MUTEX_UNLOCK(mutex) ReleaseMutex(*(mutex))
31 #endif
32
33
34 VDR::VDR()
35 {
36   if (instance) return;
37   instance = this;
38   initted = 0;
39   findingServer = 0;
40   tcp = NULL;
41 #ifndef WIN32
42   pthread_mutex_init(&mutex, NULL);
43 #else
44   mutex=CreateMutex(NULL,FALSE,NULL);
45 #endif
46   packetLength = 0;
47   packetPos = 0;
48   packet = NULL;
49   connected = false;
50 }
51
52 VDR::~VDR()
53 {
54 #ifdef WIN32
55   CloseHandle(mutex);
56 #endif
57   instance = NULL;
58   if (initted) shutdown();
59 }
60
61 VDR* VDR::getInstance()
62 {
63   return instance;
64 }
65
66 int VDR::init(int tport)
67 {
68   if (initted) return 0;
69   initted = 1;
70   port = tport;
71   logger = Log::getInstance();
72   return 1;
73 }
74
75 int VDR::shutdown()
76 {
77   if (!initted) return 0;
78   initted = 0;
79   disconnect();
80   return 1;
81 }
82
83 void VDR::findServers(vector<VDRServer>& servers)
84 {
85   findingServer = 1;
86   char* message = "VOMP";
87
88   DatagramSocket ds(port);
89   int haveAtLeastOne = 0;
90   int retval;
91   int waitType = 1;
92   while(findingServer)
93   {
94     if (waitType == 1)
95     {
96       ds.shutdown();
97       ds.init();
98       logger->log("VDR", Log::NOTICE, "Broadcasting for server");
99       ds.send("255.255.255.255", 3024, message, strlen(message));
100     }
101     retval = ds.waitforMessage(waitType);
102
103     if (retval == 2) // we got a reply
104     {
105       if (!strcmp(ds.getData(), "VOMP")) // echo.....
106       {
107         waitType = 2;
108       }
109       else
110       {
111         VDRServer newServer;
112         newServer.ip = new char[16];
113         strcpy(newServer.ip, ds.getFromIPA());
114
115         if (ds.getDataLength() == 0)
116         {
117           newServer.name = new char[1];
118           newServer.name[0] = '\0';
119         }
120         else
121         {
122           newServer.name = new char[strlen(ds.getData())+1];
123           strcpy(newServer.name, ds.getData());
124         }
125
126         servers.push_back(newServer);
127         waitType = 2;
128         haveAtLeastOne = 1;
129       }
130     }
131     else
132     {
133       if (haveAtLeastOne) break;
134       waitType = 1;
135     }
136   }
137   sort(servers.begin(), servers.end(), ServerSorter());
138 }
139
140 void VDR::cancelFindingServer()
141 {
142   findingServer = 0;
143 }
144
145 void VDR::setServerIP(char* newIP)
146 {
147   strcpy(serverIP, newIP);
148 }
149
150 int VDR::connect()
151 {
152   if (tcp) delete tcp;
153   tcp = new TCP();
154   if (tcp->connectTo(serverIP, 3024))
155   {
156     connected = true;
157     return 1;
158   }
159   else
160   {
161     return 0;
162   }
163 }
164
165 void VDR::disconnect()
166 {
167   if (tcp) delete tcp;
168   tcp = NULL;
169   connected = false;
170   Log::getInstance()->log("VDR", Log::DEBUG, "Disconnect");
171 }
172
173 void VDR::setReceiveWindow(size_t size)
174 {
175   if (connected) tcp->setReceiveWindow(size);
176 }
177
178 ///////////////////////////////////////////////////////
179
180 int VDR::getPacket()
181 {
182   packet = (UCHAR*)tcp->receivePacket();
183   if (!packet)
184   {
185     disconnect();
186     return 0;
187   }
188   packetLength = tcp->getDataLength();
189   return 1;
190 }
191
192 void VDR::freePacket()
193 {
194   // Must be called if getPacket return 1, except in getBlock
195   packetLength = 0;
196   packetPos = 0;
197   free(packet);
198   packet = NULL;
199 }
200
201 int VDR::serverError()
202 {
203   if ((packetPos == 0) && (packetLength == 4) && !ntohl(*(ULONG*)packet)) return 1;
204   else return 0;
205 }
206
207 char* VDR::extractString()
208 {
209   if (serverError()) return NULL;
210
211   int length = strlen((char*)&packet[packetPos]);
212   if ((packetPos + length) > packetLength) return NULL;
213   char* str = new char[length + 1];
214   strcpy(str, (char*)&packet[packetPos]);
215   packetPos += length + 1;
216   return str;
217 }
218
219 ULONG VDR::extractULONG()
220 {
221   if ((packetPos + sizeof(ULONG)) > packetLength) return 0;
222   ULONG ul = ntohl(*(ULONG*)&packet[packetPos]);
223   packetPos += sizeof(ULONG);
224   return ul;
225 }
226
227 ULLONG VDR::extractULLONG()
228 {
229   if ((packetPos + sizeof(ULLONG)) > packetLength) return 0;
230   ULLONG ull = ntohll(*(ULLONG*)&packet[packetPos]);
231   packetPos += sizeof(ULLONG);
232   return ull;
233 }
234
235 long VDR::extractLONG()
236 {
237   if ((packetPos + sizeof(long)) > packetLength) return 0;
238   long l = ntohl(*(long*)&packet[packetPos]);
239   packetPos += sizeof(long);
240   return l;
241 }
242
243 /////////////////////////////////////////////////////////////////////////////
244
245 int VDR::doLogin()
246 {
247   UCHAR buffer[14];
248
249   *(unsigned long*)&buffer[0] = htonl(10);
250   *(unsigned long*)&buffer[4] = htonl(VDR_LOGIN);
251
252   tcp->getMAC((char*)&buffer[8]);
253
254
255   MUTEX_LOCK(&mutex);
256   if (!connected)
257   {
258     MUTEX_UNLOCK(&mutex);
259     return 0;
260   }
261
262   int a = tcp->sendPacket(buffer, 14);
263   if (a != 14)
264   {
265     disconnect();
266     MUTEX_UNLOCK(&mutex);
267     return 0;
268   }
269
270   // reply
271
272   if (!getPacket())
273   {
274     MUTEX_UNLOCK(&mutex);
275     return 0;
276   }
277
278   ULONG vdrTime = extractULONG();
279   logger->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
280   long vdrTimeOffset = extractLONG();
281   logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
282
283   freePacket();
284   MUTEX_UNLOCK(&mutex);
285
286   // Set the time and zone on the MVP
287
288 #ifndef WIN32
289   struct timespec currentTime;
290   currentTime.tv_sec = vdrTime;
291   currentTime.tv_nsec = 0;
292   int b = clock_settime(CLOCK_REALTIME, &currentTime);
293
294   logger->log("VDR", Log::DEBUG, "set clock = %u", b);
295
296   // now make a TZ variable and set it
297   char sign;
298   int hours;
299   int minutes;
300   if (vdrTimeOffset > 0) sign = '-';
301   else sign = '+';
302
303   vdrTimeOffset = abs(vdrTimeOffset);
304
305   hours = (int)vdrTimeOffset / 3600;
306   minutes = vdrTimeOffset % 3600;
307
308   logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
309
310   minutes = (int)minutes / 60;
311
312   logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
313
314   char newTZ[30];
315   sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
316   setenv("TZ", newTZ, 1);
317
318   logger->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
319 #endif
320
321   return 1;
322 }
323
324 bool VDR::getRecordingsList(RecMan* recman)
325 {
326   UCHAR buffer[8];
327
328   *(unsigned long*)&buffer[0] = htonl(4);
329   *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
330
331   MUTEX_LOCK(&mutex);
332   if (!connected)
333   {
334     MUTEX_UNLOCK(&mutex);
335     return 0;
336   }
337
338   int a = tcp->sendPacket(buffer, 8);
339   if (a != 8)
340   {
341     disconnect();
342     MUTEX_UNLOCK(&mutex);
343     return false;
344   }
345
346   // reply
347
348   if (!getPacket())
349   {
350     MUTEX_UNLOCK(&mutex);
351     return false;
352   }
353
354   recman->setStats(extractULONG(), extractULONG(), extractULONG());
355
356   ULONG start;
357   char* name;
358   char* fileName;
359
360   while (packetPos < packetLength)
361   {
362     start = extractULONG();
363     name = extractString();
364     fileName = extractString();
365
366     recman->addEntry(start, name, fileName);
367
368     delete[] name;
369     delete[] fileName;
370   }
371
372   freePacket();
373   MUTEX_UNLOCK(&mutex);
374
375   return true;
376 }
377
378 int VDR::deleteRecording(char* fileName)
379 {
380   unsigned long totalLength = 8 + strlen(fileName) + 1;
381   UCHAR* buffer = new UCHAR[totalLength];
382
383   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
384   *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
385   strcpy((char*)&buffer[8], fileName);
386
387   MUTEX_LOCK(&mutex);
388   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
389
390   unsigned int a = tcp->sendPacket(buffer, totalLength);
391   delete []buffer;
392
393   if (a != totalLength)
394   {
395     disconnect();
396     MUTEX_UNLOCK(&mutex);
397     return 0;
398   }
399
400   if (!getPacket())
401   {
402     MUTEX_UNLOCK(&mutex);
403     return 0;
404   }
405
406   int toReturn = (int)extractULONG();
407   freePacket();
408   MUTEX_UNLOCK(&mutex);
409
410   return toReturn;
411 }
412
413 int VDR::moveRecording(char* fileName, char* newPath)
414 {
415   unsigned long totalLength = 8 + strlen(fileName) + 1 + strlen(newPath) + 1;
416   UCHAR* buffer = new UCHAR[totalLength];
417
418   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
419   *(unsigned long*)&buffer[4] = htonl(VDR_MOVERECORDING);
420   strcpy((char*)&buffer[8], fileName);
421   strcpy((char*)&buffer[8 + strlen(fileName) + 1], newPath);
422
423   MUTEX_LOCK(&mutex);
424   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
425
426   unsigned int a = tcp->sendPacket(buffer, totalLength);
427   delete []buffer;
428
429   if (a != totalLength)
430   {
431     disconnect();
432     MUTEX_UNLOCK(&mutex);
433     return 0;
434   }
435
436   if (!getPacket())
437   {
438     MUTEX_UNLOCK(&mutex);
439     return 0;
440   }
441
442   int toReturn = (int)extractULONG();
443   freePacket();
444   MUTEX_UNLOCK(&mutex);
445
446   return toReturn;
447 }
448
449 char* VDR::getRecordingSummary(char* fileName)
450 {
451   unsigned long totalLength = 8 + strlen(fileName) + 1;
452   UCHAR* buffer = new UCHAR[totalLength];
453
454   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
455   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
456   strcpy((char*)&buffer[8], fileName);
457
458   MUTEX_LOCK(&mutex);
459   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
460
461   unsigned int a = tcp->sendPacket(buffer, totalLength);
462   delete []buffer;
463
464   if (a != totalLength)
465   {
466     disconnect();
467     MUTEX_UNLOCK(&mutex);
468     return NULL;
469   }
470
471   if (!getPacket())
472   {
473     MUTEX_UNLOCK(&mutex);
474     return NULL;
475   }
476   char* toReturn = extractString();
477   freePacket();
478   MUTEX_UNLOCK(&mutex);
479
480   return toReturn;
481 }
482
483 ChannelList* VDR::getChannelsList(ULONG type)
484 {
485   UCHAR buffer[8];
486
487   *(unsigned long*)&buffer[0] = htonl(4);
488   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
489
490   MUTEX_LOCK(&mutex);
491   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
492
493   int a = tcp->sendPacket(buffer, 8);
494   if (a != 8)
495   {
496     disconnect();
497     MUTEX_UNLOCK(&mutex);
498     return NULL;
499   }
500
501   // reply
502
503   if (!getPacket())
504   {
505     MUTEX_UNLOCK(&mutex);
506     return NULL;
507   }
508
509   ChannelList* chanList = new ChannelList();
510
511   while (packetPos < packetLength)
512   {
513     Channel* chan = new Channel();
514     chan->number = extractULONG();
515     chan->type = extractULONG();
516     chan->name = extractString();
517
518     if (chan->type == type)
519     {
520       chanList->push_back(chan);
521       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
522     }
523     else
524     {
525       delete chan;
526     }
527   }
528
529   freePacket();
530   MUTEX_UNLOCK(&mutex);
531
532   return chanList;
533 }
534
535 int VDR::streamChannel(ULONG number)
536 {
537   UCHAR buffer[12];
538
539   *(unsigned long*)&buffer[0] = htonl(8);
540   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
541   *(unsigned long*)&buffer[8] = htonl(number);
542
543   MUTEX_LOCK(&mutex);
544   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
545
546   int a = tcp->sendPacket(buffer, 12);
547
548   if (a != 12)
549   {
550     disconnect();
551     MUTEX_UNLOCK(&mutex);
552     return 0;
553   }
554
555   if (!getPacket())
556   {
557     MUTEX_UNLOCK(&mutex);
558     return 0;
559   }
560
561   int toReturn = (int)extractULONG();
562   freePacket();
563   MUTEX_UNLOCK(&mutex);
564
565   return toReturn;
566 }
567
568 int VDR::stopStreaming()
569 {
570   UCHAR buffer[8];
571
572   *(unsigned long*)&buffer[0] = htonl(4);
573   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
574
575   MUTEX_LOCK(&mutex);
576   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
577
578   int a = tcp->sendPacket(buffer, 8);
579
580   if (a != 8)
581   {
582     disconnect();
583     MUTEX_UNLOCK(&mutex);
584     return 0;
585   }
586
587   if (!getPacket())
588   {
589     MUTEX_UNLOCK(&mutex);
590     return 0;
591   }
592
593   int toReturn = (int)extractULONG();
594   freePacket();
595   MUTEX_UNLOCK(&mutex);
596
597   return toReturn;
598 }
599
600 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
601 {
602   UCHAR buffer[20];
603
604   *(unsigned long*)&buffer[0] = htonl(16);
605   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
606   *(ULLONG*)&buffer[8]        = htonll(position);
607   *(unsigned long*)&buffer[16] = htonl(maxAmount);
608
609   MUTEX_LOCK(&mutex);
610   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
611
612   int a = tcp->sendPacket(buffer, 20);
613   if (a != 20)
614   {
615     disconnect();
616     MUTEX_UNLOCK(&mutex);
617     return NULL;
618   }
619
620   if (!getPacket())
621   {
622     MUTEX_UNLOCK(&mutex);
623     return NULL;
624   }
625
626   if (serverError())
627   {
628     Log::getInstance()->log("VDR", Log::DEBUG, "Detected getblock 0");
629     freePacket();
630     MUTEX_UNLOCK(&mutex);
631     return NULL;
632   }
633
634   UCHAR* toReturn = packet;
635   *amountReceived = packetLength;
636   // Manually clean up instead of running freePacket to keep the block
637   packet = NULL;
638   packetLength = 0;
639   packetPos = 0;
640   MUTEX_UNLOCK(&mutex);
641
642
643   return toReturn;
644 }
645
646 ULLONG VDR::streamRecording(char* fileName)
647 {
648   unsigned long totalLength = 8 + strlen(fileName) + 1;
649   UCHAR* buffer = new UCHAR[totalLength];
650
651   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
652   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
653   strcpy((char*)&buffer[8], fileName);
654
655   MUTEX_LOCK(&mutex);
656   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
657
658   unsigned int a = tcp->sendPacket(buffer, totalLength);
659   delete []buffer;
660
661   if (a != totalLength)
662   {
663     disconnect();
664     MUTEX_UNLOCK(&mutex);
665     return 0;
666   }
667
668   if (!getPacket())
669   {
670     MUTEX_UNLOCK(&mutex);
671     return 0;
672   }
673
674   ULLONG recordingLength = extractULLONG();
675   freePacket();
676   MUTEX_UNLOCK(&mutex);
677
678   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
679
680   return recordingLength;
681 }
682
683 ULLONG VDR::rescanRecording()
684 {
685   unsigned long totalLength = 8;
686   UCHAR* buffer = new UCHAR[totalLength];
687
688   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
689   *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
690
691   MUTEX_LOCK(&mutex);
692   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
693
694   unsigned int a = tcp->sendPacket(buffer, totalLength);
695   delete []buffer;
696
697   if (a != totalLength)
698   {
699     disconnect();
700     MUTEX_UNLOCK(&mutex);
701     return 0;
702   }
703
704   if (!getPacket())
705   {
706     MUTEX_UNLOCK(&mutex);
707     return 0;
708   }
709
710   ULLONG recordingLength = extractULLONG();
711   freePacket();
712   MUTEX_UNLOCK(&mutex);
713
714   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
715
716   return recordingLength;
717 }
718
719 ULLONG VDR::positionFromFrameNumber(ULONG frameNumber)
720 {
721   unsigned long totalLength = 12;
722   UCHAR* buffer = new UCHAR[totalLength];
723
724   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
725   *(unsigned long*)&buffer[4] = htonl(VDR_POSFROMFRAME);
726   *(unsigned long*)&buffer[8] = htonl(frameNumber);
727
728   MUTEX_LOCK(&mutex);
729   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
730
731   unsigned int a = tcp->sendPacket(buffer, totalLength);
732   delete []buffer;
733
734   if (a != totalLength)
735   {
736     disconnect();
737     MUTEX_UNLOCK(&mutex);
738     return 0;
739   }
740
741   if (!getPacket())
742   {
743     MUTEX_UNLOCK(&mutex);
744     return 0;
745   }
746
747   ULLONG position = extractULLONG();
748   freePacket();
749   MUTEX_UNLOCK(&mutex);
750
751   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said new position is: %llu", position);
752
753   return position;
754 }
755
756 ULONG VDR::frameNumberFromPosition(ULLONG position)
757 {
758   unsigned long totalLength = 16;
759   UCHAR* buffer = new UCHAR[totalLength];
760
761   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
762   *(unsigned long*)&buffer[4] = htonl(VDR_FRAMEFROMPOS);
763   *(ULLONG*)&buffer[8] = htonll(position);
764
765   MUTEX_LOCK(&mutex);
766   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
767
768   unsigned int a = tcp->sendPacket(buffer, totalLength);
769   delete []buffer;
770
771   if (a != totalLength)
772   {
773     disconnect();
774     MUTEX_UNLOCK(&mutex);
775     return 0;
776   }
777
778   if (!getPacket())
779   {
780     MUTEX_UNLOCK(&mutex);
781     return 0;
782   }
783
784   ULONG framenumber = extractULONG();
785   freePacket();
786   MUTEX_UNLOCK(&mutex);
787
788   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said new framenumber is: %u", framenumber);
789
790   return framenumber;
791 }
792
793 EventList* VDR::getChannelSchedule(ULONG number)
794 {
795   time_t now;
796   time(&now);
797   return getChannelSchedule(number, now, 24 * 60 * 60);
798 }
799
800 EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
801 {
802 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
803   UCHAR buffer[20];
804
805   *(unsigned long*)&buffer[0] = htonl(16);
806   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
807   *(unsigned long*)&buffer[8] = htonl(number);
808   *(unsigned long*)&buffer[12] = htonl(start);
809   *(unsigned long*)&buffer[16] = htonl(duration);
810
811   MUTEX_LOCK(&mutex);
812   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
813
814   int a = tcp->sendPacket(buffer, 20);
815
816   if (a != 20)
817   {
818     disconnect();
819     MUTEX_UNLOCK(&mutex);
820     return NULL;
821   }
822
823   if (!getPacket())
824   {
825     MUTEX_UNLOCK(&mutex);
826     return NULL;
827   }
828
829   // received a ulong(0) - schedules error in the plugin
830   if (serverError())
831   {
832     freePacket();
833     MUTEX_UNLOCK(&mutex);
834     return NULL;
835   }
836
837   EventList* eventList = new EventList();
838
839   while (packetPos < packetLength)
840   {
841     Event* event = new Event();
842     event->id = extractULONG();
843     event->time = extractULONG();
844     event->duration = extractULONG();
845     event->title = extractString();
846     event->subtitle = extractString();
847     event->description = extractString();
848     eventList->push_back(event);
849 //    eventList->next();
850   }
851
852   freePacket();
853   MUTEX_UNLOCK(&mutex);
854
855   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
856
857
858   // debug
859 /*
860   Log* l = Log::getInstance();
861
862
863   l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count);
864
865   Event* currentEvent;
866   for(eventList->reset(); !eventList->eol(); eventList->next())
867   {
868     currentEvent = (Event*)eventList->getCurrent();
869     l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description);
870   }
871 */
872
873   return eventList;
874 }
875
876 ULLONG VDR::getResumePoint(char* fileName)
877 {
878   if (!connected) return 0;
879
880   char* resumeString = configLoad("ResumeData", fileName);
881   if (!resumeString) return 0;
882
883   ULLONG toReturn = STRTOULL(resumeString, NULL, 10);
884   delete[] resumeString;
885   return toReturn;
886 }
887
888 int VDR::configSave(char* section, char* key, const char* value)
889 {
890   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
891   UCHAR* buffer = new UCHAR[totalLength];
892
893   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
894   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
895
896   int position = 8;
897   strcpy((char*)&buffer[position], section);
898   position += strlen(section) + 1;
899   strcpy((char*)&buffer[position], key);
900   position += strlen(key) + 1;
901   strcpy((char*)&buffer[position], value);
902
903   MUTEX_LOCK(&mutex);
904   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
905
906   unsigned int a = tcp->sendPacket(buffer, totalLength);
907   delete[] buffer;
908
909   if (a != totalLength)
910   {
911     disconnect();
912     MUTEX_UNLOCK(&mutex);
913     return 0;
914   }
915
916   if (!getPacket())
917   {
918     MUTEX_UNLOCK(&mutex);
919     return 0;
920   }
921
922   int toReturn = (int)extractULONG();
923   freePacket();
924   MUTEX_UNLOCK(&mutex);
925
926   return toReturn;
927 }
928
929 char* VDR::configLoad(char* section, char* key)
930 {
931   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
932   UCHAR* buffer = new UCHAR[totalLength];
933
934   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
935   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
936
937   int position = 8;
938   strcpy((char*)&buffer[position], section);
939   position += strlen(section) + 1;
940   strcpy((char*)&buffer[position], key);
941
942   MUTEX_LOCK(&mutex);
943   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
944
945   unsigned int a = tcp->sendPacket(buffer, totalLength);
946   delete[] buffer;
947
948   if (a != totalLength)
949   {
950     disconnect();
951     MUTEX_UNLOCK(&mutex);
952     return NULL;
953   }
954
955   if (!getPacket())
956   {
957     MUTEX_UNLOCK(&mutex);
958     return NULL;
959   }
960   char* toReturn = extractString();
961   freePacket();
962   MUTEX_UNLOCK(&mutex);
963
964   return toReturn;
965 }
966
967 RecTimerList* VDR::getRecTimersList()
968 {
969   UCHAR buffer[8];
970
971   *(unsigned long*)&buffer[0] = htonl(4);
972   *(unsigned long*)&buffer[4] = htonl(VDR_GETTIMERS);
973
974   MUTEX_LOCK(&mutex);
975   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
976
977   int a = tcp->sendPacket(buffer, 8);
978   if (a != 8)
979   {
980     disconnect();
981     MUTEX_UNLOCK(&mutex);
982     return NULL;
983   }
984
985   // reply
986
987   if (!getPacket())
988   {
989     MUTEX_UNLOCK(&mutex);
990     return NULL;
991   }
992
993   RecTimerList* recTimerList = new RecTimerList();
994
995   ULONG numTimers = extractULONG();
996   if (numTimers > 0)
997   {
998     RecTimer* newRecTimer;
999     char* tempString;
1000
1001     while (packetPos < packetLength)
1002     {
1003       newRecTimer = new RecTimer();
1004       newRecTimer->active = extractULONG();
1005       newRecTimer->recording = extractULONG();
1006       newRecTimer->pending = extractULONG();
1007       newRecTimer->priority = extractULONG();
1008       newRecTimer->lifeTime = extractULONG();
1009       newRecTimer->channelNumber = extractULONG();
1010       newRecTimer->startTime = extractULONG();
1011       newRecTimer->stopTime = extractULONG();
1012
1013       tempString = extractString();
1014       newRecTimer->setFile(tempString);
1015       delete[] tempString;
1016
1017       recTimerList->push_back(newRecTimer);
1018       Log::getInstance()->log("VDR", Log::DEBUG, "TL: %lu %lu %lu %lu %lu %lu %lu %lu %s",
1019         newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
1020         newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
1021     }
1022   }
1023
1024   freePacket();
1025   MUTEX_UNLOCK(&mutex);
1026
1027   // Sort the list
1028
1029   sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
1030
1031   return recTimerList;
1032 }
1033
1034 ULONG VDR::setEventTimer(char* timerString)
1035 {
1036   unsigned long totalLength = 8 + strlen(timerString) + 1;
1037   UCHAR* buffer = new UCHAR[totalLength];
1038
1039   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
1040   *(unsigned long*)&buffer[4] = htonl(VDR_SETTIMER);
1041   strcpy((char*)&buffer[8], timerString);
1042
1043   MUTEX_LOCK(&mutex);
1044   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
1045
1046   unsigned int a = tcp->sendPacket(buffer, totalLength);
1047   delete []buffer;
1048
1049   if (a != totalLength)
1050   {
1051     disconnect();
1052     MUTEX_UNLOCK(&mutex);
1053     return 0;
1054   }
1055
1056   if (!getPacket())
1057   {
1058     MUTEX_UNLOCK(&mutex);
1059     return 0;
1060   }
1061
1062   ULONG toReturn = extractULONG();
1063   freePacket();
1064   MUTEX_UNLOCK(&mutex);
1065
1066   return toReturn;
1067 }