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