diff options
author | Dimitar Petrovski <dimeptr@gmail.com> | 2012-10-18 14:32:04 +0200 |
---|---|---|
committer | Dimitar Petrovski <dimeptr@gmail.com> | 2012-10-18 14:32:04 +0200 |
commit | 6810f79e1b5f78a0b3d2389714924738295a6497 (patch) | |
tree | 951670799a35d3bfa389e5f9f65ba46c3c582ec8 | |
parent | cee549473dacfa3e82cb13bd9bbe1c8f0e8c1a6a (diff) | |
download | vdr-plugin-eepg-6810f79e1b5f78a0b3d2389714924738295a6497.tar.gz vdr-plugin-eepg-6810f79e1b5f78a0b3d2389714924738295a6497.tar.bz2 |
fix compile
-rw-r--r-- | eepg.c | 95 | ||||
-rw-r--r-- | eepg.h | 15 | ||||
-rw-r--r-- | eit2.c | 1110 | ||||
-rw-r--r-- | eit2.h | 43 | ||||
-rw-r--r-- | log.h | 3 | ||||
-rw-r--r-- | util.c | 23 | ||||
-rw-r--r-- | util.h | 80 |
7 files changed, 693 insertions, 676 deletions
@@ -65,14 +65,6 @@ static const char *VERSION = "0.0.6pre"; static const char *DESCRIPTION = trNOOP ("Parses Extended EPG data"); -template <class T> T REALLOC(T Var, size_t Size) -{ - T p = (T)realloc(Var, Size); - if (!p) - free(Var); - return p; -} - using namespace std; using namespace util; @@ -101,7 +93,6 @@ char *cs_hexdump (int m, const uchar * buf, int n) } cSetupEEPG* SetupPE = cSetupEEPG::getInstance(); -cEquivHandler* EquivHandler; // --- cMenuSetupPremiereEpg ------------------------------------------------------------ @@ -313,21 +304,21 @@ void syslog_with_tid (int priority, const char *format, ...) __attribute__ ((for -struct hufftab { - unsigned int value; - short bits; - char next; -}; - -#define START '\0' -#define STOP '\0' -#define ESCAPE '\1' +//struct hufftab { +// unsigned int value; +// short bits; +// char next; +//}; +// +//#define START '\0' +//#define STOP '\0' +//#define ESCAPE '\1' -int freesat_decode_error = 0; /* If set an error has occurred during decoding */ +//int freesat_decode_error = 0; /* If set an error has occurred during decoding */ -static struct hufftab *tables[2][128]; -static int table_size[2][128]; +//static struct hufftab *tables[2][128]; +//static int table_size[2][128]; static sNodeH* sky_tables[2]; /** \brief Convert a textual character description into a value @@ -569,7 +560,7 @@ static bool load_sky_file (const char *filename) char *freesat_huffman_decode (const unsigned char *src, size_t size) { int tableid; - freesat_decode_error = 0; +// freesat_decode_error = 0; if (src[0] == 0x1f && (src[1] == 1 || src[1] == 2)) { int uncompressed_len = 30; @@ -839,44 +830,28 @@ bool cFilterEEPG::InitDictionary (void) return true; } -void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize) -{ - if (from[0] == 0x1f) { - char *temp = freesat_huffman_decode (from, len); - if (temp) { - len = strlen (temp); - len = len < buffsize - 1 ? len : buffsize - 1; - strncpy (buffer, temp, len); - buffer[len] = 0; - free (temp); - return; - } - } - - SI::String convStr; - SI::CharArray charArray; - charArray.assign(from, len); - convStr.setData(charArray, len); - //LogE(5, prep("decodeText2 from %s - length %d"), from, len); - convStr.getText(buffer, buffsize); - //LogE(5, prep("decodeText2 buffer %s - buffsize %d"), buffer, buffsize); -} - -void sortSchedules(cSchedules * Schedules, tChannelID channelID){ - - LogD(3, prep("Start sortEquivalent %s"), *channelID.ToString()); - - cChannel *pChannel = GetChannelByID (channelID, false); - cSchedule *pSchedule; - if (pChannel) { - pSchedule = (cSchedule *) (Schedules->GetSchedule(pChannel, true)); - pSchedule->Sort(); - Schedules->SetModified(pSchedule); - } - if (EquivHandler->getEquiChanMap().count(*channelID.ToString()) > 0) - EquivHandler->sortEquivalents(channelID, Schedules); -} - +//void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize) +//{ +// if (from[0] == 0x1f) { +// char *temp = freesat_huffman_decode (from, len); +// if (temp) { +// len = strlen (temp); +// len = len < buffsize - 1 ? len : buffsize - 1; +// strncpy (buffer, temp, len); +// buffer[len] = 0; +// free (temp); +// return; +// } +// } +// +// SI::String convStr; +// SI::CharArray charArray; +// charArray.assign(from, len); +// convStr.setData(charArray, len); +// //LogE(5, prep("decodeText2 from %s - length %d"), from, len); +// convStr.getText(buffer, buffsize); +// //LogE(5, prep("decodeText2 buffer %s - buffsize %d"), buffer, buffsize); +//} /** * \brief Get MHW channels @@ -17,21 +17,6 @@ //#define NAGRA 6 //#define HIGHEST_FORMAT 6 -enum EFormat { -//First all batchmode, load ONCE protocols: - MHW1 = 0, - MHW2 , - SKY_IT , - SKY_UK , - NAGRA , -//Than all CONTinuous protocols, so they will be processed LAST: - PREMIERE , - FREEVIEW , - DISH_BEV , - EIT , -//the highest number of EPG-formats that is supported by this plugin - HIGHEST_FORMAT = EIT -} Format; #define NAGRA_TABLE_ID 0x55 //the lower the table Id, the more "current" it is; table_id 0x00 never gets overwritten, now/next are at 0x4e or 0x4f! #define DEFAULT_TABLE_ID 0x30 @@ -11,6 +11,7 @@ #include "log.h" #include "util.h" #include "dish.h" +#include "equivhandler.h" using namespace std; using namespace util; @@ -18,624 +19,625 @@ using namespace util; namespace SI { - cEvent* cEIT2::ProcessEitEvent(cSchedule* pSchedule,const SI::EIT::Event* EitEvent, - uchar Tid, uchar versionNumber) - { - bool ExternalData = false; - // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number. - if (EitEvent->getStartTime () == 0 || (EitEvent->getStartTime () > 0 && EitEvent->getDuration () == 0)) +cEvent* cEIT2::ProcessEitEvent(cSchedule* pSchedule,const SI::EIT::Event* EitEvent, + uchar Tid, uchar versionNumber) +{ + bool ExternalData = false; + // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number. + if (EitEvent->getStartTime () == 0 || (EitEvent->getStartTime () > 0 && EitEvent->getDuration () == 0)) + return NULL; + Empty = false; + if (!SegmentStart) + SegmentStart = EitEvent->getStartTime (); + SegmentEnd = EitEvent->getStartTime () + EitEvent->getDuration (); + // int versionNumber = getVersionNumber(); + + cEvent *newEvent = NULL; + cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EitEvent->getEventId (), EitEvent->getStartTime ()); + if (!pEvent) { + if (OnlyRunningStatus) return NULL; - Empty = false; - if (!SegmentStart) - SegmentStart = EitEvent->getStartTime (); - SegmentEnd = EitEvent->getStartTime () + EitEvent->getDuration (); -// int versionNumber = getVersionNumber(); - - cEvent *newEvent = NULL; - cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EitEvent->getEventId (), EitEvent->getStartTime ()); - if (!pEvent) { - if (OnlyRunningStatus) - return NULL; - // If we don't have that event yet, we create a new one. - // Otherwise we copy the information into the existing event anyway, because the data might have changed. - pEvent = newEvent = new cEvent (EitEvent->getEventId ()); - if (!pEvent) - return NULL; - } else { - //LogD(3, prep("existing event channelID: %s Title: %s TableID 0x%02X new TID 0x%02X Version %i, new version %i"), *channel->GetChannelID().ToString(), pEvent->Title(), pEvent->TableID(), Tid, pEvent->Version(), versionNumber); - // We have found an existing event, either through its event ID or its start time. - pEvent->SetSeen (); - - // If the existing event has a zero table ID it was defined externally and shall - // not be overwritten. - if (pEvent->TableID () == 0x00) { - if (pEvent->Version () == versionNumber) - return NULL; - /*HasExternalData = */ExternalData = true; - } - // If the new event has a higher table ID, let's skip it. - // The lower the table ID, the more "current" the information. - else if (Tid > pEvent->TableID()) - return NULL; - // If the new event comes from the same table and has the same version number - // as the existing one, let's skip it to avoid unnecessary work. - // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like - // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on - // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned - // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers. - else if (Tid == pEvent->TableID() && pEvent->Version() == versionNumber) + // If we don't have that event yet, we create a new one. + // Otherwise we copy the information into the existing event anyway, because the data might have changed. + pEvent = newEvent = new cEvent (EitEvent->getEventId ()); + if (!pEvent) + return NULL; + } else { + //LogD(3, prep("existing event channelID: %s Title: %s TableID 0x%02X new TID 0x%02X Version %i, new version %i"), *channel->GetChannelID().ToString(), pEvent->Title(), pEvent->TableID(), Tid, pEvent->Version(), versionNumber); + // We have found an existing event, either through its event ID or its start time. + pEvent->SetSeen (); + + // If the existing event has a zero table ID it was defined externally and shall + // not be overwritten. + if (pEvent->TableID () == 0x00) { + if (pEvent->Version () == versionNumber) return NULL; + /*HasExternalData = */ExternalData = true; } - if (!ExternalData) { - pEvent->SetEventID (EitEvent->getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-( - pEvent->SetTableID (Tid); - pEvent->SetStartTime (EitEvent->getStartTime ()); - pEvent->SetDuration (EitEvent->getDuration ()); - } - if (newEvent) - pSchedule->AddEvent (newEvent); - if (Tid == 0x4E) { // we trust only the present/following info on the actual TS - if (EitEvent->getRunningStatus () >= SI::RunningStatusNotRunning) - pSchedule->SetRunningStatus (pEvent, EitEvent->getRunningStatus (), channel); - } - if (OnlyRunningStatus) - return NULL; // do this before setting the version, so that the full update can be done later - pEvent->SetVersion (versionNumber); + // If the new event has a higher table ID, let's skip it. + // The lower the table ID, the more "current" the information. + else if (Tid > pEvent->TableID()) + return NULL; + // If the new event comes from the same table and has the same version number + // as the existing one, let's skip it to avoid unnecessary work. + // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like + // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on + // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned + // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers. + else if (Tid == pEvent->TableID() && pEvent->Version() == versionNumber) + return NULL; + } + if (!ExternalData) { + pEvent->SetEventID (EitEvent->getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-( + pEvent->SetTableID (Tid); + pEvent->SetStartTime (EitEvent->getStartTime ()); + pEvent->SetDuration (EitEvent->getDuration ()); + } + if (newEvent) + pSchedule->AddEvent (newEvent); + if (Tid == 0x4E) { // we trust only the present/following info on the actual TS + if (EitEvent->getRunningStatus () >= SI::RunningStatusNotRunning) + pSchedule->SetRunningStatus (pEvent, EitEvent->getRunningStatus (), channel); + } + if (OnlyRunningStatus) + return NULL; // do this before setting the version, so that the full update can be done later + pEvent->SetVersion (versionNumber); - ProcessEventDescriptors(ExternalData, channel->Source(), Tid, EitEvent, - pEvent, Schedules, channel); + ProcessEventDescriptors(ExternalData, channel->Source(), Tid, EitEvent, + pEvent, Schedules, channel); - Modified = true; - return pEvent; - } + Modified = true; + return pEvent; +} - void cEIT2::ProcessEventDescriptors(bool ExternalData, int Source, - u_char Tid, const SI::EIT::Event* SiEitEvent, cEvent* pEvent, - cSchedules* Schedules, cChannel* channel) - { +void cEIT2::ProcessEventDescriptors(bool ExternalData, int Source, + u_char Tid, const SI::EIT::Event* SiEitEvent, cEvent* pEvent, + cSchedules* Schedules, cChannel* channel) +{ - cEvent *rEvent = NULL; - int LanguagePreferenceShort = -1; - int LanguagePreferenceExt = -1; - unsigned char nDescriptorTag; - bool UseExtendedEventDescriptor = false; - SI::Descriptor * d; - SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL; - SI::ShortEventDescriptor * ShortEventDescriptor = NULL; - //SI::DishDescriptor *DishExtendedEventDescriptor = NULL; - SI::DishDescriptor *DishEventDescriptor = NULL; - //uchar DishTheme = 0, DishCategory = 0; + cEvent *rEvent = NULL; + int LanguagePreferenceShort = -1; + int LanguagePreferenceExt = -1; + unsigned char nDescriptorTag; + bool UseExtendedEventDescriptor = false; + SI::Descriptor * d; + SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL; + SI::ShortEventDescriptor * ShortEventDescriptor = NULL; + //SI::DishDescriptor *DishExtendedEventDescriptor = NULL; + SI::DishDescriptor *DishEventDescriptor = NULL; + //uchar DishTheme = 0, DishCategory = 0; - cLinkChannels *LinkChannels = NULL; - cComponents *Components = NULL; + cLinkChannels *LinkChannels = NULL; + cComponents *Components = NULL; - DescriptorLoop dl = SiEitEvent->eventDescriptors; - for (SI::Loop::Iterator it2; (d = dl.getNext(it2)); ) + DescriptorLoop dl = SiEitEvent->eventDescriptors; + for (SI::Loop::Iterator it2; (d = dl.getNext(it2)); ) + { + if (ExternalData && d->getDescriptorTag() != SI::ComponentDescriptorTag) { - if (ExternalData && d->getDescriptorTag() != SI::ComponentDescriptorTag) + delete d; + LogD(2, prep("continue:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); + continue; + } + + //LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); + nDescriptorTag = d->getDescriptorTag(); + switch (nDescriptorTag) + { + case SI::ExtendedEventDescriptorTag: + { + SI::ExtendedEventDescriptor * eed = + (SI::ExtendedEventDescriptor *) d; + if (I18nIsPreferredLanguage(Setup.EPGLanguages, eed->languageCode, + LanguagePreferenceExt) || !ExtendedEventDescriptors) { - delete d; - LogD(2, prep("continue:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); - continue; + delete ExtendedEventDescriptors; + ExtendedEventDescriptors = new SI::ExtendedEventDescriptors; + UseExtendedEventDescriptor = true; } - - //LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); - nDescriptorTag = d->getDescriptorTag(); - switch (nDescriptorTag) - { - case SI::ExtendedEventDescriptorTag: - { - SI::ExtendedEventDescriptor * eed = - (SI::ExtendedEventDescriptor *) d; - if (I18nIsPreferredLanguage(Setup.EPGLanguages, eed->languageCode, - LanguagePreferenceExt) || !ExtendedEventDescriptors) - { - delete ExtendedEventDescriptors; - ExtendedEventDescriptors = new SI::ExtendedEventDescriptors; - UseExtendedEventDescriptor = true; - } - if (UseExtendedEventDescriptor) - { - ExtendedEventDescriptors->Add(eed); - d = NULL; // so that it is not deleted - } - if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber()) - UseExtendedEventDescriptor = false; - } - break; - case SI::ShortEventDescriptorTag: - { - SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d; - if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, - LanguagePreferenceShort) || !ShortEventDescriptor) - { - delete ShortEventDescriptor; - ShortEventDescriptor = sed; - d = NULL; // so that it is not deleted - } - } - break; + if (UseExtendedEventDescriptor) + { + ExtendedEventDescriptors->Add(eed); + d = NULL; // so that it is not deleted + } + if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber()) + UseExtendedEventDescriptor = false; + } + break; + case SI::ShortEventDescriptorTag: + { + SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d; + if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, + LanguagePreferenceShort) || !ShortEventDescriptor) + { + delete ShortEventDescriptor; + ShortEventDescriptor = sed; + d = NULL; // so that it is not deleted + } + } + break; #if APIVERSNUM > 10711 - case SI::ContentDescriptorTag: - { - SI::ContentDescriptor *cd = (SI::ContentDescriptor *) d; - SI::ContentDescriptor::Nibble Nibble; - int NumContents = 0; - uchar Contents[MaxEventContents] = - { 0 }; - for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3);) - { - if (NumContents < MaxEventContents) - { - Contents[NumContents] = ((Nibble.getContentNibbleLevel1() - & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF); - NumContents++; - } - if (DishEventDescriptor && NumContents == 1) - { - DishEventDescriptor->setContent(Nibble); - } - // LogD(2, prep("EEPGDEBUG:Nibble:%x-%x-%x-%x)"), Nibble.getContentNibbleLevel1(),Nibble.getContentNibbleLevel2() - // , Nibble.getUserNibble1(), Nibble.getUserNibble2()); - - } - pEvent->SetContents(Contents); - } - break; + case SI::ContentDescriptorTag: + { + SI::ContentDescriptor *cd = (SI::ContentDescriptor *) d; + SI::ContentDescriptor::Nibble Nibble; + int NumContents = 0; + uchar Contents[MaxEventContents] = + { 0 }; + for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3);) + { + if (NumContents < MaxEventContents) + { + Contents[NumContents] = ((Nibble.getContentNibbleLevel1() + & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF); + NumContents++; + } + if (DishEventDescriptor && NumContents == 1) + { + DishEventDescriptor->setContent(Nibble); + } + // LogD(2, prep("EEPGDEBUG:Nibble:%x-%x-%x-%x)"), Nibble.getContentNibbleLevel1(),Nibble.getContentNibbleLevel2() + // , Nibble.getUserNibble1(), Nibble.getUserNibble2()); + + } + pEvent->SetContents(Contents); + } + break; #endif - case SI::ParentalRatingDescriptorTag: - { - int LanguagePreferenceRating = -1; - SI::ParentalRatingDescriptor *prd = - (SI::ParentalRatingDescriptor *) d; - SI::ParentalRatingDescriptor::Rating Rating; - for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3);) - { - if (I18nIsPreferredLanguage(Setup.EPGLanguages, - Rating.languageCode, LanguagePreferenceRating)) - { - int ParentalRating = (Rating.getRating() & 0xFF); - switch (ParentalRating) - { - // values defined by the DVB standard (minimum age = rating + 3 years): - case 0x01 ... 0x0F: - ParentalRating += 3; - break; - // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?): - case 0x11: - ParentalRating = 10; - break; - case 0x12: - ParentalRating = 12; - break; - case 0x13: - ParentalRating = 16; - break; - default: - ParentalRating = 0; - } - pEvent->SetParentalRating(ParentalRating); - } - } - } - break; - case SI::PDCDescriptorTag: - { - SI::PDCDescriptor * pd = (SI::PDCDescriptor *) d; - time_t now = time(NULL); - struct tm tm_r; - struct tm t = *localtime_r(&now, &tm_r); // this initializes the time zone in 't' - t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting - int month = t.tm_mon; - t.tm_mon = pd->getMonth() - 1; - t.tm_mday = pd->getDay(); - t.tm_hour = pd->getHour(); - t.tm_min = pd->getMinute(); - t.tm_sec = 0; - if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan - t.tm_year++; - else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec - t.tm_year--; - time_t vps = mktime(&t); - pEvent->SetVps(vps); - } - break; - case SI::TimeShiftedEventDescriptorTag: - { - if (Schedules) { - SI::TimeShiftedEventDescriptor * tsed = - (SI::TimeShiftedEventDescriptor *) d; - cSchedule *rSchedule = (cSchedule *) Schedules->GetSchedule( - tChannelID(Source, channel->Nid(), channel->Tid(), - tsed->getReferenceServiceId())); - if (!rSchedule) - break; - rEvent = (cEvent *) rSchedule->GetEvent( - tsed->getReferenceEventId()); - if (!rEvent) - break; - pEvent->SetTitle(rEvent->Title()); - pEvent->SetShortText(rEvent->ShortText()); - pEvent->SetDescription(rEvent->Description()); - } - } - break; - case SI::LinkageDescriptorTag: + case SI::ParentalRatingDescriptorTag: + { + int LanguagePreferenceRating = -1; + SI::ParentalRatingDescriptor *prd = + (SI::ParentalRatingDescriptor *) d; + SI::ParentalRatingDescriptor::Rating Rating; + for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3);) + { + if (I18nIsPreferredLanguage(Setup.EPGLanguages, + Rating.languageCode, LanguagePreferenceRating)) + { + int ParentalRating = (Rating.getRating() & 0xFF); + switch (ParentalRating) { - SI::LinkageDescriptor * ld = (SI::LinkageDescriptor *) d; - tChannelID linkID(Source, ld->getOriginalNetworkId(), - ld->getTransportStreamId(), ld->getServiceId()); - if (ld->getLinkageType() == 0xB0) - { // Premiere World - time_t now = time(NULL); - bool hit = SiEitEvent->getStartTime() <= now - && now - < SiEitEvent->getStartTime() + SiEitEvent->getDuration(); - if (hit) - { - char linkName[ld->privateData.getLength() + 1]; - strn0cpy(linkName, (const char *) ld->privateData.getData(), - sizeof(linkName)); - // TODO is there a standard way to determine the character set of this string? - cChannel *link = Channels.GetByChannelID(linkID); - if (link != channel) - { // only link to other channels, not the same one - //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX - if (link) - { - if (Setup.UpdateChannels == 1 - || Setup.UpdateChannels >= 3) - link->SetName(linkName, "", ""); - } - else if (Setup.UpdateChannels >= 4) - { - cChannel *transponder = channel; - if (channel->Tid() != ld->getTransportStreamId()) - transponder = Channels.GetByTransponderID(linkID); - link = Channels.NewChannel(transponder, linkName, - "", "", ld->getOriginalNetworkId(), - ld->getTransportStreamId(), ld->getServiceId()); - } - if (link) - { - if (!LinkChannels) - LinkChannels = new cLinkChannels; - LinkChannels->Add(new cLinkChannel(link)); - } - } - else - channel->SetPortalName(linkName); - } - } - } + // values defined by the DVB standard (minimum age = rating + 3 years): + case 0x01 ... 0x0F: + ParentalRating += 3; break; - case SI::ComponentDescriptorTag: - { - SI::ComponentDescriptor * cd = (SI::ComponentDescriptor *) d; - uchar Stream = cd->getStreamContent(); - uchar Type = cd->getComponentType(); - //if (1 <= Stream && Stream <= 3 && Type != 0) { // 1=video, 2=audio, 3=subtitles - if (1 <= Stream && Stream <= 6 && Type != 0) - { // 1=MPEG2-video, 2=MPEG1-audio, 3=subtitles, 4=AC3-audio, 5=H.264-video, 6=HEAAC-audio - if (!Components) - Components = new cComponents; - char buffer[Utf8BufSize (256)]; - Components->SetComponent(Components->NumComponents(), Stream, - Type, I18nNormalizeLanguageCode(cd->languageCode), - cd->description.getText(buffer, sizeof(buffer))); - } + // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?): + case 0x11: + ParentalRating = 10; + break; + case 0x12: + ParentalRating = 12; + break; + case 0x13: + ParentalRating = 16; + break; + default: + ParentalRating = 0; } + pEvent->SetParentalRating(ParentalRating); + } + } + } + break; + case SI::PDCDescriptorTag: + { + SI::PDCDescriptor * pd = (SI::PDCDescriptor *) d; + time_t now = time(NULL); + struct tm tm_r; + struct tm t = *localtime_r(&now, &tm_r); // this initializes the time zone in 't' + t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting + int month = t.tm_mon; + t.tm_mon = pd->getMonth() - 1; + t.tm_mday = pd->getDay(); + t.tm_hour = pd->getHour(); + t.tm_min = pd->getMinute(); + t.tm_sec = 0; + if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan + t.tm_year++; + else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec + t.tm_year--; + time_t vps = mktime(&t); + pEvent->SetVps(vps); + } + break; + case SI::TimeShiftedEventDescriptorTag: + { + if (Schedules) { + SI::TimeShiftedEventDescriptor * tsed = + (SI::TimeShiftedEventDescriptor *) d; + cSchedule *rSchedule = (cSchedule *) Schedules->GetSchedule( + tChannelID(Source, channel->Nid(), channel->Tid(), + tsed->getReferenceServiceId())); + if (!rSchedule) break; - case SI::DishExtendedEventDescriptorTag: - { - SI::UnimplementedDescriptor *deed = - (SI::UnimplementedDescriptor *) d; - if (!DishEventDescriptor) - { - DishEventDescriptor = new SI::DishDescriptor(); - } - DishEventDescriptor->setExtendedtData(Tid + 1, deed->getData()); - // HasExternalData = true; - } + rEvent = (cEvent *) rSchedule->GetEvent( + tsed->getReferenceEventId()); + if (!rEvent) break; - case SI::DishShortEventDescriptorTag: + pEvent->SetTitle(rEvent->Title()); + pEvent->SetShortText(rEvent->ShortText()); + pEvent->SetDescription(rEvent->Description()); + } + } + break; + case SI::LinkageDescriptorTag: + { + SI::LinkageDescriptor * ld = (SI::LinkageDescriptor *) d; + tChannelID linkID(Source, ld->getOriginalNetworkId(), + ld->getTransportStreamId(), ld->getServiceId()); + if (ld->getLinkageType() == 0xB0) + { // Premiere World + time_t now = time(NULL); + bool hit = SiEitEvent->getStartTime() <= now + && now + < SiEitEvent->getStartTime() + SiEitEvent->getDuration(); + if (hit) + { + char linkName[ld->privateData.getLength() + 1]; + strn0cpy(linkName, (const char *) ld->privateData.getData(), + sizeof(linkName)); + // TODO is there a standard way to determine the character set of this string? + cChannel *link = Channels.GetByChannelID(linkID); + if (link != channel) + { // only link to other channels, not the same one + //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX + if (link) { - SI::UnimplementedDescriptor *dsed = - (SI::UnimplementedDescriptor *) d; - if (!DishEventDescriptor) - { - DishEventDescriptor = new SI::DishDescriptor(); - } - DishEventDescriptor->setShortData(Tid + 1, dsed->getData()); - // HasExternalData = true; + if (Setup.UpdateChannels == 1 + || Setup.UpdateChannels >= 3) + link->SetName(linkName, "", ""); } - break; - case SI::DishRatingDescriptorTag: + else if (Setup.UpdateChannels >= 4) { - if (d->getLength() == 4) - { - if (!DishEventDescriptor) - { - DishEventDescriptor = new SI::DishDescriptor(); - } - uint16_t rating = d->getData().TwoBytes(2); - DishEventDescriptor->setRating(rating); - } + cChannel *transponder = channel; + if (channel->Tid() != ld->getTransportStreamId()) + transponder = Channels.GetByTransponderID(linkID); + link = Channels.NewChannel(transponder, linkName, + "", "", ld->getOriginalNetworkId(), + ld->getTransportStreamId(), ld->getServiceId()); } - break; - case SI::DishSeriesDescriptorTag: + if (link) { - if (d->getLength() == 10) - { - //LogD(2, prep("DishSeriesDescriptorTag: %s)"), (const char*) d->getData().getData()); - if (!DishEventDescriptor) - { - DishEventDescriptor = new SI::DishDescriptor(); - } - DishEventDescriptor->setEpisodeInfo(d->getData()); - } - // else { - // LogD(2, prep("DishSeriesDescriptorTag length: %d)"), d->getLength()); - // } + if (!LinkChannels) + LinkChannels = new cLinkChannels; + LinkChannels->Add(new cLinkChannel(link)); } - break; - default: - break; - } - delete d; + } + else + channel->SetPortalName(linkName); } - if (!rEvent) { - if (ShortEventDescriptor) { + } + } + break; + case SI::ComponentDescriptorTag: + { + SI::ComponentDescriptor * cd = (SI::ComponentDescriptor *) d; + uchar Stream = cd->getStreamContent(); + uchar Type = cd->getComponentType(); + //if (1 <= Stream && Stream <= 3 && Type != 0) { // 1=video, 2=audio, 3=subtitles + if (1 <= Stream && Stream <= 6 && Type != 0) + { // 1=MPEG2-video, 2=MPEG1-audio, 3=subtitles, 4=AC3-audio, 5=H.264-video, 6=HEAAC-audio + if (!Components) + Components = new cComponents; char buffer[Utf8BufSize (256)]; - unsigned char *f; - int l = ShortEventDescriptor->name.getLength(); - f = (unsigned char *) ShortEventDescriptor->name.getData().getData(); - decodeText2 (f, l, buffer, sizeof (buffer)); - //ShortEventDescriptor->name.getText(buffer, sizeof(buffer)); - LogD(2, prep("Title: %s Decoded: %s"), f, buffer); - pEvent->SetTitle (buffer); - LogD(3, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title()); - l = ShortEventDescriptor->text.getLength(); - if (l > 0) { //Set the Short Text only if there is data so that we do not overwrite valid data - f = (unsigned char *) ShortEventDescriptor->text.getData().getData(); - decodeText2 (f, l, buffer, sizeof (buffer)); - //ShortEventDescriptor->text.getText(buffer, sizeof(buffer)); - pEvent->SetShortText (buffer); - } - LogD(3, prep("ShortText: %s"), pEvent->ShortText()); - LogD(2, prep("ShortText: %s Decoded: %s"), f, buffer); - } else if (/*!HasExternalData*/!DishEventDescriptor) { - pEvent->SetTitle (NULL); - pEvent->SetShortText (NULL); - LogD(3, prep("SetTitle (NULL)")); + Components->SetComponent(Components->NumComponents(), Stream, + Type, I18nNormalizeLanguageCode(cd->languageCode), + cd->description.getText(buffer, sizeof(buffer))); } - if (ExtendedEventDescriptors) { - char buffer[Utf8BufSize (ExtendedEventDescriptors->getMaximumTextLength (": ")) + 1]; - pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")); - LogD(3, prep("Description: %s"), pEvent->Description()); - } else if (!/*HasExternalData*/DishEventDescriptor) - pEvent->SetDescription (NULL); - - if (DishEventDescriptor) { - if (DishEventDescriptor->getName()) - pEvent->SetTitle(DishEventDescriptor->getName()); - //LogD(2, prep("channelID: %s DishTitle: %s"), *channel->GetChannelID().ToString(), DishEventDescriptor->getName()); - pEvent->SetShortText(DishEventDescriptor->getShortText()); - char *tmp; - string fmt; - - const char * description = DishEventDescriptor->getDescription(); - //BEV sets the description previously with ExtendedEventDescriptor - if (0 == strcmp(DishEventDescriptor->getDescription(),"") && pEvent->Description()) - description = pEvent->Description(); - - - fmt = "%s"; - if (DishEventDescriptor->hasTheme()) { - fmt += "\nTheme: "; - } - fmt += "%s"; - if (DishEventDescriptor->hasCategory()) { - fmt += "\nCategory: "; - } - fmt += "%s"; - - if ((0 != strcmp(DishEventDescriptor->getRating(),"") - || 0 != strcmp(DishEventDescriptor->getStarRating(),""))) { - fmt += "\n\nRating: "; - } - fmt += "%s %s"; - if (0 != strcmp(DishEventDescriptor->getProgramId(),"")) { - fmt += "\n\nProgram ID: "; + } + break; + case SI::DishExtendedEventDescriptorTag: + { + SI::UnimplementedDescriptor *deed = + (SI::UnimplementedDescriptor *) d; + if (!DishEventDescriptor) + { + DishEventDescriptor = new SI::DishDescriptor(); + } + DishEventDescriptor->setExtendedtData(Tid + 1, deed->getData()); + // HasExternalData = true; + } + break; + case SI::DishShortEventDescriptorTag: + { + SI::UnimplementedDescriptor *dsed = + (SI::UnimplementedDescriptor *) d; + if (!DishEventDescriptor) + { + DishEventDescriptor = new SI::DishDescriptor(); + } + DishEventDescriptor->setShortData(Tid + 1, dsed->getData()); + // HasExternalData = true; + } + break; + case SI::DishRatingDescriptorTag: + { + if (d->getLength() == 4) + { + if (!DishEventDescriptor) + { + DishEventDescriptor = new SI::DishDescriptor(); } - fmt += "%s %s%s"; - time_t orgAirDate = DishEventDescriptor->getOriginalAirDate(); - char datestr [80]; - bool dateok = false; - if (orgAirDate == 0) { - dateok = strftime (datestr,80," Original Air Date: %a %b %d %Y",gmtime(&orgAirDate)) > 0; + uint16_t rating = d->getData().TwoBytes(2); + DishEventDescriptor->setRating(rating); + } + } + break; + case SI::DishSeriesDescriptorTag: + { + if (d->getLength() == 10) + { + //LogD(2, prep("DishSeriesDescriptorTag: %s)"), (const char*) d->getData().getData()); + if (!DishEventDescriptor) + { + DishEventDescriptor = new SI::DishDescriptor(); } + DishEventDescriptor->setEpisodeInfo(d->getData()); + } + // else { + // LogD(2, prep("DishSeriesDescriptorTag length: %d)"), d->getLength()); + // } + } + break; + default: + break; + } + delete d; + } + if (!rEvent) { + if (ShortEventDescriptor) { + char buffer[Utf8BufSize (256)]; + unsigned char *f; + int l = ShortEventDescriptor->name.getLength(); + f = (unsigned char *) ShortEventDescriptor->name.getData().getData(); + decodeText2 (f, l, buffer, sizeof (buffer)); + //ShortEventDescriptor->name.getText(buffer, sizeof(buffer)); + LogD(2, prep("Title: %s Decoded: %s"), f, buffer); + pEvent->SetTitle (buffer); + LogD(3, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title()); + l = ShortEventDescriptor->text.getLength(); + if (l > 0) { //Set the Short Text only if there is data so that we do not overwrite valid data + f = (unsigned char *) ShortEventDescriptor->text.getData().getData(); + decodeText2 (f, l, buffer, sizeof (buffer)); + //ShortEventDescriptor->text.getText(buffer, sizeof(buffer)); + pEvent->SetShortText (buffer); + } + LogD(3, prep("ShortText: %s"), pEvent->ShortText()); + LogD(2, prep("ShortText: %s Decoded: %s"), f, buffer); + } else if (/*!HasExternalData*/!DishEventDescriptor) { + pEvent->SetTitle (NULL); + pEvent->SetShortText (NULL); + LogD(3, prep("SetTitle (NULL)")); + } + if (ExtendedEventDescriptors) { + char buffer[Utf8BufSize (ExtendedEventDescriptors->getMaximumTextLength (": ")) + 1]; + pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")); + LogD(3, prep("Description: %s"), pEvent->Description()); + } else if (!/*HasExternalData*/DishEventDescriptor) + pEvent->SetDescription (NULL); + + if (DishEventDescriptor) { + if (DishEventDescriptor->getName()) + pEvent->SetTitle(DishEventDescriptor->getName()); + //LogD(2, prep("channelID: %s DishTitle: %s"), *channel->GetChannelID().ToString(), DishEventDescriptor->getName()); + pEvent->SetShortText(DishEventDescriptor->getShortText()); + char *tmp; + string fmt; + + const char * description = DishEventDescriptor->getDescription(); + //BEV sets the description previously with ExtendedEventDescriptor + if (0 == strcmp(DishEventDescriptor->getDescription(),"") && pEvent->Description()) + description = pEvent->Description(); + + + fmt = "%s"; + if (DishEventDescriptor->hasTheme()) { + fmt += "\nTheme: "; + } + fmt += "%s"; + if (DishEventDescriptor->hasCategory()) { + fmt += "\nCategory: "; + } + fmt += "%s"; - Asprintf (&tmp, fmt.c_str(), description - , DishEventDescriptor->getTheme(), DishEventDescriptor->getCategory() - , DishEventDescriptor->getRating(), DishEventDescriptor->getStarRating() - , DishEventDescriptor->getProgramId(), DishEventDescriptor->getSeriesId() - , orgAirDate == 0 || !dateok ? "" : datestr); - pEvent->SetDescription(tmp); - free(tmp); + if ((0 != strcmp(DishEventDescriptor->getRating(),"") + || 0 != strcmp(DishEventDescriptor->getStarRating(),""))) { + fmt += "\n\nRating: "; + } + fmt += "%s %s"; + if (0 != strcmp(DishEventDescriptor->getProgramId(),"")) { + fmt += "\n\nProgram ID: "; + } + fmt += "%s %s%s"; + time_t orgAirDate = DishEventDescriptor->getOriginalAirDate(); + char datestr [80]; + bool dateok = false; + if (orgAirDate == 0) { + dateok = strftime (datestr,80," Original Air Date: %a %b %d %Y",gmtime(&orgAirDate)) > 0; + } + Asprintf (&tmp, fmt.c_str(), description + , DishEventDescriptor->getTheme(), DishEventDescriptor->getCategory() + , DishEventDescriptor->getRating(), DishEventDescriptor->getStarRating() + , DishEventDescriptor->getProgramId(), DishEventDescriptor->getSeriesId() + , orgAirDate == 0 || !dateok ? "" : datestr); + pEvent->SetDescription(tmp); + free(tmp); - //LogD(2, prep("DishDescription: %s"), DishEventDescriptor->getDescription()); - //LogD(2, prep("DishShortText: %s"), DishEventDescriptor->getShortText()); - } + //LogD(2, prep("DishDescription: %s"), DishEventDescriptor->getDescription()); + //LogD(2, prep("DishShortText: %s"), DishEventDescriptor->getShortText()); } - delete ExtendedEventDescriptors; - delete ShortEventDescriptor; - delete DishEventDescriptor; - pEvent->SetComponents (Components); + } + delete ExtendedEventDescriptors; + delete ShortEventDescriptor; + delete DishEventDescriptor; -// LogD(2, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title()); + pEvent->SetComponents (Components); -// if (pEvent->ChannelID() == tChannelID::FromString("S119.0W-4100-6-110-110")) { -// LogD(2, prep("ID: %d Title: %s Time: %d Tid: 0x%x"), pEvent->EventID(), pEvent->Title(), pEvent->StartTime(), pEvent->TableID()); -// } + // LogD(2, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title()); -// if (!HasExternalData) - pEvent->FixEpgBugs (); - if (LinkChannels) - channel->SetLinkChannels (LinkChannels); - } + // if (pEvent->ChannelID() == tChannelID::FromString("S119.0W-4100-6-110-110")) { + // LogD(2, prep("ID: %d Title: %s Time: %d Tid: 0x%x"), pEvent->EventID(), pEvent->Title(), pEvent->StartTime(), pEvent->TableID()); + // } + + // if (!HasExternalData) + pEvent->FixEpgBugs (); + if (LinkChannels) + channel->SetLinkChannels (LinkChannels); +} cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool isEITPid, bool OnlyRunningStatus) : SI::EIT (Data, false) , OnlyRunningStatus(OnlyRunningStatus) , Schedules(Schedules) { - //LogD(2, prep("cEIT2::cEIT2")); - if (Tid > 0 && (Format == DISH_BEV || (SetupPE->ProcessEIT && isEITPid))) Tid--; - if (!CheckCRCAndParse ()) { - LogD(2, prep("!CheckCRCAndParse ()")); - return; - } + //LogD(2, prep("cEIT2::cEIT2")); + if (Tid > 0 && (Format == DISH_BEV || (cSetupEEPG::getInstance()->ProcessEIT && isEITPid))) Tid--; - bool searchOtherSatPositions = Format == DISH_BEV; + if (!CheckCRCAndParse ()) { + LogD(2, prep("!CheckCRCAndParse ()")); + return; + } - tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ()); - channel = GetChannelByID (channelID, searchOtherSatPositions); - if (!channel) { - LogD(3, prep("!channel channelID: %s"), *channelID.ToString()); - return; // only collect data for known channels - } + bool searchOtherSatPositions = Format == DISH_BEV; - //LogD(5, prep("channelID: %s format:%d"), *channel->GetChannelID().ToString(), Format); - - cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channel, true); - - Empty = true; - Modified = false; -// bool HasExternalData = false; - SegmentStart = 0; - SegmentEnd = 0; - - SI::EIT::Event SiEitEvent; - for (SI::Loop::Iterator it; eventLoop.getNext (SiEitEvent, it);) { - int versionNumber = getVersionNumber(); -// bool ExternalData = false; -// // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number. -// if (SiEitEvent.getStartTime () == 0 || (SiEitEvent.getStartTime () > 0 && SiEitEvent.getDuration () == 0)) -// continue; -// Empty = false; -// if (!SegmentStart) -// SegmentStart = SiEitEvent.getStartTime (); -// SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration (); -// int versionNumber = getVersionNumber(); -// -// cEvent *newEvent = NULL; -// cEvent *pEvent = (cEvent *) pSchedule->GetEvent (SiEitEvent.getEventId (), SiEitEvent.getStartTime ()); -// if (!pEvent) { -// if (OnlyRunningStatus) -// continue; -// // If we don't have that event yet, we create a new one. -// // Otherwise we copy the information into the existing event anyway, because the data might have changed. -// pEvent = newEvent = new cEvent (SiEitEvent.getEventId ()); -// if (!pEvent) -// continue; -// } else { -// //LogD(3, prep("existing event channelID: %s Title: %s TableID 0x%02X new TID 0x%02X Version %i, new version %i"), *channel->GetChannelID().ToString(), pEvent->Title(), pEvent->TableID(), Tid, pEvent->Version(), versionNumber); -// // We have found an existing event, either through its event ID or its start time. -// pEvent->SetSeen (); -// -// // If the existing event has a zero table ID it was defined externally and shall -// // not be overwritten. -// if (pEvent->TableID () == 0x00) { -// if (pEvent->Version () == versionNumber) -// continue; -// /*HasExternalData = */ExternalData = true; -// } -// // If the new event has a higher table ID, let's skip it. -// // The lower the table ID, the more "current" the information. -// else if (Tid > pEvent->TableID()) -// continue; -// // If the new event comes from the same table and has the same version number -// // as the existing one, let's skip it to avoid unnecessary work. -// // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like -// // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on -// // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned -// // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers. -// else if (Tid == pEvent->TableID() && pEvent->Version() == versionNumber) -// continue; -// } -// if (!ExternalData) { -// pEvent->SetEventID (SiEitEvent.getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-( -// pEvent->SetTableID (Tid); -// pEvent->SetStartTime (SiEitEvent.getStartTime ()); -// pEvent->SetDuration (SiEitEvent.getDuration ()); -// } -// if (newEvent) -// pSchedule->AddEvent (newEvent); -// if (Tid == 0x4E) { // we trust only the present/following info on the actual TS -// if (SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning) -// pSchedule->SetRunningStatus (pEvent, SiEitEvent.getRunningStatus (), channel); -// } -// if (OnlyRunningStatus) -// continue; // do this before setting the version, so that the full update can be done later -// pEvent->SetVersion (versionNumber); -// -// ProcessEventDescriptors(ExternalData, Source, Tid, SiEitEvent, -// pEvent, Schedules, channel); -// -// Modified = true; - cEvent *pEvent = ProcessEitEvent(pSchedule, &SiEitEvent, - Tid, versionNumber); - if (pEvent) - EquivHandler->updateEquivalent(Schedules, channel->GetChannelID(), pEvent); - } + tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ()); + channel = GetChannelByID (channelID, searchOtherSatPositions); + if (!channel) { + LogD(3, prep("!channel channelID: %s"), *channelID.ToString()); + return; // only collect data for known channels + } - //// + //LogD(5, prep("channelID: %s format:%d"), *channel->GetChannelID().ToString(), Format); + + cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channel, true); + + Empty = true; + Modified = false; + // bool HasExternalData = false; + SegmentStart = 0; + SegmentEnd = 0; + + SI::EIT::Event SiEitEvent; + for (SI::Loop::Iterator it; eventLoop.getNext (SiEitEvent, it);) { + int versionNumber = getVersionNumber(); + // bool ExternalData = false; + // // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number. + // if (SiEitEvent.getStartTime () == 0 || (SiEitEvent.getStartTime () > 0 && SiEitEvent.getDuration () == 0)) + // continue; + // Empty = false; + // if (!SegmentStart) + // SegmentStart = SiEitEvent.getStartTime (); + // SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration (); + // int versionNumber = getVersionNumber(); + // + // cEvent *newEvent = NULL; + // cEvent *pEvent = (cEvent *) pSchedule->GetEvent (SiEitEvent.getEventId (), SiEitEvent.getStartTime ()); + // if (!pEvent) { + // if (OnlyRunningStatus) + // continue; + // // If we don't have that event yet, we create a new one. + // // Otherwise we copy the information into the existing event anyway, because the data might have changed. + // pEvent = newEvent = new cEvent (SiEitEvent.getEventId ()); + // if (!pEvent) + // continue; + // } else { + // //LogD(3, prep("existing event channelID: %s Title: %s TableID 0x%02X new TID 0x%02X Version %i, new version %i"), *channel->GetChannelID().ToString(), pEvent->Title(), pEvent->TableID(), Tid, pEvent->Version(), versionNumber); + // // We have found an existing event, either through its event ID or its start time. + // pEvent->SetSeen (); + // + // // If the existing event has a zero table ID it was defined externally and shall + // // not be overwritten. + // if (pEvent->TableID () == 0x00) { + // if (pEvent->Version () == versionNumber) + // continue; + // /*HasExternalData = */ExternalData = true; + // } + // // If the new event has a higher table ID, let's skip it. + // // The lower the table ID, the more "current" the information. + // else if (Tid > pEvent->TableID()) + // continue; + // // If the new event comes from the same table and has the same version number + // // as the existing one, let's skip it to avoid unnecessary work. + // // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like + // // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on + // // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned + // // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers. + // else if (Tid == pEvent->TableID() && pEvent->Version() == versionNumber) + // continue; + // } + // if (!ExternalData) { + // pEvent->SetEventID (SiEitEvent.getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-( + // pEvent->SetTableID (Tid); + // pEvent->SetStartTime (SiEitEvent.getStartTime ()); + // pEvent->SetDuration (SiEitEvent.getDuration ()); + // } + // if (newEvent) + // pSchedule->AddEvent (newEvent); + // if (Tid == 0x4E) { // we trust only the present/following info on the actual TS + // if (SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning) + // pSchedule->SetRunningStatus (pEvent, SiEitEvent.getRunningStatus (), channel); + // } + // if (OnlyRunningStatus) + // continue; // do this before setting the version, so that the full update can be done later + // pEvent->SetVersion (versionNumber); + // + // ProcessEventDescriptors(ExternalData, Source, Tid, SiEitEvent, + // pEvent, Schedules, channel); + // + // Modified = true; + cEvent *pEvent = ProcessEitEvent(pSchedule, &SiEitEvent, + Tid, versionNumber); + if (pEvent) + EquivHandler->updateEquivalent(Schedules, channel->GetChannelID(), pEvent); + } - if (Empty && Tid == 0x4E && getSectionNumber () == 0) - // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running - pSchedule->ClrRunningStatus (channel); - if (Tid == 0x4E) - pSchedule->SetPresentSeen (); - if (OnlyRunningStatus) { - LogD(4, prep("OnlyRunningStatus")); - return; - } - if (Modified) { -// if (!HasExternalData) - pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ()); - sortSchedules(Schedules, channel->GetChannelID()); - } - LogD(4, prep("end of cEIT2")); + //// + if (Empty && Tid == 0x4E && getSectionNumber () == 0) + // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running + pSchedule->ClrRunningStatus (channel); + if (Tid == 0x4E) + pSchedule->SetPresentSeen (); + if (OnlyRunningStatus) { + LogD(4, prep("OnlyRunningStatus")); + return; + } + if (Modified) { + // if (!HasExternalData) + pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ()); + sortSchedules(Schedules, channel->GetChannelID()); } - //end of cEIT2 + LogD(4, prep("end of cEIT2")); + +} +//end of cEIT2 cEIT2::cEIT2 (cSchedule * Schedule) -: OnlyRunningStatus(false) -, Empty(true) +: Empty(true) , Modified(false) +, OnlyRunningStatus(false) , SegmentStart(0) , SegmentEnd(0) , Schedules(NULL) { - //LogD(2, prep("cEIT2::cEIT2")); -// if (Tid > 0 && (Format == DISH_BEV || (SetupPE->ProcessEIT && isEITPid))) Tid--; + //LogD(2, prep("cEIT2::cEIT2")); + // if (Tid > 0 && (Format == DISH_BEV || (SetupPE->ProcessEIT && isEITPid))) Tid--; - bool searchOtherSatPositions = Format == DISH_BEV; + bool searchOtherSatPositions = Format == DISH_BEV; - tChannelID channelID (Schedule->channelID.Source(), getOriginalNetworkId (), getTransportStreamId (), getServiceId ()); - channel = GetChannelByID (channelID, searchOtherSatPositions); - if (!channel) { - LogD(3, prep("!channel channelID: %s"), *channelID.ToString()); - return; // only collect data for known channels - } + tChannelID channelID (Schedule->ChannelID().Source(), getOriginalNetworkId (), getTransportStreamId (), getServiceId ()); + channel = GetChannelByID (channelID, searchOtherSatPositions); + if (!channel) { + LogD(3, prep("!channel channelID: %s"), *channelID.ToString()); + return; // only collect data for known channels + } } } //end namespace SI @@ -7,12 +7,12 @@ namespace SI { - enum DescriptorTagExt { - DishRatingDescriptorTag = 0x89, - DishShortEventDescriptorTag = 0x91, - DishExtendedEventDescriptorTag = 0x92, - DishSeriesDescriptorTag = 0x96, - }; +enum DescriptorTagExt { + DishRatingDescriptorTag = 0x89, + DishShortEventDescriptorTag = 0x91, + DishExtendedEventDescriptorTag = 0x92, + DishSeriesDescriptorTag = 0x96, +}; // typedef InheritEnum< DescriptorTagExt, SI::DescriptorTag > ExtendedDescriptorTag; @@ -22,28 +22,29 @@ extern bool SystemCharacterTableIsSingleByte;*/ class cEIT2:public SI::EIT { public: - cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool isEITPid = false, bool OnlyRunningStatus = false); + cEIT2(cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool isEITPid = false, + bool OnlyRunningStatus = false); cEIT2 (cSchedule * Schedule); -//protected: -// void updateEquivalent(cSchedules * Schedules, tChannelID channelID, cEvent *pEvent); + //protected: + // void updateEquivalent(cSchedules * Schedules, tChannelID channelID, cEvent *pEvent); cEvent* ProcessEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version); private: - void ProcessEventDescriptors(bool ExternalData, - int Source, u_char Tid, const SI::EIT::Event* SiEitEvent, cEvent* pEvent, - cSchedules* Schedules, cChannel* channel); + void ProcessEventDescriptors(bool ExternalData, int Source, u_char Tid, + const SI::EIT::Event* SiEitEvent, cEvent* pEvent, + cSchedules* Schedules, cChannel* channel); private: - bool Empty; - bool Modified; -// bool HasExternalData = false; - time_t SegmentStart; - time_t SegmentEnd; - cSchedules* Schedules; - cChannel* channel; + bool Empty; + bool Modified; + // bool HasExternalData = false; + bool OnlyRunningStatus; + time_t SegmentStart; + time_t SegmentEnd; + cSchedules* Schedules; + cChannel* channel; - bool OnlyRunningStatus; - }; +}; } //end namespace SI #endif /* CEIT2_H_ */ @@ -9,7 +9,8 @@ #define LOG_H_ #include <string> -#include <stdarg.h> +#include <vdr/tools.h> +#include <vdr/thread.h> #include "setupeepg.h" #define VERBOSE 1 @@ -5,6 +5,8 @@ * Author: d.petrovski */ #include "util.h" +#include "log.h" +#include "equivhandler.h" #include <vdr/channels.h> #include <vdr/thread.h> #include <vdr/epg.h> @@ -19,6 +21,12 @@ int Yesterday; int YesterdayEpoch; int YesterdayEpochUTC; +struct hufftab *tables[2][128]; +int table_size[2][128]; + +EFormat Format; +cEquivHandler* EquivHandler; + cChannel *GetChannelByID(tChannelID & channelID, bool searchOtherPos) { cChannel *VC = Channels.GetByChannelID(channelID, true); @@ -322,5 +330,20 @@ void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize //LogE(5, prep("decodeText2 buffer %s - buffsize %d"), buffer, buffsize); } +void sortSchedules(cSchedules * Schedules, tChannelID channelID){ + + LogD(3, prep("Start sortEquivalent %s"), *channelID.ToString()); + + cChannel *pChannel = GetChannelByID (channelID, false); + cSchedule *pSchedule; + if (pChannel) { + pSchedule = (cSchedule *) (Schedules->GetSchedule(pChannel, true)); + pSchedule->Sort(); + Schedules->SetModified(pSchedule); + } + if (EquivHandler->getEquiChanMap().count(*channelID.ToString()) > 0) + EquivHandler->sortEquivalents(channelID, Schedules); +} + } @@ -11,9 +11,18 @@ class cChannel; struct tChannelID; class cEvent; +class cEquivHandler; +class cSchedules; + +#define START '\0' +#define STOP '\0' +#define ESCAPE '\1' + +#define Asprintf(a, b, c...) void( asprintf(a, b, c) < 0 ? esyslog("memory allocation error - %s", b) : void() ) namespace util { + extern int AvailableSources[32]; extern int NumberOfAvailableSources; @@ -21,41 +30,62 @@ extern int Yesterday; extern int YesterdayEpoch; extern int YesterdayEpochUTC; +extern enum EFormat +{ +//First all batchmode, load ONCE protocols: + MHW1 = 0, + MHW2, + SKY_IT, + SKY_UK, + NAGRA, +//Than all CONTinuous protocols, so they will be processed LAST: + PREMIERE, + FREEVIEW, + DISH_BEV, + EIT, +//the highest number of EPG-formats that is supported by this plugin + HIGHEST_FORMAT = EIT +} Format; + +extern cEquivHandler* EquivHandler; + void AddEvent(cEvent *event, tChannelID ChannelID); cChannel *GetChannelByID(tChannelID & channelID, bool searchOtherPos); -time_t LocalTime2UTC (time_t t); -time_t UTC2LocalTime (time_t t); -void GetLocalTimeOffset (void); -void CleanString (unsigned char *String); -void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize); -char *freesat_huffman_decode (const unsigned char *src, size_t size); - -struct sNode -{ - char *Value; - struct sNode *P0; - struct sNode *P1; -}; +time_t LocalTime2UTC(time_t t); +time_t UTC2LocalTime(time_t t); +void GetLocalTimeOffset(void); +void CleanString(unsigned char *String); +void decodeText2(const unsigned char *from, int len, char *buffer, int buffsize); +char *freesat_huffman_decode(const unsigned char *src, size_t size); +void sortSchedules(cSchedules * Schedules, tChannelID channelID); -typedef struct sNode sNodeH; +//struct sNode +//{ +// char *Value; +// struct sNode *P0; +// struct sNode *P1; +//}; +// +//typedef struct sNode sNodeH; -struct hufftab { +template<class T> T REALLOC(T Var, size_t Size) +{ + T p = (T) realloc(Var, Size); + if (!p) free(Var); + return p; +} + +struct hufftab +{ unsigned int value; short bits; char next; }; -#define START '\0' -#define STOP '\0' -#define ESCAPE '\1' - -static struct hufftab *tables[2][128]; -static int table_size[2][128]; -static sNodeH* sky_tables[2]; - - -#define Asprintf(a, b, c...) void( asprintf(a, b, c) < 0 ? esyslog("memory allocation error - %s", b) : void() ) +extern struct hufftab *tables[2][128]; +extern int table_size[2][128]; +//static sNodeH* sky_tables[2]; } #endif /* UTIL_H_ */ |