use video stc for display. make skipping look a bit better.
[enigma2.git] / lib / dvb / dvbtime.cpp
index dc98a6d3a9d00e55812874290e73eed69c5d4d20..3bd0a78dfbaa66eaea937c929617c5b822a86cd9 100644 (file)
@@ -62,8 +62,8 @@ time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5)
        return timegm(&t);
 }
 
-TDT::TDT(eDVBChannel *chan)
-       :chan(chan)
+TDT::TDT(eDVBChannel *chan, int update_count)
+       :chan(chan), update_count(update_count)
 {
        CONNECT(tableReady, TDT::ready);
        CONNECT(m_interval_timer.timeout, TDT::start);
@@ -73,7 +73,7 @@ TDT::TDT(eDVBChannel *chan)
 
 void TDT::ready(int error)
 {
-       eDVBLocalTimeHandler::getInstance()->updateTime(error, chan);
+       eDVBLocalTimeHandler::getInstance()->updateTime(error, chan, ++update_count);
 }
 
 int TDT::createTable(int nr, const __u8 *data, unsigned int max)
@@ -84,7 +84,7 @@ int TDT::createTable(int nr, const __u8 *data, unsigned int max)
                if ( length >= 5 )
                {
                        time_t tptime = parseDVBtime(data[3], data[4], data[5], data[6], data[7]);
-                       eDVBLocalTimeHandler::getInstance()->updateTime(tptime, chan);
+                       eDVBLocalTimeHandler::getInstance()->updateTime(tptime, chan, update_count);
                        error=0;
                        return 1;
                }
@@ -173,10 +173,10 @@ void eDVBLocalTimeHandler::writeTimeOffsetData( const char* filename )
        }
 }
 
-void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
+void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int update_count )
 {
        bool restart_tdt = false;
-       if (!tp_time )
+       if (!tp_time)
                restart_tdt = true;
        else if (tp_time == -1)
        {
@@ -210,9 +210,7 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
                                        gettimeofday(&tnow,0);
                                        tnow.tv_sec=rtc_time;
                                        settimeofday(&tnow,0);
-                                       for (ePtrList<eMainloop>::iterator it(eMainloop::existing_loops)
-                                               ;it != eMainloop::existing_loops.end(); ++it)
-                                               it->addTimeOffset(m_time_difference);
+                                       eMainloop::addTimeOffset(m_time_difference);
                                        m_time_difference=0;
                                }
                                else if ( !m_time_difference )
@@ -240,6 +238,8 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
 
                int new_diff=0;
 
+               bool updated = m_time_ready;
+
                if ( m_time_ready )  // ref time ready?
                {
                        // difference between reference time (current enigma time)
@@ -306,7 +306,8 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
                time_t t = nowTime+new_diff;
                m_last_tp_time_difference=tp_time-t;
 
-               if (!new_diff)
+               if (!new_diff &&
+                       updated) // overrride this check on first received TDT
                {
                        eDebug("[eDVBLocalTimerHandler] not changed");
                        return;
@@ -322,7 +323,15 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
                eDebug("[eDVBLocalTimerHandler] m_time_difference is %d", m_time_difference );
 
 //             if ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 )  TODO !!
+               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
+                       eDebug("[eDVBLocalTimerHandler] don't update RTC");
 
                if ( abs(m_time_difference) > 59 )
                {
@@ -331,9 +340,7 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
                        gettimeofday(&tnow,0);
                        tnow.tv_sec=t;
                        settimeofday(&tnow,0);
-                       for (ePtrList<eMainloop>::iterator it(eMainloop::existing_loops)
-                               ;it != eMainloop::existing_loops.end(); ++it)
-                               it->addTimeOffset(m_time_difference);
+                       eMainloop::addTimeOffset(m_time_difference);
                        m_time_difference=0;
                }
 
@@ -346,9 +353,10 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
                        m_knownChannels.find(chan);
                if ( it != m_knownChannels.end() )
                {
-                       delete it->second.tdt;
-                       it->second.tdt = new TDT(chan);
+                       TDT *prev_tdt = it->second.tdt;
+                       it->second.tdt = new TDT(chan, prev_tdt->getUpdateCount());
                        it->second.tdt->startTimer(60*60*1000);  // restart TDT for this transponder in 60min
+                       delete prev_tdt;
                }
        }
 }
@@ -360,8 +368,9 @@ void eDVBLocalTimeHandler::DVBChannelAdded(eDVBChannel *chan)
 //             eDebug("[eDVBLocalTimerHandler] add channel %p", chan);
                std::pair<std::map<iDVBChannel*, channel_data>::iterator, bool> tmp =
                        m_knownChannels.insert( std::pair<iDVBChannel*, channel_data>(chan, channel_data()) );
-               tmp.first->second.tdt = new TDT(chan);
+               tmp.first->second.tdt = NULL;
                tmp.first->second.channel = chan;
+               tmp.first->second.m_prevChannelState = -1;
                chan->connectStateChange(slot(*this, &eDVBLocalTimeHandler::DVBChannelStateChanged), tmp.first->second.m_stateChangedConn);
        }
 }
@@ -374,17 +383,24 @@ void eDVBLocalTimeHandler::DVBChannelStateChanged(iDVBChannel *chan)
        {
                int state=0;
                chan->getState(state);
-               switch (state)
+               if ( state != it->second.m_prevChannelState )
                {
-                       case iDVBChannel::state_ok:
-                               eDebug("[eDVBLocalTimerHandler] channel %p running", chan);
-                               it->second.tdt->start();
-                               break;
-                       case iDVBChannel::state_release:
-                               eDebug("[eDVBLocalTimerHandler] remove channel %p", chan);
-                               delete it->second.tdt;
-                               m_knownChannels.erase(it);
-                               break;
+                       switch (state)
+                       {
+                               case iDVBChannel::state_ok:
+                                       eDebug("[eDVBLocalTimerHandler] channel %p running", chan);
+                                       it->second.tdt = new TDT(it->second.channel);
+                                       it->second.tdt->start();
+                                       break;
+                               case iDVBChannel::state_release:
+                                       eDebug("[eDVBLocalTimerHandler] remove channel %p", chan);
+                                       delete it->second.tdt;
+                                       m_knownChannels.erase(it);
+                                       break;
+                               default: // ignore all other events
+                                       return;
+                       }
+                       it->second.m_prevChannelState = state;
                }
        }
 }