rpi: handle VC_CEC_LOGICAL_ADDR_LOST in the rpi communication class itself, don't...
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 71e5c6960ac8d643f5ba98de374843685dcafacf..1eb272aa7197ba51db4c851b3cad825a0b706f36 100644 (file)
@@ -62,7 +62,8 @@ CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_libcec(libcec),
     m_iStandardLineTimeout(3),
     m_iRetryLineTimeout(3),
-    m_iLastTransmission(0)
+    m_iLastTransmission(0),
+    m_bMonitor(true)
 {
   m_busDevices = new CCECDeviceMap(this);
 }
@@ -603,6 +604,7 @@ bool CCECProcessor::GetDeviceInformation(const char *strPort, libcec_configurati
   config->iFirmwareVersion   = m_communication->GetFirmwareVersion();
   config->iPhysicalAddress   = m_communication->GetPhysicalAddress();
   config->iFirmwareBuildDate = m_communication->GetFirmwareBuildDate();
+  config->adapterType        = m_communication->GetAdapterType();
 
   return true;
 }
@@ -660,12 +662,24 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   if (client->IsRegistered())
     UnregisterClient(client);
 
+  // ensure that controlled mode is enabled
+  m_communication->SetControlledMode(true);
+
   // ensure that we know the vendor id of the TV
   CCECBusDevice *tv = GetTV();
+  cec_vendor_id tvVendor = CEC_VENDOR_UNKNOWN;
   if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_UNREGISTERED))
-    tv->GetVendorId(CECDEVICE_UNREGISTERED);
+    tvVendor = tv->GetVendorId(CECDEVICE_UNREGISTERED);
   else if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE))
-    tv->GetVendorId(CECDEVICE_FREEUSE);
+    tvVendor = tv->GetVendorId(CECDEVICE_FREEUSE);
+
+  // wait until the handler is replaced, to avoid double registrations
+  if (tvVendor != CEC_VENDOR_UNKNOWN &&
+      CCECCommandHandler::HasSpecificHandler(tvVendor))
+  {
+    while (!tv->ReplaceHandler(false))
+      CEvent::Sleep(5);
+  }
 
   // get the configuration from the client
   m_libcec->AddLog(CEC_LOG_NOTICE, "registering new CEC client - v%s", ToString((cec_client_version)configuration.clientVersion));
@@ -718,6 +732,7 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   configuration.serverVersion      = LIBCEC_VERSION_CURRENT;
   configuration.iFirmwareVersion   = m_communication->GetFirmwareVersion();
   configuration.iFirmwareBuildDate = m_communication->GetFirmwareBuildDate();
+  configuration.adapterType        = m_communication->GetAdapterType();
 
   // mark the client as registered
   client->SetRegistered(true);
@@ -784,7 +799,17 @@ bool CCECProcessor::UnregisterClient(CCECClient *client)
   }
 
   // set the new ackmask
-  return SetLogicalAddresses(GetLogicalAddresses());;
+  cec_logical_addresses addresses = GetLogicalAddresses();
+  if (SetLogicalAddresses(addresses))
+  {
+    // no more clients left, disable controlled mode
+    if (addresses.IsEmpty() && !m_bMonitor)
+      m_communication->SetControlledMode(false);
+
+    return true;
+  }
+
+  return false;
 }
 
 void CCECProcessor::UnregisterClients(void)
@@ -851,3 +876,29 @@ bool CCECProcessor::IsRunningLatestFirmware(void)
       m_communication->IsRunningLatestFirmware() :
       true;
 }
+
+void CCECProcessor::SwitchMonitoring(bool bSwitchTo)
+{
+  {
+    CLockObject lock(m_mutex);
+    m_bMonitor = bSwitchTo;
+  }
+  if (bSwitchTo)
+    UnregisterClients();
+}
+
+void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress, cec_logical_address newAddress)
+{
+  m_libcec->AddLog(CEC_LOG_NOTICE, "logical address %x was taken by another device, changed to %x", oldAddress, newAddress);
+  CCECClient* client = GetClient(oldAddress);
+  if (client)
+  {
+    if (newAddress == CECDEVICE_UNKNOWN)
+      UnregisterClient(client);
+    else
+    {
+      client->m_configuration.logicalAddresses.Unset(oldAddress);
+      client->m_configuration.logicalAddresses.Set(newAddress);
+    }
+  }
+}