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);
41 if (initted) shutdown();
44 VDR* VDR::getInstance()
49 int VDR::init(int tport)
51 if (initted) return 0;
54 logger = Log::getInstance();
60 if (!initted) return 0;
66 void VDR::findServers(vector<char*>& serverIPs)
69 char* message = "VOMP CLIENT";
70 DatagramSocket ds(port);
72 int haveAtLeastOne = 0;
80 logger->log("VDR", Log::NOTICE, "Broadcasting for server");
81 ds.send("255.255.255.255", 3024, message, strlen(message));
83 retval = ds.waitforMessage(waitType);
85 if (retval == 2) // we got a reply
87 if (strcmp(ds.getData(), "VOMP SERVER")) // echo.....
94 strcpy(newIP, ds.getFromIPA());
95 serverIPs.push_back(newIP);
102 if (haveAtLeastOne) break;
108 void VDR::cancelFindingServer()
113 void VDR::setServerIP(char* newIP)
115 strcpy(serverIP, newIP);
122 return tcp->connectTo(serverIP, 3024);
125 void VDR::disconnect()
129 Log::getInstance()->log("VDR", Log::DEBUG, "Disconnect");
132 ///////////////////////////////////////////////////////
136 packet = (UCHAR*)tcp->receivePacket();
137 if (!packet) return 0;
138 packetLength = tcp->getDataLength();
142 void VDR::freePacket()
144 // Must be called if getPacket return 1, except in getBlock
151 int VDR::serverError()
153 if ((packetPos == 0) && (packetLength == 4) && !ntohl(*(ULONG*)packet)) return 1;
157 char* VDR::extractString()
159 if (serverError()) return NULL;
161 int length = strlen((char*)&packet[packetPos]);
162 if ((packetPos + length) > packetLength) return NULL;
163 char* str = new char[length + 1];
164 strcpy(str, (char*)&packet[packetPos]);
165 packetPos += length + 1;
169 ULONG VDR::extractULONG()
171 if ((packetPos + sizeof(ULONG)) > packetLength) return 0;
172 ULONG ul = ntohl(*(ULONG*)&packet[packetPos]);
173 packetPos += sizeof(ULONG);
177 ULLONG VDR::extractULLONG()
179 if ((packetPos + sizeof(ULLONG)) > packetLength) return 0;
180 ULLONG ull = ntohll(*(ULLONG*)&packet[packetPos]);
181 packetPos += sizeof(ULLONG);
185 long VDR::extractLONG()
187 if ((packetPos + sizeof(long)) > packetLength) return 0;
188 long l = ntohl(*(long*)&packet[packetPos]);
189 packetPos += sizeof(long);
193 /////////////////////////////////////////////////////////////////////////////
199 *(unsigned long*)&buffer[0] = htonl(4);
200 *(unsigned long*)&buffer[4] = htonl(VDR_LOGIN);
202 pthread_mutex_lock(&mutex);
203 int a = tcp->sendPacket(buffer, 8);
206 pthread_mutex_unlock(&mutex);
214 pthread_mutex_unlock(&mutex);
218 ULONG vdrTime = extractULONG();
219 logger->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
220 long vdrTimeOffset = extractLONG();
221 logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
224 pthread_mutex_unlock(&mutex);
227 struct timespec currentTime;
228 currentTime.tv_sec = vdrTime;
229 currentTime.tv_nsec = 0;
230 int b = clock_settime(CLOCK_REALTIME, ¤tTime);
232 logger->log("VDR", Log::DEBUG, "set clock = %u", b);
234 // now make a TZ variable and set it
238 if (vdrTimeOffset > 0) sign = '-';
241 vdrTimeOffset = abs(vdrTimeOffset);
243 hours = (int)vdrTimeOffset / 3600;
244 minutes = vdrTimeOffset % 3600;
246 logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
248 minutes = (int)minutes / 60;
250 logger->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
253 sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
254 setenv("TZ", newTZ, 1);
256 logger->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
261 Directory* VDR::getRecordingsList()
265 *(unsigned long*)&buffer[0] = htonl(4);
266 *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
268 pthread_mutex_lock(&mutex);
269 int a = tcp->sendPacket(buffer, 8);
272 pthread_mutex_unlock(&mutex);
280 pthread_mutex_unlock(&mutex);
284 Directory* recDir = new Directory();
285 recDir->setName("/");
288 Directory::totalSpace = extractULONG();
289 Directory::freeSpace = extractULONG();
290 Directory::usedPercent = extractULONG();
294 while (packetPos < packetLength)
296 Recording* rec = new Recording();
298 rec->start = extractULONG();
300 string = extractString();
301 rec->setName(string);
304 rec->fileName = extractString();
308 char* dirName = rec->getDirName();
310 Directory* d = recDir->getDirByName(dirName);
315 Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
316 recDir->dirList.push_back(d);
319 d->recList.push_back(rec);
323 recDir->recList.push_back(rec);
326 Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName);
330 pthread_mutex_unlock(&mutex);
335 int VDR::deleteRecording(char* fileName)
337 unsigned long totalLength = 8 + strlen(fileName) + 1;
338 UCHAR buffer[totalLength];
340 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
341 *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
342 strcpy((char*)&buffer[8], fileName);
344 pthread_mutex_lock(&mutex);
345 unsigned int a = tcp->sendPacket(buffer, totalLength);
346 if (a != totalLength)
348 pthread_mutex_unlock(&mutex);
354 pthread_mutex_unlock(&mutex);
358 int toReturn = (int)extractULONG();
360 pthread_mutex_unlock(&mutex);
365 char* VDR::getRecordingSummary(char* fileName)
367 unsigned long totalLength = 8 + strlen(fileName) + 1;
368 UCHAR buffer[totalLength];
370 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
371 *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
372 strcpy((char*)&buffer[8], fileName);
374 pthread_mutex_lock(&mutex);
375 unsigned int a = tcp->sendPacket(buffer, totalLength);
376 if (a != totalLength)
378 pthread_mutex_unlock(&mutex);
384 pthread_mutex_unlock(&mutex);
387 char* toReturn = extractString();
389 pthread_mutex_unlock(&mutex);
394 ChannelList* VDR::getChannelsList(ULONG type)
398 *(unsigned long*)&buffer[0] = htonl(4);
399 *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
401 pthread_mutex_lock(&mutex);
402 int a = tcp->sendPacket(buffer, 8);
405 pthread_mutex_unlock(&mutex);
413 pthread_mutex_unlock(&mutex);
417 ChannelList* chanList = new ChannelList();
419 while (packetPos < packetLength)
421 Channel* chan = new Channel();
422 chan->number = extractULONG();
423 chan->type = extractULONG();
424 chan->name = extractString();
426 if (chan->type == type)
428 chanList->push_back(chan);
429 Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
438 pthread_mutex_unlock(&mutex);
443 int VDR::streamChannel(ULONG number)
447 *(unsigned long*)&buffer[0] = htonl(8);
448 *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
449 *(unsigned long*)&buffer[8] = htonl(number);
451 pthread_mutex_lock(&mutex);
452 int a = tcp->sendPacket(buffer, 12);
456 pthread_mutex_unlock(&mutex);
462 pthread_mutex_unlock(&mutex);
466 int toReturn = (int)extractULONG();
468 pthread_mutex_unlock(&mutex);
473 int VDR::stopStreaming()
477 *(unsigned long*)&buffer[0] = htonl(4);
478 *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
480 pthread_mutex_lock(&mutex);
481 int a = tcp->sendPacket(buffer, 8);
485 pthread_mutex_unlock(&mutex);
491 pthread_mutex_unlock(&mutex);
495 int toReturn = (int)extractULONG();
497 pthread_mutex_unlock(&mutex);
502 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
506 *(unsigned long*)&buffer[0] = htonl(16);
507 *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
508 *(ULLONG*)&buffer[8] = htonll(position);
509 *(unsigned long*)&buffer[16] = htonl(maxAmount);
511 pthread_mutex_lock(&mutex);
512 int a = tcp->sendPacket(buffer, 20);
515 pthread_mutex_unlock(&mutex);
521 pthread_mutex_unlock(&mutex);
525 UCHAR* toReturn = packet;
526 *amountReceived = packetLength;
527 // Manually clean up instead of running freePacket to keep the block
531 pthread_mutex_unlock(&mutex);
536 ULLONG VDR::streamRecording(Recording* rec)
538 unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
539 UCHAR buffer[totalLength];
541 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
542 *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
543 strcpy((char*)&buffer[8], rec->fileName);
545 pthread_mutex_lock(&mutex);
546 unsigned int a = tcp->sendPacket(buffer, totalLength);
547 if (a != totalLength)
549 pthread_mutex_unlock(&mutex);
555 pthread_mutex_unlock(&mutex);
559 ULLONG recordingLength = extractULLONG();
561 pthread_mutex_unlock(&mutex);
563 Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
565 return recordingLength;
568 ULLONG VDR::rescanRecording()
570 unsigned long totalLength = 8;
571 UCHAR buffer[totalLength];
573 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
574 *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
576 pthread_mutex_lock(&mutex);
577 unsigned int a = tcp->sendPacket(buffer, totalLength);
578 if (a != totalLength)
580 pthread_mutex_unlock(&mutex);
586 pthread_mutex_unlock(&mutex);
590 ULLONG recordingLength = extractULLONG();
592 pthread_mutex_unlock(&mutex);
594 Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
596 return recordingLength;
599 EventList* VDR::getChannelSchedule(ULONG number)
603 *(unsigned long*)&buffer[0] = htonl(8);
604 *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
605 *(unsigned long*)&buffer[8] = htonl(number);
607 pthread_mutex_lock(&mutex);
608 int a = tcp->sendPacket(buffer, 12);
612 pthread_mutex_unlock(&mutex);
618 pthread_mutex_unlock(&mutex);
625 pthread_mutex_unlock(&mutex);
630 EventList* eventList = new EventList();
632 while (packetPos < packetLength)
634 Event* event = new Event();
635 event->id = extractULONG();
636 event->time = extractULONG();
637 event->duration = extractULONG();
638 event->title = extractString();
639 event->subtitle = extractString();
640 event->description = extractString();
641 eventList->push_back(event);
642 // eventList->next();
646 pthread_mutex_unlock(&mutex);
648 Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule");
653 Log* l = Log::getInstance();
656 l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count);
659 for(eventList->reset(); !eventList->eol(); eventList->next())
661 currentEvent = (Event*)eventList->getCurrent();
662 l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description);
669 ULLONG VDR::getResumePoint(char* fileName)
671 char* resumeString = configLoad("ResumeData", fileName);
672 if (!resumeString) return 0;
674 ULLONG toReturn = strtoull(resumeString, NULL, 10);
675 delete[] resumeString;
679 int VDR::configSave(char* section, char* key, char* value)
681 ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
682 UCHAR buffer[totalLength];
684 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
685 *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
688 strcpy((char*)&buffer[position], section);
689 position += strlen(section) + 1;
690 strcpy((char*)&buffer[position], key);
691 position += strlen(key) + 1;
692 strcpy((char*)&buffer[position], value);
694 pthread_mutex_lock(&mutex);
695 unsigned int a = tcp->sendPacket(buffer, totalLength);
696 if (a != totalLength)
698 pthread_mutex_unlock(&mutex);
704 pthread_mutex_unlock(&mutex);
708 int toReturn = (int)extractULONG();
710 pthread_mutex_unlock(&mutex);
715 char* VDR::configLoad(char* section, char* key)
717 ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
718 UCHAR buffer[totalLength];
720 *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
721 *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
724 strcpy((char*)&buffer[position], section);
725 position += strlen(section) + 1;
726 strcpy((char*)&buffer[position], key);
728 pthread_mutex_lock(&mutex);
729 unsigned int a = tcp->sendPacket(buffer, totalLength);
730 if (a != totalLength)
732 pthread_mutex_unlock(&mutex);
738 pthread_mutex_unlock(&mutex);
741 char* toReturn = extractString();
743 pthread_mutex_unlock(&mutex);