20 #define RUNNINGSTATUSTIMEOUT 30 // seconds before the running status is considered unknown 21 #define EPGDATAWRITEDELTA 600 // seconds between writing the epg.data file 34 unsigned int Stream, Type;
55 for (
int i = 0; i < numComponents; i++)
62 if (Index >= numComponents) {
65 int n = numComponents;
66 numComponents = Index;
67 components = NewBuffer;
68 memset(&components[n], 0,
sizeof(
tComponent) * (numComponents - n));
71 esyslog(
"ERROR: out of memory");
81 components[Index].FromString(s);
100 for (
int i = 0; i < numComponents; i++) {
101 if (components[i].
stream == Stream && (
103 Stream == 2 && (components[i].
type < 5) == (Type < 5)
106 return &components[i];
125 memset(contents, 0,
sizeof(contents));
149 return schedule ? schedule->ChannelID() :
tChannelID();
154 if (eventID != EventID) {
156 schedule->UnhashEvent(
this);
159 schedule->HashEvent(
this);
198 components = Components;
204 contents[i] = Contents[i];
209 parentalRating = ParentalRating;
214 if (startTime != StartTime) {
216 schedule->UnhashEvent(
this);
217 startTime = StartTime;
219 schedule->HashEvent(
this);
240 char vpsbuf[64] =
"";
242 sprintf(vpsbuf,
"(VPS: %s) ", *GetVpsString());
243 return cString::sprintf(
"%s %s-%s %s'%s'", *GetDateString(), *GetTimeString(), *GetEndTimeString(), vpsbuf, Title());
249 if (t->Event() ==
this)
262 switch (Content & 0xF0) {
264 switch (Content & 0x0F) {
266 case 0x00:
return tr(
"Content$Movie/Drama");
267 case 0x01:
return tr(
"Content$Detective/Thriller");
268 case 0x02:
return tr(
"Content$Adventure/Western/War");
269 case 0x03:
return tr(
"Content$Science Fiction/Fantasy/Horror");
270 case 0x04:
return tr(
"Content$Comedy");
271 case 0x05:
return tr(
"Content$Soap/Melodrama/Folkloric");
272 case 0x06:
return tr(
"Content$Romance");
273 case 0x07:
return tr(
"Content$Serious/Classical/Religious/Historical Movie/Drama");
274 case 0x08:
return tr(
"Content$Adult Movie/Drama");
278 switch (Content & 0x0F) {
280 case 0x00:
return tr(
"Content$News/Current Affairs");
281 case 0x01:
return tr(
"Content$News/Weather Report");
282 case 0x02:
return tr(
"Content$News Magazine");
283 case 0x03:
return tr(
"Content$Documentary");
284 case 0x04:
return tr(
"Content$Discussion/Inverview/Debate");
288 switch (Content & 0x0F) {
290 case 0x00:
return tr(
"Content$Show/Game Show");
291 case 0x01:
return tr(
"Content$Game Show/Quiz/Contest");
292 case 0x02:
return tr(
"Content$Variety Show");
293 case 0x03:
return tr(
"Content$Talk Show");
297 switch (Content & 0x0F) {
299 case 0x00:
return tr(
"Content$Sports");
300 case 0x01:
return tr(
"Content$Special Event");
301 case 0x02:
return tr(
"Content$Sport Magazine");
302 case 0x03:
return tr(
"Content$Football/Soccer");
303 case 0x04:
return tr(
"Content$Tennis/Squash");
304 case 0x05:
return tr(
"Content$Team Sports");
305 case 0x06:
return tr(
"Content$Athletics");
306 case 0x07:
return tr(
"Content$Motor Sport");
307 case 0x08:
return tr(
"Content$Water Sport");
308 case 0x09:
return tr(
"Content$Winter Sports");
309 case 0x0A:
return tr(
"Content$Equestrian");
310 case 0x0B:
return tr(
"Content$Martial Sports");
314 switch (Content & 0x0F) {
316 case 0x00:
return tr(
"Content$Children's/Youth Programme");
317 case 0x01:
return tr(
"Content$Pre-school Children's Programme");
318 case 0x02:
return tr(
"Content$Entertainment Programme for 6 to 14");
319 case 0x03:
return tr(
"Content$Entertainment Programme for 10 to 16");
320 case 0x04:
return tr(
"Content$Informational/Educational/School Programme");
321 case 0x05:
return tr(
"Content$Cartoons/Puppets");
325 switch (Content & 0x0F) {
327 case 0x00:
return tr(
"Content$Music/Ballet/Dance");
328 case 0x01:
return tr(
"Content$Rock/Pop");
329 case 0x02:
return tr(
"Content$Serious/Classical Music");
330 case 0x03:
return tr(
"Content$Folk/Tradional Music");
331 case 0x04:
return tr(
"Content$Jazz");
332 case 0x05:
return tr(
"Content$Musical/Opera");
333 case 0x06:
return tr(
"Content$Ballet");
337 switch (Content & 0x0F) {
339 case 0x00:
return tr(
"Content$Arts/Culture");
340 case 0x01:
return tr(
"Content$Performing Arts");
341 case 0x02:
return tr(
"Content$Fine Arts");
342 case 0x03:
return tr(
"Content$Religion");
343 case 0x04:
return tr(
"Content$Popular Culture/Traditional Arts");
344 case 0x05:
return tr(
"Content$Literature");
345 case 0x06:
return tr(
"Content$Film/Cinema");
346 case 0x07:
return tr(
"Content$Experimental Film/Video");
347 case 0x08:
return tr(
"Content$Broadcasting/Press");
348 case 0x09:
return tr(
"Content$New Media");
349 case 0x0A:
return tr(
"Content$Arts/Culture Magazine");
350 case 0x0B:
return tr(
"Content$Fashion");
354 switch (Content & 0x0F) {
356 case 0x00:
return tr(
"Content$Social/Political/Economics");
357 case 0x01:
return tr(
"Content$Magazine/Report/Documentary");
358 case 0x02:
return tr(
"Content$Economics/Social Advisory");
359 case 0x03:
return tr(
"Content$Remarkable People");
363 switch (Content & 0x0F) {
365 case 0x00:
return tr(
"Content$Education/Science/Factual");
366 case 0x01:
return tr(
"Content$Nature/Animals/Environment");
367 case 0x02:
return tr(
"Content$Technology/Natural Sciences");
368 case 0x03:
return tr(
"Content$Medicine/Physiology/Psychology");
369 case 0x04:
return tr(
"Content$Foreign Countries/Expeditions");
370 case 0x05:
return tr(
"Content$Social/Spiritual Sciences");
371 case 0x06:
return tr(
"Content$Further Education");
372 case 0x07:
return tr(
"Content$Languages");
376 switch (Content & 0x0F) {
378 case 0x00:
return tr(
"Content$Leisure/Hobbies");
379 case 0x01:
return tr(
"Content$Tourism/Travel");
380 case 0x02:
return tr(
"Content$Handicraft");
381 case 0x03:
return tr(
"Content$Motoring");
382 case 0x04:
return tr(
"Content$Fitness & Health");
383 case 0x05:
return tr(
"Content$Cooking");
384 case 0x06:
return tr(
"Content$Advertisement/Shopping");
385 case 0x07:
return tr(
"Content$Gardening");
389 switch (Content & 0x0F) {
390 case 0x00:
return tr(
"Content$Original Language");
391 case 0x01:
return tr(
"Content$Black & White");
392 case 0x02:
return tr(
"Content$Unpublished");
393 case 0x03:
return tr(
"Content$Live Broadcast");
428 strftime(buf,
sizeof(buf),
"%d.%m. %R", localtime_r(&vps, &tm_r));
434 if (InfoOnly || startTime + duration +
Setup.
EPGLinger * 60 >= time(NULL)) {
435 fprintf(f,
"%sE %u %ld %d %X %X\n", Prefix, eventID, startTime, duration, tableID, version);
437 fprintf(f,
"%sT %s\n", Prefix, title);
439 fprintf(f,
"%sS %s\n", Prefix, shortText);
446 fprintf(f,
"%sG", Prefix);
447 for (
int i = 0; Contents(i); i++)
448 fprintf(f,
" %02X", Contents(i));
452 fprintf(f,
"%sR %d\n", Prefix, parentalRating);
454 for (
int i = 0; i < components->NumComponents(); i++) {
456 fprintf(f,
"%sX %s\n", Prefix, *p->
ToString());
460 fprintf(f,
"%sV %ld\n", Prefix, vps);
462 fprintf(f,
"%se\n", Prefix);
470 case 'T': SetTitle(t);
472 case 'S': SetShortText(t);
478 memset(contents, 0,
sizeof(contents));
481 int c = strtol(t, &tail, 16);
482 if (0x00 < c && c <= 0xFF) {
491 case 'R': SetParentalRating(atoi(t));
493 case 'X':
if (!components)
495 components->
SetComponent(components->NumComponents(), t);
497 case 'V': SetVps(atoi(t));
499 default:
esyslog(
"ERROR: unexpected tag while reading EPG data: %s", s);
512 while ((s = ReadLine.
Read(f)) != NULL) {
516 case 'E':
if (!Event) {
517 unsigned int EventID;
520 unsigned int TableID = 0;
521 unsigned int Version = 0xFF;
522 int n = sscanf(t,
"%u %ld %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version);
523 if (n >= 3 && n <= 5) {
529 Event = newEvent =
new cEvent(EventID);
542 case 'e':
if (Event && !Event->
Title())
548 default:
if (Event && !Event->
Parse(s)) {
549 esyslog(
"ERROR: EPG data problem in line %d", line);
554 esyslog(
"ERROR: unexpected end of file while reading EPG data");
559 #define MAXEPGBUGFIXSTATS 13 560 #define MAXEPGBUGFIXCHANS 100 576 for (; i < p->
n; i++) {
588 static time_t LastReport = 0;
589 time_t now = time(NULL);
590 if (now - LastReport > 3600 || Force) {
593 struct tm *ptm = localtime_r(&now, &tm_r);
594 if (ptm->tm_hour != 5)
599 bool GotHits =
false;
602 const char *delim =
" ";
605 bool PrintedStats =
false;
608 for (
int c = 0; c < p->
n; c++) {
612 dsyslog(
"=====================");
613 dsyslog(
"EPG bugfix statistics");
614 dsyslog(
"=====================");
615 dsyslog(
"IF SOMEBODY WHO IS IN CHARGE OF THE EPG DATA FOR ONE OF THE LISTED");
616 dsyslog(
"CHANNELS READS THIS: PLEASE TAKE A LOOK AT THE FUNCTION cEvent::FixEpgBugs()");
617 dsyslog(
"IN VDR/epg.c TO LEARN WHAT'S WRONG WITH YOUR DATA, AND FIX IT!");
618 dsyslog(
"=====================");
623 q += snprintf(q,
sizeof(buffer) - (q - buffer),
"%-3d %-4d", i, p->
hits);
626 q += snprintf(q,
sizeof(buffer) - (q - buffer),
"%s%s", delim, channel->
Name());
628 if (q - buffer > 80) {
629 q += snprintf(q,
sizeof(buffer) - (q - buffer),
"%s...", delim);
640 dsyslog(
"=====================");
651 if (l == 2 && *p == 0xC2)
653 if (*p == 0x86 || *p == 0x87) {
654 memmove(s, p + 1, len - l + 1);
684 if ((shortText == NULL) != (
description == NULL)) {
687 const char *delim =
"\".";
688 char *e = strstr(p + 1, delim);
691 char *s = strdup(p + 1);
692 char *d = strdup(e + strlen(delim));
710 if (*shortText ==
' ') {
711 memmove(shortText, shortText + 1, strlen(shortText));
723 if (shortText && strcmp(title, shortText) == 0) {
735 if (shortText && *shortText ==
'"') {
736 int l = strlen(shortText);
737 if (l > 2 && (shortText[l - 1] ==
'"' || (shortText[l - 1] ==
'.' && shortText[l - 2] ==
'"'))) {
738 memmove(shortText, shortText + 1, l);
739 char *p = strrchr(shortText,
'"');
757 #define MAX_USEFUL_EPISODE_LENGTH 40 798 for (
int i = 0; i < components->NumComponents(); i++) {
821 case 0x08: p->
description = strdup(
">16:9");
break;
823 case 0x0D: p->
description = strdup(
"HD 4:3");
break;
827 case 0x0F: p->
description = strdup(
"HD 16:9");
break;
829 case 0x10: p->
description = strdup(
"HD >16:9");
break;
848 case 0x05: p->
description = strdup(
"Dolby Digital");
break;
867 for (
int i = 0; i < components->NumComponents(); i++) {
883 channelID = ChannelID;
909 eventsHashID.Add(Event, Event->
EventID());
911 eventsHashStartTime.Add(Event, Event->
StartTime());
916 eventsHashID.Del(Event, Event->
EventID());
918 eventsHashStartTime.Del(Event, Event->
StartTime());
924 time_t now = time(NULL);
925 for (
cEvent *p = events.First(); p; p = events.
Next(p)) {
926 if (p->StartTime() <= now)
928 else if (p->StartTime() > now + 3600)
938 const cEvent *p = GetPresentEvent();
942 time_t now = time(NULL);
943 for (p = events.First(); p; p = events.
Next(p)) {
956 return eventsHashStartTime.Get(StartTime);
958 return eventsHashID.Get(EventID);
964 time_t delta = INT_MAX;
965 for (
cEvent *p = events.First(); p; p = events.
Next(p)) {
967 if (dt >= 0 && dt < delta && p->EndTime() >= Time) {
978 for (
cEvent *p = events.First(); p; p = events.
Next(p)) {
981 p->SetRunningStatus(RunningStatus, Channel);
995 for (
cEvent *p = events.First(); p; p = events.
Next(p)) {
1007 for (
cEvent *p = events.First(); p; p = events.
Next(p))
1008 p->SetVersion(0xFF);
1016 for (
cEvent *p = events.First(); p; p = events.
Next(p)) {
1026 if (SegmentStart > 0 && SegmentEnd > 0) {
1027 for (
cEvent *p = events.First(); p; p = events.
Next(p)) {
1028 if (p->EndTime() > SegmentStart) {
1029 if (p->StartTime() < SegmentEnd) {
1031 if (p->TableID() > TableID || p->TableID() == TableID && p->Version() != Version) {
1037 if (hasRunning && p->IsRunning())
1053 Cleanup(time(NULL));
1059 while ((Event = events.First()) != NULL) {
1075 for (p = events.First(); p; p = events.Next(p))
1080 if ((p = GetPresentEvent()) != NULL)
1085 if ((p = GetFollowingEvent()) != NULL)
1090 if ((p = GetEventAround(AtTime)) != NULL)
1094 default:
esyslog(
"ERROR: unknown DumpMode %d (%s %d)", DumpMode, __FUNCTION__, __LINE__);
1096 fprintf(f,
"%sc\n", Prefix);
1105 while ((s = ReadLine.
Read(f)) != NULL) {
1108 char *p = strchr(s,
' ');
1113 if (channelID.
Valid()) {
1123 esyslog(
"ERROR: invalid channel ID: %s", s);
1129 esyslog(
"ERROR: unexpected tag while reading EPG data: %s", s);
1145 virtual void Action(
void);
1153 :
cThread(
"epg data writer", true)
1170 time_t now = time(NULL);
1203 return SchedulesLock.
Locked() ? &schedules : NULL;
1208 free(epgDataFileName);
1209 epgDataFileName = FileName ? strdup(FileName) : NULL;
1210 EpgDataWriter.
SetDump(epgDataFileName != NULL);
1216 modified = time(NULL);
1223 time_t now = time(NULL);
1227 else if (!EpgDataWriter.
Active())
1228 EpgDataWriter.
Start();
1249 Timer->SetEvent(NULL);
1274 p->Dump(f, Prefix, DumpMode, AtTime);
1289 bool OwnFile = f == NULL;
1291 if (epgDataFileName && access(epgDataFileName, R_OK) == 0) {
1292 dsyslog(
"reading EPG data from %s", epgDataFileName);
1293 if ((f = fopen(epgDataFileName,
"r")) == NULL) {
1331 for (
cSchedule *p = First(); p; p = Next(p)) {
1332 if (p->ChannelID() == ChannelID)
1346 Channel->
schedule = &DummySchedule;
1347 if (Channel->
schedule == &DummySchedule && AddIfMissing) {
1385 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1386 if (eh->IgnoreChannel(Channel))
1394 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1395 if (eh->HandleEitEvent(Schedule, EitEvent, TableID, Version))
1403 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1404 if (eh->HandledExternally(Channel))
1412 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1413 if (eh->IsUpdate(EventID, StartTime, TableID, Version))
1421 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1422 if (eh->SetEventID(Event, EventID))
1430 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1431 if (eh->SetTitle(Event, Title))
1439 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1440 if (eh->SetShortText(Event, ShortText))
1448 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1449 if (eh->SetDescription(Event, Description))
1457 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1458 if (eh->SetContents(Event, Contents))
1466 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1467 if (eh->SetParentalRating(Event, ParentalRating))
1475 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1476 if (eh->SetStartTime(Event, StartTime))
1484 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1485 if (eh->SetDuration(Event, Duration))
1493 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1494 if (eh->SetVps(Event, Vps))
1502 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1503 if (eh->SetComponents(Event, Components))
1511 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1512 if (eh->FixEpgBugs(Event))
1520 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1521 if (eh->HandleEvent(Event))
1528 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1529 if (eh->SortSchedule(Schedule))
1537 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1538 if (eh->DropOutdated(Schedule, SegmentStart, SegmentEnd, TableID, Version))
1541 Schedule->
DropOutdated(SegmentStart, SegmentEnd, TableID, Version);
1546 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1547 if (eh->BeginSegmentTransfer(Channel, OnlyRunningStatus))
1554 for (
cEpgHandler *eh = First(); eh; eh = Next(eh)) {
1555 if (eh->EndSegmentTransfer(Modified, OnlyRunningStatus))
const cEvent * GetPresentEvent(void) const
tChannelID channelIDs[MAXEPGBUGFIXCHANS]
void SetContents(uchar *Contents)
void SetContents(cEvent *Event, uchar *Contents)
tComponent * GetComponent(int Index, uchar Stream, uchar Type)
static tChannelID FromString(const char *s)
bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version)
time_t EndTime(void) const
void SetComponent(int Index, const char *s)
static void ResetVersions(void)
#define MAX_USEFUL_EPISODE_LENGTH
void SetDescription(cEvent *Event, const char *Description)
void SetStartTime(time_t StartTime)
cSchedule(tChannelID ChannelID)
void SetDuration(int Duration)
void SetTableID(uchar TableID)
void Add(cListObject *Object, cListObject *After=NULL)
cString ToDescr(void) const
char language[MAXLANGCODE2]
static const char * ContentToString(uchar Content)
cString GetParentalRatingString(void) const
static cString sprintf(const char *fmt,...) __attribute__((format(printf
void ReportEpgBugFixStats(bool Force)
static bool Read(FILE *f, cSchedule *Schedule)
void DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version)
void SetParentalRating(cEvent *Event, int ParentalRating)
void SetTitle(cEvent *Event, const char *Title)
void SetEventID(cEvent *Event, tEventID EventID)
time_t StartTime(void) const
bool HandledExternally(const cChannel *Channel)
static bool Dump(FILE *f=NULL, const char *Prefix="", eDumpMode DumpMode=dmAll, time_t AtTime=0)
void SetShortText(const char *ShortText)
const cSchedule * schedule
static void SetEpgDataFileName(const char *FileName)
static const cSchedules * Schedules(cSchedulesLock &SchedulesLock)
Caller must provide a cSchedulesLock which has to survive the entire time the returned cSchedules is ...
void ClrRunningStatus(cChannel *Channel=NULL)
void SetComponents(cComponents *Components)
void HandleEvent(cEvent *Event)
cString GetVpsString(void) const
void SetTitle(const char *Title)
void SetStartTime(cEvent *Event, time_t StartTime)
const char * Name(void) const
static void EpgBugFixStat(int Number, tChannelID ChannelID)
T * Next(const T *object) const
static cEpgDataWriter EpgDataWriter
static void StripControlCharacters(char *s)
#define MAXEPGBUGFIXSTATS
cListObject * Next(void) const
static bool Read(FILE *f, cSchedules *Schedules)
tChannelID ChannelID(void) const
void SetRunningStatus(int RunningStatus, cChannel *Channel=NULL)
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
const cEvent * GetEvent(tEventID EventID, time_t StartTime=0) const
void SetDuration(cEvent *Event, int Duration)
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
const cEvent * GetEventAround(time_t Time) const
static bool Read(FILE *f=NULL)
static char * epgDataFileName
void FixEpgBugs(cEvent *Event)
static void Cleanup(bool Force=false)
static int Utf8CharLen(const char *s)
tChannelID GetChannelID(void) const
bool Lock(bool Write, int TimeoutMs=0)
tEventID EventID(void) const
void SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel=NULL)
void SortSchedule(cSchedule *Schedule)
tEpgBugFixStats EpgBugFixStats[MAXEPGBUGFIXSTATS]
bool FromString(const char *s)
static void SetModified(cSchedule *Schedule)
cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false)
cEvent * AddEvent(cEvent *Event)
bool HasTimer(void) const
const char * Title(void) const
void SetVps(cEvent *Event, time_t Vps)
void BeginSegmentTransfer(const cChannel *Channel, bool OnlyRunningStatus)
bool IgnoreChannel(const cChannel *Channel)
void HashEvent(cEvent *Event)
cString GetEndTimeString(void) const
const cSchedule * GetSchedule(tChannelID ChannelID) const
void DropOutdated(time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version)
void Del(cListObject *Object, bool DeleteObject=true)
cString ToString(void) const
void SetParentalRating(int ParentalRating)
void SetDescription(const char *Description)
bool Active(void)
Checks whether the thread is still alive.
void Dump(FILE *f, const char *Prefix="", bool InfoOnly=false) const
#define MAXEPGBUGFIXCHANS
static cSchedules schedules
cEpgHandler(void)
Constructs a new EPG handler and adds it to the list of EPG handlers.
void DelEvent(cEvent *Event)
cString GetTimeString(void) const
static bool ClearAll(void)
#define EPGDATAWRITEDELTA
void SetVersion(uchar Version)
cSchedule * AddSchedule(tChannelID ChannelID)
static const tChannelID InvalidID
#define RUNNINGSTATUSTIMEOUT
bool IsRunning(bool OrAboutToStart=false) const
void SetComponents(cEvent *Event, cComponents *Components)
void SetEventID(tEventID EventID)
cString GetDateString(void) const
bool HasTimer(void) const
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater", and a negative value if it is "smaller".
void SetShortText(cEvent *Event, const char *ShortText)
void Dump(FILE *f, const char *Prefix="", eDumpMode DumpMode=dmAll, time_t AtTime=0) const
bool IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version)
tChannelID & ClrRid(void)
void UnhashEvent(cEvent *Event)
cSchedulesLock(bool WriteLock=false, int TimeoutMs=0)
void EndSegmentTransfer(bool Modified, bool OnlyRunningStatus)
const cEvent * GetFollowingEvent(void) const