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;
13 descriptorMap eventData::descriptors;
14 __u8 eventData::data[4108];
15 extern const uint32_t crc32_table[256];
17 eventData::eventData(const eit_event_struct* e, int size, int type)
18 :ByteSize(size&0xFF), type(type&0xFF)
26 __u8 *data = (__u8*)e;
28 int descriptors_length = (data[ptr++]&0x0F) << 8;
29 descriptors_length |= data[ptr++];
30 while ( descriptors_length > 0 )
32 __u8 *descr = data+ptr;
33 int descr_len = descr[1]+2;
37 while(cnt++ < descr_len)
38 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ data[ptr++]) & 0xFF];
40 descriptorMap::iterator it =
41 descriptors.find(crc);
42 if ( it == descriptors.end() )
45 __u8 *d = new __u8[descr_len];
46 memcpy(d, descr, descr_len);
47 descriptors[crc] = descriptorPair(1, d);
53 descriptors_length -= descr_len;
55 ByteSize = 12+((pdescr-descr)*4);
56 EITdata = new __u8[ByteSize];
58 memcpy(EITdata, (__u8*) e, 12);
59 memcpy(EITdata+12, descr, ByteSize-12);
62 const eit_event_struct* eventData::get() const
65 int tmp = ByteSize-12;
67 memcpy(data, EITdata, 12);
68 __u32 *p = (__u32*)(EITdata+12);
71 descriptorMap::iterator it =
72 descriptors.find(*p++);
73 if ( it != descriptors.end() )
75 int b = it->second.second[1]+2;
76 memcpy(data+pos, it->second.second, b );
82 return (const eit_event_struct*)data;
85 eventData::~eventData()
91 __u32 *d = (__u32*)(EITdata+12);
94 descriptorMap::iterator it =
95 descriptors.find(*d++);
96 if ( it != descriptors.end() )
98 descriptorPair &p = it->second;
99 if (!--p.first) // no more used descriptor
101 CacheSize -= it->second.second[1];
102 delete [] it->second.second; // free descriptor memory
103 descriptors.erase(it); // remove entry from descriptor map
112 void eventData::load(FILE *f)
118 fread(&size, sizeof(int), 1, f);
121 fread(&id, sizeof(__u32), 1, f);
122 fread(&p.first, sizeof(int), 1, f);
123 fread(header, 2, 1, f);
124 int bytes = header[1]+2;
125 p.second = new __u8[bytes];
126 p.second[0] = header[0];
127 p.second[1] = header[1];
128 fread(p.second+2, bytes-2, 1, f);
135 void eventData::save(FILE *f)
137 int size=descriptors.size();
138 descriptorMap::iterator it(descriptors.begin());
139 fwrite(&size, sizeof(int), 1, f);
142 fwrite(&it->first, sizeof(__u32), 1, f);
143 fwrite(&it->second.first, sizeof(int), 1, f);
144 fwrite(it->second.second, it->second.second[1]+2, 1, f);
150 eEPGCache* eEPGCache::instance;
151 pthread_mutex_t eEPGCache::cache_lock=
152 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
153 pthread_mutex_t eEPGCache::channel_map_lock=
154 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
156 DEFINE_REF(eEPGCache)
158 eEPGCache::eEPGCache()
159 :messages(this,1), cleanTimer(this)//, paused(0)
161 eDebug("[EPGC] Initialized EPGCache");
163 CONNECT(messages.recv_msg, eEPGCache::gotMessage);
164 CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated);
165 CONNECT(cleanTimer.timeout, eEPGCache::cleanLoop);
167 ePtr<eDVBResourceManager> res_mgr;
168 eDVBResourceManager::getInstance(res_mgr);
170 eDebug("[eEPGCache] no resource manager !!!!!!!");
172 res_mgr->connectChannelAdded(slot(*this,&eEPGCache::DVBChannelAdded), m_chanAddedConn);
176 void eEPGCache::timeUpdated()
178 if ( !thread_running() )
180 eDebug("[EPGC] time updated.. start EPG Mainloop");
184 messages.send(Message(Message::timeChanged));
187 void eEPGCache::DVBChannelAdded(eDVBChannel *chan)
191 // eDebug("[eEPGCache] add channel %p", chan);
192 channel_data *data = new channel_data(this);
193 data->channel = chan;
194 data->prevChannelState = -1;
195 singleLock s(channel_map_lock);
196 m_knownChannels.insert( std::pair<iDVBChannel*, channel_data* >(chan, data) );
197 chan->connectStateChange(slot(*this, &eEPGCache::DVBChannelStateChanged), data->m_stateChangedConn);
201 void eEPGCache::DVBChannelRunning(iDVBChannel *chan)
203 singleLock s(channel_map_lock);
204 channelMapIterator it =
205 m_knownChannels.find(chan);
206 if ( it == m_knownChannels.end() )
207 eDebug("[eEPGCache] will start non existing channel %p !!!", chan);
210 channel_data &data = *it->second;
211 ePtr<eDVBResourceManager> res_mgr;
212 if ( eDVBResourceManager::getInstance( res_mgr ) )
213 eDebug("[eEPGCache] no res manager!!");
216 ePtr<iDVBDemux> demux;
217 if ( data.channel->getDemux(demux, 0) )
219 eDebug("[eEPGCache] no demux!!");
224 RESULT res = demux->createSectionReader( this, data.m_NowNextReader );
227 eDebug("[eEPGCache] couldnt initialize nownext reader!!");
231 res = demux->createSectionReader( this, data.m_ScheduleReader );
234 eDebug("[eEPGCache] couldnt initialize schedule reader!!");
238 res = demux->createSectionReader( this, data.m_ScheduleOtherReader );
241 eDebug("[eEPGCache] couldnt initialize schedule other reader!!");
245 messages.send(Message(Message::startChannel, chan));
246 // -> gotMessage -> changedService
252 void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan)
254 channelMapIterator it =
255 m_knownChannels.find(chan);
256 if ( it != m_knownChannels.end() )
259 chan->getState(state);
260 if ( it->second->prevChannelState != state )
264 case iDVBChannel::state_ok:
266 eDebug("[eEPGCache] channel %p running", chan);
267 DVBChannelRunning(chan);
270 case iDVBChannel::state_release:
272 eDebug("[eEPGCache] remove channel %p", chan);
273 messages.send(Message(Message::leaveChannel, chan));
274 while(!it->second->can_delete)
277 m_knownChannels.erase(it);
278 // -> gotMessage -> abortEPG
281 default: // ignore all other events
284 it->second->prevChannelState = state;
289 void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
291 eit_t *eit = (eit_t*) data;
293 int len=HILO(eit->section_length)-1;//+3-4;
298 // This fixed the EPG on the Multichoice irdeto systems
299 // the EIT packet is non-compliant.. their EIT packet stinks
300 if ( data[ptr-1] < 0x40 )
303 uniqueEPGKey service( HILO(eit->service_id), HILO(eit->original_network_id), HILO(eit->transport_stream_id) );
304 eit_event_struct* eit_event = (eit_event_struct*) (data+ptr);
308 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);
309 time_t now = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
311 if ( TM != 3599 && TM > -1)
312 channel->haveData |= source;
314 singleLock s(cache_lock);
315 // hier wird immer eine eventMap zurück gegeben.. entweder eine vorhandene..
316 // oder eine durch [] erzeugte
317 std::pair<eventMap,timeMap> &servicemap = eventDB[service];
318 eventMap::iterator prevEventIt = servicemap.first.end();
319 timeMap::iterator prevTimeIt = servicemap.second.end();
323 eit_event_size = HILO(eit_event->descriptors_loop_length)+EIT_LOOP_SIZE;
325 duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3);
327 eit_event->start_time_1,
328 eit_event->start_time_2,
329 eit_event->start_time_3,
330 eit_event->start_time_4,
331 eit_event->start_time_5);
336 if ( TM != 3599 && (TM+duration < now || TM > now+14*24*60*60) )
339 if ( now <= (TM+duration) || TM == 3599 /*NVOD Service*/ ) // old events should not be cached
341 __u16 event_id = HILO(eit_event->event_id);
342 // eDebug("event_id is %d sid is %04x", event_id, service.sid);
345 int ev_erase_count = 0;
346 int tm_erase_count = 0;
348 // search in eventmap
349 eventMap::iterator ev_it =
350 servicemap.first.find(event_id);
352 // entry with this event_id is already exist ?
353 if ( ev_it != servicemap.first.end() )
355 if ( source > ev_it->second->type ) // update needed ?
356 goto next; // when not.. the skip this entry
358 // search this event in timemap
359 timeMap::iterator tm_it_tmp =
360 servicemap.second.find(ev_it->second->getStartTime());
362 if ( tm_it_tmp != servicemap.second.end() )
364 if ( tm_it_tmp->first == TM ) // correct eventData
367 delete ev_it->second;
368 evt = new eventData(eit_event, eit_event_size, source);
370 tm_it_tmp->second=evt;
376 // delete the found record from timemap
377 servicemap.second.erase(tm_it_tmp);
378 prevTimeIt=servicemap.second.end();
383 // search in timemap, for check of a case if new time has coincided with time of other event
384 // or event was is not found in eventmap
385 timeMap::iterator tm_it =
386 servicemap.second.find(TM);
388 if ( tm_it != servicemap.second.end() )
390 // i think, if event is not found on eventmap, but found on timemap updating nevertheless demands
392 if ( source > tm_it->second->type && tm_erase_count == 0 ) // update needed ?
393 goto next; // when not.. the skip this entry
396 // search this time in eventmap
397 eventMap::iterator ev_it_tmp =
398 servicemap.first.find(tm_it->second->getEventID());
400 if ( ev_it_tmp != servicemap.first.end() )
403 // delete the found record from eventmap
404 servicemap.first.erase(ev_it_tmp);
405 prevEventIt=servicemap.first.end();
409 evt = new eventData(eit_event, eit_event_size, source);
411 bool consistencyCheck=true;
413 if (ev_erase_count > 0 && tm_erase_count > 0) // 2 different pairs have been removed
416 delete ev_it->second;
417 delete tm_it->second;
421 else if (ev_erase_count == 0 && tm_erase_count > 0)
424 delete ev_it->second;
425 tm_it=prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair<const time_t, eventData*>( TM, evt ) );
428 else if (ev_erase_count > 0 && tm_erase_count == 0)
431 delete tm_it->second;
432 ev_it=prevEventIt=servicemap.first.insert( prevEventIt, std::pair<const __u16, eventData*>( event_id, evt) );
435 else // added new eventData
438 consistencyCheck=false;
440 prevEventIt=servicemap.first.insert( prevEventIt, std::pair<const __u16, eventData*>( event_id, evt) );
441 prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair<const time_t, eventData*>( TM, evt ) );
444 if ( consistencyCheck )
446 if ( tm_it->second != evt || ev_it->second != evt )
447 eFatal("tm_it->second != ev_it->second");
448 else if ( tm_it->second->getStartTime() != tm_it->first )
449 eFatal("event start_time(%d) non equal timemap key(%d)",
450 tm_it->second->getStartTime(), tm_it->first );
451 else if ( tm_it->first != TM )
452 eFatal("timemap key(%d) non equal TM(%d)",
454 else if ( ev_it->second->getEventID() != ev_it->first )
455 eFatal("event_id (%d) non equal event_map key(%d)",
456 ev_it->second->getEventID(), ev_it->first);
457 else if ( ev_it->first != event_id )
458 eFatal("eventmap key(%d) non equal event_id(%d)",
459 ev_it->first, event_id );
465 if ( servicemap.first.size() != servicemap.second.size() )
467 FILE *f = fopen("/hdd/event_map.txt", "w+");
469 for (eventMap::iterator it(servicemap.first.begin())
470 ; it != servicemap.first.end(); ++it )
471 fprintf(f, "%d(key %d) -> time %d, event_id %d, data %p\n",
472 i++, (int)it->first, (int)it->second->getStartTime(), (int)it->second->getEventID(), it->second );
474 f = fopen("/hdd/time_map.txt", "w+");
476 for (timeMap::iterator it(servicemap.second.begin())
477 ; it != servicemap.second.end(); ++it )
478 fprintf(f, "%d(key %d) -> time %d, event_id %d, data %p\n",
479 i++, (int)it->first, (int)it->second->getStartTime(), (int)it->second->getEventID(), it->second );
482 eFatal("(1)map sizes not equal :( sid %04x tsid %04x onid %04x size %d size2 %d",
483 service.sid, service.tsid, service.onid,
484 servicemap.first.size(), servicemap.second.size() );
487 ptr += eit_event_size;
488 eit_event=(eit_event_struct*)(((__u8*)eit_event)+eit_event_size);
492 void eEPGCache::flushEPG(const uniqueEPGKey & s)
494 eDebug("[EPGC] flushEPG %d", (int)(bool)s);
495 singleLock l(cache_lock);
496 if (s) // clear only this service
498 eventCache::iterator it = eventDB.find(s);
499 if ( it != eventDB.end() )
501 eventMap &evMap = it->second.first;
502 timeMap &tmMap = it->second.second;
504 for (eventMap::iterator i = evMap.begin(); i != evMap.end(); ++i)
509 // TODO .. search corresponding channel for removed service and remove this channel from lastupdated map
512 else // clear complete EPG Cache
514 for (eventCache::iterator it(eventDB.begin());
515 it != eventDB.end(); ++it)
517 eventMap &evMap = it->second.first;
518 timeMap &tmMap = it->second.second;
519 for (eventMap::iterator i = evMap.begin(); i != evMap.end(); ++i)
525 channelLastUpdated.clear();
526 singleLock m(channel_map_lock);
527 for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it)
528 it->second->startEPG();
530 eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize);
533 void eEPGCache::cleanLoop()
535 singleLock s(cache_lock);
536 if (!eventDB.empty())
538 eDebug("[EPGC] start cleanloop");
540 time_t now = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
542 for (eventCache::iterator DBIt = eventDB.begin(); DBIt != eventDB.end(); DBIt++)
544 for (timeMap::iterator It = DBIt->second.second.begin(); It != DBIt->second.second.end() && It->first < now;)
546 if ( now > (It->first+It->second->getDuration()) ) // outdated normal entry (nvod references to)
548 // remove entry from eventMap
549 eventMap::iterator b(DBIt->second.first.find(It->second->getEventID()));
550 if ( b != DBIt->second.first.end() )
552 // release Heap Memory for this entry (new ....)
553 // eDebug("[EPGC] delete old event (evmap)");
554 DBIt->second.first.erase(b);
557 // remove entry from timeMap
558 // eDebug("[EPGC] release heap mem");
560 DBIt->second.second.erase(It++);
561 // eDebug("[EPGC] delete old event (timeMap)");
567 eDebug("[EPGC] stop cleanloop");
568 eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize);
570 cleanTimer.start(CLEAN_INTERVAL,true);
573 eEPGCache::~eEPGCache()
575 messages.send(Message::quit);
576 kill(); // waiting for thread shutdown
577 singleLock s(cache_lock);
578 for (eventCache::iterator evIt = eventDB.begin(); evIt != eventDB.end(); evIt++)
579 for (eventMap::iterator It = evIt->second.first.begin(); It != evIt->second.first.end(); It++)
583 void eEPGCache::gotMessage( const Message &msg )
588 flushEPG(msg.service);
590 case Message::startChannel:
592 singleLock s(channel_map_lock);
593 channelMapIterator channel =
594 m_knownChannels.find(msg.channel);
595 if ( channel != m_knownChannels.end() )
596 channel->second->startChannel();
599 case Message::leaveChannel:
601 singleLock s(channel_map_lock);
602 channelMapIterator channel =
603 m_knownChannels.find(msg.channel);
604 if ( channel != m_knownChannels.end() )
605 channel->second->abortEPG();
611 case Message::timeChanged:
615 eDebug("unhandled EPGCache Message!!");
620 void eEPGCache::thread()
629 void eEPGCache::load()
632 FILE *f = fopen("/hdd/epg.dat", "r");
635 unsigned char md5_saved[16];
636 unsigned char md5[16];
640 if (!md5_file("/hdd/epg.dat", 1, md5))
642 FILE *f = fopen("/hdd/epg.dat.md5", "r");
645 fread( md5_saved, 16, 1, f);
647 if ( !memcmp(md5_saved, md5, 16) )
654 fread( text1, 13, 1, f);
655 if ( !strncmp( text1, "ENIGMA_EPG_V4", 13) )
657 fread( &size, sizeof(int), 1, f);
664 fread( &key, sizeof(uniqueEPGKey), 1, f);
665 fread( &size, sizeof(int), 1, f);
671 fread( &type, sizeof(__u8), 1, f);
672 fread( &len, sizeof(__u8), 1, f);
673 event = new eventData(0, len, type);
674 event->EITdata = new __u8[len];
675 eventData::CacheSize+=len;
676 fread( event->EITdata, len, 1, f);
677 evMap[ event->getEventID() ]=event;
678 tmMap[ event->getStartTime() ]=event;
681 eventDB[key]=std::pair<eventMap,timeMap>(evMap,tmMap);
684 eDebug("%d events read from /hdd/epg.dat", cnt);
687 eDebug("[EPGC] don't read old epg database");
694 void eEPGCache::save()
699 if (statfs("/hdd", &s)<0)
707 // prevent writes to builtin flash
708 if ( tmp < 1024*1024*50 ) // storage size < 50MB
711 // check for enough free space on storage
714 if ( tmp < (eventData::CacheSize*12)/10 ) // 20% overhead
717 FILE *f = fopen("/hdd/epg.dat", "w");
721 const char *text = "ENIGMA_EPG_V4";
722 fwrite( text, 13, 1, f );
723 int size = eventDB.size();
724 fwrite( &size, sizeof(int), 1, f );
725 for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it)
727 timeMap &timemap = service_it->second.second;
728 fwrite( &service_it->first, sizeof(uniqueEPGKey), 1, f);
729 size = timemap.size();
730 fwrite( &size, sizeof(int), 1, f);
731 for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it)
733 __u8 len = time_it->second->ByteSize;
734 fwrite( &time_it->second->type, sizeof(__u8), 1, f );
735 fwrite( &len, sizeof(__u8), 1, f);
736 fwrite( time_it->second->EITdata, len, 1, f);
740 eDebug("%d events written to /hdd/epg.dat", cnt);
743 unsigned char md5[16];
744 if (!md5_file("/hdd/epg.dat", 1, md5))
746 FILE *f = fopen("/hdd/epg.dat.md5", "w");
749 fwrite( md5, 16, 1, f);
757 eEPGCache::channel_data::channel_data(eEPGCache *ml)
759 ,abortTimer(ml), zapTimer(ml)
760 ,state(0), isRunning(0), haveData(0), can_delete(1)
762 CONNECT(zapTimer.timeout, eEPGCache::channel_data::startEPG);
763 CONNECT(abortTimer.timeout, eEPGCache::channel_data::abortNonAvail);
766 bool eEPGCache::channel_data::finishEPG()
768 if (!isRunning) // epg ready
770 eDebug("[EPGC] stop caching events(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
771 zapTimer.start(UPDATE_INTERVAL, 1);
772 eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000);
773 for (int i=0; i < 3; ++i)
775 seenSections[i].clear();
776 calcedSections[i].clear();
778 singleLock l(cache->cache_lock);
779 cache->channelLastUpdated[channel->getChannelID()] = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
786 void eEPGCache::channel_data::startEPG()
788 eDebug("[EPGC] start caching events(%d)", eDVBLocalTimeHandler::getInstance()->difference()+time(0));
792 for (int i=0; i < 3; ++i)
794 seenSections[i].clear();
795 calcedSections[i].clear();
798 eDVBSectionFilterMask mask;
799 memset(&mask, 0, sizeof(mask));
801 mask.flags = eDVBSectionFilterMask::rfCRC;
805 m_NowNextReader->connectRead(slot(*this, &eEPGCache::channel_data::readData), m_NowNextConn);
806 m_NowNextReader->start(mask);
807 isRunning |= NOWNEXT;
811 m_ScheduleReader->connectRead(slot(*this, &eEPGCache::channel_data::readData), m_ScheduleConn);
812 m_ScheduleReader->start(mask);
813 isRunning |= SCHEDULE;
817 m_ScheduleOtherReader->connectRead(slot(*this, &eEPGCache::channel_data::readData), m_ScheduleOtherConn);
818 m_ScheduleOtherReader->start(mask);
819 isRunning |= SCHEDULE_OTHER;
821 abortTimer.start(7000,true);
824 void eEPGCache::channel_data::abortNonAvail()
828 if ( !(haveData&eEPGCache::NOWNEXT) && (isRunning&eEPGCache::NOWNEXT) )
830 eDebug("[EPGC] abort non avail nownext reading");
831 isRunning &= ~eEPGCache::NOWNEXT;
832 m_NowNextReader->stop();
835 if ( !(haveData&eEPGCache::SCHEDULE) && (isRunning&eEPGCache::SCHEDULE) )
837 eDebug("[EPGC] abort non avail schedule reading");
838 isRunning &= ~SCHEDULE;
839 m_ScheduleReader->stop();
842 if ( !(haveData&eEPGCache::SCHEDULE_OTHER) && (isRunning&eEPGCache::SCHEDULE_OTHER) )
844 eDebug("[EPGC] abort non avail schedule_other reading");
845 isRunning &= ~SCHEDULE_OTHER;
846 m_ScheduleOtherReader->stop();
847 m_ScheduleOtherConn=0;
850 abortTimer.start(90000, true);
854 for (int i=0; i < 3; ++i)
856 seenSections[i].clear();
857 calcedSections[i].clear();
865 void eEPGCache::channel_data::startChannel()
867 updateMap::iterator It = cache->channelLastUpdated.find( channel->getChannelID() );
869 int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (time(0)+eDVBLocalTimeHandler::getInstance()->difference()-It->second) * 1000 ) ) : ZAP_DELAY );
871 if (update < ZAP_DELAY)
874 zapTimer.start(update, 1);
876 eDebug("[EPGC] next update in %i min", update/60000);
877 else if (update >= 1000)
878 eDebug("[EPGC] next update in %i sec", update/1000);
881 void eEPGCache::channel_data::abortEPG()
883 for (int i=0; i < 3; ++i)
885 seenSections[i].clear();
886 calcedSections[i].clear();
892 eDebug("[EPGC] abort caching events !!");
893 if (isRunning & eEPGCache::SCHEDULE)
895 isRunning &= ~eEPGCache::SCHEDULE;
896 m_ScheduleReader->stop();
899 if (isRunning & eEPGCache::NOWNEXT)
901 isRunning &= ~eEPGCache::NOWNEXT;
902 m_NowNextReader->stop();
905 if (isRunning & SCHEDULE_OTHER)
907 isRunning &= ~eEPGCache::SCHEDULE_OTHER;
908 m_ScheduleOtherReader->stop();
909 m_ScheduleOtherConn=0;
915 void eEPGCache::channel_data::readData( const __u8 *data)
918 eDebug("get Null pointer from section reader !!");
923 iDVBSectionReader *reader=NULL;
927 reader=m_NowNextReader;
928 source=eEPGCache::NOWNEXT;
932 reader=m_ScheduleReader;
933 source=eEPGCache::SCHEDULE;
937 reader=m_ScheduleOtherReader;
938 source=eEPGCache::SCHEDULE_OTHER;
942 eDebug("[EPGC] unknown table_id !!!");
945 tidMap &seenSections = this->seenSections[map];
946 tidMap &calcedSections = this->calcedSections[map];
947 if ( state == 1 && calcedSections == seenSections || state > 1 )
949 eDebugNoNewLine("[EPGC] ");
952 case eEPGCache::NOWNEXT:
954 eDebugNoNewLine("nownext");
956 case eEPGCache::SCHEDULE:
958 eDebugNoNewLine("schedule");
960 case eEPGCache::SCHEDULE_OTHER:
961 m_ScheduleOtherConn=0;
962 eDebugNoNewLine("schedule other");
964 default: eDebugNoNewLine("unknown");break;
966 eDebug(" finished(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
969 isRunning &= ~source;
975 eit_t *eit = (eit_t*) data;
976 __u32 sectionNo = data[0] << 24;
977 sectionNo |= data[3] << 16;
978 sectionNo |= data[4] << 8;
979 sectionNo |= eit->section_number;
981 tidMap::iterator it =
982 seenSections.find(sectionNo);
984 if ( it == seenSections.end() )
986 seenSections.insert(sectionNo);
987 calcedSections.insert(sectionNo);
988 __u32 tmpval = sectionNo & 0xFFFFFF00;
989 __u8 incr = source == NOWNEXT ? 1 : 8;
990 for ( int i = 0; i <= eit->last_section_number; i+=incr )
992 if ( i == eit->section_number )
994 for (int x=i; x <= eit->segment_last_section_number; ++x)
995 calcedSections.insert(tmpval|(x&0xFF));
998 calcedSections.insert(tmpval|(i&0xFF));
1000 cache->sectionRead(data, source, this);
1006 RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, const eventData *&result )
1007 // if t == 0 we search the current event...
1009 singleLock s(cache_lock);
1010 uniqueEPGKey key(service);
1012 // check if EPG for this service is ready...
1013 eventCache::iterator It = eventDB.find( key );
1014 if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ?
1017 t = time(0)+eDVBLocalTimeHandler::getInstance()->difference();
1018 timeMap::iterator i = It->second.second.lower_bound(t); // find > or equal
1019 if ( i != It->second.second.end() )
1021 if ( i->second->getStartTime() != t )
1023 timeMap::iterator x = i;
1025 if ( x != It->second.second.end() )
1027 time_t start_time = x->second->getStartTime();
1030 if (t > (start_time+x->second->getDuration()))
1044 RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, const eit_event_struct *&result )
1046 singleLock s(cache_lock);
1047 const eventData *data=0;
1048 RESULT ret = lookupEventTime(service, t, data);
1050 result = data->get();
1054 RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, Event *& result )
1056 singleLock s(cache_lock);
1057 const eventData *data=0;
1058 RESULT ret = lookupEventTime(service, t, data);
1060 result = new Event((uint8_t*)data->get());
1064 RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, ePtr<eServiceEvent> &result )
1066 singleLock s(cache_lock);
1067 const eventData *data=0;
1068 RESULT ret = lookupEventTime(service, t, data);
1071 Event ev((uint8_t*)data->get());
1072 result = new eServiceEvent();
1073 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)service;
1074 ret = result->parseFrom(&ev, (ref.getTransportStreamID().get()<<16)|ref.getOriginalNetworkID().get());
1079 RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, const eventData *&result )
1081 singleLock s(cache_lock);
1082 uniqueEPGKey key( service );
1084 eventCache::iterator It = eventDB.find( key );
1085 if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached?
1087 eventMap::iterator i( It->second.first.find( event_id ));
1088 if ( i != It->second.first.end() )
1096 eDebug("event %04x not found in epgcache", event_id);
1102 RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, const eit_event_struct *&result)
1104 singleLock s(cache_lock);
1105 const eventData *data=0;
1106 RESULT ret = lookupEventId(service, event_id, data);
1108 result = data->get();
1112 RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, Event *& result)
1114 singleLock s(cache_lock);
1115 const eventData *data=0;
1116 RESULT ret = lookupEventId(service, event_id, data);
1118 result = new Event((uint8_t*)data->get());
1122 RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, ePtr<eServiceEvent> &result)
1124 singleLock s(cache_lock);
1125 const eventData *data=0;
1126 RESULT ret = lookupEventId(service, event_id, data);
1129 Event ev((uint8_t*)data->get());
1130 result = new eServiceEvent();
1131 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)service;
1132 ret = result->parseFrom(&ev, (ref.getTransportStreamID().get()<<16)|ref.getOriginalNetworkID().get());
1137 RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes)
1139 eventCache::iterator It = eventDB.find( service );
1140 if ( It != eventDB.end() && It->second.second.size() )
1142 m_timemap_end = minutes != -1 ? It->second.second.upper_bound(begin+minutes*60) : It->second.second.end();
1145 m_timemap_cursor = It->second.second.lower_bound(begin);
1146 if ( m_timemap_cursor != It->second.second.end() )
1148 if ( m_timemap_cursor->second->getStartTime() != begin )
1150 timeMap::iterator x = m_timemap_cursor;
1152 if ( x != It->second.second.end() )
1154 time_t start_time = x->second->getStartTime();
1155 if ( begin > start_time && begin < (start_time+x->second->getDuration()))
1156 m_timemap_cursor = x;
1162 m_timemap_cursor = It->second.second.begin();
1163 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)service;
1164 currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get();
1170 RESULT eEPGCache::getNextTimeEntry(const eventData *& result)
1172 if ( m_timemap_cursor != m_timemap_end )
1174 result = m_timemap_cursor++->second;
1180 RESULT eEPGCache::getNextTimeEntry(const eit_event_struct *&result)
1182 if ( m_timemap_cursor != m_timemap_end )
1184 result = m_timemap_cursor++->second->get();
1190 RESULT eEPGCache::getNextTimeEntry(Event *&result)
1192 if ( m_timemap_cursor != m_timemap_end )
1194 result = new Event((uint8_t*)m_timemap_cursor++->second->get());
1200 RESULT eEPGCache::getNextTimeEntry(ePtr<eServiceEvent> &result)
1202 if ( m_timemap_cursor != m_timemap_end )
1204 Event ev((uint8_t*)m_timemap_cursor++->second->get());
1205 result = new eServiceEvent();
1206 return result->parseFrom(&ev, currentQueryTsidOnid);