vdr  2.2.0
eit.c
Go to the documentation of this file.
1 /*
2  * eit.c: EIT section filter
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * Original version (as used in VDR before 1.3.0) written by
8  * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
9  * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
10  *
11  * $Id: eit.c 3.6 2015/02/01 14:55:27 kls Exp $
12  */
13 
14 #include "eit.h"
15 #include <sys/time.h>
16 #include "epg.h"
17 #include "i18n.h"
18 #include "libsi/section.h"
19 #include "libsi/descriptor.h"
20 
21 #define VALID_TIME (31536000 * 2) // two years
22 
23 // --- cEIT ------------------------------------------------------------------
24 
25 class cEIT : public SI::EIT {
26 public:
27  cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bool OnlyRunningStatus = false);
28  };
29 
30 cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bool OnlyRunningStatus)
31 :SI::EIT(Data, false)
32 {
33  if (!CheckCRCAndParse())
34  return;
35 
36  time_t Now = time(NULL);
37  if (Now < VALID_TIME)
38  return; // we need the current time for handling PDC descriptors
39 
40  if (!Channels.Lock(false, 10))
41  return;
43  cChannel *channel = Channels.GetByChannelID(channelID, true);
44  if (!channel || EpgHandlers.IgnoreChannel(channel)) {
45  Channels.Unlock();
46  return;
47  }
48 
49  EpgHandlers.BeginSegmentTransfer(channel, OnlyRunningStatus);
50  bool handledExternally = EpgHandlers.HandledExternally(channel);
51  cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true);
52 
53  bool Empty = true;
54  bool Modified = false;
55  time_t SegmentStart = 0;
56  time_t SegmentEnd = 0;
57  struct tm t = { 0 };
58  localtime_r(&Now, &t); // this initializes the time zone in 't'
59 
60  SI::EIT::Event SiEitEvent;
61  for (SI::Loop::Iterator it; eventLoop.getNext(SiEitEvent, it); ) {
62  if (EpgHandlers.HandleEitEvent(pSchedule, &SiEitEvent, Tid, getVersionNumber()))
63  continue; // an EPG handler has done all of the processing
64  time_t StartTime = SiEitEvent.getStartTime();
65  int Duration = SiEitEvent.getDuration();
66  // 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.
67  if (StartTime == 0 || StartTime > 0 && Duration == 0)
68  continue;
69  Empty = false;
70  if (!SegmentStart)
71  SegmentStart = StartTime;
72  SegmentEnd = StartTime + Duration;
73  cEvent *newEvent = NULL;
74  cEvent *rEvent = NULL;
75  cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), StartTime);
76  if (!pEvent || handledExternally) {
77  if (OnlyRunningStatus)
78  continue;
79  if (handledExternally && !EpgHandlers.IsUpdate(SiEitEvent.getEventId(), StartTime, Tid, getVersionNumber()))
80  continue;
81  // If we don't have that event yet, we create a new one.
82  // Otherwise we copy the information into the existing event anyway, because the data might have changed.
83  pEvent = newEvent = new cEvent(SiEitEvent.getEventId());
84  newEvent->SetStartTime(StartTime);
85  newEvent->SetDuration(Duration);
86  if (!handledExternally)
87  pSchedule->AddEvent(newEvent);
88  }
89  else {
90  // We have found an existing event, either through its event ID or its start time.
91  pEvent->SetSeen();
92  uchar TableID = max(pEvent->TableID(), uchar(0x4E)); // for backwards compatibility, table ids less than 0x4E are treated as if they were "present"
93  // If the new event has a higher table ID, let's skip it.
94  // The lower the table ID, the more "current" the information.
95  if (Tid > TableID)
96  continue;
97  // If the new event comes from the same table and has the same version number
98  // as the existing one, let's skip it to avoid unnecessary work.
99  // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like
100  // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on
101  // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned
102  // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers.
103  else if (Tid == TableID && pEvent->Version() == getVersionNumber())
104  continue;
105  EpgHandlers.SetEventID(pEvent, SiEitEvent.getEventId()); // unfortunately some stations use different event ids for the same event in different tables :-(
106  EpgHandlers.SetStartTime(pEvent, StartTime);
107  EpgHandlers.SetDuration(pEvent, Duration);
108  }
109  if (pEvent->TableID() > 0x4E) // for backwards compatibility, table ids less than 0x4E are never overwritten
110  pEvent->SetTableID(Tid);
111  if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
112  if (SiEitEvent.getRunningStatus() >= SI::RunningStatusNotRunning)
113  pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus(), channel);
114  }
115  if (OnlyRunningStatus) {
116  pEvent->SetVersion(0xFF); // we have already changed the table id above, so set the version to an invalid value to make sure the next full run will be executed
117  continue; // do this before setting the version, so that the full update can be done later
118  }
119  pEvent->SetVersion(getVersionNumber());
120 
121  int LanguagePreferenceShort = -1;
122  int LanguagePreferenceExt = -1;
123  bool UseExtendedEventDescriptor = false;
124  SI::Descriptor *d;
125  SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
126  SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
127  cLinkChannels *LinkChannels = NULL;
128  cComponents *Components = NULL;
129  for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) {
130  switch (d->getDescriptorTag()) {
133  if (I18nIsPreferredLanguage(Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt) || !ExtendedEventDescriptors) {
134  delete ExtendedEventDescriptors;
135  ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
136  UseExtendedEventDescriptor = true;
137  }
138  if (UseExtendedEventDescriptor) {
139  if (ExtendedEventDescriptors->Add(eed))
140  d = NULL; // so that it is not deleted
141  }
142  if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber())
143  UseExtendedEventDescriptor = false;
144  }
145  break;
148  if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort) || !ShortEventDescriptor) {
149  delete ShortEventDescriptor;
150  ShortEventDescriptor = sed;
151  d = NULL; // so that it is not deleted
152  }
153  }
154  break;
158  int NumContents = 0;
159  uchar Contents[MaxEventContents] = { 0 };
160  for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3); ) {
161  if (NumContents < MaxEventContents) {
162  Contents[NumContents] = ((Nibble.getContentNibbleLevel1() & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF);
163  NumContents++;
164  }
165  }
166  EpgHandlers.SetContents(pEvent, Contents);
167  }
168  break;
170  int LanguagePreferenceRating = -1;
173  for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3); ) {
174  if (I18nIsPreferredLanguage(Setup.EPGLanguages, Rating.languageCode, LanguagePreferenceRating)) {
175  int ParentalRating = (Rating.getRating() & 0xFF);
176  switch (ParentalRating) {
177  // values defined by the DVB standard (minimum age = rating + 3 years):
178  case 0x01 ... 0x0F: ParentalRating += 3; break;
179  // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?):
180  case 0x11: ParentalRating = 10; break;
181  case 0x12: ParentalRating = 12; break;
182  case 0x13: ParentalRating = 16; break;
183  default: ParentalRating = 0;
184  }
185  EpgHandlers.SetParentalRating(pEvent, ParentalRating);
186  }
187  }
188  }
189  break;
190  case SI::PDCDescriptorTag: {
192  t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
193  int month = t.tm_mon;
194  t.tm_mon = pd->getMonth() - 1;
195  t.tm_mday = pd->getDay();
196  t.tm_hour = pd->getHour();
197  t.tm_min = pd->getMinute();
198  t.tm_sec = 0;
199  if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan
200  t.tm_year++;
201  else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec
202  t.tm_year--;
203  time_t vps = mktime(&t);
204  EpgHandlers.SetVps(pEvent, vps);
205  }
206  break;
209  cSchedule *rSchedule = (cSchedule *)Schedules->GetSchedule(tChannelID(Source, channel->Nid(), channel->Tid(), tsed->getReferenceServiceId()));
210  if (!rSchedule)
211  break;
212  rEvent = (cEvent *)rSchedule->GetEvent(tsed->getReferenceEventId());
213  if (!rEvent)
214  break;
215  EpgHandlers.SetTitle(pEvent, rEvent->Title());
216  EpgHandlers.SetShortText(pEvent, rEvent->ShortText());
217  EpgHandlers.SetDescription(pEvent, rEvent->Description());
218  }
219  break;
222  tChannelID linkID(Source, ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId());
223  if (ld->getLinkageType() == SI::LinkageTypePremiere) { // Premiere World
224  bool hit = StartTime <= Now && Now < StartTime + Duration;
225  if (hit) {
226  char linkName[ld->privateData.getLength() + 1];
227  strn0cpy(linkName, (const char *)ld->privateData.getData(), sizeof(linkName));
228  // TODO is there a standard way to determine the character set of this string?
229  cChannel *link = Channels.GetByChannelID(linkID);
230  if (link != channel) { // only link to other channels, not the same one
231  //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
232  if (link) {
233  if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
234  link->SetName(linkName, "", "");
235  }
236  else if (Setup.UpdateChannels >= 4) {
237  cChannel *transponder = channel;
238  if (channel->Tid() != ld->getTransportStreamId())
239  transponder = Channels.GetByTransponderID(linkID);
240  link = Channels.NewChannel(transponder, linkName, "", "", ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId());
241  //XXX patFilter->Trigger();
242  }
243  if (link) {
244  if (!LinkChannels)
245  LinkChannels = new cLinkChannels;
246  LinkChannels->Add(new cLinkChannel(link));
247  }
248  }
249  else
250  channel->SetPortalName(linkName);
251  }
252  }
253  }
254  break;
257  uchar Stream = cd->getStreamContent();
258  uchar Type = cd->getComponentType();
259  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
260  if (!Components)
261  Components = new cComponents;
262  char buffer[Utf8BufSize(256)];
263  Components->SetComponent(Components->NumComponents(), Stream, Type, I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer)));
264  }
265  }
266  break;
267  default: ;
268  }
269  delete d;
270  }
271 
272  if (!rEvent) {
273  if (ShortEventDescriptor) {
274  char buffer[Utf8BufSize(256)];
275  EpgHandlers.SetTitle(pEvent, ShortEventDescriptor->name.getText(buffer, sizeof(buffer)));
276  EpgHandlers.SetShortText(pEvent, ShortEventDescriptor->text.getText(buffer, sizeof(buffer)));
277  }
278  else {
279  EpgHandlers.SetTitle(pEvent, NULL);
280  EpgHandlers.SetShortText(pEvent, NULL);
281  }
282  if (ExtendedEventDescriptors) {
283  char buffer[Utf8BufSize(ExtendedEventDescriptors->getMaximumTextLength(": ")) + 1];
284  EpgHandlers.SetDescription(pEvent, ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": "));
285  }
286  else
287  EpgHandlers.SetDescription(pEvent, NULL);
288  }
289  delete ExtendedEventDescriptors;
290  delete ShortEventDescriptor;
291 
292  EpgHandlers.SetComponents(pEvent, Components);
293 
294  EpgHandlers.FixEpgBugs(pEvent);
295  if (LinkChannels)
296  channel->SetLinkChannels(LinkChannels);
297  Modified = true;
298  EpgHandlers.HandleEvent(pEvent);
299  if (handledExternally)
300  delete pEvent;
301  }
302  if (Tid == 0x4E) {
303  if (Empty && getSectionNumber() == 0)
304  // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
305  pSchedule->ClrRunningStatus(channel);
306  pSchedule->SetPresentSeen();
307  }
308  if (Modified && !OnlyRunningStatus) {
309  EpgHandlers.SortSchedule(pSchedule);
310  EpgHandlers.DropOutdated(pSchedule, SegmentStart, SegmentEnd, Tid, getVersionNumber());
311  Schedules->SetModified(pSchedule);
312  }
313  Channels.Unlock();
314  EpgHandlers.EndSegmentTransfer(Modified, OnlyRunningStatus);
315 }
316 
317 // --- cTDT ------------------------------------------------------------------
318 
319 #define MAX_TIME_DIFF 1 // number of seconds the local time may differ from dvb time before making any corrections
320 #define MAX_ADJ_DIFF 10 // number of seconds the local time may differ from dvb time to allow smooth adjustment
321 #define ADJ_DELTA 300 // number of seconds between calls for smooth time adjustment
322 
323 class cTDT : public SI::TDT {
324 private:
325  static cMutex mutex;
326  static time_t lastAdj;
327 public:
328  cTDT(const u_char *Data);
329  };
330 
332 time_t cTDT::lastAdj = 0;
333 
334 cTDT::cTDT(const u_char *Data)
335 :SI::TDT(Data, false)
336 {
337  CheckParse();
338 
339  time_t dvbtim = getTime();
340  time_t loctim = time(NULL);
341 
342  int diff = dvbtim - loctim;
343  if (abs(diff) > MAX_TIME_DIFF) {
344  mutex.Lock();
345  if (abs(diff) > MAX_ADJ_DIFF) {
346  if (stime(&dvbtim) == 0)
347  isyslog("system time changed from %s (%ld) to %s (%ld)", *TimeToString(loctim), loctim, *TimeToString(dvbtim), dvbtim);
348  else
349  esyslog("ERROR while setting system time: %m");
350  }
351  else if (time(NULL) - lastAdj > ADJ_DELTA) {
352  lastAdj = time(NULL);
353  timeval delta;
354  delta.tv_sec = diff;
355  delta.tv_usec = 0;
356  if (adjtime(&delta, NULL) == 0)
357  isyslog("system time adjustment initiated from %s (%ld) to %s (%ld)", *TimeToString(loctim), loctim, *TimeToString(dvbtim), dvbtim);
358  else
359  esyslog("ERROR while adjusting system time: %m");
360  }
361  mutex.Unlock();
362  }
363 }
364 
365 // --- cEitFilter ------------------------------------------------------------
366 
367 time_t cEitFilter::disableUntil = 0;
368 
370 {
371  Set(0x12, 0x40, 0xC0); // event info now&next actual/other TS (0x4E/0x4F), future actual/other TS (0x5X/0x6X)
372  Set(0x14, 0x70); // TDT
373 }
374 
376 {
377  disableUntil = Time;
378 }
379 
380 void cEitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
381 {
382  if (disableUntil) {
383  if (time(NULL) > disableUntil)
384  disableUntil = 0;
385  else
386  return;
387  }
388  switch (Pid) {
389  case 0x12: {
390  if (Tid >= 0x4E && Tid <= 0x6F) {
391  cSchedulesLock SchedulesLock(true, 10);
392  cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
393  if (Schedules)
394  cEIT EIT(Schedules, Source(), Tid, Data);
395  else {
396  // If we don't get a write lock, let's at least get a read lock, so
397  // that we can set the running status and 'seen' timestamp (well, actually
398  // with a read lock we shouldn't be doing that, but it's only integers that
399  // get changed, so it should be ok)
400  cSchedulesLock SchedulesLock;
401  cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
402  if (Schedules)
403  cEIT EIT(Schedules, Source(), Tid, Data, true);
404  }
405  }
406  }
407  break;
408  case 0x14: {
410  cTDT TDT(Data);
411  }
412  break;
413  default: ;
414  }
415 }
int getOriginalNetworkId() const
Definition: descriptor.c:763
unsigned char uchar
Definition: tools.h:30
int Tid(void) const
Definition: channels.h:193
Definition: epg.h:71
void Lock(void)
Definition: thread.c:191
void SetContents(cEvent *Event, uchar *Contents)
Definition: epg.c:1455
StructureLoop< Nibble > nibbleLoop
Definition: descriptor.h:102
StructureLoop< Rating > ratingLoop
Definition: descriptor.h:119
cChannels Channels
Definition: channels.c:864
bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version)
Definition: epg.c:1392
void SetComponent(int Index, const char *s)
Definition: epg.c:78
char * getText()
Definition: si.c:222
cEpgHandlers EpgHandlers
Definition: epg.c:1381
void SetDescription(cEvent *Event, const char *Description)
Definition: epg.c:1446
void SetStartTime(time_t StartTime)
Definition: epg.c:212
void SetDuration(int Duration)
Definition: epg.c:223
StructureLoop< Event > eventLoop
Definition: section.h:182
int Nid(void) const
Definition: channels.h:192
void SetTableID(uchar TableID)
Definition: epg.c:163
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2014
Definition: eit.c:25
static void SetDisableUntil(time_t Time)
Definition: eit.c:375
void DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version)
Definition: epg.c:1535
int getTransportStreamId() const
Definition: descriptor.c:759
void SetParentalRating(cEvent *Event, int ParentalRating)
Definition: epg.c:1464
#define esyslog(a...)
Definition: tools.h:34
void SetTitle(cEvent *Event, const char *Title)
Definition: epg.c:1428
time_t getDuration() const
Definition: section.c:201
void SetEventID(cEvent *Event, tEventID EventID)
Definition: epg.c:1419
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
#define ADJ_DELTA
Definition: eit.c:321
int EPGLanguages[I18N_MAX_LANGUAGES+1]
Definition: config.h:292
T max(T a, T b)
Definition: tools.h:55
DescriptorTag getDescriptorTag() const
Definition: si.c:100
#define MAX_ADJ_DIFF
Definition: eit.c:320
int getServiceId() const
Definition: section.c:160
EIT()
Definition: section.h:153
bool HandledExternally(const cChannel *Channel)
Definition: epg.c:1401
static const cSchedules * Schedules(cSchedulesLock &SchedulesLock)
Caller must provide a cSchedulesLock which has to survive the entire time the returned cSchedules is ...
Definition: epg.c:1201
void SetSeen(void)
Definition: epg.c:233
void ClrRunningStatus(cChannel *Channel=NULL)
Definition: epg.c:992
void Unlock(void)
Definition: thread.c:170
int TimeTransponder
Definition: config.h:283
Definition: descriptor.c:16
void HandleEvent(cEvent *Event)
Definition: epg.c:1518
cString TimeToString(time_t t)
Converts the given time to a string of the form "www mmm dd hh:mm:ss yyyy".
Definition: tools.c:1156
int getSectionNumber() const
Definition: si.c:88
void SetStartTime(cEvent *Event, time_t StartTime)
Definition: epg.c:1473
#define VALID_TIME
Definition: eit.c:21
Definition: eit.c:323
void CheckParse()
Definition: util.c:182
cChannel * NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid=0)
Definition: channels.c:1115
void SetName(const char *Name, const char *ShortName, const char *Provider)
Definition: channels.c:261
int getMinute() const
Definition: descriptor.c:831
uchar TableID(void) const
Definition: epg.h:97
static cMutex mutex
Definition: eit.c:325
#define ISTRANSPONDER(f1, f2)
Definition: channels.h:18
int getContentNibbleLevel2() const
Definition: descriptor.c:288
const cEvent * GetEvent(tEventID EventID, time_t StartTime=0) const
Definition: epg.c:951
void SetDuration(cEvent *Event, int Duration)
Definition: epg.c:1482
bool Add(GroupDescriptor *d)
Definition: si.c:201
static time_t disableUntil
Definition: eit.h:17
int getOriginalNetworkId() const
Definition: section.c:168
int TimeSource
Definition: config.h:282
cSetup Setup
Definition: config.c:373
void FixEpgBugs(cEvent *Event)
Definition: epg.c:1509
#define MAX_TIME_DIFF
Definition: eit.c:319
bool Lock(bool Write, int TimeoutMs=0)
Definition: thread.c:155
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
Processes the data delivered to this filter.
Definition: eit.c:380
void SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel=NULL)
Definition: epg.c:975
void SortSchedule(cSchedule *Schedule)
Definition: epg.c:1526
Definition: thread.h:63
LinkageType getLinkageType() const
Definition: descriptor.c:771
cEitFilter(void)
Definition: eit.c:369
RunningStatus getRunningStatus() const
Definition: section.c:237
int getContentNibbleLevel1() const
Definition: descriptor.c:284
static void SetModified(cSchedule *Schedule)
Definition: epg.c:1213
cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bool OnlyRunningStatus=false)
Definition: eit.c:30
cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false)
Definition: channels.c:1023
void SetPresentSeen(void)
Definition: epg.h:159
time_t getStartTime() const
Definition: section.c:197
cEvent * AddEvent(cEvent *Event)
Definition: epg.c:889
const char * Title(void) const
Definition: epg.h:100
bool CheckCRCAndParse()
Definition: si.c:65
void SetVps(cEvent *Event, time_t Vps)
Definition: epg.c:1491
void BeginSegmentTransfer(const cChannel *Channel, bool OnlyRunningStatus)
Definition: epg.c:1544
bool IgnoreChannel(const cChannel *Channel)
Definition: epg.c:1383
int SetSystemTime
Definition: config.h:281
const cSchedule * GetSchedule(tChannelID ChannelID) const
Definition: epg.c:1328
int getHour() const
Definition: descriptor.c:827
int getMonth() const
Definition: descriptor.c:823
bool I18nIsPreferredLanguage(int *PreferredLanguages, const char *LanguageCode, int &OldPreference, int *Position)
Checks the given LanguageCode (which may be something like "eng" or "eng+deu") against the PreferredL...
Definition: i18n.c:269
void SetLinkChannels(cLinkChannels *LinkChannels)
Definition: channels.c:481
int getVersionNumber() const
Definition: si.c:84
Definition: epg.h:143
int getTransportStreamId() const
Definition: section.c:164
unsigned char u_char
Definition: headers.h:24
int getReferenceServiceId() const
Definition: descriptor.c:267
int UpdateChannels
Definition: config.h:314
int getStreamContent() const
Definition: descriptor.c:562
int NumComponents(void) const
Definition: epg.h:59
#define isyslog(a...)
Definition: tools.h:35
TDT()
Definition: section.h:197
static time_t lastAdj
Definition: eit.c:326
const char * Description(void) const
Definition: epg.h:102
int getLength() const
Definition: util.h:58
void SetVersion(uchar Version)
Definition: epg.c:168
cChannel * GetByTransponderID(tChannelID ChannelID)
Definition: channels.c:1052
char * getText(const char *separation1="\t", const char *separation2="\n")
Definition: descriptor.c:86
int getDay() const
Definition: descriptor.c:819
void SetComponents(cEvent *Event, cComponents *Components)
Definition: epg.c:1500
void SetShortText(cEvent *Event, const char *ShortText)
Definition: epg.c:1437
const char * ShortText(void) const
Definition: epg.h:101
void SetPortalName(const char *PortalName)
Definition: channels.c:287
bool IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version)
Definition: epg.c:1410
const char * I18nNormalizeLanguageCode(const char *Code)
Returns a 3 letter language code that may not be zero terminated.
Definition: i18n.c:238
int getComponentType() const
Definition: descriptor.c:566
int getServiceId() const
Definition: descriptor.c:767
cTDT(const u_char *Data)
Definition: eit.c:334
const unsigned char * getData() const
Definition: util.h:51
DescriptorLoop eventDescriptors
Definition: section.h:170
uchar Version(void) const
Definition: epg.h:98
int getEventId() const
Definition: section.c:205
Descriptor * getNext(Iterator &it)
Definition: si.c:112
void EndSegmentTransfer(bool Modified, bool OnlyRunningStatus)
Definition: epg.c:1552
time_t getTime() const
Definition: section.c:254
#define Utf8BufSize(s)
Definition: tools.h:133
int getMaximumTextLength(const char *separation1="\t", const char *separation2="\n")
Definition: descriptor.c:81
void Unlock(void)
Definition: thread.c:197