+eEPGCache::channel_data::channel_data(eEPGCache *ml)
+ :cache(ml)
+ ,abortTimer(ml), zapTimer(ml)
+ ,state(0), isRunning(0), haveData(0), can_delete(1)
+{
+ CONNECT(zapTimer.timeout, eEPGCache::channel_data::startEPG);
+ CONNECT(abortTimer.timeout, eEPGCache::channel_data::abortNonAvail);
+}
+
+bool eEPGCache::channel_data::finishEPG()
+{
+ if (!isRunning) // epg ready
+ {
+ eDebug("[EPGC] stop caching events(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
+ zapTimer.start(UPDATE_INTERVAL, 1);
+ eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000);
+ for (int i=0; i < 3; ++i)
+ {
+ seenSections[i].clear();
+ calcedSections[i].clear();
+ }
+ singleLock l(cache->cache_lock);
+ cache->channelLastUpdated[channel->getChannelID()] = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
+ can_delete=1;
+ return true;
+ }
+ return false;
+}
+
+void eEPGCache::channel_data::startEPG()
+{
+ eDebug("[EPGC] start caching events(%d)", eDVBLocalTimeHandler::getInstance()->difference()+time(0));
+ state=0;
+ haveData=0;
+ can_delete=0;
+ for (int i=0; i < 3; ++i)
+ {
+ seenSections[i].clear();
+ calcedSections[i].clear();
+ }
+
+ eDVBSectionFilterMask mask;
+ memset(&mask, 0, sizeof(mask));
+ mask.pid = 0x12;
+ mask.flags = eDVBSectionFilterMask::rfCRC;
+
+ mask.data[0] = 0x4E;
+ mask.mask[0] = 0xFE;
+ m_NowNextReader->connectRead(slot(*this, &eEPGCache::channel_data::readData), m_NowNextConn);
+ m_NowNextReader->start(mask);
+ isRunning |= NOWNEXT;
+
+ mask.data[0] = 0x50;
+ mask.mask[0] = 0xF0;
+ m_ScheduleReader->connectRead(slot(*this, &eEPGCache::channel_data::readData), m_ScheduleConn);
+ m_ScheduleReader->start(mask);
+ isRunning |= SCHEDULE;
+
+ mask.data[0] = 0x60;
+ mask.mask[0] = 0xF0;
+ m_ScheduleOtherReader->connectRead(slot(*this, &eEPGCache::channel_data::readData), m_ScheduleOtherConn);
+ m_ScheduleOtherReader->start(mask);
+ isRunning |= SCHEDULE_OTHER;
+
+ abortTimer.start(7000,true);
+}
+
+void eEPGCache::channel_data::abortNonAvail()
+{
+ if (!state)
+ {
+ if ( !(haveData&eEPGCache::NOWNEXT) && (isRunning&eEPGCache::NOWNEXT) )
+ {
+ eDebug("[EPGC] abort non avail nownext reading");
+ isRunning &= ~eEPGCache::NOWNEXT;
+ m_NowNextReader->stop();
+ m_NowNextConn=0;
+ }
+ if ( !(haveData&eEPGCache::SCHEDULE) && (isRunning&eEPGCache::SCHEDULE) )
+ {
+ eDebug("[EPGC] abort non avail schedule reading");
+ isRunning &= ~SCHEDULE;
+ m_ScheduleReader->stop();
+ m_ScheduleConn=0;
+ }
+ if ( !(haveData&eEPGCache::SCHEDULE_OTHER) && (isRunning&eEPGCache::SCHEDULE_OTHER) )
+ {
+ eDebug("[EPGC] abort non avail schedule_other reading");
+ isRunning &= ~SCHEDULE_OTHER;
+ m_ScheduleOtherReader->stop();
+ m_ScheduleOtherConn=0;
+ }
+ if ( isRunning )
+ abortTimer.start(90000, true);
+ else
+ {
+ ++state;
+ for (int i=0; i < 3; ++i)
+ {
+ seenSections[i].clear();
+ calcedSections[i].clear();
+ }
+ can_delete=1;
+ }
+ }
+ ++state;
+}
+
+void eEPGCache::channel_data::startChannel()
+{
+ updateMap::iterator It = cache->channelLastUpdated.find( channel->getChannelID() );
+
+ int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (time(0)+eDVBLocalTimeHandler::getInstance()->difference()-It->second) * 1000 ) ) : ZAP_DELAY );
+
+ if (update < ZAP_DELAY)
+ update = ZAP_DELAY;
+
+ zapTimer.start(update, 1);
+ if (update >= 60000)
+ eDebug("[EPGC] next update in %i min", update/60000);
+ else if (update >= 1000)
+ eDebug("[EPGC] next update in %i sec", update/1000);
+}
+
+void eEPGCache::channel_data::abortEPG()
+{
+ for (int i=0; i < 3; ++i)
+ {
+ seenSections[i].clear();
+ calcedSections[i].clear();
+ }
+ abortTimer.stop();
+ zapTimer.stop();
+ if (isRunning)
+ {
+ eDebug("[EPGC] abort caching events !!");
+ if (isRunning & eEPGCache::SCHEDULE)
+ {
+ isRunning &= ~eEPGCache::SCHEDULE;
+ m_ScheduleReader->stop();
+ m_ScheduleConn=0;
+ }
+ if (isRunning & eEPGCache::NOWNEXT)
+ {
+ isRunning &= ~eEPGCache::NOWNEXT;
+ m_NowNextReader->stop();
+ m_NowNextConn=0;
+ }
+ if (isRunning & SCHEDULE_OTHER)
+ {
+ isRunning &= ~eEPGCache::SCHEDULE_OTHER;
+ m_ScheduleOtherReader->stop();
+ m_ScheduleOtherConn=0;
+ }
+ can_delete=1;
+ }
+}
+
+void eEPGCache::channel_data::readData( const __u8 *data)
+{
+ if (!data)
+ eDebug("get Null pointer from section reader !!");
+ else
+ {
+ int source;
+ int map;
+ iDVBSectionReader *reader=NULL;
+ switch(data[0])
+ {
+ case 0x4E ... 0x4F:
+ reader=m_NowNextReader;
+ source=eEPGCache::NOWNEXT;
+ map=0;
+ break;
+ case 0x50 ... 0x5F:
+ reader=m_ScheduleReader;
+ source=eEPGCache::SCHEDULE;
+ map=1;
+ break;
+ case 0x60 ... 0x6F:
+ reader=m_ScheduleOtherReader;
+ source=eEPGCache::SCHEDULE_OTHER;
+ map=2;
+ break;
+ default:
+ eDebug("[EPGC] unknown table_id !!!");
+ return;
+ }
+ tidMap &seenSections = this->seenSections[map];
+ tidMap &calcedSections = this->calcedSections[map];
+ if ( state == 1 && calcedSections == seenSections || state > 1 )
+ {
+ eDebugNoNewLine("[EPGC] ");
+ switch (source)
+ {
+ case eEPGCache::NOWNEXT:
+ m_NowNextConn=0;
+ eDebugNoNewLine("nownext");
+ break;
+ case eEPGCache::SCHEDULE:
+ m_ScheduleConn=0;
+ eDebugNoNewLine("schedule");
+ break;
+ case eEPGCache::SCHEDULE_OTHER:
+ m_ScheduleOtherConn=0;
+ eDebugNoNewLine("schedule other");
+ break;
+ default: eDebugNoNewLine("unknown");break;
+ }
+ eDebug(" finished(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
+ if ( reader )
+ reader->stop();
+ isRunning &= ~source;
+ if (!isRunning)
+ finishEPG();
+ }
+ else
+ {
+ eit_t *eit = (eit_t*) data;
+ __u32 sectionNo = data[0] << 24;
+ sectionNo |= data[3] << 16;
+ sectionNo |= data[4] << 8;
+ sectionNo |= eit->section_number;
+
+ tidMap::iterator it =
+ seenSections.find(sectionNo);
+
+ if ( it == seenSections.end() )
+ {
+ seenSections.insert(sectionNo);
+ calcedSections.insert(sectionNo);
+ __u32 tmpval = sectionNo & 0xFFFFFF00;
+ __u8 incr = source == NOWNEXT ? 1 : 8;
+ for ( int i = 0; i <= eit->last_section_number; i+=incr )
+ {
+ if ( i == eit->section_number )
+ {
+ for (int x=i; x <= eit->segment_last_section_number; ++x)
+ calcedSections.insert(tmpval|(x&0xFF));
+ }
+ else
+ calcedSections.insert(tmpval|(i&0xFF));
+ }
+ cache->sectionRead(data, source, this);
+ }
+ }
+ }
+}