eDVBLocalTimeHandler::eDVBLocalTimeHandler() :m_use_dvb_time(true), m_updateNonTunedTimer(eTimer::create(eApp)), m_time_ready(false) { if ( !instance ) instance=this; ePtr<eDVBResourceManager> res_mgr; eDVBResourceManager::getInstance(res_mgr); if (!res_mgr) eDebug("[eDVBLocalTimerHandler] no resource manager !!!!!!!"); else { res_mgr->connectChannelAdded(slot(*this,&eDVBLocalTimeHandler::DVBChannelAdded), m_chanAddedConn); time_t now = time(0); if ( now < 1072224000 ) // 01.01.2004 eDebug("RTC not ready... wait for transponder time"); else // inform all who's waiting for valid system time.. { eDebug("Use valid Linux Time :) (RTC?)"); noRTC(); if (strncmp(mybox,"gb800solo", sizeof(mybox)) == 0 || strncmp(mybox,"gb800se", sizeof(mybox)) == 0 || strncmp(mybox,"gb800ue", sizeof(mybox)) == 0) m_time_ready = false; //sorry no RTC else m_time_ready = true; /*emit*/ m_timeUpdated(); } } CONNECT(m_updateNonTunedTimer->timeout, eDVBLocalTimeHandler::updateNonTuned); }
void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int update_count ) { int time_difference; bool restart_tdt = false; if (!tp_time) restart_tdt = true; else if (tp_time == -1) { restart_tdt = true; /*if ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 || ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7000 && eSystemInfo::getInstance()->hasStandbyWakeupTimer() ) ) TODO !!!!!!! */ { eDebug("[eDVBLocalTimerHandler] no transponder tuned... or no TDT/TOT avail .. try to use RTC :)"); time_t rtc_time = getRTC(); if ( rtc_time ) // RTC Ready? { tm now; localtime_r(&rtc_time, &now); eDebug("[eDVBLocalTimerHandler] RTC time is %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); time_t linuxTime=time(0); localtime_r(&linuxTime, &now); eDebug("[eDVBLocalTimerHandler] Receiver time is %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); time_difference = rtc_time - linuxTime; eDebug("[eDVBLocalTimerHandler] RTC to Receiver time difference is %ld seconds", linuxTime - rtc_time ); if ( time_difference ) { eDebug("[eDVBLocalTimerHandler] set Linux Time to RTC Time"); timeval tnow; gettimeofday(&tnow,0); tnow.tv_sec=rtc_time; settimeofday(&tnow,0); } else if ( !time_difference ) eDebug("[eDVBLocalTimerHandler] no change needed"); else eDebug("[eDVBLocalTimerHandler] set to RTC time"); /*emit*/ m_timeUpdated(); } else eDebug("[eDVBLocalTimerHandler] getRTC returned time=0. RTC problem?"); } } else { std::map< eDVBChannelID, int >::iterator it( m_timeOffsetMap.find( chan->getChannelID() ) ); // current linux time time_t linuxTime = time(0); // difference between current enigma time and transponder time int enigma_diff = tp_time-linuxTime; int new_diff=0; bool updated = m_time_ready; if ( m_time_ready ) // ref time ready? { // difference between reference time (current enigma time) // and the transponder time eDebug("[eDVBLocalTimerHandler] diff is %d", enigma_diff); if ( abs(enigma_diff) < 120 ) { eDebug("[eDVBLocalTimerHandler] diff < 120 .. use Transponder Time"); m_timeOffsetMap[chan->getChannelID()] = 0; new_diff = enigma_diff; } else if ( it != m_timeOffsetMap.end() ) // correction saved? { eDebug("[eDVBLocalTimerHandler] we have correction %d", it->second); time_t CorrectedTpTime = tp_time+it->second; int ddiff = CorrectedTpTime-linuxTime; eDebug("[eDVBLocalTimerHandler] diff after add correction is %d", ddiff); if ( abs(it->second) < 300 ) // stored correction < 5 min { eDebug("[eDVBLocalTimerHandler] use stored correction(<5 min)"); new_diff = ddiff; } else if ( getRTC() ) { time_t rtc=getRTC(); m_timeOffsetMap[chan->getChannelID()] = rtc-tp_time; new_diff = rtc-linuxTime; // set enigma time to rtc eDebug("[eDVBLocalTimerHandler] update stored correction to %ld (calced against RTC time)", rtc-tp_time ); } else if ( abs(ddiff) <= 120 ) { // with stored correction calced time difference is lower 2 min // this don't help when a transponder have a clock running to slow or to fast // then its better to have a DM7020 with always running RTC eDebug("[eDVBLocalTimerHandler] use stored correction(corr < 2 min)"); new_diff = ddiff; } else // big change in calced correction.. hold current time and update correction { eDebug("[eDVBLocalTimerHandler] update stored correction to %d", -enigma_diff); m_timeOffsetMap[chan->getChannelID()] = -enigma_diff; } } else { eDebug("[eDVBLocalTimerHandler] no correction found... store calced correction(%d)",-enigma_diff); m_timeOffsetMap[chan->getChannelID()] = -enigma_diff; } } else // no time setted yet { if ( it != m_timeOffsetMap.end() ) { enigma_diff += it->second; eDebug("[eDVBLocalTimerHandler] we have correction (%d)... use", it->second ); } else eDebug("[eDVBLocalTimerHandler] dont have correction.. set Transponder Diff"); new_diff=enigma_diff; m_time_ready=true; } time_t t = linuxTime+new_diff; m_last_tp_time_difference=tp_time-t; if (!new_diff && updated) // overrride this check on first received TDT { eDebug("[eDVBLocalTimerHandler] not changed"); return; } if ( !update_count ) { // set rtc to calced transponder time when the first tdt is received on this // transponder setRTC(t); eDebug("[eDVBLocalTimerHandler] update RTC"); } else if (getRTC()) { if (abs(getRTC() - t) > 60) { eDebug("[eDVBLocalTimerHandler] difference between new linux time and RTC time is > 60 sec... transponder time looks not ok... use rtc time"); t = getRTC(); } else eDebug("[eDVBLocalTimerHandler] difference between linux time and RTC time is < 60 sec... so the transponder time looks ok"); } else eDebug("[eDVBLocalTimerHandler] no RTC available :("); tm now; localtime_r(&t, &now); eDebug("[eDVBLocalTimerHandler] time update to %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); time_difference = t - linuxTime; // calc our new linux_time -> enigma_time correction eDebug("[eDVBLocalTimerHandler] m_time_difference is %d", time_difference ); if ( time_difference ) { eDebug("[eDVBLocalTimerHandler] set Linux Time"); timeval tnow; gettimeofday(&tnow,0); tnow.tv_sec=t; settimeofday(&tnow,0); } /*emit*/ m_timeUpdated(); } if ( restart_tdt ) { std::map<iDVBChannel*, channel_data>::iterator it = m_knownChannels.find(chan); if ( it != m_knownChannels.end() ) { int updateCount = it->second.tdt->getUpdateCount(); it->second.tdt = 0; it->second.tdt = new TDT(chan, updateCount); it->second.tdt->startTimer(TIME_UPDATE_INTERVAL); // restart TDT for this transponder in 30min } } }
void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int update_count ) { int time_difference; bool restart_tdt = false; if (!tp_time) restart_tdt = true; else if (tp_time == -1) { restart_tdt = true; eDebug("[eDVBLocalTimerHandler] no transponder tuned... or no TDT/TOT avail .. try to use RTC :)"); time_t rtc_time = getRTC(); if (rtc_time) // RTC Ready? { tm now; localtime_r(&rtc_time, &now); eDebug("[eDVBLocalTimerHandler] RTC time is %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); time_t linuxTime=time(0); localtime_r(&linuxTime, &now); eDebug("[eDVBLocalTimerHandler] Receiver time is %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); time_difference = rtc_time - linuxTime; eDebug("[eDVBLocalTimerHandler] RTC to Receiver time difference is %ld seconds", linuxTime - rtc_time ); if (time_difference) { if ((time_difference >= -15) && (time_difference <= 15)) { timeval tdelta, tolddelta; // Slew small diffs ... // Even good transponders can differ by 0-5 sec, if we would step these // the system clock would permanentely jump around when zapping. tdelta.tv_sec = time_difference; if(adjtime(&tdelta, &tolddelta) == 0) eDebug("[eDVBLocalTimerHandler] slewing Linux Time by %03d seconds", time_difference); else eDebug("[eDVBLocalTimerHandler] slewing Linux Time by %03d seconds FAILED", time_difference); } else { timeval tnow; // ... only step larger diffs gettimeofday(&tnow, 0); tnow.tv_sec = rtc_time; settimeofday(&tnow, 0); linuxTime = time(0); localtime_r(&linuxTime, &now); eDebug("[eDVBLocalTimerHandler] stepped Linux Time to %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); } } else if ( !time_difference ) eDebug("[eDVBLocalTimerHandler] no change needed"); else eDebug("[eDVBLocalTimerHandler] set to RTC time"); /*emit*/ m_timeUpdated(); } else eDebug("[eDVBLocalTimerHandler] getRTC returned time=0. RTC problem?"); } else { std::map< eDVBChannelID, int >::iterator it( m_timeOffsetMap.find( chan->getChannelID() ) ); // current linux time time_t linuxTime = time(0); // difference between current enigma time and transponder time int enigma_diff = tp_time-linuxTime; int new_diff=0; bool updated = m_time_ready; if ( m_time_ready ) // ref time ready? { // difference between reference time (current enigma time) // and the transponder time eDebug("[eDVBLocalTimerHandler] diff is %d", enigma_diff); if ( abs(enigma_diff) < 120 ) { eDebug("[eDVBLocalTimerHandler] diff < 120 .. use Transponder Time"); m_timeOffsetMap[chan->getChannelID()] = 0; new_diff = enigma_diff; } else if ( it != m_timeOffsetMap.end() ) // correction saved? { eDebug("[eDVBLocalTimerHandler] we have correction %d", it->second); time_t CorrectedTpTime = tp_time+it->second; int ddiff = CorrectedTpTime-linuxTime; eDebug("[eDVBLocalTimerHandler] diff after add correction is %d", ddiff); if ( abs(it->second) < 300 ) // stored correction < 5 min { eDebug("[eDVBLocalTimerHandler] use stored correction(<5 min)"); new_diff = ddiff; } else if ( getRTC() ) { time_t rtc=getRTC(); m_timeOffsetMap[chan->getChannelID()] = rtc-tp_time; new_diff = rtc-linuxTime; // set enigma time to rtc eDebug("[eDVBLocalTimerHandler] update stored correction to %ld (calced against RTC time)", rtc-tp_time ); } else if ( abs(ddiff) <= 120 ) { // with stored correction calced time difference is lower 2 min // this don't help when a transponder have a clock running to slow or to fast // then its better to have a DM7020 with always running RTC eDebug("[eDVBLocalTimerHandler] use stored correction(corr < 2 min)"); new_diff = ddiff; } else // big change in calced correction.. hold current time and update correction { eDebug("[eDVBLocalTimerHandler] update stored correction to %d", -enigma_diff); m_timeOffsetMap[chan->getChannelID()] = -enigma_diff; } } else { eDebug("[eDVBLocalTimerHandler] no correction found... store calced correction(%d)",-enigma_diff); m_timeOffsetMap[chan->getChannelID()] = -enigma_diff; } } else // no time setted yet { if ( it != m_timeOffsetMap.end() ) { enigma_diff += it->second; eDebug("[eDVBLocalTimerHandler] we have correction (%d)... use", it->second ); } else eDebug("[eDVBLocalTimerHandler] dont have correction.. set Transponder Diff"); new_diff=enigma_diff; m_time_ready=true; } time_t t = linuxTime+new_diff; m_last_tp_time_difference=tp_time-t; if (!new_diff && updated) // overrride this check on first received TDT { eDebug("[eDVBLocalTimerHandler] not changed"); return; } if ( !update_count ) { // set rtc to calced transponder time when the first tdt is received on this // transponder setRTC(t); eDebug("[eDVBLocalTimerHandler] update RTC"); } else if (getRTC()) { if (abs(getRTC() - t) > 60) { eDebug("[eDVBLocalTimerHandler] difference between new linux time and RTC time is > 60 sec... transponder time looks not ok... use rtc time"); t = getRTC(); } else eDebug("[eDVBLocalTimerHandler] difference between linux time and RTC time is < 60 sec... so the transponder time looks ok"); } else eDebug("[eDVBLocalTimerHandler] no RTC available :("); tm now; localtime_r(&t, &now); eDebug("[eDVBLocalTimerHandler] time update to %02d:%02d:%02d", now.tm_hour, now.tm_min, now.tm_sec); time_difference = t - linuxTime; // calc our new linux_time -> enigma_time correction eDebug("[eDVBLocalTimerHandler] m_time_difference is %d", time_difference ); if ( time_difference ) { eDebug("[eDVBLocalTimerHandler] set Linux Time"); timeval tnow; gettimeofday(&tnow,0); tnow.tv_sec=t; settimeofday(&tnow,0); } /*emit*/ m_timeUpdated(); } if ( restart_tdt ) { std::map<iDVBChannel*, channel_data>::iterator it = m_knownChannels.find(chan); if ( it != m_knownChannels.end() ) { int system = iDVBFrontend::feSatellite; ePtr<iDVBFrontendParameters> parms; chan->getCurrentFrontendParameters(parms); if (parms) { parms->getSystem(system); } int updateCount = it->second.timetable->getUpdateCount(); it->second.timetable = NULL; if (system == iDVBFrontend::feATSC) { it->second.timetable = new STT(chan, updateCount); } else { it->second.timetable = new TDT(chan, updateCount); } it->second.timetable->startTimer(TIME_UPDATE_INTERVAL); // restart TDT for this transponder in 30min } } }