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
21 #include "mvpclient.h"
23 MVPClient::MVPClient(int tsocket)
28 recordingManager = NULL;
29 log = Log::getInstance();
31 // Get IP address of client for config module
34 struct sockaddr_in peer;
35 socklen_t salen = sizeof(struct sockaddr);
36 if(getpeername(tsocket, (struct sockaddr*)&peer, &salen) == 0)
38 strcpy(ipa, inet_ntoa(peer.sin_addr));
43 log->log("Client", Log::DEBUG, "Cannot get peer name!");
46 const char* configDir = cPlugin::ConfigDirectory();
49 log->log("Client", Log::DEBUG, "No config dir!");
53 char configFileName[PATH_MAX];
54 snprintf(configFileName, PATH_MAX - strlen(configDir) - strlen(ipa) - 20, "%s/vomp-%s.conf", configDir, ipa);
55 config.init(configFileName);
57 log->log("Client", Log::DEBUG, "Config file name: %s", configFileName);
64 MVPClient::~MVPClient()
66 log->log("Client", Log::DEBUG, "MVP client destructor");
77 delete recordingManager;
79 recordingManager = NULL;
85 cChannel* MVPClient::channelFromNumber(ULONG channelNumber)
87 cChannel* channel = NULL;
89 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
91 if (!channel->GroupSep())
93 log->log("Client", Log::DEBUG, "Looking for channel %lu::: number: %i name: '%s'", channelNumber, channel->Number(), channel->Name());
95 if (channel->Number() == (int)channelNumber)
97 int vpid = channel->Vpid();
98 #if VDRVERSNUM < 10300
99 int apid1 = channel->Apid1();
101 int apid1 = channel->Apid(0);
103 log->log("Client", Log::DEBUG, "Found channel number %lu, vpid = %i, apid1 = %i", channelNumber, vpid, apid1);
111 log->log("Client", Log::DEBUG, "Channel not found");
118 void MVPClient::writeResumeData()
120 config.setValueLongLong("ResumeData", (char*)rp->getCurrentRecording()->FileName(), rp->getLastPosition());
123 void MVPClient::sendULONG(ULONG ul)
126 *(ULONG*)&sendBuffer[0] = htonl(4);
127 *(ULONG*)&sendBuffer[4] = htonl(ul);
129 tcp.sendPacket(sendBuffer, 8);
130 log->log("Client", Log::DEBUG, "written ULONG %lu", ul);
133 void MVPClientStartThread(void* arg)
135 MVPClient* m = (MVPClient*)arg;
137 // Nothing external to this class has a reference to it
138 // This is the end of the thread.. so delete m
145 if (pthread_create(&runThread, NULL, (void*(*)(void*))MVPClientStartThread, (void *)this) == -1) return 0;
146 log->log("Client", Log::DEBUG, "MVPClient run success");
150 void MVPClient::run2()
155 pthread_sigmask(SIG_BLOCK, &sigset, NULL);
156 pthread_detach(runThread); // Detach
158 tcp.disableReadTimeout();
160 tcp.setSoKeepTime(3);
161 tcp.setNonBlocking();
170 log->log("Client", Log::DEBUG, "Waiting");
171 buffer = (UCHAR*)tcp.receivePacket();
172 log->log("Client", Log::DEBUG, "Received packet, length = %u", tcp.getDataLength());
175 log->log("Client", Log::DEBUG, "Detected connection closed");
179 packetLength = tcp.getDataLength() - 4;
180 opcode = ntohl(*(ULONG*)buffer);
187 processLogin(data, packetLength);
190 processGetRecordingsList(data, packetLength);
193 processDeleteRecording(data, packetLength);
196 processGetSummary(data, packetLength);
199 processGetChannelsList(data, packetLength);
202 processStartStreamingChannel(data, packetLength);
205 processGetBlock(data, packetLength);
208 processStopStreaming(data, packetLength);
211 processStartStreamingRecording(data, packetLength);
214 processGetChannelSchedule(data, packetLength);
217 processConfigSave(data, packetLength);
220 processConfigLoad(data, packetLength);
223 processReScanRecording(data, packetLength);
231 void MVPClient::processLogin(UCHAR* buffer, int length)
233 time_t timeNow = time(NULL);
234 struct tm* timeStruct = localtime(&timeNow);
235 int timeOffset = timeStruct->tm_gmtoff;
237 UCHAR sendBuffer[12];
238 *(ULONG*)&sendBuffer[0] = htonl(8);
239 *(ULONG*)&sendBuffer[4] = htonl(timeNow);
240 *(signed int*)&sendBuffer[8] = htonl(timeOffset);
242 tcp.sendPacket(sendBuffer, 12);
243 log->log("Client", Log::DEBUG, "written login reply");
246 void MVPClient::processGetRecordingsList(UCHAR* data, int length)
248 UCHAR* sendBuffer = new UCHAR[50000]; // hope this is enough
249 int count = 4; // leave space for the packet length
254 int Percent = VideoDiskSpace(&FreeMB);
255 int Total = (FreeMB / (100 - Percent)) * 100;
257 *(ULONG*)&sendBuffer[count] = htonl(Total);
258 count += sizeof(ULONG);
259 *(ULONG*)&sendBuffer[count] = htonl(FreeMB);
260 count += sizeof(ULONG);
261 *(ULONG*)&sendBuffer[count] = htonl(Percent);
262 count += sizeof(ULONG);
265 cRecordings Recordings;
268 for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
270 if (count > 49000) break; // just how big is that hard disk?!
271 *(ULONG*)&sendBuffer[count] = htonl(recording->start);// + timeOffset);
274 point = (char*)recording->Name();
275 strcpy((char*)&sendBuffer[count], point);
276 count += strlen(point) + 1;
278 point = (char*)recording->FileName();
279 strcpy((char*)&sendBuffer[count], point);
280 count += strlen(point) + 1;
283 *(ULONG*)&sendBuffer[0] = htonl(count - 4); // -4 : take off the size field
285 log->log("Client", Log::DEBUG, "recorded size as %u", ntohl(*(ULONG*)&sendBuffer[0]));
287 tcp.sendPacket(sendBuffer, count);
289 log->log("Client", Log::DEBUG, "Written list");
292 void MVPClient::processDeleteRecording(UCHAR* data, int length)
294 // data is a pointer to the fileName string
296 cRecordings Recordings;
297 Recordings.Load(); // probably have to do this
299 cRecording* recording = Recordings.GetByName((char*)data);
301 log->log("Client", Log::DEBUG, "recording pointer %p", recording);
305 log->log("Client", Log::DEBUG, "deleting recording: %s", recording->Name());
315 void MVPClient::processGetSummary(UCHAR* data, int length)
317 // data is a pointer to the fileName string
319 cRecordings Recordings;
320 Recordings.Load(); // probably have to do this
322 cRecording *recording = Recordings.GetByName((char*)data);
324 log->log("Client", Log::DEBUG, "recording pointer %p", recording);
328 UCHAR* sendBuffer = new UCHAR[50000]; // hope this is enough
329 int count = 4; // leave space for the packet length
332 #if VDRVERSNUM < 10300
333 point = (char*)recording->Summary();
335 const cRecordingInfo *Info = recording->Info();
336 point = (char*)Info->ShortText();
337 log->log("Client", Log::DEBUG, "info pointer %p summary pointer %p", Info, point);
340 point = (char*)Info->Description();
341 log->log("Client", Log::DEBUG, "description pointer %p", point);
344 strcpy((char*)&sendBuffer[count], point);
345 count += strlen(point) + 1;
346 *(ULONG*)&sendBuffer[0] = htonl(count - 4); // -4 : take off the size field
348 log->log("Client", Log::DEBUG, "recorded size as %u", ntohl(*(ULONG*)&sendBuffer[0]));
350 tcp.sendPacket(sendBuffer, count);
352 log->log("Client", Log::DEBUG, "Written summary");
362 void MVPClient::processGetChannelsList(UCHAR* data, int length)
364 UCHAR* sendBuffer = new UCHAR[50000]; // FIXME hope this is enough
365 int count = 4; // leave space for the packet length
369 char* chanConfig = config.getValueString("General", "Channels");
371 if (chanConfig) allChans = strcasecmp(chanConfig, "FTA only");
373 for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
375 #if VDRVERSNUM < 10300
376 if (!channel->GroupSep() && (!channel->Ca() || allChans))
378 if (!channel->GroupSep() && (!channel->Ca(0) || allChans))
381 log->log("Client", Log::DEBUG, "name: '%s'", channel->Name());
383 if (channel->Vpid()) type = 1;
384 #if VDRVERSNUM < 10300
387 else if (channel->Apid(0)) type = 2;
391 if (count > 49000) break;
392 *(ULONG*)&sendBuffer[count] = htonl(channel->Number());
395 *(ULONG*)&sendBuffer[count] = htonl(type);
398 point = (char*)channel->Name();
399 strcpy((char*)&sendBuffer[count], point);
400 count += strlen(point) + 1;
404 *(ULONG*)&sendBuffer[0] = htonl(count - 4); // -4 : take off the size field
406 log->log("Client", Log::DEBUG, "recorded size as %u", ntohl(*(ULONG*)&sendBuffer[0]));
408 tcp.sendPacket(sendBuffer, count);
410 log->log("Client", Log::DEBUG, "Written channels list");
413 void MVPClient::processStartStreamingChannel(UCHAR* data, int length)
415 log->log("Client", Log::DEBUG, "length = %i", length);
416 ULONG channelNumber = ntohl(*(ULONG*)data);
418 cChannel* channel = channelFromNumber(channelNumber);
425 // get the priority we should use
427 int priority = config.getValueLong("General", "Live priority", &fail);
430 log->log("Client", Log::DEBUG, "Config: Live TV priority: %i", priority);
434 log->log("Client", Log::DEBUG, "Config: Live TV priority config fail");
439 if (priority < 0) priority = 0;
440 if (priority > 99) priority = 99;
442 log->log("Client", Log::DEBUG, "Using live TV priority %i", priority);
443 lp = MVPReceiver::create(channel, priority);
462 void MVPClient::processStopStreaming(UCHAR* data, int length)
464 log->log("Client", Log::DEBUG, "STOP STREAMING RECEIVED");
475 delete recordingManager;
477 recordingManager = NULL;
483 void MVPClient::processGetBlock(UCHAR* data, int length)
487 log->log("Client", Log::DEBUG, "Get block called when no streaming happening!");
491 ULLONG position = ntohll(*(ULLONG*)data);
492 data += sizeof(ULLONG);
493 ULONG amount = ntohl(*(ULONG*)data);
495 log->log("Client", Log::DEBUG, "getblock pos = %llu length = %lu", position, amount);
497 UCHAR sendBuffer[amount + 4];
498 ULONG amountReceived = 0; // compiler moan.
501 log->log("Client", Log::DEBUG, "getting from live");
502 amountReceived = lp->getBlock(&sendBuffer[4], amount);
506 // vdr has possibly disconnected the receiver
507 log->log("Client", Log::DEBUG, "VDR has disconnected the live receiver");
514 log->log("Client", Log::DEBUG, "getting from recording");
515 amountReceived = rp->getBlock(&sendBuffer[4], position, amount);
518 *(ULONG*)&sendBuffer[0] = htonl(amountReceived);
519 tcp.sendPacket(sendBuffer, amountReceived + 4);
520 log->log("Client", Log::DEBUG, "written ok %lu", amountReceived);
523 void MVPClient::processStartStreamingRecording(UCHAR* data, int length)
525 // data is a pointer to the fileName string
527 recordingManager = new cRecordings;
528 recordingManager->Load();
530 cRecording* recording = recordingManager->GetByName((char*)data);
532 log->log("Client", Log::DEBUG, "recording pointer %p", recording);
536 rp = new RecPlayer(recording);
538 UCHAR sendBuffer[12];
539 *(ULONG*)&sendBuffer[0] = htonl(8);
540 *(ULLONG*)&sendBuffer[4] = htonll(rp->getTotalLength());
542 tcp.sendPacket(sendBuffer, 12);
543 log->log("Client", Log::DEBUG, "written totalLength");
547 delete recordingManager;
548 recordingManager = NULL;
552 void MVPClient::processReScanRecording(UCHAR* data, int length)
558 log->log("Client", Log::DEBUG, "Rescan recording called when no recording being played!");
563 retval = rp->getTotalLength();
566 UCHAR sendBuffer[12];
567 *(ULONG*)&sendBuffer[0] = htonl(8);
568 *(ULLONG*)&sendBuffer[4] = htonll(retval);
570 tcp.sendPacket(sendBuffer, 12);
571 log->log("Client", Log::DEBUG, "Rescan recording, wrote new length to client");
574 void MVPClient::processGetChannelSchedule(UCHAR* data, int length)
576 ULONG channelNumber = ntohl(*(ULLONG*)data);
577 log->log("Client", Log::DEBUG, "get schedule called for channel %lu", channelNumber);
579 cChannel* channel = channelFromNumber(channelNumber);
583 *(ULONG*)&sendBuffer[0] = htonl(4);
584 *(ULONG*)&sendBuffer[4] = htonl(0);
585 tcp.sendPacket(sendBuffer, 8);
586 log->log("Client", Log::DEBUG, "written 0 because channel = NULL");
590 log->log("Client", Log::DEBUG, "Got channel");
592 #if VDRVERSNUM < 10300
593 cMutexLock MutexLock;
594 const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
596 cSchedulesLock MutexLock;
597 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
602 *(ULONG*)&sendBuffer[0] = htonl(4);
603 *(ULONG*)&sendBuffer[4] = htonl(0);
604 tcp.sendPacket(sendBuffer, 8);
605 log->log("Client", Log::DEBUG, "written 0 because Schedule!s! = NULL");
609 log->log("Client", Log::DEBUG, "Got schedule!s! object");
611 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
615 *(ULONG*)&sendBuffer[0] = htonl(4);
616 *(ULONG*)&sendBuffer[4] = htonl(0);
617 tcp.sendPacket(sendBuffer, 8);
618 log->log("Client", Log::DEBUG, "written 0 because Schedule = NULL");
622 log->log("Client", Log::DEBUG, "Got schedule object");
624 UCHAR* sendBuffer = (UCHAR*)malloc(100000);
625 ULONG sendBufferLength = 100000;
626 ULONG sendBufferUsed = sizeof(ULONG); // leave a hole for the entire packet length
630 // assign all the event info to temp vars then we know exactly what size they are
633 ULONG thisEventDuration;
634 const char* thisEventTitle;
635 const char* thisEventSubTitle;
636 const char* thisEventDescription;
638 ULONG constEventLength = sizeof(thisEventID) + sizeof(thisEventTime) + sizeof(thisEventDuration);
639 ULONG thisEventLength;
641 #if VDRVERSNUM < 10300
643 const cEventInfo *event;
644 for (int eventNumber = 0; eventNumber < Schedule->NumEvents(); eventNumber++)
646 event = Schedule->GetEventNumber(eventNumber);
648 thisEventID = event->GetEventID();
649 thisEventTime = event->GetTime();
650 thisEventDuration = event->GetDuration();
651 thisEventTitle = event->GetTitle();
652 thisEventSubTitle = event->GetSubtitle();
653 thisEventDescription = event->GetExtendedDescription();
657 for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
659 thisEventID = event->EventID();
660 thisEventTime = event->StartTime();
661 thisEventDuration = event->Duration();
662 thisEventTitle = event->Title();
663 thisEventSubTitle = NULL;
664 thisEventDescription = event->Description();
668 log->log("Client", Log::DEBUG, "Got an event object %p", event);
671 if ((thisEventTime + thisEventDuration) < (ULONG)time(NULL)) continue;
674 if (thisEventTime > ((ULONG)time(NULL) + 86400)) continue;
676 if (!thisEventTitle) thisEventTitle = empty;
677 if (!thisEventSubTitle) thisEventSubTitle = empty;
678 if (!thisEventDescription) thisEventDescription = empty;
680 thisEventLength = constEventLength + strlen(thisEventTitle) + 1 + strlen(thisEventSubTitle) + 1 + strlen(thisEventDescription) + 1;
682 log->log("Client", Log::DEBUG, "Done s1");
684 // now extend the buffer if necessary
685 if ((sendBufferUsed + thisEventLength) > sendBufferLength)
687 log->log("Client", Log::DEBUG, "Extending buffer");
688 sendBufferLength += 100000;
689 UCHAR* temp = (UCHAR*)realloc(sendBuffer, sendBufferLength);
693 UCHAR sendBuffer2[8];
694 *(ULONG*)&sendBuffer2[0] = htonl(4);
695 *(ULONG*)&sendBuffer2[4] = htonl(0);
696 tcp.sendPacket(sendBuffer2, 8);
697 log->log("Client", Log::DEBUG, "written 0 because failed to realloc packet");
703 log->log("Client", Log::DEBUG, "Done s2");
705 *(ULONG*)&sendBuffer[sendBufferUsed] = htonl(thisEventID); sendBufferUsed += sizeof(ULONG);
706 *(ULONG*)&sendBuffer[sendBufferUsed] = htonl(thisEventTime); sendBufferUsed += sizeof(ULONG);
707 *(ULONG*)&sendBuffer[sendBufferUsed] = htonl(thisEventDuration); sendBufferUsed += sizeof(ULONG);
709 strcpy((char*)&sendBuffer[sendBufferUsed], thisEventTitle); sendBufferUsed += strlen(thisEventTitle) + 1;
710 strcpy((char*)&sendBuffer[sendBufferUsed], thisEventSubTitle); sendBufferUsed += strlen(thisEventSubTitle) + 1;
711 strcpy((char*)&sendBuffer[sendBufferUsed], thisEventDescription); sendBufferUsed += strlen(thisEventDescription) + 1;
713 log->log("Client", Log::DEBUG, "Done s3 %lu", sendBufferUsed);
716 log->log("Client", Log::DEBUG, "Got all event data");
718 // Write the length into the first 4 bytes. It's sendBufferUsed - 4 because of the hole!
719 *(ULONG*)&sendBuffer[0] = htonl(sendBufferUsed - sizeof(ULONG));
721 tcp.sendPacket(sendBuffer, sendBufferUsed);
722 log->log("Client", Log::DEBUG, "written %lu schedules packet", sendBufferUsed);
729 void MVPClient::processConfigSave(UCHAR* buffer, int length)
731 char* section = (char*)buffer;
735 for (int k = 0; k < length; k++)
737 if (buffer[k] == '\0')
741 key = (char*)&buffer[k+1];
745 value = (char*)&buffer[k+1];
751 // if the last string (value) doesnt have null terminator, give up
752 if (buffer[length - 1] != '\0') return;
754 log->log("Client", Log::DEBUG, "Config save: %s %s %s", section, key, value);
755 if (config.setValueString(section, key, value))
765 void MVPClient::processConfigLoad(UCHAR* buffer, int length)
767 char* section = (char*)buffer;
770 for (int k = 0; k < length; k++)
772 if (buffer[k] == '\0')
774 key = (char*)&buffer[k+1];
779 char* value = config.getValueString(section, key);
783 UCHAR sendBuffer[4 + strlen(value) + 1];
784 *(ULONG*)&sendBuffer[0] = htonl(strlen(value) + 1);
785 strcpy((char*)&sendBuffer[4], value);
786 tcp.sendPacket(sendBuffer, 4 + strlen(value) + 1);
788 log->log("Client", Log::DEBUG, "Written config load packet");
794 *(ULONG*)&sendBuffer[0] = htonl(4);
795 *(ULONG*)&sendBuffer[4] = htonl(0);
796 tcp.sendPacket(sendBuffer, 8);
798 log->log("Client", Log::DEBUG, "Written config load failed packet");
802 void MVPClient::cleanConfig()
804 log->log("Client", Log::DEBUG, "Clean config");
806 cRecordings Recordings;
811 char* resumes = config.getSectionKeyNames("ResumeData", numReturns, length);
812 char* position = resumes;
813 for(int k = 0; k < numReturns; k++)
815 log->log("Client", Log::DEBUG, "EXAMINING: %i %i %p %s", k, numReturns, position, position);
817 cRecording* recording = Recordings.GetByName(position);
820 // doesn't exist anymore
821 log->log("Client", Log::DEBUG, "Found a recording that doesn't exist anymore");
822 config.deleteValue("ResumeData", position);
826 log->log("Client", Log::DEBUG, "This recording still exists");
829 position += strlen(position) + 1;
841 event = Schedule->GetPresentEvent();
843 fprintf(f, "\n\nCurrent event\n\n");
845 fprintf(f, "Event %i eventid = %u time = %lu duration = %li\n", 0, event->GetEventID(), event->GetTime(), event->GetDuration());
846 fprintf(f, "Event %i title = %s subtitle = %s\n", 0, event->GetTitle(), event->GetSubtitle());
847 fprintf(f, "Event %i extendeddescription = %s\n", 0, event->GetExtendedDescription());
848 fprintf(f, "Event %i isFollowing = %i, isPresent = %i\n", 0, event->IsFollowing(), event->IsPresent());
850 event = Schedule->GetFollowingEvent();
852 fprintf(f, "\n\nFollowing event\n\n");
854 fprintf(f, "Event %i eventid = %u time = %lu duration = %li\n", 0, event->GetEventID(), event->GetTime(), event->GetDuration());
855 fprintf(f, "Event %i title = %s subtitle = %s\n", 0, event->GetTitle(), event->GetSubtitle());
856 fprintf(f, "Event %i extendeddescription = %s\n", 0, event->GetExtendedDescription());
857 fprintf(f, "Event %i isFollowing = %i, isPresent = %i\n", 0, event->IsFollowing(), event->IsPresent());
863 fprintf(f, "Event %i eventid = %u time = %lu duration = %li\n", eventNumber, event->GetEventID(), event->GetTime(), event->GetDuration());
864 fprintf(f, "Event %i title = %s subtitle = %s\n", eventNumber, event->GetTitle(), event->GetSubtitle());
865 fprintf(f, "Event %i extendeddescription = %s\n", eventNumber, event->GetExtendedDescription());
866 fprintf(f, "Event %i isFollowing = %i, isPresent = %i\n", eventNumber, event->IsFollowing(), event->IsPresent());
874 void MVPClient::test2()
876 FILE* f = fopen("/tmp/s.txt", "w");
878 #if VDRVERSNUM < 10300
879 cMutexLock MutexLock;
880 const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
882 cSchedulesLock MutexLock;
883 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
888 fprintf(f, "Schedules = NULL\n");
893 fprintf(f, "Schedules dump:\n");
897 const cSchedule *Schedule;
898 int scheduleNumber = 0;
901 cChannel *thisChannel;
903 #if VDRVERSNUM < 10300
904 const cEventInfo *event;
910 // Schedule = Schedules->GetSchedule(channel->GetChannelID());
911 // Schedule = Schedules->GetSchedule();
912 Schedule = Schedules->First();
915 fprintf(f, "First Schedule = NULL\n");
922 fprintf(f, "Schedule #%i\n", scheduleNumber);
923 fprintf(f, "-------------\n\n");
925 #if VDRVERSNUM < 10300
926 tchid = Schedule->GetChannelID();
928 tchid = Schedule->ChannelID();
931 #if VDRVERSNUM < 10300
932 fprintf(f, "ChannelID.ToString() = %s\n", tchid.ToString());
933 fprintf(f, "NumEvents() = %i\n", Schedule->NumEvents());
935 // put the count at the end.
938 thisChannel = Channels.GetByChannelID(tchid, true);
941 fprintf(f, "Channel Number: %p %i\n", thisChannel, thisChannel->Number());
945 fprintf(f, "thisChannel = NULL for tchid\n");
948 #if VDRVERSNUM < 10300
949 for (eventNumber = 0; eventNumber < Schedule->NumEvents(); eventNumber++)
951 event = Schedule->GetEventNumber(eventNumber);
952 fprintf(f, "Event %i tableid = %i timestring = %s endtimestring = %s\n", eventNumber, event->GetTableID(), event->GetTimeString(), event->GetEndTimeString());
953 fprintf(f, "Event %i date = %s isfollowing = %i ispresent = %i\n", eventNumber, event->GetDate(), event->IsFollowing(), event->IsPresent());
954 fprintf(f, "Event %i extendeddescription = %s\n", eventNumber, event->GetExtendedDescription());
955 fprintf(f, "Event %i subtitle = %s title = %s\n", eventNumber, event->GetSubtitle(), event->GetTitle());
956 fprintf(f, "Event %i eventid = %u duration = %li time = %lu channelnumber = %i\n", eventNumber, event->GetEventID(), event->GetDuration(), event->GetTime(), event->GetChannelNumber());
957 fprintf(f, "Event %u dump:\n", eventNumber);
962 // This whole section needs rewriting to walk the list.
963 event = Schedule->Events()->First();
965 event = Schedule->Events()->Next(event);
970 fprintf(f, "\nDump from object:\n");
972 fprintf(f, "\nEND\n");
982 fprintf(f, "End of current Schedule\n\n\n");
984 Schedule = (const cSchedule *)Schedules->Next(Schedule);
998 const cEventInfo *GetPresentEvent(void) const;
999 const cEventInfo *GetFollowingEvent(void) const;
1000 const cEventInfo *GetEvent(unsigned short uEventID, time_t tTime = 0) const;
1001 const cEventInfo *GetEventAround(time_t tTime) const;
1002 const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
1005 const unsigned char GetTableID(void) const;
1006 const char *GetTimeString(void) const;
1007 const char *GetEndTimeString(void) const;
1008 const char *GetDate(void) const;
1009 bool IsFollowing(void) const;
1010 bool IsPresent(void) const;
1011 const char *GetExtendedDescription(void) const;
1012 const char *GetSubtitle(void) const;
1013 const char *GetTitle(void) const;
1014 unsigned short GetEventID(void) const;
1015 long GetDuration(void) const;
1016 time_t GetTime(void) const;
1017 tChannelID GetChannelID(void) const;
1018 int GetChannelNumber(void) const { return nChannelNumber; }
1019 void SetChannelNumber(int ChannelNumber) const { ((cEventInfo *)this)->nChannelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const'
1020 void Dump(FILE *f, const char *Prefix = "") const;
1026 void MVPClient::test(int channelNumber)
1028 FILE* f = fopen("/tmp/test.txt", "w");
1030 cMutexLock MutexLock;
1031 const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
1035 fprintf(f, "Schedules = NULL\n");
1040 fprintf(f, "Schedules dump:\n");
1041 // Schedules->Dump(f);
1043 const cSchedule *Schedule;
1044 cChannel *thisChannel;
1045 const cEventInfo *event;
1047 thisChannel = channelFromNumber(channelNumber);
1050 fprintf(f, "thisChannel = NULL\n");
1055 Schedule = Schedules->GetSchedule(thisChannel->GetChannelID());
1056 // Schedule = Schedules->GetSchedule();
1057 // Schedule = Schedules->First();
1060 fprintf(f, "First Schedule = NULL\n");
1065 fprintf(f, "NumEvents() = %i\n\n", Schedule->NumEvents());
1067 // For some channels VDR seems to pick a random point in time to
1068 // start dishing out events, but they are in order
1069 // at some point in the list the time snaps to the current event
1074 for (int eventNumber = 0; eventNumber < Schedule->NumEvents(); eventNumber++)
1076 event = Schedule->GetEventNumber(eventNumber);
1077 fprintf(f, "Event %i eventid = %u time = %lu duration = %li\n", eventNumber, event->GetEventID(), event->GetTime(), event->GetDuration());
1078 fprintf(f, "Event %i title = %s subtitle = %s\n", eventNumber, event->GetTitle(), event->GetSubtitle());
1079 fprintf(f, "Event %i extendeddescription = %s\n", eventNumber, event->GetExtendedDescription());
1083 fprintf(f, "\nEND\n");
1097 Schedules = the collection of all the Schedule objects
1098 Schedule = One schedule, contants all the events for a channel
1099 Event = One programme
1108 Subtitle (used for "Programmes resume at ...")
1111 IsPresent ? easy to work out tho. Oh it doesn't always work