/************** #4 ******************/ eit.c:441 void cEitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length) eit.c:442 { eit.c:443 cMutexLock MutexLock(&mutex); eit.c:444 if (disableUntil) { eit.c:445 if (time(NULL) > disableUntil) eit.c:446 disableUntil = 0; eit.c:447 else eit.c:448 return; eit.c:449 } eit.c:450 switch (Pid) { eit.c:451 case 0x12: { eit.c:452 if (Tid >= 0x4E && Tid <= 0x6F) eit.c:453 cEIT EIT(sectionSyncerHash, Source(), Tid, Data); // <--- hier /************** #3 ******************/ eit.c: 27 class cEIT : public SI::EIT { eit.c: 28 public: eit.c: 29 cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const u_char *Data); eit.c: 30 }; eit.c: 31 eit.c: 32 cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const u_char *Data) eit.c: 33 :SI::EIT(Data, false) eit.c: 34 { eit.c: 35 if (!CheckCRCAndParse()) eit.c: 36 return; eit.c: 37 int HashId = Tid + (getServiceId() << 8); eit.c: 38 cSectionSyncerEntry *SectionSyncerEntry = SectionSyncerHash.Get(HashId); eit.c: 39 if (!SectionSyncerEntry) { eit.c: 40 SectionSyncerEntry = new cSectionSyncerEntry; eit.c: 41 SectionSyncerHash.Add(SectionSyncerEntry, HashId); eit.c: 42 } eit.c: 43 bool Process = SectionSyncerEntry->Sync(getVersionNumber(), getSectionNumber(), getLastSectionNumber()); eit.c: 44 if (Tid != 0x4E && !Process) // we need to set the 'seen' tag to watch the running status of the present/following event eit.c: 45 return; eit.c: 46 eit.c: 47 time_t Now = time(NULL); eit.c: 48 if (Now < VALID_TIME) eit.c: 49 return; // we need the current time for handling PDC descriptors eit.c: 50 eit.c: 51 cStateKey ChannelsStateKey; eit.c: 52 cChannels *Channels = cChannels::GetChannelsWrite(ChannelsStateKey, 10); eit.c: 53 if (!Channels) { eit.c: 54 SectionSyncerEntry->Repeat(); // let's not miss any section of the EIT eit.c: 55 return; eit.c: 56 } eit.c: 57 tChannelID channelID(Source, getOriginalNetworkId(), getTransportStreamId(), getServiceId()); eit.c: 58 cChannel *Channel = Channels->GetByChannelID(channelID, true); eit.c: 59 if (!Channel || EpgHandlers.IgnoreChannel(Channel)) { eit.c: 60 ChannelsStateKey.Remove(false); eit.c: 61 return; eit.c: 62 } eit.c: 63 eit.c: 64 cStateKey SchedulesStateKey; eit.c: 65 cSchedules *Schedules = cSchedules::GetSchedulesWrite(SchedulesStateKey, 10); eit.c: 66 if (!Schedules) { eit.c: 67 SectionSyncerEntry->Repeat(); // let's not miss any section of the EIT eit.c: 68 ChannelsStateKey.Remove(false); eit.c: 69 return; eit.c: 70 } eit.c: 71 eit.c: 72 if (!EpgHandlers.BeginSegmentTransfer(Channel)) { eit.c: 73 SchedulesStateKey.Remove(false); eit.c: 74 ChannelsStateKey.Remove(false); eit.c: 75 return; eit.c: 76 } eit.c: 77 eit.c: 78 bool ChannelsModified = false; eit.c: 79 bool handledExternally = EpgHandlers.HandledExternally(Channel); eit.c: 80 cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(Channel, true); eit.c: 81 eit.c: 82 bool Empty = true; eit.c: 83 bool Modified = false; eit.c: 84 time_t LingerLimit = Now - Setup.EPGLinger * 60; eit.c: 85 time_t SegmentStart = 0; eit.c: 86 time_t SegmentEnd = 0; eit.c: 87 struct tm t = { 0 }; eit.c: 88 localtime_r(&Now, &t); // this initializes the time zone in 't' eit.c: 89 eit.c: 90 SI::EIT::Event SiEitEvent; eit.c: 91 for (SI::Loop::Iterator it; eventLoop.getNext(SiEitEvent, it); ) { eit.c: 92 if (EpgHandlers.HandleEitEvent(pSchedule, &SiEitEvent, Tid, getVersionNumber())) eit.c: 93 continue; // an EPG handler has done all of the processing eit.c: 94 time_t StartTime = SiEitEvent.getStartTime(); eit.c: 95 int Duration = SiEitEvent.getDuration(); eit.c: 96 // 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. eit.c: 97 if (StartTime == 0 || StartTime > 0 && Duration == 0) eit.c: 98 continue; eit.c: 99 Empty = false; eit.c:100 // Ignore events that ended before the "EPG linger time": eit.c:101 if (StartTime + Duration < LingerLimit) eit.c:102 continue; eit.c:103 if (!SegmentStart) eit.c:104 SegmentStart = StartTime; eit.c:105 SegmentEnd = StartTime + Duration; eit.c:106 cEvent *newEvent = NULL; eit.c:107 cEvent *rEvent = NULL; eit.c:108 cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), StartTime); eit.c:109 if (!pEvent || handledExternally) { eit.c:110 if (handledExternally && !EpgHandlers.IsUpdate(SiEitEvent.getEventId(), StartTime, Tid, getVersionNumber())) eit.c:111 continue; eit.c:112 // If we don't have that event yet, we create a new one. eit.c:113 // Otherwise we copy the information into the existing event anyway, because the data might have changed. eit.c:114 pEvent = newEvent = new cEvent(SiEitEvent.getEventId()); eit.c:115 newEvent->SetStartTime(StartTime); eit.c:116 newEvent->SetDuration(Duration); eit.c:117 if (!handledExternally) eit.c:118 pSchedule->AddEvent(newEvent); eit.c:119 } eit.c:120 else { eit.c:121 // We have found an existing event, either through its event ID or its start time. eit.c:122 pEvent->SetSeen(); eit.c:123 uchar TableID = max(pEvent->TableID(), uchar(0x4E)); // for backwards compatibility, table ids less than 0x4E are treated as if they were "present" eit.c:124 // If the new event has a higher table ID, let's skip it. eit.c:125 // The lower the table ID, the more "current" the information. eit.c:126 if (Tid > TableID) eit.c:127 continue; eit.c:128 EpgHandlers.SetEventID(pEvent, SiEitEvent.getEventId()); // unfortunately some stations use different event ids for the same event in different tables :-( eit.c:129 EpgHandlers.SetStartTime(pEvent, StartTime); eit.c:130 EpgHandlers.SetDuration(pEvent, Duration); eit.c:131 } eit.c:132 if (pEvent->TableID() > 0x4E) // for backwards compatibility, table ids less than 0x4E are never overwritten eit.c:133 pEvent->SetTableID(Tid); eit.c:134 if (Tid == 0x4E) { // we trust only the present/following info on the actual TS eit.c:135 int RunningStatus = SiEitEvent.getRunningStatus(); eit.c:136 #if DBGEIT eit.c:137 if (Process) eit.c:138 dsyslog("channel %d (%s) event %s status %d (raw data from '%s' section)", Channel->Number(), Channel->Name(), *pEvent->ToDescr(), RunningStatus, getSectionNumber() ? "following" : "present"); eit.c:139 #endif eit.c:140 if (RunningStatus >= SI::RunningStatusNotRunning) { eit.c:141 // Workaround for broadcasters who set an event to status "not running" where eit.c:142 // this is inappropriate: eit.c:143 if (RunningStatus != pEvent->RunningStatus()) { // if the running status of the event has changed... eit.c:144 if (RunningStatus == SI::RunningStatusNotRunning) { // ...and the new status is "not running"... eit.c:145 int OverrideStatus = -1; eit.c:146 if (getSectionNumber() == 0) { // ...and if this the "present" event... eit.c:147 if (pEvent->RunningStatus() == SI::RunningStatusPausing) // ...and if the event has already been set to "pausing"... eit.c:148 OverrideStatus = SI::RunningStatusPausing; // ...then we ignore the faulty new status and stay with "pausing" eit.c:149 } eit.c:150 else // ...and if this is the "following" event... eit.c:151 OverrideStatus = SI::RunningStatusUndefined; // ...then we ignore the faulty new status and fall back to "undefined" eit.c:152 if (OverrideStatus >= 0) { eit.c:153 #if DBGEIT eit.c:154 if (Process) eit.c:155 dsyslog("channel %d (%s) event %s status %d (ignored status %d from '%s' section)", Channel->Number(), Channel->Name(), *pEvent->ToDescr(), OverrideStatus, RunningStatus, getSectionNumber() ? "following" : "present"); eit.c:156 #endif eit.c:157 RunningStatus = OverrideStatus; eit.c:158 } eit.c:159 } eit.c:160 } eit.c:161 pSchedule->SetRunningStatus(pEvent, RunningStatus, Channel); eit.c:162 } eit.c:163 if (!Process) eit.c:164 continue; eit.c:165 } eit.c:166 pEvent->SetVersion(getVersionNumber()); eit.c:167 eit.c:168 int LanguagePreferenceShort = -1; eit.c:169 int LanguagePreferenceExt = -1; eit.c:170 bool UseExtendedEventDescriptor = false; eit.c:171 SI::Descriptor *d; eit.c:172 SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL; eit.c:173 SI::ShortEventDescriptor *ShortEventDescriptor = NULL; eit.c:174 cLinkChannels *LinkChannels = NULL; eit.c:175 cComponents *Components = NULL; eit.c:176 for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) { eit.c:177 switch (d->getDescriptorTag()) { eit.c:178 case SI::ExtendedEventDescriptorTag: { eit.c:179 SI::ExtendedEventDescriptor *eed = (SI::ExtendedEventDescriptor *)d; eit.c:180 if (I18nIsPreferredLanguage(Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt) || !ExtendedEventDescriptors) { eit.c:181 delete ExtendedEventDescriptors; eit.c:182 ExtendedEventDescriptors = new SI::ExtendedEventDescriptors; eit.c:183 UseExtendedEventDescriptor = true; eit.c:184 } eit.c:185 if (UseExtendedEventDescriptor) { eit.c:186 if (ExtendedEventDescriptors->Add(eed)) eit.c:187 d = NULL; // so that it is not deleted eit.c:188 } eit.c:189 if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber()) eit.c:190 UseExtendedEventDescriptor = false; eit.c:191 } eit.c:192 break; eit.c:193 case SI::ShortEventDescriptorTag: { eit.c:194 SI::ShortEventDescriptor *sed = (SI::ShortEventDescriptor *)d; eit.c:195 if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort) || !ShortEventDescriptor) { eit.c:196 delete ShortEventDescriptor; eit.c:197 ShortEventDescriptor = sed; eit.c:198 d = NULL; // so that it is not deleted eit.c:199 } eit.c:200 } eit.c:201 break; eit.c:202 case SI::ContentDescriptorTag: { eit.c:203 SI::ContentDescriptor *cd = (SI::ContentDescriptor *)d; eit.c:204 SI::ContentDescriptor::Nibble Nibble; eit.c:205 int NumContents = 0; eit.c:206 uchar Contents[MaxEventContents] = { 0 }; eit.c:207 for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3); ) { eit.c:208 if (NumContents < MaxEventContents) { eit.c:209 Contents[NumContents] = ((Nibble.getContentNibbleLevel1() & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF); eit.c:210 NumContents++; eit.c:211 } eit.c:212 } eit.c:213 EpgHandlers.SetContents(pEvent, Contents); eit.c:214 } eit.c:215 break; eit.c:216 case SI::ParentalRatingDescriptorTag: { eit.c:217 int LanguagePreferenceRating = -1; eit.c:218 SI::ParentalRatingDescriptor *prd = (SI::ParentalRatingDescriptor *)d; eit.c:219 SI::ParentalRatingDescriptor::Rating Rating; eit.c:220 for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3); ) { eit.c:221 if (I18nIsPreferredLanguage(Setup.EPGLanguages, Rating.languageCode, LanguagePreferenceRating)) { eit.c:222 int ParentalRating = (Rating.getRating() & 0xFF); eit.c:223 switch (ParentalRating) { eit.c:224 // values defined by the DVB standard (minimum age = rating + 3 years): eit.c:225 case 0x01 ... 0x0F: ParentalRating += 3; break; eit.c:226 // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?): eit.c:227 case 0x11: ParentalRating = 10; break; eit.c:228 case 0x12: ParentalRating = 12; break; eit.c:229 case 0x13: ParentalRating = 16; break; eit.c:230 default: ParentalRating = 0; eit.c:231 } eit.c:232 EpgHandlers.SetParentalRating(pEvent, ParentalRating); eit.c:233 } eit.c:234 } eit.c:235 } eit.c:236 break; eit.c:237 case SI::PDCDescriptorTag: { eit.c:238 SI::PDCDescriptor *pd = (SI::PDCDescriptor *)d; eit.c:239 t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting eit.c:240 int month = t.tm_mon; eit.c:241 t.tm_mon = pd->getMonth() - 1; eit.c:242 t.tm_mday = pd->getDay(); eit.c:243 t.tm_hour = pd->getHour(); eit.c:244 t.tm_min = pd->getMinute(); eit.c:245 t.tm_sec = 0; eit.c:246 if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan eit.c:247 t.tm_year++; eit.c:248 else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec eit.c:249 t.tm_year--; eit.c:250 time_t vps = mktime(&t); eit.c:251 EpgHandlers.SetVps(pEvent, vps); eit.c:252 } eit.c:253 break; eit.c:254 case SI::TimeShiftedEventDescriptorTag: { eit.c:255 SI::TimeShiftedEventDescriptor *tsed = (SI::TimeShiftedEventDescriptor *)d; eit.c:256 cSchedule *rSchedule = (cSchedule *)Schedules->GetSchedule(tChannelID(Source, Channel->Nid(), Channel->Tid(), tsed->getReferenceServiceId())); eit.c:257 if (!rSchedule) eit.c:258 break; eit.c:259 rEvent = (cEvent *)rSchedule->GetEvent(tsed->getReferenceEventId()); eit.c:260 if (!rEvent) eit.c:261 break; eit.c:262 EpgHandlers.SetTitle(pEvent, rEvent->Title()); eit.c:263 EpgHandlers.SetShortText(pEvent, rEvent->ShortText()); eit.c:264 EpgHandlers.SetDescription(pEvent, rEvent->Description()); eit.c:265 } eit.c:266 break; eit.c:267 case SI::LinkageDescriptorTag: { eit.c:268 SI::LinkageDescriptor *ld = (SI::LinkageDescriptor *)d; eit.c:269 tChannelID linkID(Source, ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId()); eit.c:270 if (ld->getLinkageType() == SI::LinkageTypePremiere) { // Premiere World eit.c:271 bool hit = StartTime <= Now && Now < StartTime + Duration; eit.c:272 if (hit) { eit.c:273 char linkName[ld->privateData.getLength() + 1]; eit.c:274 strn0cpy(linkName, (const char *)ld->privateData.getData(), sizeof(linkName)); eit.c:275 // TODO is there a standard way to determine the character set of this string? eit.c:276 cChannel *link = Channels->GetByChannelID(linkID); eit.c:277 if (link != Channel) { // only link to other channels, not the same one eit.c:278 if (link) { eit.c:279 if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) eit.c:280 ChannelsModified |= link->SetName(linkName, "", ""); eit.c:281 } eit.c:282 else if (Setup.UpdateChannels >= 4) { eit.c:283 cChannel *Transponder = Channel; eit.c:284 if (Channel->Tid() != ld->getTransportStreamId()) eit.c:285 Transponder = Channels->GetByTransponderID(linkID); eit.c:286 link = Channels->NewChannel(Transponder, linkName, "", "", ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId()); eit.c:287 ChannelsModified = true; eit.c:288 //XXX patFilter->Trigger(); eit.c:289 } eit.c:290 if (link) { eit.c:291 if (!LinkChannels) eit.c:292 LinkChannels = new cLinkChannels; eit.c:293 LinkChannels->Add(new cLinkChannel(link)); eit.c:294 } eit.c:295 } eit.c:296 else eit.c:297 ChannelsModified |= Channel->SetPortalName(linkName); eit.c:298 } eit.c:299 } eit.c:300 } eit.c:301 break; eit.c:302 case SI::ComponentDescriptorTag: { eit.c:303 SI::ComponentDescriptor *cd = (SI::ComponentDescriptor *)d; eit.c:304 uchar Stream = cd->getStreamContent(); eit.c:305 uchar Ext = cd->getStreamContentExt(); eit.c:306 uchar Type = cd->getComponentType(); eit.c:307 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 eit.c:308 || (Stream == 9 && Ext < 2)) { // 0x09=HEVC-video, 0x19=AC-4-audio eit.c:309 if (!Components) eit.c:310 Components = new cComponents; eit.c:311 char buffer[Utf8BufSize(256)]; eit.c:312 if (Stream == 9) eit.c:313 Stream |= Ext << 4; eit.c:314 Components->SetComponent(Components->NumComponents(), Stream, Type, I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer))); eit.c:315 } eit.c:316 } eit.c:317 break; eit.c:318 default: ; eit.c:319 } eit.c:320 delete d; eit.c:321 } eit.c:322 eit.c:323 if (!rEvent) { eit.c:324 if (ShortEventDescriptor) { eit.c:325 char buffer[Utf8BufSize(256)]; eit.c:326 EpgHandlers.SetTitle(pEvent, ShortEventDescriptor->name.getText(buffer, sizeof(buffer))); eit.c:327 EpgHandlers.SetShortText(pEvent, ShortEventDescriptor->text.getText(buffer, sizeof(buffer))); eit.c:328 } eit.c:329 else { eit.c:330 EpgHandlers.SetTitle(pEvent, NULL); eit.c:331 EpgHandlers.SetShortText(pEvent, NULL); eit.c:332 } eit.c:333 if (ExtendedEventDescriptors) { eit.c:334 char buffer[Utf8BufSize(ExtendedEventDescriptors->getMaximumTextLength(": ")) + 1]; eit.c:335 EpgHandlers.SetDescription(pEvent, ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": ")); eit.c:336 } eit.c:337 else eit.c:338 EpgHandlers.SetDescription(pEvent, NULL); eit.c:339 } eit.c:340 delete ExtendedEventDescriptors; eit.c:341 delete ShortEventDescriptor; eit.c:342 eit.c:343 EpgHandlers.SetComponents(pEvent, Components); eit.c:344 eit.c:345 EpgHandlers.FixEpgBugs(pEvent); eit.c:346 if (LinkChannels) eit.c:347 ChannelsModified |= Channel->SetLinkChannels(LinkChannels); eit.c:348 Modified = true; eit.c:349 EpgHandlers.HandleEvent(pEvent); eit.c:350 if (handledExternally) eit.c:351 delete pEvent; eit.c:352 } eit.c:353 if (Tid == 0x4E) { eit.c:354 if (Empty && getSectionNumber() == 0) eit.c:355 // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running eit.c:356 pSchedule->ClrRunningStatus(Channel); eit.c:357 pSchedule->SetPresentSeen(); eit.c:358 } eit.c:359 if (Modified) { eit.c:360 EpgHandlers.SortSchedule(pSchedule); // <--- hier /************** #2 ******************/ epg.c:1529 void cEpgHandlers::SortSchedule(cSchedule *Schedule) epg.c:1530 { epg.c:1531 for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { epg.c:1532 if (eh->SortSchedule(Schedule)) epg.c:1533 return; epg.c:1534 } epg.c:1535 Schedule->Sort(); // <--- hier /************** #1 ******************/ epg.c:1053 epg.c:1054 void cSchedule::Sort(void) epg.c:1055 { epg.c:1056 events.Sort(); // <--- hier /************** #0 ******************/ tools.c:2285 tools.c:2286 void cListBase::Sort(void) tools.c:2287 { tools.c:2288 int n = Count(); tools.c:2289 cListObject **a = MALLOC(cListObject *, n); tools.c:2290 if (a == NULL) tools.c:2291 return; tools.c:2292 cListObject *object = objects; tools.c:2293 int i = 0; tools.c:2294 while (object && i < n) { // n == 141 tools.c:2295 a[i++] = object; // a == 0xffffdcfac4a0, object == 0x200000002000005a tools.c:2296 object = object->Next(); // <--- BUMMMMMMM. object ist entweder kein cListObject und hat deswegen keinen member Next(void) oder ist ein ungültiger Pointer.