cec: replace the handler directly after getting the vendor id of a device when regist...
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 3bfa061548c0e4b74d4811e7296790a6849b2630..28adee3282e4a22b6631a267403b5df512ed544f 100644 (file)
 #include "implementations/CECCommandHandler.h"
 #include "LibCEC.h"
 #include "CECClient.h"
+#include "CECTypeUtils.h"
 #include "platform/util/timeutils.h"
+#include "platform/util/util.h"
 
 using namespace CEC;
 using namespace std;
 using namespace PLATFORM;
 
 #define CEC_PROCESSOR_SIGNAL_WAIT_TIME 1000
+#define ACTIVE_SOURCE_CHECK_INTERVAL   500
 
-#define ToString(x) m_libcec->ToString(x)
+#define ToString(x) CCECTypeUtils::ToString(x)
 
 CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_bInitialised(false),
@@ -66,7 +69,7 @@ CCECProcessor::CCECProcessor(CLibCEC *libcec) :
 CCECProcessor::~CCECProcessor(void)
 {
   Close();
-  delete m_busDevices;
+  DELETE_AND_NULL(m_busDevices);
 }
 
 bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = CEC_SERIAL_DEFAULT_BAUDRATE */, uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
@@ -98,21 +101,13 @@ void CCECProcessor::Close(void)
   StopThread();
 
   // close the connection
-  if (m_communication)
-  {
-    delete m_communication;
-    m_communication = NULL;
-  }
+  DELETE_AND_NULL(m_communication);
 }
 
 void CCECProcessor::ResetMembers(void)
 {
   // close the connection
-  if (m_communication)
-  {
-    delete m_communication;
-    m_communication = NULL;
-  }
+  DELETE_AND_NULL(m_communication);
 
   // reset the other members to the initial state
   m_iStandardLineTimeout = 3;
@@ -153,9 +148,6 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint
 
   m_libcec->AddLog(CEC_LOG_NOTICE, "connection opened");
 
-  // always start by setting the ackmask to 0, to clear previous values
-  SetAckMask(0);
-
   // mark as initialised
   SetCECInitialised(true);
 
@@ -215,7 +207,8 @@ void *CCECProcessor::Process(void)
 {
   m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
 
-  cec_command command;
+  cec_command command; command.Clear();
+  CTimeout activeSourceCheck(ACTIVE_SOURCE_CHECK_INTERVAL);
 
   // as long as we're not being stopped and the connection is open
   while (!IsStopped() && m_communication->IsOpen())
@@ -231,6 +224,14 @@ void *CCECProcessor::Process(void)
 
       // check if we need to replace handlers
       ReplaceHandlers();
+
+      // check whether we need to activate a source, if it failed before
+      if (activeSourceCheck.TimeLeft() == 0)
+      {
+        if (CECInitialised())
+          TransmitPendingActiveSourceCommands();
+        activeSourceCheck.Init(ACTIVE_SOURCE_CHECK_INTERVAL);
+      }
     }
   }
 
@@ -400,6 +401,7 @@ bool CCECProcessor::Transmit(const cec_command &data)
     m_iLastTransmission = GetTimeMs();
     // set the number of tries
     iMaxTries = initiator->GetHandler()->GetTransmitRetries() + 1;
+    initiator->MarkHandlerReady();
   }
 
   // and try to send the command
@@ -517,7 +519,7 @@ bool CCECProcessor::StartBootloader(const char *strPort /* = NULL */)
     if (comm->IsOpen())
     {
       bReturn = comm->StartBootloader();
-      delete comm;
+      DELETE_AND_NULL(comm);
     }
     return bReturn;
   }
@@ -552,7 +554,9 @@ bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator)
 bool CCECProcessor::SetStreamPath(uint16_t iPhysicalAddress)
 {
   // stream path changes are sent by the TV
-  return GetTV()->GetHandler()->TransmitSetStreamPath(iPhysicalAddress);
+  bool bReturn = GetTV()->GetHandler()->TransmitSetStreamPath(iPhysicalAddress);
+  GetTV()->MarkHandlerReady();
+  return bReturn;
 }
 
 bool CCECProcessor::CanPersistConfiguration(void)
@@ -632,6 +636,11 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
     return false;
   }
 
+  // ensure that we know the vendor id of the TV
+  CCECBusDevice *tv = GetTV();
+  tv->GetVendorId(CECDEVICE_UNREGISTERED);
+  tv->ReplaceHandler(false);
+
   // unregister the client first if it's already been marked as registered
   if (client->IsRegistered())
     UnregisterClient(client);
@@ -659,6 +668,10 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   m_busDevices->GetByLogicalAddresses(devices, configuration.logicalAddresses);
   for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
   {
+               // set the physical address of the device at this LA
+    if (CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress))
+      (*it)->SetPhysicalAddress(configuration.iPhysicalAddress);
+
     // replace a previous client
     CLockObject lock(m_mutex);
     m_clients.erase((*it)->GetLogicalAddress());
@@ -668,7 +681,7 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   // get the settings from the rom
   if (configuration.bGetSettingsFromROM == 1)
   {
-    libcec_configuration config;
+    libcec_configuration config; config.Clear();
     m_communication->GetConfiguration(config);
 
     CLockObject lock(m_mutex);
@@ -707,6 +720,15 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
     client->Alert(CEC_ALERT_SERVICE_DEVICE, param);
   }
 
+  // ensure that the command handler for the TV is initialised
+  if (bReturn)
+  {
+    CCECCommandHandler *handler = GetTV()->GetHandler();
+    if (handler)
+      handler->InitHandler();
+    GetTV()->MarkHandlerReady();
+  }
+
   return bReturn;
 }