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