2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
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.
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.
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
23 VDR* VDR::instance = NULL;
32 pthread_mutex_init(&mutex, NULL);
42 if (initted) shutdown();
45 VDR* VDR::getInstance()
50 int VDR::init(int tport)
52 if (initted) return 0;
55 logger = Log::getInstance();
61 if (!initted) return 0;
67 void VDR::findServers(vector<char*>& serverIPs)
70 char* message = "VOMP CLIENT";
71 DatagramSocket ds(port);
73 int haveAtLeastOne = 0;
81 logger->log("VDR", Log::NOTICE, "Broadcasting for server");
82 ds.send("255.255.255.255", 3024, message, strlen(message));
84 retval = ds.waitforMessage(waitType);
86 if (retval == 2) // we got a reply
88 if (strcmp(ds.getData(), "VOMP SERVER")) // echo.....
95 strcpy(newIP, ds.getFromIPA());
96 serverIPs.push_back(newIP);
103 if (haveAtLeastOne) break;
109 void VDR::cancelFindingServer()
114 void VDR::setServerIP(char* newIP)
116 strcpy(serverIP, newIP);
123 if (tcp->connectTo(serverIP, 3024))
134 void VDR::disconnect()
139 Log::getInstance()->log("VDR", Log::DEBUG, "Disconnect");
142 ///////////////////////////////////////////////////////
146 packet = (UCHAR*)tcp->receivePacket();
147 if (!packet) return 0;
148 packetLength = tcp->getDataLength();
152 void VDR::freePacket()
154 // Must be called if getPacket return 1, except in getBlock
161 int VDR::serverError()
163 if ((packetPos == 0) && (packetLength == 4) && !ntohl(*(ULONG*)packet)) return 1;
167 char* VDR::extractString()
169 if (serverError()) return NULL;
171 int length = strlen((char*)&packet[packetPos]);
172 if ((packetPos + length) > packetLength) return NULL;
173 char* str = new char[length + 1];
174 strcpy(str, (char*)&packet[packetPos]);
175 packetPos += length + 1;
179 ULONG VDR::extractULONG()
181 if ((packetPos + sizeof(ULONG)) > packetLength) return 0;
182 ULONG ul = ntohl(*(ULONG*)&packet[packetPos]);
183 packetPos += sizeof(ULONG);
187 ULLONG VDR::extractULLONG()
189 if ((packetPos + sizeof(ULLONG)) > packetLength) return 0;
190 ULLONG ull = ntohll(*(ULLONG*)&packet[packetPos]);
191 packetPos += sizeof(ULLONG);
195 long VDR::extractLONG()
197 if ((packetPos + sizeof(long)) > packetLength) return 0;
198 long l = ntohl(*(long*)&packet[packetPos]);
199 packetPos += sizeof(long);
203 /////////////////////////////////////////////////////////////////////////////
207 if (!connected) return 0;
211 *(unsigned long*)&buffer[0] = htonl(10);
212 *(unsigned long*)&buffer[4] = htonl(VDR_LOGIN);
214 tcp->getMAC((char*)&buffer[8]);
217 pthread_mutex_lock(&mutex);
218 int a = tcp->sendPacket(buffer, 14);
221 pthread_mutex_unlock(&mutex);
229 pthread_mutex_unlock(&mutex);
233 ULONG vdrTime = extractULONG();
234 logger->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
235 long vdrTimeOffset = extractLONG();
236 logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
239 pthread_mutex_unlock(&mutex);
242 struct timespec currentTime;
243 currentTime.tv_sec = vdrTime;
244 currentTime.tv_nsec = 0;
245 int b = clock_settime(CLOCK_REALTIME, ¤tTime);
247 logger->log("VDR", Log::DEBUG, "set clock = %u", b);
249 // now make a TZ variable and set it
253 if (vdrTimeOffset > 0) sign = '-';
256 vdrTimeOffset = abs(vdrTimeOffset);
258 hours = (int)vdrTimeOffset / 3600;
259 minutes = vdrTimeOffset % 3600;
261 logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
263 minutes = (int)minutes / 60;
265 logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
268 sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
269 setenv("TZ", newTZ, 1);
271 logger->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
276 Directory* VDR::getRecordingsList()
278 if (!connected) return 0;
282 *(unsigned long*)&buffer[0] = htonl(4);
283 *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
285 pthread_mutex_lock(&mutex);
286 int a = tcp->sendPacket(buffer, 8);
289 pthread_mutex_unlock(&mutex);
297 pthread_mutex_unlock(&mutex);
301 Directory* recDir = new Directory();
302 recDir->setName("/");
305 Directory::totalSpace = extractULONG();
306 Directory::freeSpace = extractULONG();
307 Directory::usedPercent = extractULONG();
311 while (packetPos < packetLength)
313 Recording* rec = new Recording();
315 rec->start = extractULONG();
317 string = extractString();
318 rec->setName(string);
321 rec->fileName = extractString();
325 char* dirName = rec->getDirName();
327 Directory* d = recDir->getDirByName(dirName);
332 Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
333 recDir->dirList.push_back(d);
336 d->recList.push_back(rec);
340 recDir->recList.push_back(rec);
343 Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName);
347 pthread_mutex_unlock(&mutex);
352 int VDR::deleteRecording(char* fileName)
354 if (!connected) return 0;
356 unsigned long totalLength = 8 + strlen(fileName) + 1;
357 UCHAR buffer[totalLength];
359 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
360 *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
361 strcpy((char*)&buffer[8], fileName);
363 pthread_mutex_lock(&mutex);
364 unsigned int a = tcp->sendPacket(buffer, totalLength);
365 if (a != totalLength)
367 pthread_mutex_unlock(&mutex);
373 pthread_mutex_unlock(&mutex);
377 int toReturn = (int)extractULONG();
379 pthread_mutex_unlock(&mutex);
384 char* VDR::getRecordingSummary(char* fileName)
386 if (!connected) return 0;
388 unsigned long totalLength = 8 + strlen(fileName) + 1;
389 UCHAR buffer[totalLength];
391 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
392 *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
393 strcpy((char*)&buffer[8], fileName);
395 pthread_mutex_lock(&mutex);
396 unsigned int a = tcp->sendPacket(buffer, totalLength);
397 if (a != totalLength)
399 pthread_mutex_unlock(&mutex);
405 pthread_mutex_unlock(&mutex);
408 char* toReturn = extractString();
410 pthread_mutex_unlock(&mutex);
415 ChannelList* VDR::getChannelsList(ULONG type)
417 if (!connected) return 0;
421 *(unsigned long*)&buffer[0] = htonl(4);
422 *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
424 pthread_mutex_lock(&mutex);
425 int a = tcp->sendPacket(buffer, 8);
428 pthread_mutex_unlock(&mutex);
436 pthread_mutex_unlock(&mutex);
440 ChannelList* chanList = new ChannelList();
442 while (packetPos < packetLength)
444 Channel* chan = new Channel();
445 chan->number = extractULONG();
446 chan->type = extractULONG();
447 chan->name = extractString();
449 if (chan->type == type)
451 chanList->push_back(chan);
452 Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
461 pthread_mutex_unlock(&mutex);
466 int VDR::streamChannel(ULONG number)
468 if (!connected) return 0;
472 *(unsigned long*)&buffer[0] = htonl(8);
473 *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
474 *(unsigned long*)&buffer[8] = htonl(number);
476 pthread_mutex_lock(&mutex);
477 int a = tcp->sendPacket(buffer, 12);
481 pthread_mutex_unlock(&mutex);
487 pthread_mutex_unlock(&mutex);
491 int toReturn = (int)extractULONG();
493 pthread_mutex_unlock(&mutex);
498 int VDR::stopStreaming()
500 if (!connected) return 0;
504 *(unsigned long*)&buffer[0] = htonl(4);
505 *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
507 pthread_mutex_lock(&mutex);
508 int a = tcp->sendPacket(buffer, 8);
512 pthread_mutex_unlock(&mutex);
516 printf("sent request\n");
520 pthread_mutex_unlock(&mutex);
523 printf("got reply\n");
526 int toReturn = (int)extractULONG();
528 pthread_mutex_unlock(&mutex);
533 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
535 if (!connected) return 0;
539 *(unsigned long*)&buffer[0] = htonl(16);
540 *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
541 *(ULLONG*)&buffer[8] = htonll(position);
542 *(unsigned long*)&buffer[16] = htonl(maxAmount);
544 pthread_mutex_lock(&mutex);
545 int a = tcp->sendPacket(buffer, 20);
548 pthread_mutex_unlock(&mutex);
554 pthread_mutex_unlock(&mutex);
558 UCHAR* toReturn = packet;
559 *amountReceived = packetLength;
560 // Manually clean up instead of running freePacket to keep the block
564 pthread_mutex_unlock(&mutex);
569 ULLONG VDR::streamRecording(Recording* rec)
571 if (!connected) return 0;
573 unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
574 UCHAR buffer[totalLength];
576 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
577 *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
578 strcpy((char*)&buffer[8], rec->fileName);
580 pthread_mutex_lock(&mutex);
581 unsigned int a = tcp->sendPacket(buffer, totalLength);
582 if (a != totalLength)
584 pthread_mutex_unlock(&mutex);
590 pthread_mutex_unlock(&mutex);
594 ULLONG recordingLength = extractULLONG();
596 pthread_mutex_unlock(&mutex);
598 Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
600 return recordingLength;
603 ULLONG VDR::rescanRecording()
605 if (!connected) return 0;
607 unsigned long totalLength = 8;
608 UCHAR buffer[totalLength];
610 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
611 *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
613 pthread_mutex_lock(&mutex);
614 unsigned int a = tcp->sendPacket(buffer, totalLength);
615 if (a != totalLength)
617 pthread_mutex_unlock(&mutex);
623 pthread_mutex_unlock(&mutex);
627 ULLONG recordingLength = extractULLONG();
629 pthread_mutex_unlock(&mutex);
631 Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
633 return recordingLength;
636 EventList* VDR::getChannelSchedule(ULONG number)
640 return getChannelSchedule(number, now, 24 * 60 * 60);
643 EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
645 // retrieve event list (vector of events) from vdr within filter window. duration is in seconds
646 if (!connected) return 0;
650 *(unsigned long*)&buffer[0] = htonl(16);
651 *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
652 *(unsigned long*)&buffer[8] = htonl(number);
653 *(unsigned long*)&buffer[12] = htonl(start);
654 *(unsigned long*)&buffer[16] = htonl(duration);
656 pthread_mutex_lock(&mutex);
657 int a = tcp->sendPacket(buffer, 20);
661 pthread_mutex_unlock(&mutex);
667 pthread_mutex_unlock(&mutex);
674 pthread_mutex_unlock(&mutex);
679 EventList* eventList = new EventList();
681 while (packetPos < packetLength)
683 Event* event = new Event();
684 event->id = extractULONG();
685 event->time = extractULONG();
686 event->duration = extractULONG();
687 event->title = extractString();
688 event->subtitle = extractString();
689 event->description = extractString();
690 eventList->push_back(event);
691 // eventList->next();
695 pthread_mutex_unlock(&mutex);
697 Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
702 Log* l = Log::getInstance();
705 l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count);
708 for(eventList->reset(); !eventList->eol(); eventList->next())
710 currentEvent = (Event*)eventList->getCurrent();
711 l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description);
718 ULLONG VDR::getResumePoint(char* fileName)
720 if (!connected) return 0;
722 char* resumeString = configLoad("ResumeData", fileName);
723 if (!resumeString) return 0;
725 ULLONG toReturn = strtoull(resumeString, NULL, 10);
726 delete[] resumeString;
730 int VDR::configSave(char* section, char* key, const char* value)
732 if (!connected) return 0;
734 ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
735 UCHAR buffer[totalLength];
737 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
738 *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
741 strcpy((char*)&buffer[position], section);
742 position += strlen(section) + 1;
743 strcpy((char*)&buffer[position], key);
744 position += strlen(key) + 1;
745 strcpy((char*)&buffer[position], value);
747 pthread_mutex_lock(&mutex);
748 unsigned int a = tcp->sendPacket(buffer, totalLength);
749 if (a != totalLength)
751 pthread_mutex_unlock(&mutex);
757 pthread_mutex_unlock(&mutex);
761 int toReturn = (int)extractULONG();
763 pthread_mutex_unlock(&mutex);
768 char* VDR::configLoad(char* section, char* key)
770 if (!connected) return 0;
772 ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
773 UCHAR buffer[totalLength];
775 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
776 *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
779 strcpy((char*)&buffer[position], section);
780 position += strlen(section) + 1;
781 strcpy((char*)&buffer[position], key);
783 pthread_mutex_lock(&mutex);
784 unsigned int a = tcp->sendPacket(buffer, totalLength);
785 if (a != totalLength)
787 pthread_mutex_unlock(&mutex);
793 pthread_mutex_unlock(&mutex);
796 char* toReturn = extractString();
798 pthread_mutex_unlock(&mutex);