release 0.0.6 trunk 0.0.6
authornathan
Sat, 29 Dec 2007 11:19:49 +0100
branchtrunk
changeset 10967afc97e51d
parent 9 23e350c6b6d9
child 11 7196c6d57fab
release 0.0.6
HISTORY
Makefile
premiereepg.c
     1.1 --- a/HISTORY	Sat Dec 29 11:19:37 2007 +0100
     1.2 +++ b/HISTORY	Sat Dec 29 11:19:49 2007 +0100
     1.3 @@ -1,6 +1,15 @@
     1.4  VDR Plugin 'premiereepg' Revision History
     1.5  -----------------------------------------
     1.6  
     1.7 +05.06.2006: Version 0.0.6
     1.8 +- Fixed and improved generation of EventId. You should delete your epg.data file
     1.9 +  to avoid duplicate entries.
    1.10 +- Now using libsi code introduced in VDR 1.3.47 and fixed in 1.4.0-3.
    1.11 +  Obviously requires VDR with API version 1.4.1 or later.
    1.12 +- Checking for broken PMT entries.
    1.13 +- Setting event running status by looking at the start & end time.
    1.14 +- Updated Makefile according to changes in VDR 1.3.47 (APIVERSION & DVBDIR).
    1.15 +
    1.16  21.03.2006: Version 0.0.5
    1.17  - Fixed compiling for VDR < 1.3.18.
    1.18  - Fixed compiling for VDR >= 1.3.43.
     2.1 --- a/Makefile	Sat Dec 29 11:19:37 2007 +0100
     2.2 +++ b/Makefile	Sat Dec 29 11:19:49 2007 +0100
     2.3 @@ -1,7 +1,7 @@
     2.4  #
     2.5  # PremiereEpg plugin to VDR
     2.6  #
     2.7 -# (C) 2005 Stefan Huelswitt <s.huelswitt@gmx.de>
     2.8 +# (C) 2005-2006 Stefan Huelswitt <s.huelswitt@gmx.de>
     2.9  #
    2.10  # This code is free software; you can redistribute it and/or
    2.11  # modify it under the terms of the GNU General Public License
    2.12 @@ -35,7 +35,6 @@
    2.13  
    2.14  ### The directory environment:
    2.15  
    2.16 -DVBDIR = ../../../../DVB
    2.17  VDRDIR = ../../..
    2.18  LIBDIR = ../../lib
    2.19  TMPDIR = /tmp
    2.20 @@ -46,7 +45,11 @@
    2.21  
    2.22  ### The version number of VDR (taken from VDR's "config.h"):
    2.23  
    2.24 -VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
    2.25 +VDRVERSION = $(shell sed -ne '/define VDRVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
    2.26 +APIVERSION = $(shell sed -ne '/define APIVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
    2.27 +ifeq ($(strip $(APIVERSION)),)
    2.28 +   APIVERSION = $(VDRVERSION)
    2.29 +endif
    2.30  
    2.31  ### The name of the distribution archive:
    2.32  
    2.33 @@ -55,7 +58,7 @@
    2.34  
    2.35  ### Includes and Defines (add further entries here):
    2.36  
    2.37 -INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
    2.38 +INCLUDES += -I$(VDRDIR)/include
    2.39  
    2.40  DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
    2.41  
    2.42 @@ -87,7 +90,7 @@
    2.43  
    2.44  libvdr-$(PLUGIN).so: $(OBJS)
    2.45  	$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
    2.46 -	@cp $@ $(LIBDIR)/$@.$(VDRVERSION)
    2.47 +	@cp $@ $(LIBDIR)/$@.$(APIVERSION)
    2.48  
    2.49  dist: clean
    2.50  	@-rm -rf $(TMPDIR)/$(ARCHIVE)
     3.1 --- a/premiereepg.c	Sat Dec 29 11:19:37 2007 +0100
     3.2 +++ b/premiereepg.c	Sat Dec 29 11:19:49 2007 +0100
     3.3 @@ -1,7 +1,7 @@
     3.4  /*
     3.5   * PremiereEpg plugin to VDR (C++)
     3.6   *
     3.7 - * (C) 2005 Stefan Huelswitt <s.huelswitt@gmx.de>
     3.8 + * (C) 2005-2006 Stefan Huelswitt <s.huelswitt@gmx.de>
     3.9   *
    3.10   * This code is base on the commandline tool premiereepg2vdr
    3.11   * (C) 2004-2005 by Axel Katzur software@katzur.de
    3.12 @@ -29,6 +29,7 @@
    3.13  #include <vdr/channels.h>
    3.14  #include <vdr/dvbdevice.h>
    3.15  #include <vdr/i18n.h>
    3.16 +#include <vdr/config.h>
    3.17  #include <libsi/section.h>
    3.18  #include <libsi/descriptor.h>
    3.19  
    3.20 @@ -49,9 +50,13 @@
    3.21  #define PMT_SCAN_TIMEOUT  10  // seconds
    3.22  #define PMT_SCAN_IDLE     300 // seconds
    3.23  
    3.24 -static const char *VERSION        = "0.0.5";
    3.25 +static const char *VERSION        = "0.0.6";
    3.26  static const char *DESCRIPTION    = "Parses extended Premiere EPG data";
    3.27  
    3.28 +#if APIVERSNUM < 10401
    3.29 +#error You need at least VDR API version 1.4.1 for this plugin
    3.30 +#endif
    3.31 +
    3.32  // --- cSetupPremiereEpg -------------------------------------------------------
    3.33  
    3.34  const char *optPats[] = {
    3.35 @@ -330,140 +335,27 @@
    3.36    SetupStore("RatingInfo",SetupPE.RatingInfo);
    3.37  }
    3.38  
    3.39 -// --- CIT ---------------------------------------------------------------------
    3.40 -
    3.41 -namespace SI {
    3.42 -
    3.43 -#define CIT_LEN 17
    3.44 -
    3.45 -struct cit {
    3.46 -   u_char table_id                               :8;
    3.47 -#if BYTE_ORDER == BIG_ENDIAN
    3.48 -   u_char section_syntax_indicator               :1;
    3.49 -   u_char                                        :3;
    3.50 -   u_char section_length_hi                      :4;
    3.51 -#else
    3.52 -   u_char section_length_hi                      :4;
    3.53 -   u_char                                        :3;
    3.54 -   u_char section_syntax_indicator               :1;
    3.55 -#endif
    3.56 -   u_char section_length_lo                      :8;
    3.57 -   u_char service_id_hi                          :8;
    3.58 -   u_char service_id_lo                          :8;
    3.59 -#if BYTE_ORDER == BIG_ENDIAN
    3.60 -   u_char                                        :2;
    3.61 -   u_char version_number                         :5;
    3.62 -   u_char current_next_indicator                 :1;
    3.63 -#else
    3.64 -   u_char current_next_indicator                 :1;
    3.65 -   u_char version_number                         :5;
    3.66 -   u_char                                        :2;
    3.67 -#endif
    3.68 -   u_char section_number                         :8;
    3.69 -   u_char last_section_number                    :8;
    3.70 -   u_char content_id_hi_hi                       :8;
    3.71 -   u_char content_id_hi_lo                       :8;
    3.72 -   u_char content_id_lo_hi                       :8;
    3.73 -   u_char content_id_lo_lo                       :8;
    3.74 -   u_char duration_h                             :8;
    3.75 -   u_char duration_m                             :8;
    3.76 -   u_char duration_s                             :8;
    3.77 -#if BYTE_ORDER == BIG_ENDIAN
    3.78 -   u_char                                        :4;
    3.79 -   u_char descriptors_loop_length_hi             :4;
    3.80 -#else
    3.81 -   u_char descriptors_loop_length_hi             :4;
    3.82 -   u_char                                        :4;
    3.83 -#endif
    3.84 -   u_char descriptors_loop_length_lo             :8;
    3.85 -};
    3.86 -
    3.87 -class CIT : public NumberedSection {
    3.88 -public:
    3.89 -   CIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
    3.90 -   CIT() {}
    3.91 -   int getContentId(void) const;
    3.92 -   time_t getDuration(void) const;
    3.93 -   DescriptorLoop eventDescriptors;
    3.94 -protected:
    3.95 -   virtual void Parse(void);
    3.96 -private:
    3.97 -   const cit *s;
    3.98 -};
    3.99 -
   3.100 -int CIT::getContentId(void) const {
   3.101 -   return (HILO(s->content_id_hi)<<16) | (HILO(s->content_id_lo));
   3.102 -}
   3.103 -
   3.104 -time_t CIT::getDuration(void) const {
   3.105 -   return DVBTime::getDuration(s->duration_h,s->duration_m,s->duration_s);
   3.106 -}
   3.107 -
   3.108 -void CIT::Parse(void) {
   3.109 -#if VDRVERSNUM >= 10343
   3.110 -   int offset=0;
   3.111 -#else
   3.112 -   unsigned int offset=0;
   3.113 -#endif
   3.114 -   data.setPointerAndOffset<const cit>(s, offset);
   3.115 -   eventDescriptors.setData(data+offset,HILO(s->descriptors_loop_length));
   3.116 -}
   3.117 -
   3.118 -} // end of namespace
   3.119 -
   3.120 -// --- cDescrF2 ----------------------------------------------------------------
   3.121 -
   3.122 -class cDescrF2 {
   3.123 -private:
   3.124 -  SI::Descriptor *d;
   3.125 -  SI::CharArray data;
   3.126 -  int idx, loop, nloop, index;
   3.127 -public:
   3.128 -  cDescrF2(SI::Descriptor *D);
   3.129 -  int TransportStreamId(void) { return data.TwoBytes(2); }
   3.130 -  int OrgNetworkId(void)      { return data.TwoBytes(4); }
   3.131 -  int ServiceId(void)         { return data.TwoBytes(6); }
   3.132 -  void Start(void);
   3.133 -  bool Next(void);
   3.134 -  time_t StartTime(void);
   3.135 -  int Index(void) { return index; }
   3.136 -  };
   3.137 -
   3.138 -cDescrF2::cDescrF2(SI::Descriptor *D)
   3.139 -{
   3.140 -  d=D;
   3.141 -  data=d->getData();
   3.142 -  Start();
   3.143 -}
   3.144 -
   3.145 -void cDescrF2::Start(void)
   3.146 -{
   3.147 -  idx=8; loop=0; nloop=-3; index=-1;
   3.148 -}
   3.149 -
   3.150 -bool cDescrF2::Next(void)
   3.151 -{
   3.152 -  loop+=3;
   3.153 -  if(loop>=nloop) {
   3.154 -    idx+=nloop+3;
   3.155 -    if(idx>=d->getLength()) return false;
   3.156 -    loop=0; nloop=data[idx+2];
   3.157 +// --- CRC16 -------------------------------------------------------------------
   3.158 +
   3.159 +#define POLY 0xA001 // CRC16
   3.160 +
   3.161 +unsigned int crc16(unsigned int crc, unsigned char const *p, int len)
   3.162 +{
   3.163 +  while(len--) {
   3.164 +    crc^=*p++;
   3.165 +    for(int i=0; i<8; i++)
   3.166 +      crc=(crc&1) ? (crc>>1)^POLY : (crc>>1);
   3.167      }
   3.168 - index++;
   3.169 - return true;
   3.170 -}
   3.171 -
   3.172 -time_t cDescrF2::StartTime(void)
   3.173 -{
   3.174 -  int off=idx+3+loop;
   3.175 -  return SI::DVBTime::getTime(data[idx+0],data[idx+1],data[off+0],data[off+1],data[off+2]);
   3.176 +  return crc&0xFFFF;
   3.177  }
   3.178  
   3.179  // --- cFilterPremiereEpg ------------------------------------------------------
   3.180  
   3.181 +#define STARTTIME_BIAS (20*60)
   3.182 +
   3.183  class cFilterPremiereEpg : public cFilter {
   3.184  private:
   3.185 -  int pmtpid, pmtidx, pmtnext;
   3.186 +  int pmtpid, pmtsid, pmtidx, pmtnext;
   3.187    //
   3.188    void NextPmt(void);
   3.189  protected:
   3.190 @@ -503,8 +395,8 @@
   3.191  
   3.192  void cFilterPremiereEpg::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
   3.193  {
   3.194 +  int now=time(0);
   3.195    if(Pid==0 && Tid==SI::TableIdPAT) {
   3.196 -    int now=time(0);
   3.197      if(!pmtnext || now>pmtnext) {
   3.198        if(pmtpid) NextPmt();
   3.199        if(!pmtpid) {
   3.200 @@ -516,6 +408,7 @@
   3.201              if(!assoc.isNITPid()) {
   3.202                if(idx++==pmtidx) {
   3.203                  pmtpid=assoc.getPid();
   3.204 +                pmtsid=assoc.getServiceId();
   3.205                  Add(pmtpid,0x02);
   3.206                  pmtnext=now+PMT_SCAN_TIMEOUT;
   3.207                  d(printf("PMT pid now 0x%04x (idx=%d)\n",pmtpid,pmtidx))
   3.208 @@ -534,7 +427,7 @@
   3.209      }
   3.210    else if(pmtpid>0 && Pid==pmtpid && Tid==SI::TableIdPMT && Source() && Transponder()) {
   3.211      SI::PMT pmt(Data,false);
   3.212 -    if(pmt.CheckCRCAndParse()) {
   3.213 +    if(pmt.CheckCRCAndParse() && pmt.getServiceId()==pmtsid) {
   3.214        SI::PMT::Stream stream;
   3.215        for(SI::Loop::Iterator it; pmt.streamLoop.getNext(stream,it); ) {
   3.216          if(stream.getStreamType()==0x05) {
   3.217 @@ -575,20 +468,21 @@
   3.218        }
   3.219      }
   3.220    else if(Tid==0xA0 && Source()) {
   3.221 -    SI::CIT cit(Data,false);
   3.222 +    SI::PremiereCIT cit(Data,false);
   3.223      if(cit.CheckCRCAndParse()) {
   3.224        cSchedulesLock SchedulesLock(true,10);
   3.225        cSchedules *Schedules=(cSchedules *)cSchedules::Schedules(SchedulesLock);
   3.226        if(Schedules) {
   3.227          int nCount=0;
   3.228 -        time_t firstTime=0;
   3.229 -        SI::Descriptor *d;
   3.230 -        int LanguagePreferenceShort=-1;
   3.231 -        int LanguagePreferenceExt=-1;
   3.232 -        bool UseExtendedEventDescriptor=false;
   3.233          SI::ExtendedEventDescriptors *ExtendedEventDescriptors=0;
   3.234          SI::ShortEventDescriptor *ShortEventDescriptor=0;
   3.235          char *order=0, *rating=0;
   3.236 +        {
   3.237 +        time_t firstTime=0;
   3.238 +        SI::Descriptor *d;
   3.239 +        bool UseExtendedEventDescriptor=false;
   3.240 +        int LanguagePreferenceShort=-1;
   3.241 +        int LanguagePreferenceExt=-1;
   3.242          for(SI::Loop::Iterator it; (d=cit.eventDescriptors.getNext(it)); ) {
   3.243            switch(d->getDescriptorTag()) {
   3.244              case 0xF0: // order information
   3.245 @@ -623,15 +517,19 @@
   3.246                  if(p>0) rating=strdup(buff);
   3.247                  }
   3.248                break;
   3.249 -            case 0xF2: // transmisions
   3.250 +            case SI::PremiereContentTransmissionDescriptorTag:
   3.251                if(nCount>=0) {
   3.252 +                SI::PremiereContentTransmissionDescriptor *pct=(SI::PremiereContentTransmissionDescriptor *)d;
   3.253                  nCount++;
   3.254 -                cDescrF2 f2(d);
   3.255 -                if(f2.Next()) {
   3.256 -                  if(nCount==1) firstTime=f2.StartTime();
   3.257 -                  else {
   3.258 -                    time_t time=f2.StartTime();
   3.259 -                    if(firstTime<time-5*50 || firstTime>time+5*60)
   3.260 +                SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
   3.261 +                SI::Loop::Iterator it;
   3.262 +                if(pct->startDayLoop.getNext(sd,it)) {
   3.263 +                  SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
   3.264 +                  SI::Loop::Iterator it2;
   3.265 +                  if(sd.startTimeLoop.getNext(st,it2)) {
   3.266 +                    time_t StartTime=st.getStartTime(sd.getMJD());
   3.267 +                    if(nCount==1) firstTime=StartTime;
   3.268 +                    else if(firstTime<StartTime-5*50 || firstTime>StartTime+5*60)
   3.269                        nCount=-1;
   3.270                      }
   3.271                    }
   3.272 @@ -640,11 +538,7 @@
   3.273              case SI::ExtendedEventDescriptorTag:
   3.274                {
   3.275                SI::ExtendedEventDescriptor *eed=(SI::ExtendedEventDescriptor *)d;
   3.276 -#if VDRVERSNUM < 10332
   3.277 -              if(I18nIsPreferredLanguage(Setup.EPGLanguages,I18nLanguageIndex(eed->languageCode), LanguagePreferenceExt) || !ExtendedEventDescriptors) {
   3.278 -#else
   3.279                if(I18nIsPreferredLanguage(Setup.EPGLanguages,eed->languageCode, LanguagePreferenceExt) || !ExtendedEventDescriptors) {
   3.280 -#endif
   3.281                   delete ExtendedEventDescriptors;
   3.282                   ExtendedEventDescriptors=new SI::ExtendedEventDescriptors;
   3.283                   UseExtendedEventDescriptor=true;
   3.284 @@ -660,11 +554,7 @@
   3.285              case SI::ShortEventDescriptorTag:
   3.286                {
   3.287                SI::ShortEventDescriptor *sed=(SI::ShortEventDescriptor *)d;
   3.288 -#if VDRVERSNUM < 10332
   3.289 -              if(I18nIsPreferredLanguage(Setup.EPGLanguages,I18nLanguageIndex(sed->languageCode), LanguagePreferenceShort) || !ShortEventDescriptor) {
   3.290 -#else
   3.291                if(I18nIsPreferredLanguage(Setup.EPGLanguages,sed->languageCode, LanguagePreferenceShort) || !ShortEventDescriptor) {
   3.292 -#endif
   3.293                   delete ShortEventDescriptor;
   3.294                   ShortEventDescriptor=sed;
   3.295                   d=NULL; // so that it is not deleted
   3.296 @@ -676,55 +566,64 @@
   3.297              }
   3.298            delete d;
   3.299            }
   3.300 -
   3.301 +        }
   3.302 +
   3.303 +        {
   3.304          bool Modified=false;
   3.305          int optCount=0;
   3.306 -        for(SI::Loop::Iterator it; (d=cit.eventDescriptors.getNext(it)); ) {
   3.307 -          if(d->getDescriptorTag()==0xF2) {
   3.308 -            optCount++;
   3.309 -
   3.310 -            cDescrF2 f2(d);
   3.311 -            tChannelID channelID(Source(),f2.OrgNetworkId(),f2.TransportStreamId(),f2.ServiceId());
   3.312 -            cChannel *channel=Channels.GetByChannelID(channelID,true);
   3.313 -            if(!channel) continue;
   3.314 -
   3.315 -            cSchedule *pSchedule=(cSchedule *)Schedules->GetSchedule(channelID);
   3.316 -            if(!pSchedule) {
   3.317 -               pSchedule=new cSchedule(channelID);
   3.318 -               Schedules->Add(pSchedule);
   3.319 -               }
   3.320 -
   3.321 -            for(f2.Start(); f2.Next();) {
   3.322 -              u_int16_t EventId=(cit.getContentId()<<4) | f2.Index();
   3.323 -              time_t StartTime=f2.StartTime();
   3.324 -
   3.325 +        unsigned int crc[3];
   3.326 +        crc[0]=cit.getContentId();
   3.327 +        SI::PremiereContentTransmissionDescriptor *pct;
   3.328 +        for(SI::Loop::Iterator it; (pct=(SI::PremiereContentTransmissionDescriptor *)cit.eventDescriptors.getNext(it,SI::PremiereContentTransmissionDescriptorTag)); ) {
   3.329 +          tChannelID channelID(Source(),pct->getOriginalNetworkId(),pct->getTransportStreamId(),pct->getServiceId());
   3.330 +          cChannel *channel=Channels.GetByChannelID(channelID,true);
   3.331 +          if(!channel) continue;
   3.332 +
   3.333 +          cSchedule *pSchedule=(cSchedule *)Schedules->GetSchedule(channelID);
   3.334 +          if(!pSchedule) {
   3.335 +             pSchedule=new cSchedule(channelID);
   3.336 +             Schedules->Add(pSchedule);
   3.337 +             }
   3.338 +
   3.339 +          optCount++;
   3.340 +          SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
   3.341 +          int index=0;
   3.342 +          for(SI::Loop::Iterator it; pct->startDayLoop.getNext(sd,it); ) {
   3.343 +            int mjd=sd.getMJD();
   3.344 +            SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
   3.345 +            for(SI::Loop::Iterator it2; sd.startTimeLoop.getNext(st,it2); ) {
   3.346 +              time_t StartTime=st.getStartTime(mjd);
   3.347 +              time_t EndTime=StartTime+cit.getDuration();
   3.348 +              int runningStatus=(StartTime<now && now<EndTime) ? SI::RunningStatusRunning : ((StartTime-30<now && now<StartTime) ? SI::RunningStatusStartsInAFewSeconds : SI::RunningStatusNotRunning);
   3.349                bool isOpt=false;
   3.350 -              if(f2.Index()==0 && nCount>1) isOpt=true;
   3.351 -
   3.352 -              d2(printf("ch=%s id=%04x/%08x %d opt=%d/%d st=%s ",*channelID.ToString(),EventId,cit.getContentId(),f2.Index(),isOpt,optCount,stripspace(ctime(&StartTime))))
   3.353 -              if(StartTime+cit.getDuration()+Setup.EPGLinger*60<time(0)) {
   3.354 +              if(index++==0 && nCount>1) isOpt=true;
   3.355 +              crc[1]=isOpt ? optCount : 0;
   3.356 +              crc[2]=StartTime / STARTTIME_BIAS;
   3.357 +              tEventID EventId=((('P'<<8)|'W')<<16) | crc16(0,(unsigned char *)crc,sizeof(crc));
   3.358 +
   3.359 +              d2(printf("%s R%d %04x/%.4x %d %d/%d %s +%d ",*channelID.ToString(),runningStatus,EventId&0xFFFF,cit.getContentId(),index,isOpt,optCount,stripspace(ctime(&StartTime)),(int)cit.getDuration()/60))
   3.360 +              if(EndTime+Setup.EPGLinger*60<now) {
   3.361                  d2(printf("(old)\n"))
   3.362                  continue;
   3.363                  }
   3.364  
   3.365                bool newEvent=false;
   3.366 -              cEvent *pEvent=(cEvent *)pSchedule->GetEvent(EventId,StartTime);
   3.367 +              cEvent *pEvent=(cEvent *)pSchedule->GetEvent(EventId,-1);
   3.368                if(!pEvent) {
   3.369 -                 d2(printf("(new)\n"))
   3.370 -#if VDRVERSNUM >= 10325
   3.371 -                 pEvent=new cEvent(EventId);
   3.372 -#else
   3.373 -                 pEvent=new cEvent(channelID,EventId);
   3.374 -#endif
   3.375 -                 if(!pEvent) continue;
   3.376 -                 newEvent=true;
   3.377 -                 }
   3.378 +                d2(printf("(new)\n"))
   3.379 +                pEvent=new cEvent(EventId);
   3.380 +                if(!pEvent) continue;
   3.381 +                newEvent=true;
   3.382 +                }
   3.383                else {
   3.384 -                 d2(printf("(upd)\n"))
   3.385 -                 pEvent->SetSeen();
   3.386 -                 if(pEvent->TableID()==0x00) continue;
   3.387 -                 if(Tid==pEvent->TableID() && pEvent->Version()==cit.getVersionNumber()) continue;
   3.388 -                 }
   3.389 +                d2(printf("(upd)\n"))
   3.390 +                pEvent->SetSeen();
   3.391 +                if(pEvent->TableID()==0x00 || pEvent->Version()==cit.getVersionNumber()) {
   3.392 +                  if(pEvent->RunningStatus()!=runningStatus)
   3.393 +                    pSchedule->SetRunningStatus(pEvent,runningStatus,channel);
   3.394 +                  continue;
   3.395 +                  }
   3.396 +                }
   3.397                pEvent->SetEventID(EventId);
   3.398                pEvent->SetTableID(Tid);
   3.399                pEvent->SetVersion(cit.getVersionNumber());
   3.400 @@ -741,6 +640,7 @@
   3.401                    }
   3.402                  else
   3.403                    pEvent->SetTitle(buffer);
   3.404 +                d2(printf("title: %s\n",pEvent->Title()))
   3.405                  pEvent->SetShortText(ShortEventDescriptor->text.getText(buffer,sizeof(buffer)));
   3.406                  }
   3.407                if(ExtendedEventDescriptors) {
   3.408 @@ -760,19 +660,21 @@
   3.409                  }
   3.410  
   3.411                if(newEvent) pSchedule->AddEvent(pEvent);
   3.412 -#if VDRVERSNUM >= 10318
   3.413                pEvent->SetComponents(NULL);
   3.414 -#endif
   3.415                pEvent->FixEpgBugs();
   3.416 +              if(pEvent->RunningStatus()!=runningStatus)
   3.417 +                pSchedule->SetRunningStatus(pEvent,runningStatus,channel);
   3.418 +              pSchedule->DropOutdated(StartTime,EndTime,Tid,cit.getVersionNumber());
   3.419                Modified=true;
   3.420                }
   3.421 -            if(Modified) {
   3.422 -              pSchedule->Sort();
   3.423 -              Schedules->SetModified(pSchedule);
   3.424 -              }
   3.425              }
   3.426 -          delete d;
   3.427 +          if(Modified) {
   3.428 +            pSchedule->Sort();
   3.429 +            Schedules->SetModified(pSchedule);
   3.430 +            }
   3.431 +          delete pct;
   3.432            }
   3.433 +        }
   3.434          delete ExtendedEventDescriptors;
   3.435          delete ShortEventDescriptor;
   3.436          free(order);