]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Frame number stuff
[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 ULLONG VDR::positionFromFrameNumber(ULONG frameNumber)
667 {
668   if (!connected) return 0;
669
670   unsigned long totalLength = 12;
671   UCHAR buffer[totalLength];
672
673   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
674   *(unsigned long*)&buffer[4] = htonl(VDR_POSFROMFRAME);
675   *(unsigned long*)&buffer[8] = htonl(frameNumber);
676
677   pthread_mutex_lock(&mutex);
678   unsigned int a = tcp->sendPacket(buffer, totalLength);
679   if (a != totalLength)
680   {
681     pthread_mutex_unlock(&mutex);
682     return 0;
683   }
684
685   if (!getPacket())
686   {
687     pthread_mutex_unlock(&mutex);
688     return 0;
689   }
690
691   ULLONG position = extractULLONG();
692   freePacket();
693   pthread_mutex_unlock(&mutex);
694
695   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said new position is: %llu", position);
696
697   return position;
698 }
699
700 EventList* VDR::getChannelSchedule(ULONG number)
701 {
702   time_t now;
703   time(&now);
704   return getChannelSchedule(number, now, 24 * 60 * 60);
705 }
706
707 EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
708 {
709 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
710   if (!connected) return 0;
711
712   UCHAR buffer[20];
713
714   *(unsigned long*)&buffer[0] = htonl(16);
715   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
716   *(unsigned long*)&buffer[8] = htonl(number);
717   *(unsigned long*)&buffer[12] = htonl(start);
718   *(unsigned long*)&buffer[16] = htonl(duration);
719
720   pthread_mutex_lock(&mutex);
721   int a = tcp->sendPacket(buffer, 20);
722
723   if (a != 20)
724   {
725     pthread_mutex_unlock(&mutex);
726     return NULL;
727   }
728
729   if (!getPacket())
730   {
731     pthread_mutex_unlock(&mutex);
732     return NULL;
733   }
734
735   if (serverError())
736   {
737     freePacket();
738     pthread_mutex_unlock(&mutex);
739     return NULL;
740   }
741
742
743   EventList* eventList = new EventList();
744
745   while (packetPos < packetLength)
746   {
747     Event* event = new Event();
748     event->id = extractULONG();
749     event->time = extractULONG();
750     event->duration = extractULONG();
751     event->title = extractString();
752     event->subtitle = extractString();
753     event->description = extractString();
754     eventList->push_back(event);
755 //    eventList->next();
756   }
757
758   freePacket();
759   pthread_mutex_unlock(&mutex);
760
761   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
762
763
764   // debug
765 /*
766   Log* l = Log::getInstance();
767
768
769   l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count);
770
771   Event* currentEvent;
772   for(eventList->reset(); !eventList->eol(); eventList->next())
773   {
774     currentEvent = (Event*)eventList->getCurrent();
775     l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description);
776   }
777 */
778
779   return eventList;
780 }
781
782 ULLONG VDR::getResumePoint(char* fileName)
783 {
784   if (!connected) return 0;
785
786   char* resumeString = configLoad("ResumeData", fileName);
787   if (!resumeString) return 0;
788
789   ULLONG toReturn = strtoull(resumeString, NULL, 10);
790   delete[] resumeString;
791   return toReturn;
792 }
793
794 int VDR::configSave(char* section, char* key, const char* value)
795 {
796   if (!connected) return 0;
797
798   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
799   UCHAR buffer[totalLength];
800
801   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
802   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
803
804   int position = 8;
805   strcpy((char*)&buffer[position], section);
806   position += strlen(section) + 1;
807   strcpy((char*)&buffer[position], key);
808   position += strlen(key) + 1;
809   strcpy((char*)&buffer[position], value);
810
811   pthread_mutex_lock(&mutex);
812   unsigned int a = tcp->sendPacket(buffer, totalLength);
813   if (a != totalLength)
814   {
815     pthread_mutex_unlock(&mutex);
816     return 0;
817   }
818
819   if (!getPacket())
820   {
821     pthread_mutex_unlock(&mutex);
822     return 0;
823   }
824
825   int toReturn = (int)extractULONG();
826   freePacket();
827   pthread_mutex_unlock(&mutex);
828
829   return toReturn;
830 }
831
832 char* VDR::configLoad(char* section, char* key)
833 {
834   if (!connected) return 0;
835
836   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
837   UCHAR buffer[totalLength];
838
839   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
840   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
841
842   int position = 8;
843   strcpy((char*)&buffer[position], section);
844   position += strlen(section) + 1;
845   strcpy((char*)&buffer[position], key);
846
847   pthread_mutex_lock(&mutex);
848   unsigned int a = tcp->sendPacket(buffer, totalLength);
849   if (a != totalLength)
850   {
851     pthread_mutex_unlock(&mutex);
852     return NULL;
853   }
854
855   if (!getPacket())
856   {
857     pthread_mutex_unlock(&mutex);
858     return NULL;
859   }
860   char* toReturn = extractString();
861   freePacket();
862   pthread_mutex_unlock(&mutex);
863
864   return toReturn;
865 }
866
867 RecTimerList* VDR::getRecTimersList()
868 {
869   if (!connected) return NULL;
870
871   UCHAR buffer[8];
872
873   *(unsigned long*)&buffer[0] = htonl(4);
874   *(unsigned long*)&buffer[4] = htonl(VDR_GETTIMERS);
875
876   pthread_mutex_lock(&mutex);
877   int a = tcp->sendPacket(buffer, 8);
878   if (a != 8)
879   {
880     pthread_mutex_unlock(&mutex);
881     return NULL;
882   }
883
884   // reply
885
886   if (!getPacket())
887   {
888     pthread_mutex_unlock(&mutex);
889     return NULL;
890   }
891
892   RecTimerList* recTimerList = new RecTimerList();
893
894   ULONG numTimers = extractULONG();
895   if (numTimers > 0)
896   {
897     RecTimer* newRecTimer;
898     char* tempString;
899
900     while (packetPos < packetLength)
901     {
902       newRecTimer = new RecTimer();
903       newRecTimer->active = extractULONG();
904       newRecTimer->recording = extractULONG();
905       newRecTimer->pending = extractULONG();
906       newRecTimer->priority = extractULONG();
907       newRecTimer->lifeTime = extractULONG();
908       newRecTimer->channelNumber = extractULONG();
909       newRecTimer->startTime = extractULONG();
910       newRecTimer->stopTime = extractULONG();
911
912       tempString = extractString();
913       newRecTimer->setFile(tempString);
914       delete[] tempString;
915
916       recTimerList->push_back(newRecTimer);
917       Log::getInstance()->log("VDR", Log::DEBUG, "TL: %lu %lu %lu %lu %lu %lu %lu %lu %s",
918         newRecTimer->active, newRecTimer->recording, newRecTimer->pending, newRecTimer->priority, newRecTimer->lifeTime,
919         newRecTimer->channelNumber, newRecTimer->startTime, newRecTimer->stopTime, newRecTimer->getFile());
920     }
921   }
922
923   freePacket();
924   pthread_mutex_unlock(&mutex);
925
926   // Sort the list
927
928   sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
929
930   return recTimerList;
931 }
932
933 ULONG VDR::setEventTimer(char* timerString)
934 {
935   if (!connected) return false;
936
937   unsigned long totalLength = 8 + strlen(timerString) + 1;
938   UCHAR buffer[totalLength];
939
940   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
941   *(unsigned long*)&buffer[4] = htonl(VDR_SETTIMER);
942   strcpy((char*)&buffer[8], timerString);
943
944   pthread_mutex_lock(&mutex);
945   unsigned int a = tcp->sendPacket(buffer, totalLength);
946   if (a != totalLength)
947   {
948     pthread_mutex_unlock(&mutex);
949     return 0;
950   }
951
952   if (!getPacket())
953   {
954     pthread_mutex_unlock(&mutex);
955     return 0;
956   }
957
958   ULONG toReturn = extractULONG();
959   freePacket();
960   pthread_mutex_unlock(&mutex);
961
962   return toReturn;
963 }