]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Connection failed detection
[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   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   if (!connected) return 0;
230
231   UCHAR buffer[14];
232
233   *(unsigned long*)&buffer[0] = htonl(10);
234   *(unsigned long*)&buffer[4] = htonl(VDR_LOGIN);
235
236   tcp->getMAC((char*)&buffer[8]);
237
238
239   pthread_mutex_lock(&mutex);
240   int a = tcp->sendPacket(buffer, 14);
241   if (a != 14)
242   {
243     disconnect();
244     pthread_mutex_unlock(&mutex);
245     return 0;
246   }
247
248   // reply
249
250   if (!getPacket())
251   {
252     pthread_mutex_unlock(&mutex);
253     return 0;
254   }
255
256   ULONG vdrTime = extractULONG();
257   logger->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
258   long vdrTimeOffset = extractLONG();
259   logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
260
261   freePacket();
262   pthread_mutex_unlock(&mutex);
263
264
265   struct timespec currentTime;
266   currentTime.tv_sec = vdrTime;
267   currentTime.tv_nsec = 0;
268   int b = clock_settime(CLOCK_REALTIME, &currentTime);
269
270   logger->log("VDR", Log::DEBUG, "set clock = %u", b);
271
272   // now make a TZ variable and set it
273   char sign;
274   int hours;
275   int minutes;
276   if (vdrTimeOffset > 0) sign = '-';
277   else sign = '+';
278
279   vdrTimeOffset = abs(vdrTimeOffset);
280
281   hours = (int)vdrTimeOffset / 3600;
282   minutes = vdrTimeOffset % 3600;
283
284   logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
285
286   minutes = (int)minutes / 60;
287
288   logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
289
290   char newTZ[30];
291   sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
292   setenv("TZ", newTZ, 1);
293
294   logger->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
295
296   return 1;
297 }
298
299 Directory* VDR::getRecordingsList()
300 {
301   if (!connected) return 0;
302
303   UCHAR buffer[8];
304
305   *(unsigned long*)&buffer[0] = htonl(4);
306   *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
307
308   pthread_mutex_lock(&mutex);
309   int a = tcp->sendPacket(buffer, 8);
310   if (a != 8)
311   {
312     disconnect();
313     pthread_mutex_unlock(&mutex);
314     return NULL;
315   }
316
317   // reply
318
319   if (!getPacket())
320   {
321     pthread_mutex_unlock(&mutex);
322     return NULL;
323   }
324
325   Directory* recDir = new Directory();
326   recDir->setName("/");
327   recDir->isRoot = 1;
328
329   Directory::totalSpace = extractULONG();
330   Directory::freeSpace = extractULONG();
331   Directory::usedPercent = extractULONG();
332
333   char* string;
334
335   while (packetPos < packetLength)
336   {
337     Recording* rec = new Recording();
338
339     rec->start = extractULONG();
340
341     string = extractString();
342     rec->setName(string);
343     delete[] string;
344
345     rec->fileName = extractString();
346
347     if(rec->isInDir())
348     {
349       char* dirName = rec->getDirName();
350
351       Directory* d = recDir->getDirByName(dirName);
352       if (!d)
353       {
354         d = new Directory();
355         d->setName(dirName);
356 //        Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
357         recDir->dirList.push_back(d);
358       }
359
360       d->recList.push_back(rec);
361     }
362     else
363     {
364       recDir->recList.push_back(rec);
365     }
366
367 //    Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName);
368   }
369
370   freePacket();
371   pthread_mutex_unlock(&mutex);
372
373   // Sort the directory order
374   sort(recDir->dirList.begin(), recDir->dirList.end(), DirectorySorter());
375
376   // Sort all the sub lists
377
378   Directory* sortDir;
379   DirectoryList::iterator i;
380   for (i = recDir->dirList.begin(); i != recDir->dirList.end(); i++)
381   {
382     sortDir = *i;
383     sort(sortDir->recList.begin(), sortDir->recList.end(), RecordingSorter());
384   }
385
386   // Sort the root level list
387   sort(recDir->recList.begin(), recDir->recList.end(), RecordingSorter());
388
389   return recDir;
390 }
391
392 int VDR::deleteRecording(char* fileName)
393 {
394   if (!connected) return 0;
395
396   unsigned long totalLength = 8 + strlen(fileName) + 1;
397   UCHAR buffer[totalLength];
398
399   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
400   *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
401   strcpy((char*)&buffer[8], fileName);
402
403   pthread_mutex_lock(&mutex);
404   unsigned int a = tcp->sendPacket(buffer, totalLength);
405   if (a != totalLength)
406   {
407     disconnect();
408     pthread_mutex_unlock(&mutex);
409     return 0;
410   }
411
412   if (!getPacket())
413   {
414     pthread_mutex_unlock(&mutex);
415     return 0;
416   }
417
418   int toReturn = (int)extractULONG();
419   freePacket();
420   pthread_mutex_unlock(&mutex);
421
422   return toReturn;
423 }
424
425 char* VDR::getRecordingSummary(char* fileName)
426 {
427   if (!connected) return 0;
428
429   unsigned long totalLength = 8 + strlen(fileName) + 1;
430   UCHAR buffer[totalLength];
431
432   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
433   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
434   strcpy((char*)&buffer[8], fileName);
435
436   pthread_mutex_lock(&mutex);
437   unsigned int a = tcp->sendPacket(buffer, totalLength);
438   if (a != totalLength)
439   {
440     disconnect();
441     pthread_mutex_unlock(&mutex);
442     return NULL;
443   }
444
445   if (!getPacket())
446   {
447     pthread_mutex_unlock(&mutex);
448     return NULL;
449   }
450   char* toReturn = extractString();
451   freePacket();
452   pthread_mutex_unlock(&mutex);
453
454   return toReturn;
455 }
456
457 ChannelList* VDR::getChannelsList(ULONG type)
458 {
459   if (!connected) return 0;
460
461   UCHAR buffer[8];
462
463   *(unsigned long*)&buffer[0] = htonl(4);
464   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
465
466   pthread_mutex_lock(&mutex);
467   int a = tcp->sendPacket(buffer, 8);
468   if (a != 8)
469   {
470     disconnect();
471     pthread_mutex_unlock(&mutex);
472     return NULL;
473   }
474
475   // reply
476
477   if (!getPacket())
478   {
479     pthread_mutex_unlock(&mutex);
480     return NULL;
481   }
482
483   ChannelList* chanList = new ChannelList();
484
485   while (packetPos < packetLength)
486   {
487     Channel* chan = new Channel();
488     chan->number = extractULONG();
489     chan->type = extractULONG();
490     chan->name = extractString();
491
492     if (chan->type == type)
493     {
494       chanList->push_back(chan);
495       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
496     }
497     else
498     {
499       delete chan;
500     }
501   }
502
503   freePacket();
504   pthread_mutex_unlock(&mutex);
505
506   return chanList;
507 }
508
509 int VDR::streamChannel(ULONG number)
510 {
511   if (!connected) return 0;
512
513   UCHAR buffer[12];
514
515   *(unsigned long*)&buffer[0] = htonl(8);
516   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
517   *(unsigned long*)&buffer[8] = htonl(number);
518
519   pthread_mutex_lock(&mutex);
520   int a = tcp->sendPacket(buffer, 12);
521
522   if (a != 12)
523   {
524     disconnect();
525     pthread_mutex_unlock(&mutex);
526     return 0;
527   }
528
529   if (!getPacket())
530   {
531     pthread_mutex_unlock(&mutex);
532     return 0;
533   }
534
535   int toReturn = (int)extractULONG();
536   freePacket();
537   pthread_mutex_unlock(&mutex);
538
539   return toReturn;
540 }
541
542 int VDR::stopStreaming()
543 {
544   if (!connected) return 0;
545
546   UCHAR buffer[8];
547
548   *(unsigned long*)&buffer[0] = htonl(4);
549   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
550
551   pthread_mutex_lock(&mutex);
552   int a = tcp->sendPacket(buffer, 8);
553
554   if (a != 8)
555   {
556     disconnect();
557     pthread_mutex_unlock(&mutex);
558     return 0;
559   }
560
561   if (!getPacket())
562   {
563     pthread_mutex_unlock(&mutex);
564     return 0;
565   }
566
567   int toReturn = (int)extractULONG();
568   freePacket();
569   pthread_mutex_unlock(&mutex);
570
571   return toReturn;
572 }
573
574 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
575 {
576   if (!connected) return 0;
577
578   UCHAR buffer[20];
579
580   *(unsigned long*)&buffer[0] = htonl(16);
581   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
582   *(ULLONG*)&buffer[8]        = htonll(position);
583   *(unsigned long*)&buffer[16] = htonl(maxAmount);
584
585   pthread_mutex_lock(&mutex);
586   int a = tcp->sendPacket(buffer, 20);
587   if (a != 20)
588   {
589     disconnect();
590     pthread_mutex_unlock(&mutex);
591     return NULL;
592   }
593
594   if (!getPacket())
595   {
596     pthread_mutex_unlock(&mutex);
597     return NULL;
598   }
599
600   UCHAR* toReturn = packet;
601   *amountReceived = packetLength;
602   // Manually clean up instead of running freePacket to keep the block
603   packet = NULL;
604   packetLength = 0;
605   packetPos = 0;
606   pthread_mutex_unlock(&mutex);
607
608   return toReturn;
609 }
610
611 ULLONG VDR::streamRecording(Recording* rec)
612 {
613   if (!connected) return 0;
614
615   unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
616   UCHAR buffer[totalLength];
617
618   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
619   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
620   strcpy((char*)&buffer[8], rec->fileName);
621
622   pthread_mutex_lock(&mutex);
623   unsigned int a = tcp->sendPacket(buffer, totalLength);
624   if (a != totalLength)
625   {
626     disconnect();
627     pthread_mutex_unlock(&mutex);
628     return 0;
629   }
630
631   if (!getPacket())
632   {
633     pthread_mutex_unlock(&mutex);
634     return 0;
635   }
636
637   ULLONG recordingLength = extractULLONG();
638   freePacket();
639   pthread_mutex_unlock(&mutex);
640
641   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
642
643   return recordingLength;
644 }
645
646 ULLONG VDR::rescanRecording()
647 {
648   if (!connected) return 0;
649
650   unsigned long totalLength = 8;
651   UCHAR buffer[totalLength];
652
653   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
654   *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
655
656   pthread_mutex_lock(&mutex);
657   unsigned int a = tcp->sendPacket(buffer, totalLength);
658   if (a != totalLength)
659   {
660     disconnect();
661     pthread_mutex_unlock(&mutex);
662     return 0;
663   }
664
665   if (!getPacket())
666   {
667     pthread_mutex_unlock(&mutex);
668     return 0;
669   }
670
671   ULLONG recordingLength = extractULLONG();
672   freePacket();
673   pthread_mutex_unlock(&mutex);
674
675   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
676
677   return recordingLength;
678 }
679
680 ULLONG VDR::positionFromFrameNumber(ULONG frameNumber)
681 {
682   if (!connected) return 0;
683
684   unsigned long totalLength = 12;
685   UCHAR buffer[totalLength];
686
687   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
688   *(unsigned long*)&buffer[4] = htonl(VDR_POSFROMFRAME);
689   *(unsigned long*)&buffer[8] = htonl(frameNumber);
690
691   pthread_mutex_lock(&mutex);
692   unsigned int a = tcp->sendPacket(buffer, totalLength);
693   if (a != totalLength)
694   {
695     disconnect();
696     pthread_mutex_unlock(&mutex);
697     return 0;
698   }
699
700   if (!getPacket())
701   {
702     pthread_mutex_unlock(&mutex);
703     return 0;
704   }
705
706   ULLONG position = extractULLONG();
707   freePacket();
708   pthread_mutex_unlock(&mutex);
709
710   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said new position is: %llu", position);
711
712   return position;
713 }
714
715 EventList* VDR::getChannelSchedule(ULONG number)
716 {
717   time_t now;
718   time(&now);
719   return getChannelSchedule(number, now, 24 * 60 * 60);
720 }
721
722 EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
723 {
724 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
725   if (!connected) return 0;
726
727   UCHAR buffer[20];
728
729   *(unsigned long*)&buffer[0] = htonl(16);
730   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
731   *(unsigned long*)&buffer[8] = htonl(number);
732   *(unsigned long*)&buffer[12] = htonl(start);
733   *(unsigned long*)&buffer[16] = htonl(duration);
734
735   pthread_mutex_lock(&mutex);
736   int a = tcp->sendPacket(buffer, 20);
737
738   if (a != 20)
739   {
740     disconnect();
741     pthread_mutex_unlock(&mutex);
742     return NULL;
743   }
744
745   if (!getPacket())
746   {
747     pthread_mutex_unlock(&mutex);
748     return NULL;
749   }
750
751   if (serverError())
752   {
753     freePacket();
754     disconnect();
755     pthread_mutex_unlock(&mutex);
756     return NULL;
757   }
758
759
760   EventList* eventList = new EventList();
761
762   while (packetPos < packetLength)
763   {
764     Event* event = new Event();
765     event->id = extractULONG();
766     event->time = extractULONG();
767     event->duration = extractULONG();
768     event->title = extractString();
769     event->subtitle = extractString();
770     event->description = extractString();
771     eventList->push_back(event);
772 //    eventList->next();
773   }
774
775   freePacket();
776   pthread_mutex_unlock(&mutex);
777
778   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
779
780
781   // debug
782 /*
783   Log* l = Log::getInstance();
784
785
786   l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count);
787
788   Event* currentEvent;
789   for(eventList->reset(); !eventList->eol(); eventList->next())
790   {
791     currentEvent = (Event*)eventList->getCurrent();
792     l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description);
793   }
794 */
795
796   return eventList;
797 }
798
799 ULLONG VDR::getResumePoint(char* fileName)
800 {
801   if (!connected) return 0;
802
803   char* resumeString = configLoad("ResumeData", fileName);
804   if (!resumeString) return 0;
805
806   ULLONG toReturn = strtoull(resumeString, NULL, 10);
807   delete[] resumeString;
808   return toReturn;
809 }
810
811 int VDR::configSave(char* section, char* key, const char* value)
812 {
813   if (!connected) return 0;
814
815   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
816   UCHAR buffer[totalLength];
817
818   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
819   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
820
821   int position = 8;
822   strcpy((char*)&buffer[position], section);
823   position += strlen(section) + 1;
824   strcpy((char*)&buffer[position], key);
825   position += strlen(key) + 1;
826   strcpy((char*)&buffer[position], value);
827
828   pthread_mutex_lock(&mutex);
829   unsigned int a = tcp->sendPacket(buffer, totalLength);
830   if (a != totalLength)
831   {
832     disconnect();
833     pthread_mutex_unlock(&mutex);
834     return 0;
835   }
836
837   if (!getPacket())
838   {
839     pthread_mutex_unlock(&mutex);
840     return 0;
841   }
842
843   int toReturn = (int)extractULONG();
844   freePacket();
845   pthread_mutex_unlock(&mutex);
846
847   return toReturn;
848 }
849
850 char* VDR::configLoad(char* section, char* key)
851 {
852   if (!connected) return 0;
853
854   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
855   UCHAR buffer[totalLength];
856
857   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
858   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
859
860   int position = 8;
861   strcpy((char*)&buffer[position], section);
862   position += strlen(section) + 1;
863   strcpy((char*)&buffer[position], key);
864
865   pthread_mutex_lock(&mutex);
866   unsigned int a = tcp->sendPacket(buffer, totalLength);
867   if (a != totalLength)
868   {
869     disconnect();
870     pthread_mutex_unlock(&mutex);
871     return NULL;
872   }
873
874   if (!getPacket())
875   {
876     pthread_mutex_unlock(&mutex);
877     return NULL;
878   }
879   char* toReturn = extractString();
880   freePacket();
881   pthread_mutex_unlock(&mutex);
882
883   printf("%p %s\n", toReturn, toReturn);
884
885   return toReturn;
886 }
887
888 RecTimerList* VDR::getRecTimersList()
889 {
890   if (!connected) return NULL;
891
892   UCHAR buffer[8];
893
894   *(unsigned long*)&buffer[0] = htonl(4);
895   *(unsigned long*)&buffer[4] = htonl(VDR_GETTIMERS);
896
897   pthread_mutex_lock(&mutex);
898   int a = tcp->sendPacket(buffer, 8);
899   if (a != 8)
900   {
901     disconnect();
902     pthread_mutex_unlock(&mutex);
903     return NULL;
904   }
905
906   // reply
907
908   if (!getPacket())
909   {
910     pthread_mutex_unlock(&mutex);
911     return NULL;
912   }
913
914   RecTimerList* recTimerList = new RecTimerList();
915
916   ULONG numTimers = extractULONG();
917   if (numTimers > 0)
918   {
919     RecTimer* newRecTimer;
920     char* tempString;
921
922     while (packetPos < packetLength)
923     {
924       newRecTimer = new RecTimer();
925       newRecTimer->active = extractULONG();
926       newRecTimer->recording = extractULONG();
927       newRecTimer->pending = extractULONG();
928       newRecTimer->priority = extractULONG();
929       newRecTimer->lifeTime = extractULONG();
930       newRecTimer->channelNumber = extractULONG();
931       newRecTimer->startTime = extractULONG();
932       newRecTimer->stopTime = extractULONG();
933
934       tempString = extractString();
935       newRecTimer->setFile(tempString);
936       delete[] tempString;
937
938       recTimerList->push_back(newRecTimer);
939       Log::getInstance()->log("VDR", Log::DEBUG, "TL: %lu %lu %lu %lu %lu %lu %lu %lu %s",
940         newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
941         newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
942     }
943   }
944
945   freePacket();
946   pthread_mutex_unlock(&mutex);
947
948   // Sort the list
949
950   sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
951
952   return recTimerList;
953 }
954
955 ULONG VDR::setEventTimer(char* timerString)
956 {
957   if (!connected) return false;
958
959   unsigned long totalLength = 8 + strlen(timerString) + 1;
960   UCHAR buffer[totalLength];
961
962   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
963   *(unsigned long*)&buffer[4] = htonl(VDR_SETTIMER);
964   strcpy((char*)&buffer[8], timerString);
965
966   pthread_mutex_lock(&mutex);
967   unsigned int a = tcp->sendPacket(buffer, totalLength);
968   if (a != totalLength)
969   {
970     disconnect();
971     pthread_mutex_unlock(&mutex);
972     return 0;
973   }
974
975   if (!getPacket())
976   {
977     pthread_mutex_unlock(&mutex);
978     return 0;
979   }
980
981   ULONG toReturn = extractULONG();
982   freePacket();
983   pthread_mutex_unlock(&mutex);
984
985   return toReturn;
986 }