]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Fix for #1233050 timezone on client. Also got log to use localtime not utc
[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 }
34
35 VDR::~VDR()
36 {
37   instance = NULL;
38   if (initted) shutdown();
39 }
40
41 VDR* VDR::getInstance()
42 {
43   return instance;
44 }
45
46 int VDR::init(int tport)
47 {
48   if (initted) return 0;
49   initted = 1;
50   port = tport;
51   logger = Log::getInstance();
52   return 1;
53 }
54
55 int VDR::shutdown()
56 {
57   if (!initted) return 0;
58   initted = 0;
59   disconnect();
60   return 1;
61 }
62
63 void VDR::findServers(std::vector<char*>& serverIPs)
64 {
65   findingServer = 1;
66   char* message = "VOMP CLIENT";
67   DatagramSocket ds(port);
68
69   int haveAtLeastOne = 0;
70   char* newIP;
71   int retval;
72   int waitType = 1;
73   while(findingServer)
74   {
75     if (waitType == 1)
76     {
77       logger->log("Core", Log::NOTICE, "Broadcasting for server");
78       ds.send("255.255.255.255", 3024, message, strlen(message));
79     }
80     retval = ds.waitforMessage(waitType);
81
82     if (retval == 2) // we got a reply
83     {
84       if (strcmp(ds.getData(), "VOMP SERVER")) // echo.....
85       {
86         waitType = 2;
87       }
88       else
89       {
90         newIP = new char[16];
91         strcpy(newIP, ds.getFromIPA());
92         serverIPs.push_back(newIP);
93         waitType = 2;
94         haveAtLeastOne = 1;
95       }
96     }
97     else
98     {
99       if (haveAtLeastOne) break;
100       waitType = 1;
101     }
102   }
103 }
104
105 void VDR::cancelFindingServer()
106 {
107   findingServer = 0;
108 }
109
110 void VDR::setServerIP(char* newIP)
111 {
112   strcpy(serverIP, newIP);
113 }
114
115 int VDR::connect()
116 {
117   if (tcp) delete tcp;
118   tcp = new TCP();
119   return tcp->connectTo(serverIP, 3024);
120 }
121
122 void VDR::disconnect()
123 {
124   if (tcp) delete tcp;
125   tcp = NULL;
126 }
127
128 long VDR::getSimpleReply()
129 {
130   unsigned char* p = (unsigned char*)tcp->receivePacket();
131   if (!p) return -1;
132
133   Log::getInstance()->log("VDR", Log::DEBUG, "tcp data length = %i", tcp->getDataLength());
134
135   if (tcp->getDataLength() != 4)
136   {
137     free(p);
138     return -1;
139   }
140
141   ULONG reply = ntohl(*(ULONG*)p);
142
143   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said %li", reply);
144
145   free(p);
146
147   return reply;
148 }
149
150 char* VDR::getStringReply()
151 {
152   unsigned char* p = (unsigned char*)tcp->receivePacket();
153   if (!p) return NULL;
154
155   int dataLength = tcp->getDataLength();
156
157   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
158
159   int count = 0;
160
161   char* returnText;
162   int tLength;
163
164   tLength = strlen((char*)&p[count]);
165   returnText = new char[tLength + 1];
166   strcpy(returnText, (char*)&p[count]);
167   count += tLength + 1;
168
169   free(p);
170
171   return returnText;
172 }
173
174 /////////////////////////////////////////////////////////////////////////////
175
176 int VDR::doLogin()
177 {
178   UCHAR buffer[8];
179
180   *(unsigned long*)&buffer[0] = htonl(4);
181   *(unsigned long*)&buffer[4] = htonl(VDR_LOGIN);
182
183   pthread_mutex_lock(&mutex);
184   int a = tcp->sendPacket(buffer, 8);
185   if (a != 8)
186   {
187     pthread_mutex_unlock(&mutex);
188     return 0;
189   }
190
191   // reply
192
193   UCHAR* p = tcp->receivePacket();
194   pthread_mutex_unlock(&mutex);
195   if (!p) return 0;
196
197   int count = 0;
198
199   unsigned long vdrTime = ntohl(*(unsigned long*)&p[count]);
200   count += sizeof(unsigned long);
201   Log::getInstance()->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
202
203   struct timespec currentTime;
204   currentTime.tv_sec = vdrTime;
205   currentTime.tv_nsec = 0;
206   int b = clock_settime(CLOCK_REALTIME, &currentTime);
207
208   Log::getInstance()->log("VDR", Log::DEBUG, "set clock = %u", b);
209
210   // now make a TZ variable and set it
211   signed int vdrTimeOffset = ntohl(*(signed int*)&p[count]);
212   Log::getInstance()->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
213
214   char sign;
215   int hours;
216   int minutes;
217   if (vdrTimeOffset > 0) sign = '-';
218   else sign = '+';
219
220   vdrTimeOffset = abs(vdrTimeOffset);
221
222   hours = (int)vdrTimeOffset / 3600;
223   minutes = vdrTimeOffset % 3600;
224
225   Log::getInstance()->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
226
227   minutes = (int)minutes / 60;
228
229   Log::getInstance()->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
230
231   char newTZ[30];
232   sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
233   setenv("TZ", newTZ, 1);
234
235   Log::getInstance()->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
236
237   free(p);
238   return 1;
239 }
240
241 Directory* VDR::getRecordingsList()
242 {
243   UCHAR buffer[8];
244
245   *(unsigned long*)&buffer[0] = htonl(4);
246   *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
247
248   pthread_mutex_lock(&mutex);
249   int a = tcp->sendPacket(buffer, 8);
250   if (a != 8)
251   {
252     pthread_mutex_unlock(&mutex);
253     return NULL;
254   }
255
256   // reply
257
258   unsigned char* p = (unsigned char*)tcp->receivePacket();
259   pthread_mutex_unlock(&mutex);
260   if (!p) return 0;
261
262   Directory* recDir = new Directory();
263   recDir->setName("/");
264   recDir->isRoot = 1;
265
266   int dataLength = tcp->getDataLength();
267
268   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
269
270   int count = 0;
271
272   Directory::totalSpace = (*(ULONG*)&p[count]);
273   count += sizeof(ULONG);
274   Directory::freeSpace = (*(ULONG*)&p[count]);
275   count += sizeof(ULONG);
276   Directory::usedPercent = (*(ULONG*)&p[count]);
277   count += sizeof(ULONG);
278
279   int tLength;
280
281   while (count < dataLength)
282   {
283     Recording* rec = new Recording();
284     rec->start = ntohl(*(unsigned long*)&p[count]);
285     count += 4;
286
287     tLength = strlen((char*)&p[count]);
288     rec->setName((char*)&p[count]);
289
290 //    rec->name = new char[tLength + 1];
291 //    strcpy(rec->name, (char*)&p[count]);
292     count += tLength + 1;
293
294     tLength = strlen((char*)&p[count]);
295     rec->fileName = new char[tLength + 1];
296     strcpy(rec->fileName, (char*)&p[count]);
297     count += tLength + 1;
298
299     if(rec->isInDir())
300     {
301       char* dirName = rec->getDirName();
302
303       Directory* d = recDir->getDirByName(dirName);
304       if (!d)
305       {
306         d = new Directory();
307         d->setName(dirName);
308         Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
309         recDir->dirList->add(d);
310       }
311
312       d->recList->add(rec);
313       d->recList->next();
314     }
315     else
316     {
317       recDir->recList->add(rec);
318       recDir->recList->next();
319     }
320
321     Log::getInstance()->log("VDR", Log::DEBUG, "Have added a recording to list. %lu %s", rec->start, rec->getProgName());
322   }
323
324   free(p);
325
326   return recDir;
327 }
328
329 int VDR::deleteRecording(char* fileName)
330 {
331   unsigned long totalLength = 8 + strlen(fileName) + 1;
332   UCHAR buffer[totalLength];
333
334   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
335   *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
336   strcpy((char*)&buffer[8], fileName);
337
338   pthread_mutex_lock(&mutex);
339   unsigned int a = tcp->sendPacket(buffer, totalLength);
340   if (a != totalLength)
341   {
342     pthread_mutex_unlock(&mutex);
343     return 0;
344   }
345
346   int toReturn = getSimpleReply();
347   pthread_mutex_unlock(&mutex);
348   return toReturn;
349 }
350
351 char* VDR::getRecordingSummary(char* fileName)
352 {
353   unsigned long totalLength = 8 + strlen(fileName) + 1;
354   UCHAR buffer[totalLength];
355
356   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
357   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
358   strcpy((char*)&buffer[8], fileName);
359
360   pthread_mutex_lock(&mutex);
361   unsigned int a = tcp->sendPacket(buffer, totalLength);
362   if (a != totalLength)
363   {
364     pthread_mutex_unlock(&mutex);
365     return NULL;
366   }
367
368   char* toReturn = getStringReply();
369   pthread_mutex_unlock(&mutex);
370   return toReturn;
371 }
372
373 List* VDR::getChannelsList(ULONG type)
374 {
375   UCHAR buffer[8];
376
377   *(unsigned long*)&buffer[0] = htonl(4);
378   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
379
380   pthread_mutex_lock(&mutex);
381   int a = tcp->sendPacket(buffer, 8);
382   if (a != 8)
383   {
384     pthread_mutex_unlock(&mutex);
385     return NULL;
386   }
387
388   // reply
389
390   unsigned char* p = (unsigned char*)tcp->receivePacket();
391   pthread_mutex_unlock(&mutex);
392   if (!p) return NULL;
393
394   List* chanList = new List();
395
396   int dataLength = tcp->getDataLength();
397
398   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
399
400   int count = 0;
401
402   int tLength;
403
404   while (count < dataLength)
405   {
406     Channel* chan = new Channel();
407     chan->number = ntohl(*(unsigned long*)&p[count]);
408     count += 4;
409     chan->type = ntohl(*(unsigned long*)&p[count]);
410     count += 4;
411
412     tLength = strlen((char*)&p[count]);
413     chan->name = new char[tLength + 1];
414     strcpy(chan->name, (char*)&p[count]);
415     count += tLength + 1;
416
417     if (chan->type == type)
418     {
419       chanList->add(chan);
420       chanList->next();
421       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
422     }
423     else
424     {
425       delete chan;
426     }
427   }
428
429   free(p);
430
431   return chanList;
432 }
433
434 int VDR::streamChannel(ULONG number)
435 {
436   UCHAR buffer[12];
437
438   *(unsigned long*)&buffer[0] = htonl(8);
439   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
440   *(unsigned long*)&buffer[8] = htonl(number);
441
442   pthread_mutex_lock(&mutex);
443   int a = tcp->sendPacket(buffer, 12);
444
445   if (a != 12)
446   {
447     pthread_mutex_unlock(&mutex);
448     return 0;
449   }
450
451   int toReturn = getSimpleReply();
452   pthread_mutex_unlock(&mutex);
453   return toReturn;
454 }
455
456 int VDR::stopStreaming()
457 {
458   UCHAR buffer[8];
459
460   *(unsigned long*)&buffer[0] = htonl(4);
461   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
462
463   pthread_mutex_lock(&mutex);
464   int a = tcp->sendPacket(buffer, 8);
465
466   if (a != 8)
467   {
468     pthread_mutex_unlock(&mutex);
469     return 0;
470   }
471
472   int toReturn = getSimpleReply();
473   pthread_mutex_unlock(&mutex);
474   return toReturn;
475 }
476
477 int VDR::getBlock(UCHAR* buf, ULLONG position, int amount)
478 {
479   UCHAR buffer[20];
480
481   *(unsigned long*)&buffer[0] = htonl(16);
482   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
483   *(ULLONG*)&buffer[8]        = htonll(position);
484   *(unsigned long*)&buffer[16] = htonl(amount);
485
486   pthread_mutex_lock(&mutex);
487   int a = tcp->sendPacket(buffer, 20);
488   if (a != 20)
489   {
490     pthread_mutex_unlock(&mutex);
491     return 0;
492   }
493
494   unsigned char* p = (unsigned char*)tcp->receivePacket();
495   pthread_mutex_unlock(&mutex);
496   if (!p) return 0;
497   int dataLength = tcp->getDataLength();
498
499   memcpy(buf, p, dataLength);
500   free(p);
501   return dataLength;
502 }
503
504 ULLONG VDR::streamRecording(Recording* rec)
505 {
506   unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
507   UCHAR buffer[totalLength];
508
509   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
510   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
511   strcpy((char*)&buffer[8], rec->fileName);
512
513   pthread_mutex_lock(&mutex);
514   unsigned int a = tcp->sendPacket(buffer, totalLength);
515   if (a != totalLength)
516   {
517     pthread_mutex_unlock(&mutex);
518     return 0;
519   }
520
521   unsigned char* p = (unsigned char*)tcp->receivePacket();
522   pthread_mutex_unlock(&mutex);
523   if (!p) return 0;
524
525   if (tcp->getDataLength() != 8)
526   {
527     free(p);
528     return 0;
529   }
530
531   ULLONG recordingLength = ntohll(*(ULLONG*)p);
532
533   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
534   free(p);
535
536   return recordingLength;
537 }
538
539 int VDR::getChannelSchedule(ULONG number)
540 {
541   UCHAR buffer[12];
542
543   *(unsigned long*)&buffer[0] = htonl(8);
544   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
545   *(unsigned long*)&buffer[8] = htonl(number);
546
547   pthread_mutex_lock(&mutex);
548   int a = tcp->sendPacket(buffer, 12);
549
550   if (a != 12)
551   {
552     pthread_mutex_unlock(&mutex);
553     return -1;
554   }
555
556   unsigned char* p = (unsigned char*)tcp->receivePacket();
557   pthread_mutex_unlock(&mutex);
558   if (!p) return -1;
559
560   int dataLength = tcp->getDataLength();
561
562   if (dataLength != 4)
563   {
564     free(p);
565     return -1;
566   }
567
568   ULONG data = ntohl(*(ULONG*)p);
569   free(p);
570
571   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule %lu", data);
572
573   return data;
574 }
575
576 ULLONG VDR::getResumePoint(char* fileName)
577 {
578   char* resumeString = configLoad("ResumeData", fileName);
579   if (!resumeString) return 0;
580
581   ULLONG toReturn = strtoull(resumeString, NULL, 10);
582   delete[] resumeString;
583   return toReturn;
584 }
585
586 int VDR::configSave(char* section, char* key, char* value)
587 {
588   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
589   UCHAR buffer[totalLength];
590
591   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
592   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
593
594   int position = 8;
595   strcpy((char*)&buffer[position], section);
596   position += strlen(section) + 1;
597   strcpy((char*)&buffer[position], key);
598   position += strlen(key) + 1;
599   strcpy((char*)&buffer[position], value);
600
601   pthread_mutex_lock(&mutex);
602   unsigned int a = tcp->sendPacket(buffer, totalLength);
603   if (a != totalLength)
604   {
605     pthread_mutex_unlock(&mutex);
606     return 0;
607   }
608
609   int toReturn = getSimpleReply();
610   pthread_mutex_unlock(&mutex);
611   return toReturn;
612 }
613
614 char* VDR::configLoad(char* section, char* key)
615 {
616   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
617   UCHAR buffer[totalLength];
618
619   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
620   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
621
622   int position = 8;
623   strcpy((char*)&buffer[position], section);
624   position += strlen(section) + 1;
625   strcpy((char*)&buffer[position], key);
626
627   pthread_mutex_lock(&mutex);
628   unsigned int a = tcp->sendPacket(buffer, totalLength);
629   if (a != totalLength)
630   {
631     pthread_mutex_unlock(&mutex);
632     return NULL;
633   }
634
635   char* toReturn = getStringReply();
636   pthread_mutex_unlock(&mutex);
637   return toReturn;
638 }