From 340d9bcb0fdf49fbe2740dde29af37f46887c122 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 21 Feb 2004 13:56:20 +0100 Subject: [PATCH] The EPG data is now always kept sorted chronologically in the internal data structures --- HISTORY | 3 +++ eit.c | 7 +++++- epg.c | 15 +++++++++-- epg.h | 8 +++--- menu.c | 77 ++++++++++++++++----------------------------------------- 5 files changed, 46 insertions(+), 64 deletions(-) diff --git a/HISTORY b/HISTORY index 3460d055..e021d812 100644 --- a/HISTORY +++ b/HISTORY @@ -2681,3 +2681,6 @@ Video Disk Recorder Revision History event randomly, making it impossible for a timer to be programmed on a ceartain event rather than a specific time. Well, let's see where this leads us... - Removed the obsolete 'present' and 'following' handling from the EPG data. +- The EPG data is now always kept sorted chronologically in the internal data + structures. This also means that any EPG data retrieved through the SVRDP + command LSTE is guaranteed to be sorted by start time. diff --git a/eit.c b/eit.c index 857e06e3..0ef3590b 100644 --- a/eit.c +++ b/eit.c @@ -8,7 +8,7 @@ * Robert Schneider and Rolf Hakenes . * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg . * - * $Id: eit.c 1.87 2004/02/21 12:20:26 kls Exp $ + * $Id: eit.c 1.88 2004/02/21 13:26:52 kls Exp $ */ #include "eit.h" @@ -43,6 +43,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) Schedules->Add(pSchedule); } + bool Modified = false; + SI::EIT::Event SiEitEvent; for (SI::Loop::Iterator it; eventLoop.hasNext(it); ) { SiEitEvent = eventLoop.getNext(it); @@ -188,7 +190,10 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) if (LinkChannels) channel->SetLinkChannels(LinkChannels); + Modified = true; } + if (Modified) + pSchedule->Sort(); } // --- cTDT ------------------------------------------------------------------ diff --git a/epg.c b/epg.c index 19108047..1c392b98 100644 --- a/epg.c +++ b/epg.c @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.c 1.7 2004/02/21 12:32:31 kls Exp $ + * $Id: epg.c 1.8 2004/02/21 13:46:23 kls Exp $ */ #include "epg.h" @@ -29,7 +29,6 @@ cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID) description = NULL; startTime = 0; duration = 0; - channelNumber = 0; } cEvent::~cEvent() @@ -39,6 +38,12 @@ cEvent::~cEvent() free(description); } +bool cEvent::operator< (const cListObject &ListObject) +{ + cEvent *e = (cEvent *)&ListObject; + return startTime < e->startTime; +} + void cEvent::SetEventID(u_int16_t EventID) { eventID = EventID; @@ -500,6 +505,11 @@ void cSchedule::ResetVersions(void) p->SetVersion(0xFF); } +void cSchedule::Sort(void) +{ + events.Sort(); +} + void cSchedule::Cleanup(void) { Cleanup(time(NULL)); @@ -547,6 +557,7 @@ bool cSchedule::Read(FILE *f, cSchedules *Schedules) if (p) { if (!cEvent::Read(f, p)) return false; + p->Sort(); } } else { diff --git a/epg.h b/epg.h index 817540c2..73d0f2f0 100644 --- a/epg.h +++ b/epg.h @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.h 1.6 2004/02/21 12:31:43 kls Exp $ + * $Id: epg.h 1.7 2004/02/21 13:46:18 kls Exp $ */ #ifndef __EPG_H @@ -33,11 +33,10 @@ private: char *description; // Description of this event time_t startTime; // Start time of this event int duration; // Duration of this event in seconds - //XXX find an other solution, avoiding channelNumber??? - int channelNumber; // the actual channel number from VDR's channel list (used in cMenuSchedule for sorting by channel number) public: cEvent(tChannelID ChannelID, u_int16_t EventID); ~cEvent(); + virtual bool operator< (const cListObject &ListObject); tChannelID ChannelID(void) const { return channelID; } u_int16_t EventID(void) const { return eventID; } uchar TableID(void) const { return tableID; } @@ -48,7 +47,6 @@ public: const char *Description(void) const { return description; } time_t StartTime(void) const { return startTime; } int Duration(void) const { return duration; } - int ChannelNumber(void) const { return channelNumber; } const char *GetDateString(void) const; const char *GetTimeString(void) const; const char *GetEndTimeString(void) const; @@ -61,7 +59,6 @@ public: void SetDescription(const char *Description); void SetStartTime(time_t StartTime); void SetDuration(int Duration); - void SetChannelNumber(int ChannelNumber) const { ((cEvent *)this)->channelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const' //XXX void Dump(FILE *f, const char *Prefix = "") const; static bool Read(FILE *f, cSchedule *Schedule); void FixEpgBugs(void); @@ -78,6 +75,7 @@ public: tChannelID ChannelID(void) const { return channelID; } void SetRunningStatus(cEvent *Event, int RunningStatus); void ResetVersions(void); + void Sort(void); void Cleanup(time_t Time); void Cleanup(void); cEvent *AddEvent(cEvent *Event); diff --git a/menu.c b/menu.c index 790bb179..bf189692 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.286 2004/02/15 14:29:53 kls Exp $ + * $Id: menu.c 1.287 2004/02/21 13:53:25 kls Exp $ */ #include "menu.h" @@ -1195,15 +1195,16 @@ eOSState cMenuEvent::ProcessKey(eKeys Key) class cMenuWhatsOnItem : public cOsdItem { public: const cEvent *event; - cMenuWhatsOnItem(const cEvent *Event); + const cChannel *channel; + cMenuWhatsOnItem(const cEvent *Event, cChannel *Channel); }; -cMenuWhatsOnItem::cMenuWhatsOnItem(const cEvent *Event) +cMenuWhatsOnItem::cMenuWhatsOnItem(const cEvent *Event, cChannel *Channel) { event = Event; + channel = Channel; char *buffer = NULL; - cChannel *channel = Channels.GetByNumber(event->ChannelNumber()); - asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", event->ChannelNumber(), 6, channel ? channel->Name() : "???", 5, event->GetTimeString(), event->Title()); + asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", channel->Number(), 6, channel->Name(), 5, event->GetTimeString(), event->Title()); SetText(buffer, false); } @@ -1226,39 +1227,18 @@ public: int cMenuWhatsOn::currentChannel = 0; const cEvent *cMenuWhatsOn::scheduleEvent = NULL; -static int CompareEventChannel(const void *p1, const void *p2) -{ - return (int)( (*(const cEvent **)p1)->ChannelNumber() - (*(const cEvent **)p2)->ChannelNumber()); -} - cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr) :cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, 7, 6) { - const cSchedule *Schedule = Schedules->First(); - const cEvent **pArray = NULL; - int num = 0; - - while (Schedule) { - pArray = (const cEvent **)realloc(pArray, (num + 1) * sizeof(cEvent *)); - - pArray[num] = Now ? Schedule->GetPresentEvent() : Schedule->GetFollowingEvent(); - if (pArray[num]) { - cChannel *channel = Channels.GetByChannelID(pArray[num]->ChannelID(), true); - if (channel) { - pArray[num]->SetChannelNumber(channel->Number()); - num++; - } - } - Schedule = (const cSchedule *)Schedules->Next(Schedule); - } - - qsort(pArray, num, sizeof(cEvent *), CompareEventChannel); - - for (int a = 0; a < num; a++) - Add(new cMenuWhatsOnItem(pArray[a]), pArray[a]->ChannelNumber() == CurrentChannelNr); - + for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) { + const cSchedule *Schedule = Schedules->GetSchedule(Channel->GetChannelID()); + if (Schedule) { + const cEvent *Event = Now ? Schedule->GetPresentEvent() : Schedule->GetFollowingEvent(); + if (Event) + Add(new cMenuWhatsOnItem(Event, Channel), Channel->Number() == CurrentChannelNr); + } + } currentChannel = CurrentChannelNr; - free(pArray); SetHelp(Count() ? tr("Record") : NULL, Now ? tr("Next") : tr("Now"), tr("Button$Schedule"), tr("Switch")); } @@ -1310,7 +1290,7 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key) cMenuWhatsOnItem *mi = (cMenuWhatsOnItem *)Get(Current()); if (mi) { scheduleEvent = mi->event; - currentChannel = mi->event->ChannelNumber(); + currentChannel = mi->channel->Number(); } } break; @@ -1376,11 +1356,6 @@ cMenuSchedule::~cMenuSchedule() cMenuWhatsOn::ScheduleEvent(); // makes sure any posted data is cleared } -static int CompareEventTime(const void *p1, const void *p2) -{ - return (int)((*(cEvent **)p1)->StartTime() - (*(cEvent **)p2)->StartTime()); -} - void cMenuSchedule::PrepareSchedule(cChannel *Channel) { Clear(); @@ -1392,22 +1367,12 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel) const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID()); if (Schedule) { int num = Schedule->NumEvents(); - const cEvent **pArray = MALLOC(const cEvent *, num); - if (pArray) { - time_t now = time(NULL); - int numreal = 0; - for (int a = 0; a < num; a++) { - const cEvent *Event = Schedule->GetEventNumber(a); - if (Event->StartTime() + Event->Duration() > now) - pArray[numreal++] = Event; - } - - qsort(pArray, numreal, sizeof(cEvent *), CompareEventTime); - - for (int a = 0; a < numreal; a++) - Add(new cMenuScheduleItem(pArray[a])); - free(pArray); - } + time_t now = time(NULL); + for (int a = 0; a < num; a++) { + const cEvent *Event = Schedule->GetEventNumber(a); + if (Event->StartTime() + Event->Duration() > now) + Add(new cMenuScheduleItem(Event)); + } } } }