]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Language changes, fix for main menu hang
[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 Directory* VDR::getRecordingsList()
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 NULL;
344   }
345
346   // reply
347
348   if (!getPacket())
349   {
350     MUTEX_UNLOCK(&mutex);
351     return NULL;
352   }
353
354   Directory* recDir = new Directory();
355   recDir->setName("/");
356   recDir->isRoot = 1;
357
358   Directory::totalSpace = extractULONG();
359   Directory::freeSpace = extractULONG();
360   Directory::usedPercent = extractULONG();
361
362   char* string;
363
364   while (packetPos < packetLength)
365   {
366     Recording* rec = new Recording();
367
368     rec->start = extractULONG();
369
370     string = extractString();
371     rec->setName(string);
372     delete[] string;
373
374     rec->fileName = extractString();
375
376     if(rec->isInDir())
377     {
378       char* dirName = rec->getDirName();
379
380       Directory* d = recDir->getDirByName(dirName);
381       if (!d)
382       {
383         d = new Directory();
384         d->setName(dirName);
385 //        Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
386         recDir->dirList.push_back(d);
387       }
388
389       d->recList.push_back(rec);
390     }
391     else
392     {
393       recDir->recList.push_back(rec);
394     }
395
396 //    Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName);
397   }
398
399   freePacket();
400   MUTEX_UNLOCK(&mutex);
401   // Sort the directory order
402   sort(recDir->dirList.begin(), recDir->dirList.end(), DirectorySorter());
403
404   // Sort all the sub lists
405
406   Directory* sortDir;
407   DirectoryList::iterator i;
408   for (i = recDir->dirList.begin(); i != recDir->dirList.end(); i++)
409   {
410     sortDir = *i;
411     sort(sortDir->recList.begin(), sortDir->recList.end(), RecordingSorter());
412   }
413
414   // Sort the root level list
415   sort(recDir->recList.begin(), recDir->recList.end(), RecordingSorter());
416
417   return recDir;
418 }
419
420 int VDR::deleteRecording(char* fileName)
421 {
422   unsigned long totalLength = 8 + strlen(fileName) + 1;
423   UCHAR* buffer = new UCHAR[totalLength];
424
425   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
426   *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
427   strcpy((char*)&buffer[8], fileName);
428
429   MUTEX_LOCK(&mutex);
430   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
431
432   unsigned int a = tcp->sendPacket(buffer, totalLength);
433   delete []buffer;
434
435   if (a != totalLength)
436   {
437     disconnect();
438     MUTEX_UNLOCK(&mutex);
439     return 0;
440   }
441
442   if (!getPacket())
443   {
444     MUTEX_UNLOCK(&mutex);
445     return 0;
446   }
447
448   int toReturn = (int)extractULONG();
449   freePacket();
450   MUTEX_UNLOCK(&mutex);
451
452   return toReturn;
453 }
454
455 char* VDR::getRecordingSummary(char* fileName)
456 {
457   unsigned long totalLength = 8 + strlen(fileName) + 1;
458   UCHAR* buffer = new UCHAR[totalLength];
459
460   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
461   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
462   strcpy((char*)&buffer[8], fileName);
463
464   MUTEX_LOCK(&mutex);
465   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
466
467   unsigned int a = tcp->sendPacket(buffer, totalLength);
468   delete []buffer;
469
470   if (a != totalLength)
471   {
472     disconnect();
473     MUTEX_UNLOCK(&mutex);
474     return NULL;
475   }
476
477   if (!getPacket())
478   {
479     MUTEX_UNLOCK(&mutex);
480     return NULL;
481   }
482   char* toReturn = extractString();
483   freePacket();
484   MUTEX_UNLOCK(&mutex);
485
486   return toReturn;
487 }
488
489 ChannelList* VDR::getChannelsList(ULONG type)
490 {
491   UCHAR buffer[8];
492
493   *(unsigned long*)&buffer[0] = htonl(4);
494   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
495
496   MUTEX_LOCK(&mutex);
497   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
498
499   int a = tcp->sendPacket(buffer, 8);
500   if (a != 8)
501   {
502     disconnect();
503     MUTEX_UNLOCK(&mutex);
504     return NULL;
505   }
506
507   // reply
508
509   if (!getPacket())
510   {
511     MUTEX_UNLOCK(&mutex);
512     return NULL;
513   }
514
515   ChannelList* chanList = new ChannelList();
516
517   while (packetPos < packetLength)
518   {
519     Channel* chan = new Channel();
520     chan->number = extractULONG();
521     chan->type = extractULONG();
522     chan->name = extractString();
523
524     if (chan->type == type)
525     {
526       chanList->push_back(chan);
527       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
528     }
529     else
530     {
531       delete chan;
532     }
533   }
534
535   freePacket();
536   MUTEX_UNLOCK(&mutex);
537
538   return chanList;
539 }
540
541 int VDR::streamChannel(ULONG number)
542 {
543   UCHAR buffer[12];
544
545   *(unsigned long*)&buffer[0] = htonl(8);
546   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
547   *(unsigned long*)&buffer[8] = htonl(number);
548
549   MUTEX_LOCK(&mutex);
550   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
551
552   int a = tcp->sendPacket(buffer, 12);
553
554   if (a != 12)
555   {
556     disconnect();
557     MUTEX_UNLOCK(&mutex);
558     return 0;
559   }
560
561   if (!getPacket())
562   {
563     MUTEX_UNLOCK(&mutex);
564     return 0;
565   }
566
567   int toReturn = (int)extractULONG();
568   freePacket();
569   MUTEX_UNLOCK(&mutex);
570
571   return toReturn;
572 }
573
574 int VDR::stopStreaming()
575 {
576   UCHAR buffer[8];
577
578   *(unsigned long*)&buffer[0] = htonl(4);
579   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
580
581   MUTEX_LOCK(&mutex);
582   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
583
584   int a = tcp->sendPacket(buffer, 8);
585
586   if (a != 8)
587   {
588     disconnect();
589     MUTEX_UNLOCK(&mutex);
590     return 0;
591   }
592
593   if (!getPacket())
594   {
595     MUTEX_UNLOCK(&mutex);
596     return 0;
597   }
598
599   int toReturn = (int)extractULONG();
600   freePacket();
601   MUTEX_UNLOCK(&mutex);
602
603   return toReturn;
604 }
605
606 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
607 {
608   UCHAR buffer[20];
609
610   *(unsigned long*)&buffer[0] = htonl(16);
611   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
612   *(ULLONG*)&buffer[8]        = htonll(position);
613   *(unsigned long*)&buffer[16] = htonl(maxAmount);
614
615   MUTEX_LOCK(&mutex);
616   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
617
618   int a = tcp->sendPacket(buffer, 20);
619   if (a != 20)
620   {
621     disconnect();
622     MUTEX_UNLOCK(&mutex);
623     return NULL;
624   }
625
626   if (!getPacket())
627   {
628     MUTEX_UNLOCK(&mutex);
629     return NULL;
630   }
631
632   if (serverError())
633   {
634     Log::getInstance()->log("VDR", Log::DEBUG, "Detected getblock 0");
635     freePacket();
636     MUTEX_UNLOCK(&mutex);
637     return NULL;
638   }
639
640   UCHAR* toReturn = packet;
641   *amountReceived = packetLength;
642   // Manually clean up instead of running freePacket to keep the block
643   packet = NULL;
644   packetLength = 0;
645   packetPos = 0;
646   MUTEX_UNLOCK(&mutex);
647
648
649   return toReturn;
650 }
651
652 ULLONG VDR::streamRecording(Recording* rec)
653 {
654   unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
655   UCHAR* buffer = new UCHAR[totalLength];
656
657   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
658   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
659   strcpy((char*)&buffer[8], rec->fileName);
660
661   MUTEX_LOCK(&mutex);
662   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
663
664   unsigned int a = tcp->sendPacket(buffer, totalLength);
665   delete []buffer;
666
667   if (a != totalLength)
668   {
669     disconnect();
670     MUTEX_UNLOCK(&mutex);
671     return 0;
672   }
673
674   if (!getPacket())
675   {
676     MUTEX_UNLOCK(&mutex);
677     return 0;
678   }
679
680   ULLONG recordingLength = extractULLONG();
681   freePacket();
682   MUTEX_UNLOCK(&mutex);
683
684   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
685
686   return recordingLength;
687 }
688
689 ULLONG VDR::rescanRecording()
690 {
691   unsigned long totalLength = 8;
692   UCHAR* buffer = new UCHAR[totalLength];
693
694   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
695   *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
696
697   MUTEX_LOCK(&mutex);
698   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
699
700   unsigned int a = tcp->sendPacket(buffer, totalLength);
701   delete []buffer;
702
703   if (a != totalLength)
704   {
705     disconnect();
706     MUTEX_UNLOCK(&mutex);
707     return 0;
708   }
709
710   if (!getPacket())
711   {
712     MUTEX_UNLOCK(&mutex);
713     return 0;
714   }
715
716   ULLONG recordingLength = extractULLONG();
717   freePacket();
718   MUTEX_UNLOCK(&mutex);
719
720   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
721
722   return recordingLength;
723 }
724
725 ULLONG VDR::positionFromFrameNumber(ULONG frameNumber)
726 {
727   unsigned long totalLength = 12;
728   UCHAR* buffer = new UCHAR[totalLength];
729
730   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
731   *(unsigned long*)&buffer[4] = htonl(VDR_POSFROMFRAME);
732   *(unsigned long*)&buffer[8] = htonl(frameNumber);
733
734   MUTEX_LOCK(&mutex);
735   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
736
737   unsigned int a = tcp->sendPacket(buffer, totalLength);
738   delete []buffer;
739
740   if (a != totalLength)
741   {
742     disconnect();
743     MUTEX_UNLOCK(&mutex);
744     return 0;
745   }
746
747   if (!getPacket())
748   {
749     MUTEX_UNLOCK(&mutex);
750     return 0;
751   }
752
753   ULLONG position = extractULLONG();
754   freePacket();
755   MUTEX_UNLOCK(&mutex);
756
757   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said new position is: %llu", position);
758
759   return position;
760 }
761
762 ULONG VDR::frameNumberFromPosition(ULLONG position)
763 {
764   unsigned long totalLength = 16;
765   UCHAR* buffer = new UCHAR[totalLength];
766
767   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
768   *(unsigned long*)&buffer[4] = htonl(VDR_FRAMEFROMPOS);
769   *(ULLONG*)&buffer[8] = htonll(position);
770
771   MUTEX_LOCK(&mutex);
772   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
773
774   unsigned int a = tcp->sendPacket(buffer, totalLength);
775   delete []buffer;
776
777   if (a != totalLength)
778   {
779     disconnect();
780     MUTEX_UNLOCK(&mutex);
781     return 0;
782   }
783
784   if (!getPacket())
785   {
786     MUTEX_UNLOCK(&mutex);
787     return 0;
788   }
789
790   ULONG framenumber = extractULONG();
791   freePacket();
792   MUTEX_UNLOCK(&mutex);
793
794   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said new framenumber is: %u", framenumber);
795
796   return framenumber;
797 }
798
799 EventList* VDR::getChannelSchedule(ULONG number)
800 {
801   time_t now;
802   time(&now);
803   return getChannelSchedule(number, now, 24 * 60 * 60);
804 }
805
806 EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
807 {
808 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
809   UCHAR buffer[20];
810
811   *(unsigned long*)&buffer[0] = htonl(16);
812   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
813   *(unsigned long*)&buffer[8] = htonl(number);
814   *(unsigned long*)&buffer[12] = htonl(start);
815   *(unsigned long*)&buffer[16] = htonl(duration);
816
817   MUTEX_LOCK(&mutex);
818   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
819
820   int a = tcp->sendPacket(buffer, 20);
821
822   if (a != 20)
823   {
824     disconnect();
825     MUTEX_UNLOCK(&mutex);
826     return NULL;
827   }
828
829   if (!getPacket())
830   {
831     MUTEX_UNLOCK(&mutex);
832     return NULL;
833   }
834
835   // received a ulong(0) - schedules error in the plugin
836   if (serverError())
837   {
838     freePacket();
839     MUTEX_UNLOCK(&mutex);
840     return NULL;
841   }
842
843   EventList* eventList = new EventList();
844
845   while (packetPos < packetLength)
846   {
847     Event* event = new Event();
848     event->id = extractULONG();
849     event->time = extractULONG();
850     event->duration = extractULONG();
851     event->title = extractString();
852     event->subtitle = extractString();
853     event->description = extractString();
854     eventList->push_back(event);
855 //    eventList->next();
856   }
857
858   freePacket();
859   MUTEX_UNLOCK(&mutex);
860
861   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
862
863
864   // debug
865 /*
866   Log* l = Log::getInstance();
867
868
869   l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count);
870
871   Event* currentEvent;
872   for(eventList->reset(); !eventList->eol(); eventList->next())
873   {
874     currentEvent = (Event*)eventList->getCurrent();
875     l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description);
876   }
877 */
878
879   return eventList;
880 }
881
882 ULLONG VDR::getResumePoint(char* fileName)
883 {
884   if (!connected) return 0;
885
886   char* resumeString = configLoad("ResumeData", fileName);
887   if (!resumeString) return 0;
888
889   ULLONG toReturn = STRTOULL(resumeString, NULL, 10);
890   delete[] resumeString;
891   return toReturn;
892 }
893
894 int VDR::configSave(char* section, char* key, const char* value)
895 {
896   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
897   UCHAR* buffer = new UCHAR[totalLength];
898
899   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
900   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
901
902   int position = 8;
903   strcpy((char*)&buffer[position], section);
904   position += strlen(section) + 1;
905   strcpy((char*)&buffer[position], key);
906   position += strlen(key) + 1;
907   strcpy((char*)&buffer[position], value);
908
909   MUTEX_LOCK(&mutex);
910   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
911
912   unsigned int a = tcp->sendPacket(buffer, totalLength);
913   delete[] buffer;
914
915   if (a != totalLength)
916   {
917     disconnect();
918     MUTEX_UNLOCK(&mutex);
919     return 0;
920   }
921
922   if (!getPacket())
923   {
924     MUTEX_UNLOCK(&mutex);
925     return 0;
926   }
927
928   int toReturn = (int)extractULONG();
929   freePacket();
930   MUTEX_UNLOCK(&mutex);
931
932   return toReturn;
933 }
934
935 char* VDR::configLoad(char* section, char* key)
936 {
937   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
938   UCHAR* buffer = new UCHAR[totalLength];
939
940   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
941   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
942
943   int position = 8;
944   strcpy((char*)&buffer[position], section);
945   position += strlen(section) + 1;
946   strcpy((char*)&buffer[position], key);
947
948   MUTEX_LOCK(&mutex);
949   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
950
951   unsigned int a = tcp->sendPacket(buffer, totalLength);
952   delete[] buffer;
953
954   if (a != totalLength)
955   {
956     disconnect();
957     MUTEX_UNLOCK(&mutex);
958     return NULL;
959   }
960
961   if (!getPacket())
962   {
963     MUTEX_UNLOCK(&mutex);
964     return NULL;
965   }
966   char* toReturn = extractString();
967   freePacket();
968   MUTEX_UNLOCK(&mutex);
969
970   return toReturn;
971 }
972
973 RecTimerList* VDR::getRecTimersList()
974 {
975   UCHAR buffer[8];
976
977   *(unsigned long*)&buffer[0] = htonl(4);
978   *(unsigned long*)&buffer[4] = htonl(VDR_GETTIMERS);
979
980   MUTEX_LOCK(&mutex);
981   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
982
983   int a = tcp->sendPacket(buffer, 8);
984   if (a != 8)
985   {
986     disconnect();
987     MUTEX_UNLOCK(&mutex);
988     return NULL;
989   }
990
991   // reply
992
993   if (!getPacket())
994   {
995     MUTEX_UNLOCK(&mutex);
996     return NULL;
997   }
998
999   RecTimerList* recTimerList = new RecTimerList();
1000
1001   ULONG numTimers = extractULONG();
1002   if (numTimers > 0)
1003   {
1004     RecTimer* newRecTimer;
1005     char* tempString;
1006
1007     while (packetPos < packetLength)
1008     {
1009       newRecTimer = new RecTimer();
1010       newRecTimer->active = extractULONG();
1011       newRecTimer->recording = extractULONG();
1012       newRecTimer->pending = extractULONG();
1013       newRecTimer->priority = extractULONG();
1014       newRecTimer->lifeTime = extractULONG();
1015       newRecTimer->channelNumber = extractULONG();
1016       newRecTimer->startTime = extractULONG();
1017       newRecTimer->stopTime = extractULONG();
1018
1019       tempString = extractString();
1020       newRecTimer->setFile(tempString);
1021       delete[] tempString;
1022
1023       recTimerList->push_back(newRecTimer);
1024       Log::getInstance()->log("VDR", Log::DEBUG, "TL: %lu %lu %lu %lu %lu %lu %lu %lu %s",
1025         newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
1026         newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
1027     }
1028   }
1029
1030   freePacket();
1031   MUTEX_UNLOCK(&mutex);
1032
1033   // Sort the list
1034
1035   sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
1036
1037   return recTimerList;
1038 }
1039
1040 ULONG VDR::setEventTimer(char* timerString)
1041 {
1042   unsigned long totalLength = 8 + strlen(timerString) + 1;
1043   UCHAR* buffer = new UCHAR[totalLength];
1044
1045   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
1046   *(unsigned long*)&buffer[4] = htonl(VDR_SETTIMER);
1047   strcpy((char*)&buffer[8], timerString);
1048
1049   MUTEX_LOCK(&mutex);
1050   if (!connected) { MUTEX_UNLOCK(&mutex); return 0; }
1051
1052   unsigned int a = tcp->sendPacket(buffer, totalLength);
1053   delete []buffer;
1054
1055   if (a != totalLength)
1056   {
1057     disconnect();
1058     MUTEX_UNLOCK(&mutex);
1059     return 0;
1060   }
1061
1062   if (!getPacket())
1063   {
1064     MUTEX_UNLOCK(&mutex);
1065     return 0;
1066   }
1067
1068   ULONG toReturn = extractULONG();
1069   freePacket();
1070   MUTEX_UNLOCK(&mutex);
1071
1072   return toReturn;
1073 }