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