From: Andreas Monzner Date: Wed, 20 Jul 2005 20:58:53 +0000 (+0000) Subject: the epgcache can now handle more then one channel(transponder), X-Git-Tag: 2.6.0~5807 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/0cb7bd236d96662117bf8928cedd953b7b68579f?hp=66fb1ae9101fc20911a7a1585b333b2333cf697a the epgcache can now handle more then one channel(transponder), todo: implement a python interface to get epgcache entries --- diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index 634aead3..34bd9f2f 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -14,24 +14,26 @@ int eventData::CacheSize=0; eEPGCache* eEPGCache::instance; pthread_mutex_t eEPGCache::cache_lock= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +pthread_mutex_t eEPGCache::channel_map_lock= + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; DEFINE_REF(eEPGCache) eEPGCache::eEPGCache() - :messages(this,1), back_messages(this,1) ,paused(0) - ,CleanTimer(this), zapTimer(this), abortTimer(this) + :messages(this,1), cleanTimer(this)//, paused(0) { eDebug("[EPGC] Initialized EPGCache"); - isRunning=0; CONNECT(messages.recv_msg, eEPGCache::gotMessage); - CONNECT(back_messages.recv_msg, eEPGCache::gotBackMessage); -// CONNECT(eDVB::getInstance()->switchedService, eEPGCache::enterService); -// CONNECT(eDVB::getInstance()->leaveService, eEPGCache::leaveService); CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated); - CONNECT(zapTimer.timeout, eEPGCache::startEPG); - CONNECT(CleanTimer.timeout, eEPGCache::cleanLoop); - CONNECT(abortTimer.timeout, eEPGCache::abortNonAvail); + CONNECT(cleanTimer.timeout, eEPGCache::cleanLoop); + + ePtr res_mgr; + eDVBResourceManager::getInstance(res_mgr); + if (!res_mgr) + eDebug("[eEPGCache] no resource manager !!!!!!!"); + else + res_mgr->connectChannelAdded(slot(*this,&eEPGCache::DVBChannelAdded), m_chanAddedConn); instance=this; } @@ -46,7 +48,109 @@ void eEPGCache::timeUpdated() messages.send(Message(Message::timeChanged)); } -int eEPGCache::sectionRead(const __u8 *data, int source) +void eEPGCache::DVBChannelAdded(eDVBChannel *chan) +{ + if ( chan ) + { + eDebug("[eEPGCache] add channel %p", chan); + channel_data *data = new channel_data(this); + data->channel = chan; + singleLock s(channel_map_lock); + m_knownChannels.insert( std::pair(chan, data) ); + chan->connectStateChange(slot(*this, &eEPGCache::DVBChannelStateChanged), data->m_stateChangedConn); + } +} + +void eEPGCache::DVBChannelRunning(iDVBChannel *chan) +{ + singleLock s(channel_map_lock); + channelMapIterator it = + m_knownChannels.find(chan); + if ( it == m_knownChannels.end() ) + eDebug("[eEPGCache] will start non existing channel %p !!!", chan); + else + { + channel_data &data = *it->second; + ePtr res_mgr; + if ( eDVBResourceManager::getInstance( res_mgr ) ) + eDebug("[eEPGCache] no res manager!!"); + else + { + ePtr demux; + if ( data.channel->getDemux(demux) ) + { + eDebug("[eEPGCache] no demux!!"); + return; + } + else + { + RESULT res; + data.m_NowNextReader = new eDVBSectionReader( demux, this, res ); + if ( res ) + { + eDebug("[eEPGCache] couldnt initialize nownext reader!!"); + return; + } + data.m_NowNextReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_NowNextConn); + data.m_ScheduleReader = new eDVBSectionReader( demux, this, res ); + if ( res ) + { + eDebug("[eEPGCache] couldnt initialize schedule reader!!"); + return; + } + data.m_ScheduleReader->connectRead(slot(data, &eEPGCache::channel_data::readData), data.m_ScheduleConn); + data.m_ScheduleOtherReader = new eDVBSectionReader( demux, this, res ); + 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 + } + } + } +} + +void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan) +{ + channelMapIterator it = + m_knownChannels.find(chan); + if ( it != m_knownChannels.end() ) + { + int state=0; + 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); + DVBChannelRunning(chan); + break; + } + case iDVBChannel::state_release: + { + eDebug("[eEPGCache] remove channel %p", chan); + messages.send(Message(Message::leaveChannel, chan)); + while(!it->second->can_delete) + usleep(1000); + delete it->second; + m_knownChannels.erase(it); + // -> gotMessage -> abortEPG + break; + } + } + } +} + +int eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) { eit_t *eit = (eit_t*) data; @@ -71,22 +175,9 @@ int eEPGCache::sectionRead(const __u8 *data, int source) time_t now = time(0)+eDVBLocalTimeHandler::getInstance()->difference(); if ( TM != 3599 && TM > -1) - { - switch(source) - { - case NOWNEXT: - haveData |= 2; - break; - case SCHEDULE: - haveData |= 1; - break; - case SCHEDULE_OTHER: - haveData |= 4; - break; - } - } + channel->haveData |= source; - Lock(); + singleLock s(cache_lock); // hier wird immer eine eventMap zurück gegeben.. entweder eine vorhandene.. // oder eine durch [] erzeugte std::pair &servicemap = eventDB[service]; @@ -129,6 +220,7 @@ int eEPGCache::sectionRead(const __u8 *data, int source) { if ( source > ev_it->second->type ) // update needed ? goto next; // when not.. the skip this entry + // search this event in timemap timeMap::iterator tm_it_tmp = servicemap.second.find(ev_it->second->getStartTime()); @@ -161,7 +253,6 @@ int eEPGCache::sectionRead(const __u8 *data, int source) if ( tm_it != servicemap.second.end() ) { - // i think, if event is not found on eventmap, but found on timemap updating nevertheless demands #if 0 if ( source > tm_it->second->type && tm_erase_count == 0 ) // update needed ? @@ -263,67 +354,13 @@ next: eit_event=(eit_event_struct*)(((__u8*)eit_event)+eit_event_size); } - tmpMap::iterator it = temp.find( service ); - if ( it != temp.end() ) - { - if ( source > it->second.second ) - { - it->second.first=now; - it->second.second=source; - } - } - else - temp[service] = std::pair< time_t, int> (now, source); - - Unlock(); - return 0; } -bool eEPGCache::finishEPG() -{ - if (!isRunning) // epg ready - { - eDebug("[EPGC] stop caching events"); - zapTimer.start(UPDATE_INTERVAL, 1); - eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000); - - singleLock l(cache_lock); - tmpMap::iterator It = temp.begin(); - abortTimer.stop(); - - while (It != temp.end()) - { -// eDebug("sid = %02x, onid = %02x, type %d", It->first.sid, It->first.onid, It->second.second ); - if ( It->second.second == SCHEDULE - || ( It->second.second == NOWNEXT && !(haveData&1) ) - ) - { -// eDebug("ADD to last updated Map"); - serviceLastUpdated[It->first]=It->second.first; - } - if ( eventDB.find( It->first ) == eventDB.end() ) - { -// eDebug("REMOVE from update Map"); - temp.erase(It++); - } - else - It++; - } - if (!eventDB[current_service].first.empty()) - /*emit*/ EPGAvail(1); - - /*emit*/ EPGUpdated(); - - return true; - } - return false; -} - void eEPGCache::flushEPG(const uniqueEPGKey & s) { eDebug("[EPGC] flushEPG %d", (int)(bool)s); - Lock(); + singleLock l(cache_lock); if (s) // clear only this service { eventCache::iterator it = eventDB.find(s); @@ -336,10 +373,8 @@ void eEPGCache::flushEPG(const uniqueEPGKey & s) delete i->second; evMap.clear(); eventDB.erase(it); - updateMap::iterator u = serviceLastUpdated.find(s); - if ( u != serviceLastUpdated.end() ) - serviceLastUpdated.erase(u); - startEPG(); + + // TODO .. search corresponding channel for removed service and remove this channel from lastupdated map } } else // clear complete EPG Cache @@ -354,24 +389,19 @@ void eEPGCache::flushEPG(const uniqueEPGKey & s) evMap.clear(); tmMap.clear(); } - serviceLastUpdated.clear(); eventDB.clear(); - startEPG(); + channelLastUpdated.clear(); + singleLock m(channel_map_lock); + for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it) + it->second->startEPG(); } eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize); - Unlock(); } void eEPGCache::cleanLoop() { singleLock s(cache_lock); - if ( isRunning ) - { - CleanTimer.start(5000,true); - eDebug("[EPGC] schedule cleanloop"); - return; - } - if (!eventDB.empty() && !paused ) + if (!eventDB.empty()) { eDebug("[EPGC] start cleanloop"); const eit_event_struct* cur_event; @@ -403,51 +433,25 @@ void eEPGCache::cleanLoop() delete It->second; DBIt->second.second.erase(It++); // eDebug("[EPGC] delete old event (timeMap)"); - - // add this (changed) service to temp map... - if ( temp.find(DBIt->first) == temp.end() ) - temp[DBIt->first]=std::pair(now, NOWNEXT); } else ++It; } - if ( DBIt->second.second.size() < 2 ) - // less than two events for this service in cache.. - { - updateMap::iterator u = serviceLastUpdated.find(DBIt->first); - if ( u != serviceLastUpdated.end() ) - { - // remove from lastupdated map.. - serviceLastUpdated.erase(u); - // current service? - if ( DBIt->first == current_service ) - { - // immediate .. after leave cleanloop - // update epgdata for this service - zapTimer.start(0,true); - } - } - } } - - if (temp.size()) - /*emit*/ EPGUpdated(); - eDebug("[EPGC] stop cleanloop"); eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize); } - CleanTimer.start(CLEAN_INTERVAL,true); + cleanTimer.start(CLEAN_INTERVAL,true); } eEPGCache::~eEPGCache() { messages.send(Message::quit); kill(); // waiting for thread shutdown - Lock(); + singleLock s(cache_lock); for (eventCache::iterator evIt = eventDB.begin(); evIt != eventDB.end(); evIt++) for (eventMap::iterator It = evIt->second.first.begin(); It != evIt->second.first.end(); It++) delete It->second; - Unlock(); } Event *eEPGCache::lookupEvent(const eServiceReferenceDVB &service, int event_id, bool plain) @@ -526,250 +530,6 @@ Event *eEPGCache::lookupEvent(const eServiceReferenceDVB &service, time_t t, boo return 0; } -void eEPGCache::pauseEPG() -{ - if (!paused) - { - abortEPG(); - eDebug("[EPGC] paused]"); - paused=1; - } -} - -void eEPGCache::restartEPG() -{ - if (paused) - { - isRunning=0; - eDebug("[EPGC] restarted"); - paused--; - if (paused) - { - paused = 0; - startEPG(); // updateEPG - } - cleanLoop(); - } -} - -void eEPGCache::startEPG() -{ - if (paused) // called from the updateTimer during pause... - { - paused++; - return; - } - if (eDVBLocalTimeHandler::getInstance()->ready()) - { - Lock(); - temp.clear(); - Unlock(); - eDebug("[EPGC] start caching events"); - state=0; - haveData=0; - - eDVBSectionFilterMask mask; - memset(&mask, 0, sizeof(mask)); - mask.pid = 0x12; - mask.flags = eDVBSectionFilterMask::rfCRC; - - mask.data[0] = 0x4E; - mask.mask[0] = 0xFE; - m_NowNextReader->start(mask); - isRunning |= 1; - - mask.data[0] = 0x50; - mask.mask[0] = 0xF0; - m_ScheduleReader->start(mask); - isRunning |= 2; - - mask.data[0] = 0x60; - mask.mask[0] = 0xF0; - m_ScheduleOtherReader->start(mask); - isRunning |= 4; - - abortTimer.start(5000,true); - } - else - { - eDebug("[EPGC] wait for clock update"); - zapTimer.start(1000, 1); // restart Timer - } -} - -void eEPGCache::abortNonAvail() -{ - if (!state) - { - if ( !(haveData&2) && (isRunning&2) ) - { - eDebug("[EPGC] abort non avail nownext reading"); - isRunning &= ~2; - if ( m_NowNextReader ) - m_NowNextReader->stop(); - } - if ( !(haveData&1) && (isRunning&1) ) - { - eDebug("[EPGC] abort non avail schedule reading"); - isRunning &= ~1; - m_ScheduleReader->stop(); - } - if ( !(haveData&4) && (isRunning&4) ) - { - eDebug("[EPGC] abort non avail schedule_other reading"); - isRunning &= ~4; - m_ScheduleOtherReader->stop(); - } - abortTimer.start(20000, true); - } - ++state; -} - -void eEPGCache::startCache(const eServiceReferenceDVB& ref) -{ - if ( m_currentChannel ) - { - next_service = ref; - leaveChannel(m_currentChannel); - return; - } - eDVBChannelID chid; - ref.getChannelID( chid ); - ePtr res_mgr; - if ( eDVBResourceManager::getInstance( res_mgr ) ) - eDebug("[eEPGCache] no res manager!!"); - else - { - ePtr demux; -// res_mgr->allocateChannel(chid, m_currentChannel); - if ( m_currentChannel->getDemux(demux) ) - { - eDebug("[eEPGCache] no demux!!"); - goto error4; - } - else - { - RESULT res; - m_NowNextReader = new eDVBSectionReader( demux, this, res ); - if ( res ) - { - eDebug("[eEPGCache] couldnt initialize nownext reader!!"); - goto error3; - } - m_NowNextReader->connectRead(slot(*this, &eEPGCache::readNowNextData), m_NowNextConn); - m_ScheduleReader = new eDVBSectionReader( demux, this, res ); - if ( res ) - { - eDebug("[eEPGCache] couldnt initialize schedule reader!!"); - goto error2; - } - m_ScheduleReader->connectRead(slot(*this, &eEPGCache::readScheduleData), m_ScheduleConn); - m_ScheduleOtherReader = new eDVBSectionReader( demux, this, res ); - if ( res ) - { - eDebug("[eEPGCache] couldnt initialize schedule other reader!!"); - goto error1; - } - m_ScheduleOtherReader->connectRead(slot(*this, &eEPGCache::readScheduleOtherData), m_ScheduleOtherConn); - messages.send(Message(Message::startService, ref)); - // -> gotMessage -> changedService - } - } - return; -error1: - m_ScheduleOtherReader=0; - m_ScheduleOtherConn=0; -error2: - m_ScheduleReader=0; - m_ScheduleConn=0; -error3: - m_NowNextReader=0; - m_NowNextConn=0; -error4: - m_currentChannel=0; -} - -void eEPGCache::leaveChannel(iDVBChannel * chan) -{ - if ( chan && chan == m_currentChannel ) - { - messages.send(Message(Message::leaveChannel, chan)); - // -> gotMessage -> abortEPG - } -} - -void eEPGCache::changedService(const uniqueEPGKey &service) -{ - current_service = service; - updateMap::iterator It = serviceLastUpdated.find( current_service ); - - int update; - -// check if this is a subservice and this is only a dbox2 -// then we dont start epgcache on subservice change.. -// ever and ever.. - -// if ( !err || err == -ENOCASYS ) - { - update = ( It != serviceLastUpdated.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); - } - - Lock(); - bool empty=eventDB[current_service].first.empty(); - Unlock(); - - if (!empty) - { - eDebug("[EPGC] yet cached"); - /*emit*/ EPGAvail(1); - } - else - { - eDebug("[EPGC] not cached yet"); - /*emit*/ EPGAvail(0); - } -} - -void eEPGCache::abortEPG() -{ - abortTimer.stop(); - zapTimer.stop(); - if (isRunning) - { - if (isRunning & 1) - { - isRunning &= ~1; - if ( m_ScheduleReader ) - m_ScheduleReader->stop(); - } - if (isRunning & 2) - { - isRunning &= ~2; - if ( m_NowNextReader ) - m_NowNextReader->stop(); - } - if (isRunning & 4) - { - isRunning &= ~4; - if ( m_ScheduleOtherReader ) - m_ScheduleOtherReader->stop(); - } - eDebug("[EPGC] abort caching events !!"); - Lock(); - temp.clear(); - Unlock(); - } -} - void eEPGCache::gotMessage( const Message &msg ) { switch (msg.type) @@ -777,19 +537,24 @@ void eEPGCache::gotMessage( const Message &msg ) case Message::flush: flushEPG(msg.service); break; - case Message::startService: - changedService(msg.service); + case Message::startChannel: + { + singleLock s(channel_map_lock); + channelMapIterator channel = + m_knownChannels.find(msg.channel); + if ( channel != m_knownChannels.end() ) + channel->second->startChannel(); break; + } case Message::leaveChannel: - abortEPG(); - back_messages.send(Message(Message::leaveChannelFinished)); - break; - case Message::pause: - pauseEPG(); - break; - case Message::restart: - restartEPG(); + { + singleLock s(channel_map_lock); + channelMapIterator channel = + m_knownChannels.find(msg.channel); + if ( channel != m_knownChannels.end() ) + channel->second->abortEPG(); break; + } case Message::quit: quit(0); break; @@ -802,31 +567,6 @@ void eEPGCache::gotMessage( const Message &msg ) } } -void eEPGCache::gotBackMessage( const Message &msg ) -{ - switch (msg.type) - { - case Message::leaveChannelFinished: - m_ScheduleOtherReader=0; - m_ScheduleOtherConn=0; - m_ScheduleReader=0; - m_ScheduleConn=0; - m_NowNextReader=0; - m_NowNextConn=0; - m_currentChannel=0; - eDebug("[eEPGC] channel leaved"); - if (next_service) - { - startCache(next_service); - next_service = eServiceReferenceDVB(); - } - break; - default: - eDebug("unhandled EPGCache BackMessage!!"); - break; - } -} - void eEPGCache::thread() { nice(4); @@ -955,3 +695,165 @@ RESULT eEPGCache::getInstance(ePtr &ptr) return 0; } +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"); + zapTimer.start(UPDATE_INTERVAL, 1); + eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000); + + 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"); + state=0; + haveData=0; + can_delete=0; + + eDVBSectionFilterMask mask; + memset(&mask, 0, sizeof(mask)); + mask.pid = 0x12; + mask.flags = eDVBSectionFilterMask::rfCRC; + + mask.data[0] = 0x4E; + mask.mask[0] = 0xFE; + m_NowNextReader->start(mask); + isRunning |= NOWNEXT; + + mask.data[0] = 0x50; + mask.mask[0] = 0xF0; + m_ScheduleReader->start(mask); + isRunning |= SCHEDULE; + + mask.data[0] = 0x60; + mask.mask[0] = 0xF0; + m_ScheduleOtherReader->start(mask); + isRunning |= SCHEDULE_OTHER; + + abortTimer.start(5000,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; + if ( m_NowNextReader ) + m_NowNextReader->stop(); + } + if ( !(haveData&eEPGCache::SCHEDULE) && (isRunning&eEPGCache::SCHEDULE) ) + { + eDebug("[EPGC] abort non avail schedule reading"); + isRunning &= ~SCHEDULE; + m_ScheduleReader->stop(); + } + if ( !(haveData&eEPGCache::SCHEDULE_OTHER) && (isRunning&eEPGCache::SCHEDULE_OTHER) ) + { + eDebug("[EPGC] abort non avail schedule_other reading"); + isRunning &= ~SCHEDULE_OTHER; + m_ScheduleOtherReader->stop(); + } + if ( isRunning ) + abortTimer.start(20000, true); + else + finishEPG(); + } + ++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() +{ + abortTimer.stop(); + zapTimer.stop(); + if (isRunning) + { + eDebug("[EPGC] abort caching events !!"); + if (isRunning & eEPGCache::SCHEDULE) + { + isRunning &= eEPGCache::SCHEDULE; + if ( m_ScheduleReader ) + m_ScheduleReader->stop(); + } + if (isRunning & eEPGCache::NOWNEXT) + { + isRunning &= ~eEPGCache::NOWNEXT; + if ( m_NowNextReader ) + m_NowNextReader->stop(); + } + if (isRunning & SCHEDULE_OTHER) + { + isRunning &= ~eEPGCache::SCHEDULE_OTHER; + if ( m_ScheduleOtherReader ) + m_ScheduleOtherReader->stop(); + } + can_delete=1; + } +} + +void eEPGCache::channel_data::readData( const __u8 *data) +{ + if (!data) + eDebug("get Null pointer from section reader !!"); + else + { + int source = data[0] > 0x5F ? eEPGCache::SCHEDULE_OTHER : data[0] > 0x4F ? eEPGCache::SCHEDULE : eEPGCache::NOWNEXT; + if ( state == 2 ) + { + iDVBSectionReader *reader=NULL; + switch (source) + { + case eEPGCache::SCHEDULE_OTHER: + reader=m_ScheduleOtherReader; + break; + case eEPGCache::SCHEDULE: + reader=m_ScheduleReader; + break; + case eEPGCache::NOWNEXT: + reader=m_NowNextReader; + break; + } + reader->stop(); + isRunning &= ~source; + if (!isRunning) + finishEPG(); + } + else + cache->sectionRead(data, source, this); + } +} diff --git a/lib/dvb/epgcache.h b/lib/dvb/epgcache.h index bc25692e..5dea4630 100644 --- a/lib/dvb/epgcache.h +++ b/lib/dvb/epgcache.h @@ -1,8 +1,6 @@ #ifndef __epgcache_h_ #define __epgcache_h_ -#ifndef SWIG - #include #include #include @@ -75,15 +73,16 @@ struct uniqueEPGKey //timeMap is sorted by beginTime #define timeMap std::map +#define channelMapIterator std::map::iterator + #define tmpMap std::map > +#define updateMap std::map #if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ == 4 ) // check if gcc version >= 3.1 #define eventCache __gnu_cxx::hash_map, __gnu_cxx::hash, uniqueEPGKey::equal> - #define updateMap __gnu_cxx::hash_map, uniqueEPGKey::equal > namespace __gnu_cxx #else // for older gcc use following #define eventCache std::hash_map, std::hash, uniqueEPGKey::equal > - #define updateMap std::hash_map, uniqueEPGKey::equal > namespace std #endif { @@ -91,9 +90,7 @@ template<> struct hash { inline size_t operator()( const uniqueEPGKey &x) const { - int v=(x.onid^x.sid); - v^=v>>8; - return v&0xFF; + return (x.tsid << 16) | x.onid; } }; } @@ -139,32 +136,44 @@ public: EITdata[4], EITdata[5], EITdata[6]); } }; -#else - #include -#endif class eEPGCache: public eMainloop, private eThread, public Object { DECLARE_REF(eEPGCache) + struct channel_data: public Object + { + channel_data(eEPGCache*); + eEPGCache *cache; + eTimer abortTimer, zapTimer; + __u8 state, isRunning, haveData, can_delete; + ePtr channel; + ePtr m_stateChangedConn, m_NowNextConn, m_ScheduleConn, m_ScheduleOtherConn; + ePtr m_NowNextReader, m_ScheduleReader, m_ScheduleOtherReader; + void readData(const __u8 *data); + void startChannel(); + void startEPG(); + bool finishEPG(); + void abortEPG(); + void abortNonAvail(); + }; public: -#ifndef SWIG - enum {NOWNEXT, SCHEDULE, SCHEDULE_OTHER}; + enum {NOWNEXT=1, SCHEDULE=2, SCHEDULE_OTHER=4}; struct Message { enum { flush, - startService, + startChannel, leaveChannel, pause, restart, updated, isavail, quit, - timeChanged, - leaveChannelFinished + timeChanged }; int type; + iDVBChannel *channel; uniqueEPGKey service; union { int err; @@ -177,78 +186,53 @@ public: :type(type) {} Message(int type, bool b) :type(type), avail(b) {} + Message(int type, iDVBChannel *channel, int err=0) + :type(type), channel(channel), err(err) {} Message(int type, const eServiceReferenceDVB& service, int err=0) :type(type), service(service), err(err) {} Message(int type, time_t time) :type(type), time(time) {} }; eFixedMessagePump messages; - eFixedMessagePump back_messages; private: - static pthread_mutex_t cache_lock; - eServiceReferenceDVB next_service; - uniqueEPGKey current_service; - int paused; - - int state; - __u8 isRunning, haveData; - - ePtr m_currentChannel; - ePtr m_NowNextConn, m_ScheduleConn, m_ScheduleOtherConn; - ePtr m_NowNextReader, m_ScheduleReader, m_ScheduleOtherReader; - - int sectionRead(const __u8 *data, int source); - void readNowNextData(const __u8 *data); - void readScheduleData(const __u8 *data); - void readScheduleOtherData(const __u8 *data); - + friend class channel_data; static eEPGCache *instance; + eTimer cleanTimer; + std::map m_knownChannels; + ePtr m_chanAddedConn; + eventCache eventDB; - updateMap serviceLastUpdated; - tmpMap temp; - eTimer CleanTimer; - eTimer zapTimer; - eTimer abortTimer; - bool finishEPG(); - void abortNonAvail(); - void flushEPG(const uniqueEPGKey & s=uniqueEPGKey()); - void startEPG(); + updateMap channelLastUpdated; + static pthread_mutex_t cache_lock, channel_map_lock; - void changedService(const uniqueEPGKey &); - void abortEPG(); + void thread(); // thread function - void cleanLoop(); - void pauseEPG(); - void restartEPG(); - void thread(); - void gotMessage(const Message &message); - void gotBackMessage(const Message &message); - void timeUpdated(); +// called from epgcache thread void save(); void load(); - void leaveChannel(iDVBChannel *); -#endif + int sectionRead(const __u8 *data, int source, channel_data *channel); + void gotMessage(const Message &message); + void flushEPG(const uniqueEPGKey & s=uniqueEPGKey()); + void cleanLoop(); + +// called from main thread + void timeUpdated(); + void DVBChannelAdded(eDVBChannel*); + void DVBChannelStateChanged(iDVBChannel*); + void DVBChannelRunning(iDVBChannel *); public: static RESULT getInstance(ePtr &ptr); - // called from other thread context !! - void startCache(const eServiceReferenceDVB &); - Event *lookupEvent(const eServiceReferenceDVB &service, int event_id, bool plain=false ); - Event *lookupEvent(const eServiceReferenceDVB &service, time_t=0, bool plain=false ); -#ifndef SWIG eEPGCache(); ~eEPGCache(); + // called from main thread inline void Lock(); inline void Unlock(); - + Event *lookupEvent(const eServiceReferenceDVB &service, int event_id, bool plain=false ); + Event *lookupEvent(const eServiceReferenceDVB &service, time_t=0, bool plain=false ); const eventMap* getEventMap(const eServiceReferenceDVB &service); const timeMap* getTimeMap(const eServiceReferenceDVB &service); - tmpMap* getUpdatedMap() { return &temp; } - - Signal1 EPGAvail; - Signal0 EPGUpdated; -#endif }; TEMPLATE_TYPEDEF(ePtr,eEPGCachePtr); @@ -271,30 +255,6 @@ inline const timeMap* eEPGCache::getTimeMap(const eServiceReferenceDVB &service) return 0; } -inline void eEPGCache::readNowNextData( const __u8 *data) -{ - if ( !data || state == 2 ) - m_NowNextReader->stop(); - else - sectionRead(data, eEPGCache::NOWNEXT); -} - -inline void eEPGCache::readScheduleData(const __u8 *data) -{ - if ( !data || state == 2 ) - m_ScheduleReader->stop(); - else - sectionRead(data, eEPGCache::SCHEDULE); -} - -inline void eEPGCache::readScheduleOtherData(const __u8 *data) -{ - if ( !data || state == 2 ) - m_ScheduleOtherReader->stop(); - else - sectionRead(data, eEPGCache::SCHEDULE_OTHER); -} - inline void eEPGCache::Lock() { pthread_mutex_lock(&cache_lock); diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index 477e1bf7..ae8bf92d 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -67,7 +67,6 @@ is usually caused by not marking PSignals as immutable. #include #include #include -#include extern void runMainloop(); extern void quitMainloop(); @@ -124,7 +123,6 @@ extern PSignal1 &keyPressedSignal(); %include %include %include -%include %include /************** eptr **************/ diff --git a/main/Makefile.am b/main/Makefile.am index ad838f5f..fd536df7 100644 --- a/main/Makefile.am +++ b/main/Makefile.am @@ -28,6 +28,7 @@ enigma2_LDADD = \ @PNG_LIBS@ \ @SIGC_LIBS@ \ @SDL_LIBS@ \ + @MD5SUM_LIBS@ \ -ldl -lpthread -lcrypt -lresolv -lpython2.3 enigma2$(EXEEXT): $(enigma2_OBJECTS) $(enigma2_DEPENDENCIES) $(enigma2_LDADD_WHOLE)