Merge branch 'fantempplugin' into experimental
[enigma2.git] / lib / dvb / dvbtime.cpp
index 4c5911c9178ce8da1356ea5fd125ee8acf6d76ad..bb6b94b0d9e7207a9a77ed4ddaedf855dd59f1d8 100644 (file)
@@ -11,6 +11,8 @@
 #define FP_IOCTL_SET_RTC         0x101
 #define FP_IOCTL_GET_RTC         0x102
 
+#define TIME_UPDATE_INTERVAL (30*60*1000)
+
 static time_t prev_time;
 
 void setRTC(time_t time)
@@ -18,7 +20,7 @@ void setRTC(time_t time)
        FILE *f = fopen("/proc/stb/fp/rtc", "w");
        if (f)
        {
-               if (fprintf(f, "%u", time))
+               if (fprintf(f, "%u", (unsigned int)time))
                        prev_time = time;
                else
                        eDebug("write /proc/stb/fp/rtc failed (%m)");
@@ -45,8 +47,11 @@ time_t getRTC()
        if (f)
        {
                // sanity check to detect corrupt atmel firmware
-               if (fscanf(f, "%u", &rtc_time) != 1)
+               unsigned int tmp;
+               if (fscanf(f, "%u", &tmp) != 1)
                        eDebug("read /proc/stb/fp/rtc failed (%m)");
+               else
+                       rtc_time=tmp;
                fclose(f);
        }
        else
@@ -62,7 +67,7 @@ time_t getRTC()
        return rtc_time != prev_time ? rtc_time : 0;
 }
 
-time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5)
+time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5, __u16 *hash)
 {
        tm t;
        t.tm_sec=fromBCD(t5);
@@ -82,6 +87,11 @@ time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5)
        t.tm_isdst =  0;
        t.tm_gmtoff = 0;
 
+       if (hash) {
+               *hash = t.tm_hour * 60 + t.tm_min;
+               *hash |= t.tm_mday << 11;
+       }
+
        return timegm(&t);
 }
 
@@ -143,7 +153,7 @@ eDVBLocalTimeHandler *eDVBLocalTimeHandler::instance;
 DEFINE_REF(eDVBLocalTimeHandler);
 
 eDVBLocalTimeHandler::eDVBLocalTimeHandler()
-       :m_time_ready(false)
+       :m_use_dvb_time(false), m_updateNonTunedTimer(eTimer::create(eApp)), m_time_ready(false)
 {
        if ( !instance )
                instance=this;
@@ -164,13 +174,12 @@ eDVBLocalTimeHandler::eDVBLocalTimeHandler()
                        /*emit*/ m_timeUpdated();
                }
        }
+       CONNECT(m_updateNonTunedTimer->timeout, eDVBLocalTimeHandler::updateNonTuned);
 }
 
 eDVBLocalTimeHandler::~eDVBLocalTimeHandler()
 {
        instance=0;
-       for (std::map<iDVBChannel*, channel_data>::iterator it=m_knownChannels.begin(); it != m_knownChannels.end(); ++it)
-               delete it->second.tdt;
        if (ready())
        {
                eDebug("set RTC to previous valid time");
@@ -213,6 +222,39 @@ void eDVBLocalTimeHandler::writeTimeOffsetData( const char* filename )
        }
 }
 
+void eDVBLocalTimeHandler::setUseDVBTime(bool b)
+{
+       if (m_use_dvb_time != b) {
+               if (m_use_dvb_time) {
+                       eDebug("[eDVBLocalTimeHandler] disable sync local time with transponder time!");
+                       std::map<iDVBChannel*, channel_data>::iterator it =
+                               m_knownChannels.begin();
+                       for (; it != m_knownChannels.end(); ++it) {
+                               if (it->second.m_prevChannelState == iDVBChannel::state_ok)
+                                       it->second.tdt = 0;
+                       }
+               }
+               else {
+                       eDebug("[eDVBLocalTimeHandler] enable sync local time with transponder time!");
+                       std::map<iDVBChannel*, channel_data>::iterator it =
+                               m_knownChannels.begin();
+                       for (; it != m_knownChannels.end(); ++it) {
+                               if (it->second.m_prevChannelState == iDVBChannel::state_ok) {
+                                       it->second.tdt = new TDT(it->second.channel);
+                                       it->second.tdt->start();
+                               }
+                       }
+               }
+               m_use_dvb_time = b;
+       }
+}
+
+void eDVBLocalTimeHandler::updateNonTuned()
+{
+       updateTime(-1, 0, 0);
+       m_updateNonTunedTimer->start(TIME_UPDATE_INTERVAL, true);
+}
+
 void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int update_count )
 {
        int time_difference;
@@ -396,10 +438,10 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int up
                        m_knownChannels.find(chan);
                if ( it != m_knownChannels.end() )
                {
-                       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;
+                       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
                }
        }
 }
@@ -432,13 +474,17 @@ void eDVBLocalTimeHandler::DVBChannelStateChanged(iDVBChannel *chan)
                        {
                                case iDVBChannel::state_ok:
                                        eDebug("[eDVBLocalTimerHandler] channel %p running", chan);
-                                       it->second.tdt = new TDT(it->second.channel);
-                                       it->second.tdt->start();
+                                       m_updateNonTunedTimer->stop();
+                                       if (m_use_dvb_time) {
+                                               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);
+                                       if (m_knownChannels.empty())
+                                               m_updateNonTunedTimer->start(TIME_UPDATE_INTERVAL, true);
                                        break;
                                default: // ignore all other events
                                        return;