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