]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Initial import
[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   unsigned long vdrTime = ntohl(*(unsigned long*)p);
198   Log::getInstance()->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
199
200   struct timespec currentTime;
201   currentTime.tv_sec = vdrTime;
202   currentTime.tv_nsec = 0;
203   int b = clock_settime(CLOCK_REALTIME, &currentTime);
204
205   Log::getInstance()->log("VDR", Log::DEBUG, "set clock = %u", b);
206
207   free(p);
208   return 1;
209 }
210
211 Directory* VDR::getRecordingsList()
212 {
213   UCHAR buffer[8];
214
215   *(unsigned long*)&buffer[0] = htonl(4);
216   *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
217
218   pthread_mutex_lock(&mutex);
219   int a = tcp->sendPacket(buffer, 8);
220   if (a != 8)
221   {
222     pthread_mutex_unlock(&mutex);
223     return NULL;
224   }
225
226   // reply
227
228   unsigned char* p = (unsigned char*)tcp->receivePacket();
229   pthread_mutex_unlock(&mutex);
230   if (!p) return 0;
231
232   Directory* recDir = new Directory();
233   recDir->setName("/");
234   recDir->isRoot = 1;
235
236   int dataLength = tcp->getDataLength();
237
238   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
239
240   int count = 0;
241
242   Directory::totalSpace = (*(ULONG*)&p[count]);
243   count += sizeof(ULONG);
244   Directory::freeSpace = (*(ULONG*)&p[count]);
245   count += sizeof(ULONG);
246   Directory::usedPercent = (*(ULONG*)&p[count]);
247   count += sizeof(ULONG);
248
249   int tLength;
250
251   while (count < dataLength)
252   {
253     Recording* rec = new Recording();
254     rec->start = ntohl(*(unsigned long*)&p[count]);
255     count += 4;
256
257     tLength = strlen((char*)&p[count]);
258     rec->setName((char*)&p[count]);
259
260 //    rec->name = new char[tLength + 1];
261 //    strcpy(rec->name, (char*)&p[count]);
262     count += tLength + 1;
263
264     tLength = strlen((char*)&p[count]);
265     rec->fileName = new char[tLength + 1];
266     strcpy(rec->fileName, (char*)&p[count]);
267     count += tLength + 1;
268
269     if(rec->isInDir())
270     {
271       char* dirName = rec->getDirName();
272
273       Directory* d = recDir->getDirByName(dirName);
274       if (!d)
275       {
276         d = new Directory();
277         d->setName(dirName);
278         Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
279         recDir->dirList->add(d);
280       }
281
282       d->recList->add(rec);
283       d->recList->next();
284     }
285     else
286     {
287       recDir->recList->add(rec);
288       recDir->recList->next();
289     }
290
291     Log::getInstance()->log("VDR", Log::DEBUG, "Have added a recording to list. %lu %s", rec->start, rec->getProgName());
292   }
293
294   free(p);
295
296   return recDir;
297 }
298
299 int VDR::deleteRecording(char* fileName)
300 {
301   unsigned long totalLength = 8 + strlen(fileName) + 1;
302   UCHAR buffer[totalLength];
303
304   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
305   *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
306   strcpy((char*)&buffer[8], fileName);
307
308   pthread_mutex_lock(&mutex);
309   unsigned int a = tcp->sendPacket(buffer, totalLength);
310   if (a != totalLength)
311   {
312     pthread_mutex_unlock(&mutex);
313     return 0;
314   }
315
316   int toReturn = getSimpleReply();
317   pthread_mutex_unlock(&mutex);
318   return toReturn;
319 }
320
321 char* VDR::getRecordingSummary(char* fileName)
322 {
323   unsigned long totalLength = 8 + strlen(fileName) + 1;
324   UCHAR buffer[totalLength];
325
326   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
327   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
328   strcpy((char*)&buffer[8], fileName);
329
330   pthread_mutex_lock(&mutex);
331   unsigned int a = tcp->sendPacket(buffer, totalLength);
332   if (a != totalLength)
333   {
334     pthread_mutex_unlock(&mutex);
335     return NULL;
336   }
337
338   char* toReturn = getStringReply();
339   pthread_mutex_unlock(&mutex);
340   return toReturn;
341 }
342
343 List* VDR::getChannelsList(ULONG type)
344 {
345   UCHAR buffer[8];
346
347   *(unsigned long*)&buffer[0] = htonl(4);
348   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
349
350   pthread_mutex_lock(&mutex);
351   int a = tcp->sendPacket(buffer, 8);
352   if (a != 8)
353   {
354     pthread_mutex_unlock(&mutex);
355     return NULL;
356   }
357
358   // reply
359
360   unsigned char* p = (unsigned char*)tcp->receivePacket();
361   pthread_mutex_unlock(&mutex);
362   if (!p) return NULL;
363
364   List* chanList = new List();
365
366   int dataLength = tcp->getDataLength();
367
368   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
369
370   int count = 0;
371
372   int tLength;
373
374   while (count < dataLength)
375   {
376     Channel* chan = new Channel();
377     chan->number = ntohl(*(unsigned long*)&p[count]);
378     count += 4;
379     chan->type = ntohl(*(unsigned long*)&p[count]);
380     count += 4;
381
382     tLength = strlen((char*)&p[count]);
383     chan->name = new char[tLength + 1];
384     strcpy(chan->name, (char*)&p[count]);
385     count += tLength + 1;
386
387     if (chan->type == type)
388     {
389       chanList->add(chan);
390       chanList->next();
391       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
392     }
393     else
394     {
395       delete chan;
396     }
397   }
398
399   free(p);
400
401   return chanList;
402 }
403
404 int VDR::streamChannel(ULONG number)
405 {
406   UCHAR buffer[12];
407
408   *(unsigned long*)&buffer[0] = htonl(8);
409   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
410   *(unsigned long*)&buffer[8] = htonl(number);
411
412   pthread_mutex_lock(&mutex);
413   int a = tcp->sendPacket(buffer, 12);
414
415   if (a != 12)
416   {
417     pthread_mutex_unlock(&mutex);
418     return 0;
419   }
420
421   int toReturn = getSimpleReply();
422   pthread_mutex_unlock(&mutex);
423   return toReturn;
424 }
425
426 int VDR::stopStreaming()
427 {
428   UCHAR buffer[8];
429
430   *(unsigned long*)&buffer[0] = htonl(4);
431   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
432
433   pthread_mutex_lock(&mutex);
434   int a = tcp->sendPacket(buffer, 8);
435
436   if (a != 8)
437   {
438     pthread_mutex_unlock(&mutex);
439     return 0;
440   }
441
442   int toReturn = getSimpleReply();
443   pthread_mutex_unlock(&mutex);
444   return toReturn;
445 }
446
447 int VDR::getBlock(UCHAR* buf, ULLONG position, int amount)
448 {
449   UCHAR buffer[20];
450
451   *(unsigned long*)&buffer[0] = htonl(16);
452   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
453   *(ULLONG*)&buffer[8]        = htonll(position);
454   *(unsigned long*)&buffer[16] = htonl(amount);
455
456   pthread_mutex_lock(&mutex);
457   int a = tcp->sendPacket(buffer, 20);
458   if (a != 20)
459   {
460     pthread_mutex_unlock(&mutex);
461     return 0;
462   }
463
464   unsigned char* p = (unsigned char*)tcp->receivePacket();
465   pthread_mutex_unlock(&mutex);
466   if (!p) return 0;
467   int dataLength = tcp->getDataLength();
468
469   memcpy(buf, p, dataLength);
470   free(p);
471   return dataLength;
472 }
473
474 ULLONG VDR::streamRecording(Recording* rec)
475 {
476   unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
477   UCHAR buffer[totalLength];
478
479   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
480   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
481   strcpy((char*)&buffer[8], rec->fileName);
482
483   pthread_mutex_lock(&mutex);
484   unsigned int a = tcp->sendPacket(buffer, totalLength);
485   if (a != totalLength)
486   {
487     pthread_mutex_unlock(&mutex);
488     return 0;
489   }
490
491   unsigned char* p = (unsigned char*)tcp->receivePacket();
492   pthread_mutex_unlock(&mutex);
493   if (!p) return 0;
494
495   if (tcp->getDataLength() != 8)
496   {
497     free(p);
498     return 0;
499   }
500
501   ULLONG recordingLength = ntohll(*(ULLONG*)p);
502
503   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
504   free(p);
505
506   return recordingLength;
507 }
508
509 int VDR::getChannelSchedule(ULONG number)
510 {
511   UCHAR buffer[12];
512
513   *(unsigned long*)&buffer[0] = htonl(8);
514   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
515   *(unsigned long*)&buffer[8] = htonl(number);
516
517   pthread_mutex_lock(&mutex);
518   int a = tcp->sendPacket(buffer, 12);
519
520   if (a != 12)
521   {
522     pthread_mutex_unlock(&mutex);
523     return -1;
524   }
525
526   unsigned char* p = (unsigned char*)tcp->receivePacket();
527   pthread_mutex_unlock(&mutex);
528   if (!p) return -1;
529
530   int dataLength = tcp->getDataLength();
531
532   if (dataLength != 4)
533   {
534     free(p);
535     return -1;
536   }
537
538   ULONG data = ntohl(*(ULONG*)p);
539   free(p);
540
541   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule %lu", data);
542
543   return data;
544 }
545
546 ULLONG VDR::getResumePoint(char* fileName)
547 {
548   char* resumeString = configLoad("ResumeData", fileName);
549   if (!resumeString) return 0;
550
551   ULLONG toReturn = strtoull(resumeString, NULL, 10);
552   delete[] resumeString;
553   return toReturn;
554 }
555
556 int VDR::configSave(char* section, char* key, char* value)
557 {
558   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
559   UCHAR buffer[totalLength];
560
561   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
562   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
563
564   int position = 8;
565   strcpy((char*)&buffer[position], section);
566   position += strlen(section) + 1;
567   strcpy((char*)&buffer[position], key);
568   position += strlen(key) + 1;
569   strcpy((char*)&buffer[position], value);
570
571   pthread_mutex_lock(&mutex);
572   unsigned int a = tcp->sendPacket(buffer, totalLength);
573   if (a != totalLength)
574   {
575     pthread_mutex_unlock(&mutex);
576     return 0;
577   }
578
579   int toReturn = getSimpleReply();
580   pthread_mutex_unlock(&mutex);
581   return toReturn;
582 }
583
584 char* VDR::configLoad(char* section, char* key)
585 {
586   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
587   UCHAR buffer[totalLength];
588
589   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
590   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
591
592   int position = 8;
593   strcpy((char*)&buffer[position], section);
594   position += strlen(section) + 1;
595   strcpy((char*)&buffer[position], key);
596
597   pthread_mutex_lock(&mutex);
598   unsigned int a = tcp->sendPacket(buffer, totalLength);
599   if (a != totalLength)
600   {
601     pthread_mutex_unlock(&mutex);
602     return NULL;
603   }
604
605   char* toReturn = getStringReply();
606   pthread_mutex_unlock(&mutex);
607   return toReturn;
608 }