1 #include <lib/dvb/epgcache.h>
2 #include <lib/dvb/dvb.h>
7 #include <unistd.h> // for usleep
8 #include <sys/vfs.h> // for statfs
9 // #include <libmd5sum.h>
10 #include <lib/base/eerror.h>
12 int eventData::CacheSize=0;
14 eEPGCache* eEPGCache::instance;
15 pthread_mutex_t eEPGCache::cache_lock=
16 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
17 pthread_mutex_t eEPGCache::channel_map_lock=
18 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
22 eEPGCache::eEPGCache()
23 :messages(this,1), cleanTimer(this)//, paused(0)
25 eDebug("[EPGC] Initialized EPGCache");
27 CONNECT(messages.recv_msg, eEPGCache::gotMessage);
28 CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated);
29 CONNECT(cleanTimer.timeout, eEPGCache::cleanLoop);
31 ePtr<eDVBResourceManager> res_mgr;
32 eDVBResourceManager::getInstance(res_mgr);
34 eDebug("[eEPGCache] no resource manager !!!!!!!");
36 res_mgr->connectChannelAdded(slot(*this,&eEPGCache::DVBChannelAdded), m_chanAddedConn);
40 void eEPGCache::timeUpdated()
42 if ( !thread_running() )
44 eDebug("[EPGC] time updated.. start EPG Mainloop");
48 messages.send(Message(Message::timeChanged));
51 void eEPGCache::DVBChannelAdded(eDVBChannel *chan)
55 eDebug("[eEPGCache] add channel %p", chan);
56 channel_data *data = new channel_data(this);
58 singleLock s(channel_map_lock);
59 m_knownChannels.insert( std::pair<iDVBChannel*, channel_data* >(chan, data) );
60 chan->connectStateChange(slot(*this, &eEPGCache::DVBChannelStateChanged), data->m_stateChangedConn);
64 void eEPGCache::DVBChannelRunning(iDVBChannel *chan)
66 singleLock s(channel_map_lock);
67 channelMapIterator it =
68 m_knownChannels.find(chan);
69 if ( it == m_knownChannels.end() )
70 eDebug("[eEPGCache] will start non existing channel %p !!!", chan);
73 channel_data &data = *it->second;
74 ePtr<eDVBResourceManager> res_mgr;
75 if ( eDVBResourceManager::getInstance( res_mgr ) )
76 eDebug("[eEPGCache] no res manager!!");
79 ePtr<iDVBDemux> demux;
80 if ( data.channel->getDemux(demux) )
82 eDebug("[eEPGCache] no demux!!");
87 RESULT res = demux->createSectionReader( this, data.m_NowNextReader );
90 eDebug("[eEPGCache] couldnt initialize nownext reader!!");
93 data.m_NowNextReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_NowNextConn);
94 res = demux->createSectionReader( this, data.m_ScheduleReader );
97 eDebug("[eEPGCache] couldnt initialize schedule reader!!");
100 data.m_ScheduleReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_ScheduleConn);
101 res = demux->createSectionReader( this, data.m_ScheduleOtherReader );
104 eDebug("[eEPGCache] couldnt initialize schedule other reader!!");
107 data.m_ScheduleOtherReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_ScheduleOtherConn);
108 messages.send(Message(Message::startChannel, chan));
109 // -> gotMessage -> changedService
115 void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan)
117 channelMapIterator it =
118 m_knownChannels.find(chan);
119 if ( it != m_knownChannels.end() )
122 chan->getState(state);
125 case iDVBChannel::state_idle:
127 case iDVBChannel::state_tuning:
129 case iDVBChannel::state_unavailable:
131 case iDVBChannel::state_ok:
133 eDebug("[eEPGCache] channel %p running", chan);
134 DVBChannelRunning(chan);
137 case iDVBChannel::state_release:
139 eDebug("[eEPGCache] remove channel %p", chan);
140 messages.send(Message(Message::leaveChannel, chan));
141 while(!it->second->can_delete)
144 m_knownChannels.erase(it);
145 // -> gotMessage -> abortEPG
152 void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
154 eit_t *eit = (eit_t*) data;
156 int len=HILO(eit->section_length)-1;//+3-4;
161 // This fixed the EPG on the Multichoice irdeto systems
162 // the EIT packet is non-compliant.. their EIT packet stinks
163 if ( data[ptr-1] < 0x40 )
166 uniqueEPGKey service( HILO(eit->service_id), HILO(eit->original_network_id), HILO(eit->transport_stream_id) );
167 eit_event_struct* eit_event = (eit_event_struct*) (data+ptr);
171 time_t TM = parseDVBtime( eit_event->start_time_1, eit_event->start_time_2, eit_event->start_time_3, eit_event->start_time_4, eit_event->start_time_5);
172 time_t now = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
174 if ( TM != 3599 && TM > -1)
175 channel->haveData |= source;
177 singleLock s(cache_lock);
178 // hier wird immer eine eventMap zurück gegeben.. entweder eine vorhandene..
179 // oder eine durch [] erzeugte
180 std::pair<eventMap,timeMap> &servicemap = eventDB[service];
181 eventMap::iterator prevEventIt = servicemap.first.end();
182 timeMap::iterator prevTimeIt = servicemap.second.end();
186 eit_event_size = HILO(eit_event->descriptors_loop_length)+EIT_LOOP_SIZE;
188 duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3);
190 eit_event->start_time_1,
191 eit_event->start_time_2,
192 eit_event->start_time_3,
193 eit_event->start_time_4,
194 eit_event->start_time_5);
199 if ( TM != 3599 && (TM+duration < now || TM > now+14*24*60*60) )
202 if ( now <= (TM+duration) || TM == 3599 /*NVOD Service*/ ) // old events should not be cached
204 __u16 event_id = HILO(eit_event->event_id);
205 // eDebug("event_id is %d sid is %04x", event_id, service.sid);
208 int ev_erase_count = 0;
209 int tm_erase_count = 0;
211 // search in eventmap
212 eventMap::iterator ev_it =
213 servicemap.first.find(event_id);
215 // entry with this event_id is already exist ?
216 if ( ev_it != servicemap.first.end() )
218 if ( source > ev_it->second->type ) // update needed ?
219 goto next; // when not.. the skip this entry
221 // search this event in timemap
222 timeMap::iterator tm_it_tmp =
223 servicemap.second.find(ev_it->second->getStartTime());
225 if ( tm_it_tmp != servicemap.second.end() )
227 if ( tm_it_tmp->first == TM ) // correct eventData
230 delete ev_it->second;
231 evt = new eventData(eit_event, eit_event_size, source);
233 tm_it_tmp->second=evt;
239 // delete the found record from timemap
240 servicemap.second.erase(tm_it_tmp);
241 prevTimeIt=servicemap.second.end();
246 // search in timemap, for check of a case if new time has coincided with time of other event
247 // or event was is not found in eventmap
248 timeMap::iterator tm_it =
249 servicemap.second.find(TM);
251 if ( tm_it != servicemap.second.end() )
253 // i think, if event is not found on eventmap, but found on timemap updating nevertheless demands
255 if ( source > tm_it->second->type && tm_erase_count == 0 ) // update needed ?
256 goto next; // when not.. the skip this entry
259 // search this time in eventmap
260 eventMap::iterator ev_it_tmp =
261 servicemap.first.find(tm_it->second->getEventID());
263 if ( ev_it_tmp != servicemap.first.end() )
266 // delete the found record from eventmap
267 servicemap.first.erase(ev_it_tmp);
268 prevEventIt=servicemap.first.end();
272 evt = new eventData(eit_event, eit_event_size, source);
274 bool consistencyCheck=true;
276 if (ev_erase_count > 0 && tm_erase_count > 0) // 2 different pairs have been removed
279 delete ev_it->second;
280 delete tm_it->second;
284 else if (ev_erase_count == 0 && tm_erase_count > 0)
287 delete ev_it->second;
288 tm_it=prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair<const time_t, eventData*>( TM, evt ) );
291 else if (ev_erase_count > 0 && tm_erase_count == 0)
294 delete tm_it->second;
295 ev_it=prevEventIt=servicemap.first.insert( prevEventIt, std::pair<const __u16, eventData*>( event_id, evt) );
298 else // added new eventData
301 consistencyCheck=false;
303 prevEventIt=servicemap.first.insert( prevEventIt, std::pair<const __u16, eventData*>( event_id, evt) );
304 prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair<const time_t, eventData*>( TM, evt ) );
307 if ( consistencyCheck )
309 if ( tm_it->second != evt || ev_it->second != evt )
310 eFatal("tm_it->second != ev_it->second");
311 else if ( tm_it->second->getStartTime() != tm_it->first )
312 eFatal("event start_time(%d) non equal timemap key(%d)",
313 tm_it->second->getStartTime(), tm_it->first );
314 else if ( tm_it->first != TM )
315 eFatal("timemap key(%d) non equal TM(%d)",
317 else if ( ev_it->second->getEventID() != ev_it->first )
318 eFatal("event_id (%d) non equal event_map key(%d)",
319 ev_it->second->getEventID(), ev_it->first);
320 else if ( ev_it->first != event_id )
321 eFatal("eventmap key(%d) non equal event_id(%d)",
322 ev_it->first, event_id );
328 if ( servicemap.first.size() != servicemap.second.size() )
330 FILE *f = fopen("/hdd/event_map.txt", "w+");
332 for (eventMap::iterator it(servicemap.first.begin())
333 ; it != servicemap.first.end(); ++it )
334 fprintf(f, "%d(key %d) -> time %d, event_id %d, data %p\n",
335 i++, (int)it->first, (int)it->second->getStartTime(), (int)it->second->getEventID(), it->second );
337 f = fopen("/hdd/time_map.txt", "w+");
339 for (timeMap::iterator it(servicemap.second.begin())
340 ; it != servicemap.second.end(); ++it )
341 fprintf(f, "%d(key %d) -> time %d, event_id %d, data %p\n",
342 i++, (int)it->first, (int)it->second->getStartTime(), (int)it->second->getEventID(), it->second );
345 eFatal("(1)map sizes not equal :( sid %04x tsid %04x onid %04x size %d size2 %d",
346 service.sid, service.tsid, service.onid,
347 servicemap.first.size(), servicemap.second.size() );
350 ptr += eit_event_size;
351 eit_event=(eit_event_struct*)(((__u8*)eit_event)+eit_event_size);
355 void eEPGCache::flushEPG(const uniqueEPGKey & s)
357 eDebug("[EPGC] flushEPG %d", (int)(bool)s);
358 singleLock l(cache_lock);
359 if (s) // clear only this service
361 eventCache::iterator it = eventDB.find(s);
362 if ( it != eventDB.end() )
364 eventMap &evMap = it->second.first;
365 timeMap &tmMap = it->second.second;
367 for (eventMap::iterator i = evMap.begin(); i != evMap.end(); ++i)
372 // TODO .. search corresponding channel for removed service and remove this channel from lastupdated map
375 else // clear complete EPG Cache
377 for (eventCache::iterator it(eventDB.begin());
378 it != eventDB.end(); ++it)
380 eventMap &evMap = it->second.first;
381 timeMap &tmMap = it->second.second;
382 for (eventMap::iterator i = evMap.begin(); i != evMap.end(); ++i)
388 channelLastUpdated.clear();
389 singleLock m(channel_map_lock);
390 for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it)
391 it->second->startEPG();
393 eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize);
396 void eEPGCache::cleanLoop()
398 singleLock s(cache_lock);
399 if (!eventDB.empty())
401 eDebug("[EPGC] start cleanloop");
402 const eit_event_struct* cur_event;
405 // FIXME !!! TIME_CORRECTION
406 time_t now = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
408 for (eventCache::iterator DBIt = eventDB.begin(); DBIt != eventDB.end(); DBIt++)
410 for (timeMap::iterator It = DBIt->second.second.begin(); It != DBIt->second.second.end() && It->first < now;)
412 cur_event = (*It->second).get();
413 duration = fromBCD( cur_event->duration_1)*3600 + fromBCD(cur_event->duration_2)*60 + fromBCD(cur_event->duration_3);
415 if ( now > (It->first+duration) ) // outdated normal entry (nvod references to)
417 // remove entry from eventMap
418 eventMap::iterator b(DBIt->second.first.find(It->second->getEventID()));
419 if ( b != DBIt->second.first.end() )
421 // release Heap Memory for this entry (new ....)
422 // eDebug("[EPGC] delete old event (evmap)");
423 DBIt->second.first.erase(b);
426 // remove entry from timeMap
427 // eDebug("[EPGC] release heap mem");
429 DBIt->second.second.erase(It++);
430 // eDebug("[EPGC] delete old event (timeMap)");
436 eDebug("[EPGC] stop cleanloop");
437 eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize);
439 cleanTimer.start(CLEAN_INTERVAL,true);
442 eEPGCache::~eEPGCache()
444 messages.send(Message::quit);
445 kill(); // waiting for thread shutdown
446 singleLock s(cache_lock);
447 for (eventCache::iterator evIt = eventDB.begin(); evIt != eventDB.end(); evIt++)
448 for (eventMap::iterator It = evIt->second.first.begin(); It != evIt->second.first.end(); It++)
452 Event *eEPGCache::lookupEvent(const eServiceReferenceDVB &service, int event_id, bool plain)
454 singleLock s(cache_lock);
455 uniqueEPGKey key( service );
457 eventCache::iterator It = eventDB.find( key );
458 if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached?
460 eventMap::iterator i( It->second.first.find( event_id ));
461 if ( i != It->second.first.end() )
463 if ( service.getServiceType() == 4 ) // nvod ref
464 return lookupEvent( service, i->second->getStartTime(), plain );
466 // get plain data... not in Event Format !!!
467 // before use .. cast it to eit_event_struct*
468 return (Event*) i->second->get();
470 return new Event( (uint8_t*)i->second->get() /*, (It->first.tsid<<16)|It->first.onid*/ );
473 eDebug("event %04x not found in epgcache", event_id);
478 Event *eEPGCache::lookupEvent(const eServiceReferenceDVB &service, time_t t, bool plain )
479 // if t == 0 we search the current event...
481 singleLock s(cache_lock);
482 uniqueEPGKey key(service);
484 // check if EPG for this service is ready...
485 eventCache::iterator It = eventDB.find( key );
486 if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ?
489 t = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
491 timeMap::iterator i = It->second.second.lower_bound(t);
492 if ( i != It->second.second.end() )
495 if ( i != It->second.second.end() )
497 const eit_event_struct* eit_event = i->second->get();
498 int duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3);
499 if ( t <= i->first+duration )
502 // get plain data... not in Event Format !!!
503 // before use .. cast it to eit_event_struct*
504 return (Event*) i->second->get();
505 return new Event( (uint8_t*)i->second->get() /*, (It->first.tsid<<16)|It->first.onid */ );
510 for ( eventMap::iterator i( It->second.first.begin() ); i != It->second.first.end(); i++)
512 const eit_event_struct* eit_event = i->second->get();
513 int duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3);
514 time_t begTime = parseDVBtime( eit_event->start_time_1, eit_event->start_time_2, eit_event->start_time_3, eit_event->start_time_4, eit_event->start_time_5);
515 if ( t >= begTime && t <= begTime+duration) // then we have found
518 // get plain data... not in Event Format !!!
519 // before use .. cast it to eit_event_struct*
520 return (Event*) i->second->get();
521 return new Event( (uint8_t*)i->second->get()/*, (It->first.tsid<<16)|It->first.onid*/ );
528 void eEPGCache::gotMessage( const Message &msg )
533 flushEPG(msg.service);
535 case Message::startChannel:
537 singleLock s(channel_map_lock);
538 channelMapIterator channel =
539 m_knownChannels.find(msg.channel);
540 if ( channel != m_knownChannels.end() )
541 channel->second->startChannel();
544 case Message::leaveChannel:
546 singleLock s(channel_map_lock);
547 channelMapIterator channel =
548 m_knownChannels.find(msg.channel);
549 if ( channel != m_knownChannels.end() )
550 channel->second->abortEPG();
556 case Message::timeChanged:
560 eDebug("unhandled EPGCache Message!!");
565 void eEPGCache::thread()
574 void eEPGCache::load()
577 FILE *f = fopen("/hdd/epg.dat", "r");
580 unsigned char md5_saved[16];
581 unsigned char md5[16];
585 if (!md5_file("/hdd/epg.dat", 1, md5))
587 FILE *f = fopen("/hdd/epg.dat.md5", "r");
590 fread( md5_saved, 16, 1, f);
592 if ( !memcmp(md5_saved, md5, 16) )
598 fread( &size, sizeof(int), 1, f);
605 fread( &key, sizeof(uniqueEPGKey), 1, f);
606 fread( &size, sizeof(int), 1, f);
612 fread( &type, sizeof(int), 1, f);
613 fread( &len, sizeof(int), 1, f);
614 event = new eventData(0, len, type);
615 fread( event->EITdata, len, 1, f);
616 evMap[ event->getEventID() ]=event;
617 tmMap[ event->getStartTime() ]=event;
620 eventDB[key]=std::pair<eventMap,timeMap>(evMap,tmMap);
622 eDebug("%d events read from /hdd/epg.dat.md5", cnt);
629 void eEPGCache::save()
634 if (statfs("/hdd", &s)<0)
642 // prevent writes to builtin flash
643 if ( tmp < 1024*1024*50 ) // storage size < 50MB
646 // check for enough free space on storage
649 if ( tmp < (eventData::CacheSize*12)/10 ) // 20% overhead
652 FILE *f = fopen("/hdd/epg.dat", "w");
656 int size = eventDB.size();
657 fwrite( &size, sizeof(int), 1, f );
658 for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it)
660 timeMap &timemap = service_it->second.second;
661 fwrite( &service_it->first, sizeof(uniqueEPGKey), 1, f);
662 size = timemap.size();
663 fwrite( &size, sizeof(int), 1, f);
664 for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it)
666 int len = time_it->second->ByteSize;
667 fwrite( &time_it->second->type, sizeof(int), 1, f );
668 fwrite( &len, sizeof(int), 1, f);
669 fwrite( time_it->second->EITdata, len, 1, f);
673 eDebug("%d events written to /hdd/epg.dat", cnt);
675 unsigned char md5[16];
676 if (!md5_file("/hdd/epg.dat", 1, md5))
678 FILE *f = fopen("/hdd/epg.dat.md5", "w");
681 fwrite( md5, 16, 1, f);
689 RESULT eEPGCache::getInstance(ePtr<eEPGCache> &ptr)
697 eEPGCache::channel_data::channel_data(eEPGCache *ml)
699 ,abortTimer(ml), zapTimer(ml)
700 ,state(0), isRunning(0), haveData(0), can_delete(1)
702 CONNECT(zapTimer.timeout, eEPGCache::channel_data::startEPG);
703 CONNECT(abortTimer.timeout, eEPGCache::channel_data::abortNonAvail);
706 bool eEPGCache::channel_data::finishEPG()
708 if (!isRunning) // epg ready
710 eDebug("[EPGC] stop caching events(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
711 zapTimer.start(UPDATE_INTERVAL, 1);
712 eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000);
713 for (int i=0; i < 3; ++i)
715 seenSections[i].clear();
716 calcedSections[i].clear();
718 singleLock l(cache->cache_lock);
719 cache->channelLastUpdated[channel->getChannelID()] = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
726 void eEPGCache::channel_data::startEPG()
728 eDebug("[EPGC] start caching events(%d)", eDVBLocalTimeHandler::getInstance()->difference()+time(0));
732 for (int i=0; i < 3; ++i)
734 seenSections[i].clear();
735 calcedSections[i].clear();
738 eDVBSectionFilterMask mask;
739 memset(&mask, 0, sizeof(mask));
741 mask.flags = eDVBSectionFilterMask::rfCRC;
745 m_NowNextReader->start(mask);
746 isRunning |= NOWNEXT;
750 m_ScheduleReader->start(mask);
751 isRunning |= SCHEDULE;
755 m_ScheduleOtherReader->start(mask);
756 isRunning |= SCHEDULE_OTHER;
758 abortTimer.start(7000,true);
761 void eEPGCache::channel_data::abortNonAvail()
765 if ( !(haveData&eEPGCache::NOWNEXT) && (isRunning&eEPGCache::NOWNEXT) )
767 eDebug("[EPGC] abort non avail nownext reading");
768 isRunning &= ~eEPGCache::NOWNEXT;
769 if ( m_NowNextReader )
770 m_NowNextReader->stop();
772 if ( !(haveData&eEPGCache::SCHEDULE) && (isRunning&eEPGCache::SCHEDULE) )
774 eDebug("[EPGC] abort non avail schedule reading");
775 isRunning &= ~SCHEDULE;
776 m_ScheduleReader->stop();
778 if ( !(haveData&eEPGCache::SCHEDULE_OTHER) && (isRunning&eEPGCache::SCHEDULE_OTHER) )
780 eDebug("[EPGC] abort non avail schedule_other reading");
781 isRunning &= ~SCHEDULE_OTHER;
782 m_ScheduleOtherReader->stop();
785 abortTimer.start(50000, true);
789 for (int i=0; i < 3; ++i)
791 seenSections[i].clear();
792 calcedSections[i].clear();
800 void eEPGCache::channel_data::startChannel()
802 updateMap::iterator It = cache->channelLastUpdated.find( channel->getChannelID() );
804 int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (time(0)+eDVBLocalTimeHandler::getInstance()->difference()-It->second) * 1000 ) ) : ZAP_DELAY );
806 if (update < ZAP_DELAY)
809 zapTimer.start(update, 1);
811 eDebug("[EPGC] next update in %i min", update/60000);
812 else if (update >= 1000)
813 eDebug("[EPGC] next update in %i sec", update/1000);
816 void eEPGCache::channel_data::abortEPG()
818 for (int i=0; i < 3; ++i)
820 seenSections[i].clear();
821 calcedSections[i].clear();
827 eDebug("[EPGC] abort caching events !!");
828 if (isRunning & eEPGCache::SCHEDULE)
830 isRunning &= eEPGCache::SCHEDULE;
831 if ( m_ScheduleReader )
832 m_ScheduleReader->stop();
834 if (isRunning & eEPGCache::NOWNEXT)
836 isRunning &= ~eEPGCache::NOWNEXT;
837 if ( m_NowNextReader )
838 m_NowNextReader->stop();
840 if (isRunning & SCHEDULE_OTHER)
842 isRunning &= ~eEPGCache::SCHEDULE_OTHER;
843 if ( m_ScheduleOtherReader )
844 m_ScheduleOtherReader->stop();
850 void eEPGCache::channel_data::readData( const __u8 *data)
853 eDebug("get Null pointer from section reader !!");
858 iDVBSectionReader *reader=NULL;
862 reader=m_NowNextReader;
863 source=eEPGCache::NOWNEXT;
867 reader=m_ScheduleReader;
868 source=eEPGCache::SCHEDULE;
872 reader=m_ScheduleOtherReader;
873 source=eEPGCache::SCHEDULE_OTHER;
877 tidMap &seenSections = this->seenSections[map];
878 tidMap &calcedSections = this->calcedSections[map];
879 if ( state == 1 && calcedSections == seenSections || state > 1 )
881 eDebugNoNewLine("[EPGC] ");
884 case eEPGCache::NOWNEXT: eDebugNoNewLine("nownext");break;
885 case eEPGCache::SCHEDULE: eDebugNoNewLine("schedule");break;
886 case eEPGCache::SCHEDULE_OTHER: eDebugNoNewLine("schedule other");break;
887 default: eDebugNoNewLine("unknown");break;
889 eDebug(" finished(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
891 isRunning &= ~source;
897 eit_t *eit = (eit_t*) data;
898 __u32 sectionNo = data[0] << 24;
899 sectionNo |= data[3] << 16;
900 sectionNo |= data[4] << 8;
901 sectionNo |= eit->section_number;
903 tidMap::iterator it =
904 seenSections.find(sectionNo);
906 if ( it == seenSections.end() )
908 seenSections.insert(sectionNo);
909 __u32 tmpval = sectionNo & 0xFFFFFF00;
910 __u8 incr = source == NOWNEXT ? 1 : 8;
911 for ( int i = 0; i <= eit->last_section_number; i+=incr )
913 if ( i == eit->section_number )
915 for (int x=i; x <= eit->segment_last_section_number; ++x)
916 calcedSections.insert(tmpval|(x&0xFF));
919 calcedSections.insert(tmpval|(i&0xFF));
921 cache->sectionRead(data, source, this);