X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/0560f2a18da104507c1a44cfc96ad5812307f5f3..afb996e31e73607e2ef25ba679a15f15c94701e4:/lib/dvb/epgcache.cpp diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index bc857176..c1f294a6 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -10,6 +10,142 @@ #include int eventData::CacheSize=0; +descriptorMap eventData::descriptors; +__u8 eventData::data[4108]; +extern const uint32_t crc32_table[256]; + +eventData::eventData(const eit_event_struct* e, int size, int type) + :ByteSize(size&0xFF), type(type&0xFF) +{ + if (!e) + return; + + __u32 descr[65]; + __u32 *pdescr=descr; + + __u8 *data = (__u8*)e; + int ptr=10; + int descriptors_length = (data[ptr++]&0x0F) << 8; + descriptors_length |= data[ptr++]; + while ( descriptors_length > 0 ) + { + __u8 *descr = data+ptr; + int descr_len = descr[1]+2; + + __u32 crc = 0; + int cnt=0; + while(cnt++ < descr_len) + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ data[ptr++]) & 0xFF]; + + descriptorMap::iterator it = + descriptors.find(crc); + if ( it == descriptors.end() ) + { + CacheSize+=descr_len; + __u8 *d = new __u8[descr_len]; + memcpy(d, descr, descr_len); + descriptors[crc] = descriptorPair(1, d); + } + else + ++it->second.first; + + *pdescr++=crc; + descriptors_length -= descr_len; + } + ByteSize = 12+((pdescr-descr)*4); + EITdata = new __u8[ByteSize]; + CacheSize+=ByteSize; + memcpy(EITdata, (__u8*) e, 12); + memcpy(EITdata+12, descr, ByteSize-12); +} + +const eit_event_struct* eventData::get() const +{ + int pos = 12; + int tmp = ByteSize-12; + + memcpy(data, EITdata, 12); + __u32 *p = (__u32*)(EITdata+12); + while(tmp>0) + { + descriptorMap::iterator it = + descriptors.find(*p++); + if ( it != descriptors.end() ) + { + int b = it->second.second[1]+2; + memcpy(data+pos, it->second.second, b ); + pos += b; + } + tmp-=4; + } + + return (const eit_event_struct*)data; +} + +eventData::~eventData() +{ + if ( ByteSize ) + { + CacheSize-=ByteSize; + ByteSize-=12; + __u32 *d = (__u32*)(EITdata+12); + while(ByteSize) + { + descriptorMap::iterator it = + descriptors.find(*d++); + if ( it != descriptors.end() ) + { + descriptorPair &p = it->second; + if (!--p.first) // no more used descriptor + { + CacheSize -= it->second.second[1]; + delete [] it->second.second; // free descriptor memory + descriptors.erase(it); // remove entry from descriptor map + } + } + ByteSize-=4; + } + delete [] EITdata; + } +} + +void eventData::load(FILE *f) +{ + int size=0; + int id=0; + __u8 header[2]; + descriptorPair p; + fread(&size, sizeof(int), 1, f); + while(size) + { + fread(&id, sizeof(__u32), 1, f); + fread(&p.first, sizeof(int), 1, f); + fread(header, 2, 1, f); + int bytes = header[1]+2; + p.second = new __u8[bytes]; + p.second[0] = header[0]; + p.second[1] = header[1]; + fread(p.second+2, bytes-2, 1, f); + descriptors[id]=p; + --size; + CacheSize+=bytes; + } +} + +void eventData::save(FILE *f) +{ + int size=descriptors.size(); + descriptorMap::iterator it(descriptors.begin()); + fwrite(&size, sizeof(int), 1, f); + while(size) + { + fwrite(&it->first, sizeof(__u32), 1, f); + fwrite(&it->second.first, sizeof(int), 1, f); + fwrite(it->second.second, it->second.second[1]+2, 1, f); + ++it; + --size; + } +} eEPGCache* eEPGCache::instance; pthread_mutex_t eEPGCache::cache_lock= @@ -52,7 +188,7 @@ void eEPGCache::DVBChannelAdded(eDVBChannel *chan) { if ( chan ) { - eDebug("[eEPGCache] add channel %p", chan); +// eDebug("[eEPGCache] add channel %p", chan); channel_data *data = new channel_data(this); data->channel = chan; singleLock s(channel_map_lock); @@ -77,7 +213,7 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan) else { ePtr demux; - if ( data.channel->getDemux(demux) ) + if ( data.channel->getDemux(demux, 0) ) { eDebug("[eEPGCache] no demux!!"); return; @@ -90,21 +226,21 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan) eDebug("[eEPGCache] couldnt initialize nownext reader!!"); return; } - data.m_NowNextReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_NowNextConn); + res = demux->createSectionReader( this, data.m_ScheduleReader ); if ( res ) { eDebug("[eEPGCache] couldnt initialize schedule reader!!"); return; } - data.m_ScheduleReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_ScheduleConn); + res = demux->createSectionReader( this, data.m_ScheduleOtherReader ); if ( res ) { eDebug("[eEPGCache] couldnt initialize schedule other reader!!"); return; } - data.m_ScheduleOtherReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_ScheduleOtherConn); + messages.send(Message(Message::startChannel, chan)); // -> gotMessage -> changedService } @@ -122,12 +258,6 @@ void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan) chan->getState(state); switch (state) { - case iDVBChannel::state_idle: - break; - case iDVBChannel::state_tuning: - break; - case iDVBChannel::state_unavailable: - break; case iDVBChannel::state_ok: { eDebug("[eEPGCache] channel %p running", chan); @@ -399,20 +529,14 @@ void eEPGCache::cleanLoop() if (!eventDB.empty()) { eDebug("[EPGC] start cleanloop"); - const eit_event_struct* cur_event; - int duration; -// FIXME !!! TIME_CORRECTION time_t now = time(0)+eDVBLocalTimeHandler::getInstance()->difference(); for (eventCache::iterator DBIt = eventDB.begin(); DBIt != eventDB.end(); DBIt++) { for (timeMap::iterator It = DBIt->second.second.begin(); It != DBIt->second.second.end() && It->first < now;) { - cur_event = (*It->second).get(); - duration = fromBCD( cur_event->duration_1)*3600 + fromBCD(cur_event->duration_2)*60 + fromBCD(cur_event->duration_3); - - if ( now > (It->first+duration) ) // outdated normal entry (nvod references to) + if ( now > (It->first+It->second->getDuration()) ) // outdated normal entry (nvod references to) { // remove entry from eventMap eventMap::iterator b(DBIt->second.first.find(It->second->getEventID())); @@ -449,82 +573,6 @@ eEPGCache::~eEPGCache() delete It->second; } -Event *eEPGCache::lookupEvent(const eServiceReferenceDVB &service, int event_id, bool plain) -{ - singleLock s(cache_lock); - uniqueEPGKey key( service ); - - eventCache::iterator It = eventDB.find( key ); - if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached? - { - eventMap::iterator i( It->second.first.find( event_id )); - if ( i != It->second.first.end() ) - { - if ( service.getServiceType() == 4 ) // nvod ref - return lookupEvent( service, i->second->getStartTime(), plain ); - else if ( plain ) - // get plain data... not in Event Format !!! - // before use .. cast it to eit_event_struct* - return (Event*) i->second->get(); - else - return new Event( (uint8_t*)i->second->get() /*, (It->first.tsid<<16)|It->first.onid*/ ); - } - else - eDebug("event %04x not found in epgcache", event_id); - } - return 0; -} - -Event *eEPGCache::lookupEvent(const eServiceReferenceDVB &service, time_t t, bool plain ) -// if t == 0 we search the current event... -{ - singleLock s(cache_lock); - uniqueEPGKey key(service); - - // check if EPG for this service is ready... - eventCache::iterator It = eventDB.find( key ); - if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ? - { - if (!t) - t = time(0)+eDVBLocalTimeHandler::getInstance()->difference(); - - timeMap::iterator i = It->second.second.lower_bound(t); - if ( i != It->second.second.end() ) - { - i--; - if ( i != It->second.second.end() ) - { - const eit_event_struct* eit_event = i->second->get(); - int duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3); - if ( t <= i->first+duration ) - { - if ( plain ) - // get plain data... not in Event Format !!! - // before use .. cast it to eit_event_struct* - return (Event*) i->second->get(); - return new Event( (uint8_t*)i->second->get() /*, (It->first.tsid<<16)|It->first.onid */ ); - } - } - } - - for ( eventMap::iterator i( It->second.first.begin() ); i != It->second.first.end(); i++) - { - const eit_event_struct* eit_event = i->second->get(); - int duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3); - 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); - if ( t >= begTime && t <= begTime+duration) // then we have found - { - if ( plain ) - // get plain data... not in Event Format !!! - // before use .. cast it to eit_event_struct* - return (Event*) i->second->get(); - return new Event( (uint8_t*)i->second->get()/*, (It->first.tsid<<16)|It->first.onid*/ ); - } - } - } - return 0; -} - void eEPGCache::gotMessage( const Message &msg ) { switch (msg.type) @@ -595,33 +643,43 @@ void eEPGCache::load() } if ( md5ok ) { - fread( &size, sizeof(int), 1, f); - while(size--) + char text1[13]; + fread( text1, 13, 1, f); + if ( !strncmp( text1, "ENIGMA_EPG_V4", 13) ) { - uniqueEPGKey key; - eventMap evMap; - timeMap tmMap; - int size=0; - fread( &key, sizeof(uniqueEPGKey), 1, f); fread( &size, sizeof(int), 1, f); while(size--) { - int len=0; - int type=0; - eventData *event=0; - fread( &type, sizeof(int), 1, f); - fread( &len, sizeof(int), 1, f); - event = new eventData(0, len, type); - fread( event->EITdata, len, 1, f); - evMap[ event->getEventID() ]=event; - tmMap[ event->getStartTime() ]=event; - ++cnt; + uniqueEPGKey key; + eventMap evMap; + timeMap tmMap; + int size=0; + fread( &key, sizeof(uniqueEPGKey), 1, f); + fread( &size, sizeof(int), 1, f); + while(size--) + { + __u8 len=0; + __u8 type=0; + eventData *event=0; + fread( &type, sizeof(__u8), 1, f); + fread( &len, sizeof(__u8), 1, f); + event = new eventData(0, len, type); + event->EITdata = new __u8[len]; + eventData::CacheSize+=len; + fread( event->EITdata, len, 1, f); + evMap[ event->getEventID() ]=event; + tmMap[ event->getStartTime() ]=event; + ++cnt; + } + eventDB[key]=std::pair(evMap,tmMap); } - eventDB[key]=std::pair(evMap,tmMap); + eventData::load(f); + eDebug("%d events read from /hdd/epg.dat", cnt); } - eDebug("%d events read from /hdd/epg.dat.md5", cnt); + else + eDebug("[EPGC] don't read old epg database"); + fclose(f); } - fclose(f); } #endif } @@ -653,6 +711,8 @@ void eEPGCache::save() int cnt=0; if ( f ) { + const char *text = "ENIGMA_EPG_V4"; + fwrite( text, 13, 1, f ); int size = eventDB.size(); fwrite( &size, sizeof(int), 1, f ); for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it) @@ -663,14 +723,15 @@ void eEPGCache::save() fwrite( &size, sizeof(int), 1, f); for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it) { - int len = time_it->second->ByteSize; - fwrite( &time_it->second->type, sizeof(int), 1, f ); - fwrite( &len, sizeof(int), 1, f); + __u8 len = time_it->second->ByteSize; + fwrite( &time_it->second->type, sizeof(__u8), 1, f ); + fwrite( &len, sizeof(__u8), 1, f); fwrite( time_it->second->EITdata, len, 1, f); ++cnt; } } eDebug("%d events written to /hdd/epg.dat", cnt); + eventData::save(f); fclose(f); unsigned char md5[16]; if (!md5_file("/hdd/epg.dat", 1, md5)) @@ -686,14 +747,6 @@ void eEPGCache::save() #endif } -RESULT eEPGCache::getInstance(ePtr &ptr) -{ - ptr = instance; - if (!ptr) - return -1; - return 0; -} - eEPGCache::channel_data::channel_data(eEPGCache *ml) :cache(ml) ,abortTimer(ml), zapTimer(ml) @@ -707,11 +760,14 @@ bool eEPGCache::channel_data::finishEPG() { if (!isRunning) // epg ready { - eDebug("[EPGC] stop caching events"); + 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); - seenSections.clear(); - calcedSections.clear(); + 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; @@ -722,12 +778,15 @@ bool eEPGCache::channel_data::finishEPG() void eEPGCache::channel_data::startEPG() { - eDebug("[EPGC] start caching events"); + eDebug("[EPGC] start caching events(%d)", eDVBLocalTimeHandler::getInstance()->difference()+time(0)); state=0; haveData=0; can_delete=0; - seenSections.clear(); - calcedSections.clear(); + for (int i=0; i < 3; ++i) + { + seenSections[i].clear(); + calcedSections[i].clear(); + } eDVBSectionFilterMask mask; memset(&mask, 0, sizeof(mask)); @@ -736,16 +795,19 @@ void eEPGCache::channel_data::startEPG() 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; @@ -760,28 +822,33 @@ void eEPGCache::channel_data::abortNonAvail() { eDebug("[EPGC] abort non avail nownext reading"); isRunning &= ~eEPGCache::NOWNEXT; - if ( m_NowNextReader ) - m_NowNextReader->stop(); + 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(50000, true); + abortTimer.start(90000, true); else { ++state; - seenSections.clear(); - calcedSections.clear(); + for (int i=0; i < 3; ++i) + { + seenSections[i].clear(); + calcedSections[i].clear(); + } can_delete=1; } } @@ -806,8 +873,11 @@ void eEPGCache::channel_data::startChannel() void eEPGCache::channel_data::abortEPG() { - seenSections.clear(); - calcedSections.clear(); + for (int i=0; i < 3; ++i) + { + seenSections[i].clear(); + calcedSections[i].clear(); + } abortTimer.stop(); zapTimer.stop(); if (isRunning) @@ -815,21 +885,21 @@ void eEPGCache::channel_data::abortEPG() eDebug("[EPGC] abort caching events !!"); if (isRunning & eEPGCache::SCHEDULE) { - isRunning &= eEPGCache::SCHEDULE; - if ( m_ScheduleReader ) - m_ScheduleReader->stop(); + isRunning &= ~eEPGCache::SCHEDULE; + m_ScheduleReader->stop(); + m_ScheduleConn=0; } if (isRunning & eEPGCache::NOWNEXT) { isRunning &= ~eEPGCache::NOWNEXT; - if ( m_NowNextReader ) - m_NowNextReader->stop(); + m_NowNextReader->stop(); + m_NowNextConn=0; } if (isRunning & SCHEDULE_OTHER) { isRunning &= ~eEPGCache::SCHEDULE_OTHER; - if ( m_ScheduleOtherReader ) - m_ScheduleOtherReader->stop(); + m_ScheduleOtherReader->stop(); + m_ScheduleOtherConn=0; } can_delete=1; } @@ -841,23 +911,54 @@ void eEPGCache::channel_data::readData( const __u8 *data) eDebug("get Null pointer from section reader !!"); else { - int source = data[0] > 0x5F ? eEPGCache::SCHEDULE_OTHER : data[0] > 0x4F ? eEPGCache::SCHEDULE : eEPGCache::NOWNEXT; + 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 ) { - iDVBSectionReader *reader=NULL; + eDebugNoNewLine("[EPGC] "); switch (source) { - case eEPGCache::SCHEDULE_OTHER: - reader=m_ScheduleOtherReader; + case eEPGCache::NOWNEXT: + m_NowNextConn=0; + eDebugNoNewLine("nownext"); break; case eEPGCache::SCHEDULE: - reader=m_ScheduleReader; + m_ScheduleConn=0; + eDebugNoNewLine("schedule"); break; - case eEPGCache::NOWNEXT: - reader=m_NowNextReader; + case eEPGCache::SCHEDULE_OTHER: + m_ScheduleOtherConn=0; + eDebugNoNewLine("schedule other"); break; + default: eDebugNoNewLine("unknown");break; } - reader->stop(); + eDebug(" finished(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference()); + if ( reader ) + reader->stop(); isRunning &= ~source; if (!isRunning) finishEPG(); @@ -876,6 +977,7 @@ void eEPGCache::channel_data::readData( const __u8 *data) 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 ) @@ -893,3 +995,200 @@ void eEPGCache::channel_data::readData( const __u8 *data) } } } + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, time_t t, const eventData *&result ) +// if t == 0 we search the current event... +{ + singleLock s(cache_lock); + uniqueEPGKey key(service); + + // check if EPG for this service is ready... + eventCache::iterator It = eventDB.find( key ); + if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ? + { + if (!t) + t = time(0)+eDVBLocalTimeHandler::getInstance()->difference(); + +// TODO: optimize this.. why we here search first in timemap.. and then in eventmap?? + timeMap::iterator i = It->second.second.lower_bound(t); + if ( i != It->second.second.end() ) + { + if ( i != It->second.second.end() ) + { + if ( t <= i->first+i->second->getDuration() ) + { + result = i->second; + return 0; + } + } + } + + for ( eventMap::iterator i( It->second.first.begin() ); i != It->second.first.end(); i++) + { + int duration = i->second->getDuration(); + time_t begTime = i->second->getStartTime(); + if ( t >= begTime && t <= begTime+duration) // then we have found + { + result = i->second; + return 0; + } + } + } + return -1; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, time_t t, const eit_event_struct *&result ) +{ + singleLock s(cache_lock); + const eventData *data=0; + RESULT ret = lookupEvent(service, t, data); + if ( !ret && data ) + result = data->get(); + return ret; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, time_t t, Event *& result ) +{ + singleLock s(cache_lock); + const eventData *data=0; + RESULT ret = lookupEvent(service, t, data); + if ( !ret && data ) + result = new Event((uint8_t*)data->get()); + return ret; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, time_t t, ePtr &result ) +{ + singleLock s(cache_lock); + const eventData *data=0; + RESULT ret = lookupEvent(service, t, data); + if ( !ret && data ) + { + Event ev((uint8_t*)data->get()); + result = new eServiceEvent(); + ret = result->parseFrom(&ev); + } + return ret; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, int event_id, const eventData *&result ) +{ + singleLock s(cache_lock); + uniqueEPGKey key( service ); + + eventCache::iterator It = eventDB.find( key ); + if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached? + { + eventMap::iterator i( It->second.first.find( event_id )); + if ( i != It->second.first.end() ) + { + result = i->second; + return 0; + } + else + { + result = 0; + eDebug("event %04x not found in epgcache", event_id); + } + } + return -1; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, int event_id, const eit_event_struct *&result) +{ + singleLock s(cache_lock); + const eventData *data=0; + RESULT ret = lookupEvent(service, event_id, data); + if ( !ret && data ) + result = data->get(); + return ret; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, int event_id, Event *& result) +{ + singleLock s(cache_lock); + const eventData *data=0; + RESULT ret = lookupEvent(service, event_id, data); + if ( !ret && data ) + result = new Event((uint8_t*)data->get()); + return ret; +} + +RESULT eEPGCache::lookupEvent(const eServiceReference &service, int event_id, ePtr &result) +{ + singleLock s(cache_lock); + const eventData *data=0; + RESULT ret = lookupEvent(service, event_id, data); + if ( !ret && data ) + { + Event ev((uint8_t*)data->get()); + result = new eServiceEvent(); + ret = result->parseFrom(&ev); + } + return ret; +} + +RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes) +{ + eventCache::iterator It = eventDB.find( service ); + if ( It != eventDB.end() && It->second.second.size() ) + { + m_timemap_end = minutes != -1 ? It->second.second.upper_bound(begin+minutes*60) : It->second.second.end(); + if ( begin != -1 ) + { + m_timemap_cursor = It->second.second.lower_bound(begin); + if ( m_timemap_cursor != It->second.second.end() && m_timemap_cursor != It->second.second.begin() ) + { + timeMap::iterator it = m_timemap_cursor; + --it; + if ( (it->second->getStartTime() + it->second->getDuration()) > begin ) + m_timemap_cursor = it; + } + } + else + m_timemap_cursor = It->second.second.begin(); + return 0; + } + return -1; +} + +RESULT eEPGCache::getNextTimeEntry(const eventData *& result) +{ + if ( m_timemap_cursor != m_timemap_end ) + { + result = m_timemap_cursor++->second; + return 0; + } + return -1; +} + +RESULT eEPGCache::getNextTimeEntry(const eit_event_struct *&result) +{ + if ( m_timemap_cursor != m_timemap_end ) + { + result = m_timemap_cursor++->second->get(); + return 0; + } + return -1; +} + +RESULT eEPGCache::getNextTimeEntry(Event *&result) +{ + if ( m_timemap_cursor != m_timemap_end ) + { + result = new Event((uint8_t*)m_timemap_cursor++->second->get()); + return 0; + } + return -1; +} + +RESULT eEPGCache::getNextTimeEntry(ePtr &result) +{ + if ( m_timemap_cursor != m_timemap_end ) + { + Event ev((uint8_t*)m_timemap_cursor++->second->get()); + result = new eServiceEvent(); + return result->parseFrom(&ev); + } + return -1; +}