added protection against standby without a notification from XBMC and clock changes...
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 2aa81cadfdecd719db27d43976ad374a3510e705..63e481551457682c0e58545b37272028a56979f0 100644 (file)
@@ -57,6 +57,34 @@ using namespace PLATFORM;
 
 #define ToString(x) CCECTypeUtils::ToString(x)
 
+CCECStandbyProtection::CCECStandbyProtection(CCECProcessor* processor) :
+    m_processor(processor) {}
+CCECStandbyProtection::~CCECStandbyProtection(void) {}
+
+void* CCECStandbyProtection::Process(void)
+{
+  int64_t last = GetTimeMs();
+  int64_t next;
+  while (!IsStopped())
+  {
+    PLATFORM::CEvent::Sleep(1000);
+
+    next = GetTimeMs();
+
+    // reset the connection if the clock changed
+    if (next < last || next - last > 10000)
+    {
+      libcec_parameter param;
+      param.paramData = NULL; param.paramType = CEC_PARAMETER_TYPE_UNKOWN;
+      m_processor->GetLib()->Alert(CEC_ALERT_CONNECTION_LOST, param);
+      break;
+    }
+
+    last = next;
+  }
+  return NULL;
+}
+
 CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_bInitialised(false),
     m_communication(NULL),
@@ -66,7 +94,8 @@ CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_iLastTransmission(0),
     m_bMonitor(true),
     m_addrAllocator(NULL),
-    m_bStallCommunication(false)
+    m_bStallCommunication(false),
+    m_connCheck(NULL)
 {
   m_busDevices = new CCECDeviceMap(this);
 }
@@ -105,6 +134,7 @@ void CCECProcessor::Close(void)
   SetCECInitialised(false);
 
   // stop the processor
+  DELETE_AND_NULL(m_connCheck);
   StopThread(-1);
   m_inBuffer.Broadcast();
   StopThread();
@@ -215,6 +245,10 @@ void *CCECProcessor::Process(void)
 {
   m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
 
+  if (!m_connCheck)
+    m_connCheck = new CCECStandbyProtection(this);
+  m_connCheck->CreateThread();
+
   cec_command command; command.Clear();
   CTimeout activeSourceCheck(ACTIVE_SOURCE_CHECK_INTERVAL);
   CTimeout tvPresentCheck(TV_PRESENT_CHECK_INTERVAL);
@@ -245,12 +279,17 @@ void *CCECProcessor::Process(void)
       // check whether the TV is present and responding
       if (tvPresentCheck.TimeLeft() == 0)
       {
-        if (!m_busDevices->At(CECDEVICE_TV)->IsPresent())
+        CCECClient *primary = GetPrimaryClient();
+        // only check whether the tv responds to polls when a client is connected and not in monitoring mode
+        if (primary && primary->GetConfiguration()->bMonitorOnly != 1)
         {
-          libcec_parameter param;
-          param.paramType = CEC_PARAMETER_TYPE_STRING;
-          param.paramData = (void*)"TV does not respond to CEC polls";
-          GetPrimaryClient()->Alert(CEC_ALERT_TV_POLL_FAILED, param);
+          if (!m_busDevices->At(CECDEVICE_TV)->IsPresent())
+          {
+            libcec_parameter param;
+            param.paramType = CEC_PARAMETER_TYPE_STRING;
+            param.paramData = (void*)"TV does not respond to CEC polls";
+            primary->Alert(CEC_ALERT_TV_POLL_FAILED, param);
+          }
         }
         tvPresentCheck.Init(TV_PRESENT_CHECK_INTERVAL);
       }
@@ -480,7 +519,7 @@ void CCECProcessor::TransmitAbort(cec_logical_address source, cec_logical_addres
 void CCECProcessor::ProcessCommand(const cec_command &command)
 {
   // log the command
-  m_libcec->AddLog(CEC_LOG_TRAFFIC, CCECTypeUtils::ToString(command).c_str());
+  m_libcec->AddLog(CEC_LOG_TRAFFIC, ToString(command).c_str());
 
   // find the initiator
   CCECBusDevice *device = m_busDevices->At(command.initiator);
@@ -854,7 +893,7 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   client->GetPrimaryDevice()->TransmitOSDName(CECDEVICE_TV, false);
 
   // request the power status of the TV
-  tv->RequestPowerStatus(sourceAddress, true);
+  tv->RequestPowerStatus(sourceAddress, true, true);
 
   return bReturn;
 }