signal all waiting threads when receiving an active source message, cache the current...
[deb_libcec.git] / src / lib / devices / CECBusDevice.cpp
index 5137cfbc00ad08ce7bf7940cd9fde57e30586484..4234ec72254d0ee436e352588f3c6c5c1f797488 100644 (file)
@@ -532,6 +532,9 @@ bool CCECBusDevice::SetPhysicalAddress(uint16_t iNewAddress)
   {
     LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): physical address changed from %04x to %04x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress, iNewAddress);
     m_iPhysicalAddress = iNewAddress;
+
+    if (m_processor->GetDevices()->GetActiveSourceAddress() == iNewAddress)
+      MarkAsActiveSource();
   }
   return true;
 }
@@ -740,8 +743,13 @@ cec_bus_device_status CCECBusDevice::GetStatus(bool bForcePoll /* = false */, bo
     CLockObject lock(m_mutex);
     status = m_deviceStatus;
     bNeedsPoll = !bSuppressPoll &&
-        (bForcePoll || m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN) &&
-        m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC;
+        m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC &&
+            // poll forced
+            (bForcePoll ||
+            // don't know the status
+            m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN ||
+            // always poll the TV if it's marked as not present
+            (m_deviceStatus == CEC_DEVICE_STATUS_NOT_PRESENT && m_iLogicalAddress == CECDEVICE_TV));
   }
 
   if (bNeedsPoll)
@@ -788,7 +796,7 @@ void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus, cec_v
       if (m_deviceStatus != newStatus)
       {
         LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): device status changed into 'not present'", GetLogicalAddressName(), m_iLogicalAddress);
-        ResetDeviceStatus();
+        ResetDeviceStatus(true);
         m_deviceStatus = newStatus;
       }
       break;
@@ -799,7 +807,7 @@ void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus, cec_v
   }
 }
 
-void CCECBusDevice::ResetDeviceStatus(void)
+void CCECBusDevice::ResetDeviceStatus(bool bClientUnregistered /* = false */)
 {
   CLockObject lock(m_mutex);
   SetPowerStatus   (CEC_POWER_STATUS_UNKNOWN);
@@ -808,7 +816,7 @@ void CCECBusDevice::ResetDeviceStatus(void)
   SetCecVersion    (CEC_VERSION_UNKNOWN);
   SetStreamPath    (CEC_INVALID_PHYSICAL_ADDRESS);
   SetOSDName       (ToString(m_iLogicalAddress));
-  MarkAsInactiveSource();
+  MarkAsInactiveSource(bClientUnregistered);
 
   m_iLastActive = 0;
   m_bVendorIdRequested = false;
@@ -961,13 +969,15 @@ void CCECBusDevice::MarkAsActiveSource(void)
 
   if (bWasActivated)
   {
+    if (IsHandledByLibCEC())
+      m_processor->SetActiveSource(true, false);
     CCECClient *client = GetClient();
     if (client)
       client->SourceActivated(m_iLogicalAddress);
   }
 }
 
-void CCECBusDevice::MarkAsInactiveSource(void)
+void CCECBusDevice::MarkAsInactiveSource(bool bClientUnregistered /* = false */)
 {
   bool bWasDeactivated(false);
   {
@@ -982,6 +992,8 @@ void CCECBusDevice::MarkAsInactiveSource(void)
 
   if (bWasDeactivated)
   {
+    if (IsHandledByLibCEC())
+      m_processor->SetActiveSource(false, bClientUnregistered);
     CCECClient *client = GetClient();
     if (client)
       client->SourceDeactivated(m_iLogicalAddress);
@@ -1066,6 +1078,26 @@ bool CCECBusDevice::TransmitPendingActiveSourceCommands(void)
   return bReturn;
 }
 
+void CCECBusDevice::SetActiveRoute(uint16_t iRoute)
+{
+  CCECDeviceMap* map = m_processor->GetDevices();
+  if (!map)
+    return;
+
+  CCECBusDevice* previouslyActive = map->GetActiveSource();
+  if (!previouslyActive)
+    return;
+
+  CECDEVICEVEC devices;
+  m_processor->GetDevices()->GetChildrenOf(devices, this);
+
+  for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++)
+  {
+    if (!CCECTypeUtils::PhysicalAddressIsIncluded(iRoute, (*it)->GetCurrentPhysicalAddress()))
+      (*it)->MarkAsInactiveSource();
+  }
+}
+
 void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /* = CEC_INVALID_PHYSICAL_ADDRESS */)
 {
   CLockObject lock(m_mutex);