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