2003-12-22 13:29:24 +01:00
/*
* eit . c : EIT section filter
*
* See the main source file ' vdr . c ' for copyright information and
* how to reach the author .
*
* Original version ( as used in VDR before 1.3 .0 ) written by
* Robert Schneider < Robert . Schneider @ web . de > and Rolf Hakenes < hakenes @ hippomi . de > .
* Adapted to ' libsi ' for VDR 1.3 .0 by Marcel Wiesweg < marcel . wiesweg @ gmx . de > .
*
2013-08-23 10:54:49 +02:00
* $ Id : eit . c 3.1 2013 / 08 / 23 10 : 52 : 27 kls Exp $
2003-12-22 13:29:24 +01:00
*/
2000-09-03 11:40:00 +02:00
# include "eit.h"
2012-12-04 09:34:06 +01:00
# include <sys/time.h>
2003-12-22 13:29:24 +01:00
# include "epg.h"
2004-01-09 15:53:59 +01:00
# include "i18n.h"
2003-12-22 13:29:24 +01:00
# include "libsi/section.h"
# include "libsi/descriptor.h"
2001-03-31 15:04:37 +02:00
2009-05-15 12:41:50 +02:00
# define VALID_TIME (31536000 * 2) // two years
2003-12-22 13:29:24 +01:00
// --- cEIT ------------------------------------------------------------------
2000-09-03 11:40:00 +02:00
2003-12-22 13:29:24 +01:00
class cEIT : public SI : : EIT {
2001-03-31 15:04:37 +02:00
public :
2006-05-25 14:53:15 +02:00
cEIT ( cSchedules * Schedules , int Source , u_char Tid , const u_char * Data , bool OnlyRunningStatus = false ) ;
2003-12-22 13:29:24 +01:00
} ;
2001-03-31 15:04:37 +02:00
2006-05-25 14:53:15 +02:00
cEIT : : cEIT ( cSchedules * Schedules , int Source , u_char Tid , const u_char * Data , bool OnlyRunningStatus )
2003-12-22 13:29:24 +01:00
: SI : : EIT ( Data , false )
2000-10-29 13:17:22 +01:00
{
2003-12-22 13:29:24 +01:00
if ( ! CheckCRCAndParse ( ) )
return ;
2000-10-29 13:17:22 +01:00
2012-03-14 10:41:48 +01:00
time_t Now = time ( NULL ) ;
if ( Now < VALID_TIME )
return ; // we need the current time for handling PDC descriptors
if ( ! Channels . Lock ( false , 10 ) )
return ;
2004-01-04 12:30:00 +01:00
tChannelID channelID ( Source , getOriginalNetworkId ( ) , getTransportStreamId ( ) , getServiceId ( ) ) ;
cChannel * channel = Channels . GetByChannelID ( channelID , true ) ;
2012-03-14 10:41:48 +01:00
if ( ! channel | | EpgHandlers . IgnoreChannel ( channel ) ) {
Channels . Unlock ( ) ;
2012-03-10 15:10:43 +01:00
return ;
2012-03-14 10:41:48 +01:00
}
2000-10-29 13:17:22 +01:00
2013-08-23 10:54:49 +02:00
EpgHandlers . BeginSegmentTransfer ( channel , OnlyRunningStatus ) ;
2012-06-04 10:19:23 +02:00
bool handledExternally = EpgHandlers . HandledExternally ( channel ) ;
2006-01-14 15:52:40 +01:00
cSchedule * pSchedule = ( cSchedule * ) Schedules - > GetSchedule ( channel , true ) ;
2002-02-02 12:13:35 +01:00
2004-03-13 15:01:05 +01:00
bool Empty = true ;
2004-02-21 13:56:20 +01:00
bool Modified = false ;
2005-12-26 14:44:28 +01:00
time_t SegmentStart = 0 ;
time_t SegmentEnd = 0 ;
2009-04-12 09:09:47 +02:00
struct tm tm_r ;
struct tm t = * localtime_r ( & Now , & tm_r ) ; // this initializes the time zone in 't'
2004-02-21 13:56:20 +01:00
2003-12-22 13:29:24 +01:00
SI : : EIT : : Event SiEitEvent ;
2004-10-16 10:14:19 +02:00
for ( SI : : Loop : : Iterator it ; eventLoop . getNext ( SiEitEvent , it ) ; ) {
2012-03-10 15:10:43 +01:00
if ( EpgHandlers . HandleEitEvent ( pSchedule , & SiEitEvent , Tid , getVersionNumber ( ) ) )
continue ; // an EPG handler has done all of the processing
2009-05-10 14:55:15 +02:00
time_t StartTime = SiEitEvent . getStartTime ( ) ;
2009-04-12 09:09:47 +02:00
int Duration = SiEitEvent . getDuration ( ) ;
2005-06-11 16:05:11 +02:00
// 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.
2009-04-12 09:09:47 +02:00
if ( StartTime = = 0 | | StartTime > 0 & & Duration = = 0 )
2005-05-26 10:27:06 +02:00
continue ;
2004-03-13 15:01:05 +01:00
Empty = false ;
2005-12-26 14:44:28 +01:00
if ( ! SegmentStart )
2009-04-12 09:09:47 +02:00
SegmentStart = StartTime ;
SegmentEnd = StartTime + Duration ;
2005-05-28 13:17:20 +02:00
cEvent * newEvent = NULL ;
2005-08-13 13:30:04 +02:00
cEvent * rEvent = NULL ;
2009-04-12 09:09:47 +02:00
cEvent * pEvent = ( cEvent * ) pSchedule - > GetEvent ( SiEitEvent . getEventId ( ) , StartTime ) ;
2012-06-04 10:19:23 +02:00
if ( ! pEvent | | handledExternally ) {
2006-05-25 14:53:15 +02:00
if ( OnlyRunningStatus )
continue ;
2012-08-25 11:31:35 +02:00
if ( handledExternally & & ! EpgHandlers . IsUpdate ( SiEitEvent . getEventId ( ) , StartTime , Tid , getVersionNumber ( ) ) )
continue ;
2004-02-21 12:28:17 +01:00
// If we don't have that event yet, we create a new one.
2003-12-22 13:29:24 +01:00
// Otherwise we copy the information into the existing event anyway, because the data might have changed.
2005-05-28 13:17:20 +02:00
pEvent = newEvent = new cEvent ( SiEitEvent . getEventId ( ) ) ;
2012-03-10 15:10:43 +01:00
newEvent - > SetStartTime ( StartTime ) ;
newEvent - > SetDuration ( Duration ) ;
2012-06-04 10:19:23 +02:00
if ( ! handledExternally )
pSchedule - > AddEvent ( newEvent ) ;
2002-02-02 12:13:35 +01:00
}
2003-12-22 13:29:24 +01:00
else {
// We have found an existing event, either through its event ID or its start time.
2004-10-24 15:01:50 +02:00
pEvent - > SetSeen ( ) ;
2012-03-10 15:10:43 +01:00
uchar TableID = max ( pEvent - > TableID ( ) , uchar ( 0x4E ) ) ; // for backwards compatibility, table ids less than 0x4E are treated as if they were "present"
2004-02-21 12:28:17 +01:00
// If the new event has a higher table ID, let's skip it.
// The lower the table ID, the more "current" the information.
2012-03-10 15:10:43 +01:00
if ( Tid > TableID )
2003-12-25 12:50:22 +01:00
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
2004-01-04 12:30:00 +01:00
// to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers.
2009-04-12 09:09:47 +02:00
else if ( Tid = = TableID & & pEvent - > Version ( ) = = getVersionNumber ( ) )
2003-12-22 13:29:24 +01:00
continue ;
2012-03-10 15:10:43 +01:00
EpgHandlers . SetEventID ( pEvent , SiEitEvent . getEventId ( ) ) ; // unfortunately some stations use different event ids for the same event in different tables :-(
EpgHandlers . SetStartTime ( pEvent , StartTime ) ;
EpgHandlers . SetDuration ( pEvent , Duration ) ;
2002-02-02 12:13:35 +01:00
}
2012-03-10 15:10:43 +01:00
if ( pEvent - > TableID ( ) > 0x4E ) // for backwards compatibility, table ids less than 0x4E are never overwritten
2006-02-19 09:51:02 +01:00
pEvent - > SetTableID ( Tid ) ;
2006-05-25 14:53:15 +02:00
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 ) ;
}
2012-03-10 15:10:43 +01:00
if ( OnlyRunningStatus ) {
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
2006-05-25 14:53:15 +02:00
continue ; // do this before setting the version, so that the full update can be done later
2012-03-10 15:10:43 +01:00
}
2004-02-21 12:28:17 +01:00
pEvent - > SetVersion ( getVersionNumber ( ) ) ;
2001-08-17 13:19:10 +02:00
2004-01-09 15:53:59 +01:00
int LanguagePreferenceShort = - 1 ;
int LanguagePreferenceExt = - 1 ;
bool UseExtendedEventDescriptor = false ;
2003-12-22 13:29:24 +01:00
SI : : Descriptor * d ;
2004-01-09 15:53:59 +01:00
SI : : ExtendedEventDescriptors * ExtendedEventDescriptors = NULL ;
SI : : ShortEventDescriptor * ShortEventDescriptor = NULL ;
2004-02-08 11:05:22 +01:00
cLinkChannels * LinkChannels = NULL ;
2005-05-16 14:45:11 +02:00
cComponents * Components = NULL ;
2003-12-22 13:29:24 +01:00
for ( SI : : Loop : : Iterator it2 ; ( d = SiEitEvent . eventDescriptors . getNext ( it2 ) ) ; ) {
switch ( d - > getDescriptorTag ( ) ) {
2004-01-09 15:53:59 +01:00
case SI : : ExtendedEventDescriptorTag : {
SI : : ExtendedEventDescriptor * eed = ( SI : : ExtendedEventDescriptor * ) d ;
2005-09-04 14:48:39 +02:00
if ( I18nIsPreferredLanguage ( Setup . EPGLanguages , eed - > languageCode , LanguagePreferenceExt ) | | ! ExtendedEventDescriptors ) {
2004-01-09 15:53:59 +01:00
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 ;
}
2003-12-22 13:29:24 +01:00
break ;
case SI : : ShortEventDescriptorTag : {
SI : : ShortEventDescriptor * sed = ( SI : : ShortEventDescriptor * ) d ;
2005-09-04 14:48:39 +02:00
if ( I18nIsPreferredLanguage ( Setup . EPGLanguages , sed - > languageCode , LanguagePreferenceShort ) | | ! ShortEventDescriptor ) {
2004-01-09 15:53:59 +01:00
delete ShortEventDescriptor ;
ShortEventDescriptor = sed ;
d = NULL ; // so that it is not deleted
}
2002-09-15 14:35:32 +02:00
}
2003-12-22 13:29:24 +01:00
break ;
2010-01-03 12:20:37 +01:00
case SI : : ContentDescriptorTag : {
SI : : ContentDescriptor * cd = ( SI : : ContentDescriptor * ) d ;
SI : : ContentDescriptor : : Nibble Nibble ;
int NumContents = 0 ;
2010-01-08 15:23:34 +01:00
uchar Contents [ MaxEventContents ] = { 0 } ;
2010-01-03 12:20:37 +01:00
for ( SI : : Loop : : Iterator it3 ; cd - > nibbleLoop . getNext ( Nibble , it3 ) ; ) {
2010-01-08 15:23:34 +01:00
if ( NumContents < MaxEventContents ) {
2010-01-03 12:20:37 +01:00
Contents [ NumContents ] = ( ( Nibble . getContentNibbleLevel1 ( ) & 0xF ) < < 4 ) | ( Nibble . getContentNibbleLevel2 ( ) & 0xF ) ;
NumContents + + ;
}
}
2012-03-10 15:10:43 +01:00
EpgHandlers . SetContents ( pEvent , Contents ) ;
2010-01-03 12:20:37 +01:00
}
2003-12-22 13:29:24 +01:00
break ;
2010-01-03 14:28:33 +01:00
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 ;
}
2012-03-10 15:10:43 +01:00
EpgHandlers . SetParentalRating ( pEvent , ParentalRating ) ;
2010-01-03 14:28:33 +01:00
}
}
}
2003-12-22 13:29:24 +01:00
break ;
2004-02-22 13:33:20 +01:00
case SI : : PDCDescriptorTag : {
SI : : PDCDescriptor * pd = ( SI : : PDCDescriptor * ) d ;
t . tm_isdst = - 1 ; // makes sure mktime() will determine the correct DST setting
2004-03-07 11:53:43 +01:00
int month = t . tm_mon ;
2004-02-22 13:33:20 +01:00
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 ;
2004-03-07 11:53:43 +01:00
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 - - ;
2004-02-22 13:33:20 +01:00
time_t vps = mktime ( & t ) ;
2012-03-10 15:10:43 +01:00
EpgHandlers . SetVps ( pEvent , vps ) ;
2004-02-22 13:33:20 +01:00
}
break ;
2003-12-22 13:29:24 +01:00
case SI : : TimeShiftedEventDescriptorTag : {
SI : : TimeShiftedEventDescriptor * tsed = ( SI : : TimeShiftedEventDescriptor * ) d ;
2004-07-18 11:02:50 +02:00
cSchedule * rSchedule = ( cSchedule * ) Schedules - > GetSchedule ( tChannelID ( Source , channel - > Nid ( ) , channel - > Tid ( ) , tsed - > getReferenceServiceId ( ) ) ) ;
2003-12-22 13:29:24 +01:00
if ( ! rSchedule )
break ;
rEvent = ( cEvent * ) rSchedule - > GetEvent ( tsed - > getReferenceEventId ( ) ) ;
if ( ! rEvent )
break ;
2012-03-10 15:10:43 +01:00
EpgHandlers . SetTitle ( pEvent , rEvent - > Title ( ) ) ;
EpgHandlers . SetShortText ( pEvent , rEvent - > ShortText ( ) ) ;
EpgHandlers . SetDescription ( pEvent , rEvent - > Description ( ) ) ;
2001-08-17 13:19:10 +02:00
}
2003-12-22 13:29:24 +01:00
break ;
2004-02-08 11:05:22 +01:00
case SI : : LinkageDescriptorTag : {
SI : : LinkageDescriptor * ld = ( SI : : LinkageDescriptor * ) d ;
tChannelID linkID ( Source , ld - > getOriginalNetworkId ( ) , ld - > getTransportStreamId ( ) , ld - > getServiceId ( ) ) ;
if ( ld - > getLinkageType ( ) = = 0xB0 ) { // Premiere World
2009-04-12 09:09:47 +02:00
bool hit = StartTime < = Now & & Now < StartTime + Duration ;
2004-02-08 11:05:22 +01:00
if ( hit ) {
2004-10-31 13:01:35 +01:00
char linkName [ ld - > privateData . getLength ( ) + 1 ] ;
strn0cpy ( linkName , ( const char * ) ld - > privateData . getData ( ) , sizeof ( linkName ) ) ;
2007-06-10 13:02:43 +02:00
// TODO is there a standard way to determine the character set of this string?
2004-02-08 11:05:22 +01:00
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 ) {
2006-04-15 14:18:25 +02:00
if ( Setup . UpdateChannels = = 1 | | Setup . UpdateChannels > = 3 )
2004-10-31 12:53:00 +01:00
link - > SetName ( linkName , " " , " " ) ;
2004-02-08 11:05:22 +01:00
}
2006-04-15 14:18:25 +02:00
else if ( Setup . UpdateChannels > = 4 ) {
2007-07-21 15:05:20 +02:00
cChannel * transponder = channel ;
if ( channel - > Tid ( ) ! = ld - > getTransportStreamId ( ) )
2007-07-28 13:23:37 +02:00
transponder = Channels . GetByTransponderID ( linkID ) ;
2007-07-21 15:05:20 +02:00
link = Channels . NewChannel ( transponder , linkName , " " , " " , ld - > getOriginalNetworkId ( ) , ld - > getTransportStreamId ( ) , ld - > getServiceId ( ) ) ;
2004-02-08 11:05:22 +01:00
//XXX patFilter->Trigger();
}
if ( link ) {
if ( ! LinkChannels )
LinkChannels = new cLinkChannels ;
LinkChannels - > Add ( new cLinkChannel ( link ) ) ;
}
}
2004-10-31 13:01:35 +01:00
else
channel - > SetPortalName ( linkName ) ;
2004-02-08 11:05:22 +01:00
}
}
}
break ;
2005-01-02 15:11:44 +01:00
case SI : : ComponentDescriptorTag : {
SI : : ComponentDescriptor * cd = ( SI : : ComponentDescriptor * ) d ;
uchar Stream = cd - > getStreamContent ( ) ;
uchar Type = cd - > getComponentType ( ) ;
2010-05-16 10:23:55 +02:00
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
2005-05-16 14:45:11 +02:00
if ( ! Components )
Components = new cComponents ;
2007-06-10 13:02:43 +02:00
char buffer [ Utf8BufSize ( 256 ) ] ;
2007-10-12 14:52:30 +02:00
Components - > SetComponent ( Components - > NumComponents ( ) , Stream , Type , I18nNormalizeLanguageCode ( cd - > languageCode ) , cd - > description . getText ( buffer , sizeof ( buffer ) ) ) ;
2005-01-02 15:11:44 +01:00
}
}
break ;
2003-12-22 13:29:24 +01:00
default : ;
}
delete d ;
}
2002-10-07 16:24:04 +02:00
2003-12-22 13:29:24 +01:00
if ( ! rEvent ) {
2004-01-09 15:53:59 +01:00
if ( ShortEventDescriptor ) {
2007-06-10 13:02:43 +02:00
char buffer [ Utf8BufSize ( 256 ) ] ;
2012-03-10 15:10:43 +01:00
EpgHandlers . SetTitle ( pEvent , ShortEventDescriptor - > name . getText ( buffer , sizeof ( buffer ) ) ) ;
EpgHandlers . SetShortText ( pEvent , ShortEventDescriptor - > text . getText ( buffer , sizeof ( buffer ) ) ) ;
2004-01-09 15:53:59 +01:00
}
2012-03-10 15:10:43 +01:00
else {
EpgHandlers . SetTitle ( pEvent , NULL ) ;
EpgHandlers . SetShortText ( pEvent , NULL ) ;
2006-10-07 12:37:59 +02:00
}
2004-01-09 15:53:59 +01:00
if ( ExtendedEventDescriptors ) {
2007-06-10 13:02:43 +02:00
char buffer [ Utf8BufSize ( ExtendedEventDescriptors - > getMaximumTextLength ( " : " ) ) + 1 ] ;
2012-03-10 15:10:43 +01:00
EpgHandlers . SetDescription ( pEvent , ExtendedEventDescriptors - > getText ( buffer , sizeof ( buffer ) , " : " ) ) ;
2004-01-09 15:53:59 +01:00
}
2012-03-10 15:10:43 +01:00
else
EpgHandlers . SetDescription ( pEvent , NULL ) ;
2000-11-01 15:53:00 +01:00
}
2004-01-09 15:53:59 +01:00
delete ExtendedEventDescriptors ;
delete ShortEventDescriptor ;
2002-10-07 16:24:04 +02:00
2012-06-04 10:29:19 +02:00
EpgHandlers . SetComponents ( pEvent , Components ) ;
2001-03-31 15:04:37 +02:00
2012-03-10 15:10:43 +01:00
EpgHandlers . FixEpgBugs ( pEvent ) ;
2004-02-08 11:05:22 +01:00
if ( LinkChannels )
channel - > SetLinkChannels ( LinkChannels ) ;
2004-02-21 13:56:20 +01:00
Modified = true ;
2012-03-10 15:10:43 +01:00
EpgHandlers . HandleEvent ( pEvent ) ;
2012-06-04 10:19:23 +02:00
if ( handledExternally )
delete pEvent ;
2002-10-07 16:24:04 +02:00
}
2009-04-12 09:09:47 +02:00
if ( Tid = = 0x4E ) {
if ( Empty & & getSectionNumber ( ) = = 0 )
// ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
pSchedule - > ClrRunningStatus ( channel ) ;
2005-03-20 13:12:07 +01:00
pSchedule - > SetPresentSeen ( ) ;
2009-04-12 09:09:47 +02:00
}
2012-03-14 10:41:48 +01:00
if ( Modified & & ! OnlyRunningStatus ) {
2012-03-10 15:10:43 +01:00
EpgHandlers . SortSchedule ( pSchedule ) ;
EpgHandlers . DropOutdated ( pSchedule , SegmentStart , SegmentEnd , Tid , getVersionNumber ( ) ) ;
2004-10-24 15:01:50 +02:00
Schedules - > SetModified ( pSchedule ) ;
}
2012-03-14 10:41:48 +01:00
Channels . Unlock ( ) ;
2013-08-23 10:54:49 +02:00
EpgHandlers . EndSegmentTransfer ( Modified , OnlyRunningStatus ) ;
2000-09-03 11:40:00 +02:00
}
2003-12-22 13:29:24 +01:00
// --- cTDT ------------------------------------------------------------------
2003-01-06 14:44:27 +01:00
2012-12-04 09:34:06 +01:00
# define MAX_TIME_DIFF 1 // number of seconds the local time may differ from dvb time before making any corrections
# define MAX_ADJ_DIFF 10 // number of seconds the local time may differ from dvb time to allow smooth adjustment
# define ADJ_DELTA 300 // number of seconds between calls for smooth time adjustment
2003-12-22 13:29:24 +01:00
class cTDT : public SI : : TDT {
2003-01-06 14:44:27 +01:00
private :
2003-12-22 13:29:24 +01:00
static cMutex mutex ;
2012-12-04 09:34:06 +01:00
static time_t lastAdj ;
2003-01-06 14:44:27 +01:00
public :
2003-12-22 13:29:24 +01:00
cTDT ( const u_char * Data ) ;
2003-01-06 14:44:27 +01:00
} ;
2003-12-22 13:29:24 +01:00
cMutex cTDT : : mutex ;
2012-12-04 09:34:06 +01:00
time_t cTDT : : lastAdj = 0 ;
2003-01-06 14:44:27 +01:00
2003-12-22 13:29:24 +01:00
cTDT : : cTDT ( const u_char * Data )
: SI : : TDT ( Data , false )
2003-01-06 14:44:27 +01:00
{
2003-12-22 13:29:24 +01:00
CheckParse ( ) ;
2000-10-29 13:17:22 +01:00
2012-12-04 09:34:06 +01:00
time_t dvbtim = getTime ( ) ;
2003-12-22 13:29:24 +01:00
time_t loctim = time ( NULL ) ;
2000-10-29 13:17:22 +01:00
2012-12-04 09:34:06 +01:00
int diff = dvbtim - loctim ;
if ( abs ( diff ) > MAX_TIME_DIFF ) {
2003-12-22 13:29:24 +01:00
mutex . Lock ( ) ;
2012-12-04 09:34:06 +01:00
if ( abs ( diff ) > MAX_ADJ_DIFF ) {
if ( stime ( & dvbtim ) = = 0 )
isyslog ( " system time changed from %s (%ld) to %s (%ld) " , * TimeToString ( loctim ) , loctim , * TimeToString ( dvbtim ) , dvbtim ) ;
2008-04-13 11:44:48 +02:00
else
2005-08-07 13:52:29 +02:00
esyslog ( " ERROR while setting system time: %m " ) ;
}
2012-12-04 09:34:06 +01:00
else if ( time ( NULL ) - lastAdj > ADJ_DELTA ) {
lastAdj = time ( NULL ) ;
timeval delta ;
delta . tv_sec = diff ;
delta . tv_usec = 0 ;
if ( adjtime ( & delta , NULL ) = = 0 )
isyslog ( " system time adjustment initiated from %s (%ld) to %s (%ld) " , * TimeToString ( loctim ) , loctim , * TimeToString ( dvbtim ) , dvbtim ) ;
else
esyslog ( " ERROR while adjusting system time: %m " ) ;
}
2003-12-22 13:29:24 +01:00
mutex . Unlock ( ) ;
2002-02-23 17:11:19 +01:00
}
}
2003-12-22 13:29:24 +01:00
// --- cEitFilter ------------------------------------------------------------
2002-08-25 10:49:02 +02:00
2010-01-03 15:45:23 +01:00
time_t cEitFilter : : disableUntil = 0 ;
2003-12-22 13:29:24 +01:00
cEitFilter : : cEitFilter ( void )
2001-08-11 09:38:12 +02:00
{
2009-06-21 13:59:22 +02:00
Set ( 0x12 , 0x40 , 0xC0 ) ; // event info now&next actual/other TS (0x4E/0x4F), future actual/other TS (0x5X/0x6X)
2012-12-04 11:15:28 +01:00
Set ( 0x14 , 0x70 ) ; // TDT
2001-08-11 09:38:12 +02:00
}
2010-01-03 15:45:23 +01:00
void cEitFilter : : SetDisableUntil ( time_t Time )
{
disableUntil = Time ;
}
2003-12-22 13:29:24 +01:00
void cEitFilter : : Process ( u_short Pid , u_char Tid , const u_char * Data , int Length )
2001-08-11 09:38:12 +02:00
{
2010-01-03 15:45:23 +01:00
if ( disableUntil ) {
if ( time ( NULL ) > disableUntil )
disableUntil = 0 ;
else
return ;
}
2003-12-22 13:29:24 +01:00
switch ( Pid ) {
case 0x12 : {
2009-06-21 13:59:22 +02:00
if ( Tid > = 0x4E & & Tid < = 0x6F ) {
cSchedulesLock SchedulesLock ( true , 10 ) ;
2006-05-25 14:53:15 +02:00
cSchedules * Schedules = ( cSchedules * ) cSchedules : : Schedules ( SchedulesLock ) ;
if ( Schedules )
2009-06-21 13:59:22 +02:00
cEIT EIT ( Schedules , Source ( ) , Tid , Data ) ;
else {
// If we don't get a write lock, let's at least get a read lock, so
// that we can set the running status and 'seen' timestamp (well, actually
// with a read lock we shouldn't be doing that, but it's only integers that
// get changed, so it should be ok)
cSchedulesLock SchedulesLock ;
cSchedules * Schedules = ( cSchedules * ) cSchedules : : Schedules ( SchedulesLock ) ;
if ( Schedules )
cEIT EIT ( Schedules , Source ( ) , Tid , Data , true ) ;
}
2006-05-25 14:53:15 +02:00
}
2000-11-26 15:23:39 +01:00
}
2003-12-22 13:29:24 +01:00
break ;
case 0x14 : {
if ( Setup . SetSystemTime & & Setup . TimeTransponder & & ISTRANSPONDER ( Transponder ( ) , Setup . TimeTransponder ) )
cTDT TDT ( Data ) ;
2003-04-25 14:46:22 +02:00
}
2003-12-22 13:29:24 +01:00
break ;
2009-12-06 12:57:45 +01:00
default : ;
2003-12-22 13:29:24 +01:00
}
2003-01-06 14:44:27 +01:00
}