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