cec: only poll devices that need to be polled. fix libcec initialisation
[deb_libcec.git] / src / lib / devices / CECBusDevice.cpp
index d5a0be6aef11dcb76351ad0bea58eaf4e3eb408a..702b561c1016611bb9999484dac28537dd0a2bb1 100644 (file)
@@ -214,6 +214,40 @@ uint16_t CCECBusDevice::GetMyPhysicalAddress(void) const
   return m_processor->GetPhysicalAddress();
 }
 
+CStdString CCECBusDevice::GetOSDName(void)
+{
+  if (GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+  {
+    CLockObject lock(&m_mutex);
+    if (m_strDeviceName.Equals(ToString(m_iLogicalAddress)))
+    {
+      lock.Leave();
+      RequestOSDName();
+      lock.Lock();
+    }
+  }
+
+  CLockObject lock(&m_mutex);
+  return m_strDeviceName;
+}
+
+bool CCECBusDevice::RequestOSDName(void)
+{
+  bool bReturn(false);
+  if (!MyLogicalAddressContains(m_iLogicalAddress))
+  {
+    CStdString strLog;
+    strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+    AddLog(CEC_LOG_NOTICE, strLog);
+    cec_command command;
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_OSD_NAME);
+    CLockObject lock(&m_transmitMutex);
+    if (m_processor->Transmit(command))
+      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+  }
+  return bReturn;
+}
+
 uint16_t CCECBusDevice::GetPhysicalAddress(bool bRefresh /* = true */)
 {
   if (GetStatus() == CEC_DEVICE_STATUS_PRESENT)
@@ -222,7 +256,8 @@ uint16_t CCECBusDevice::GetPhysicalAddress(bool bRefresh /* = true */)
     if (m_iPhysicalAddress == 0xFFFF || bRefresh)
     {
       lock.Leave();
-      RequestPhysicalAddress();
+      if (!RequestPhysicalAddress())
+        AddLog(CEC_LOG_ERROR, "failed to request the physical address");
       lock.Lock();
     }
   }
@@ -317,15 +352,65 @@ bool CCECBusDevice::MyLogicalAddressContains(cec_logical_address address) const
   return m_processor->HasLogicalAddress(address);
 }
 
-cec_bus_device_status CCECBusDevice::GetStatus(void)
+bool CCECBusDevice::NeedsPoll(void)
+{
+  bool bSendPoll(false);
+  switch (m_iLogicalAddress)
+  {
+  case CECDEVICE_PLAYBACKDEVICE3:
+    if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_PLAYBACKDEVICE2:
+    if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_RECORDINGDEVICE3:
+    if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_RECORDINGDEVICE2:
+    if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_TUNER4:
+    if (m_processor->m_busDevices[CECDEVICE_TUNER3]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_TUNER3:
+    if (m_processor->m_busDevices[CECDEVICE_TUNER2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_TUNER2:
+    if (m_processor->m_busDevices[CECDEVICE_TUNER1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+      bSendPoll = true;
+    break;
+  case CECDEVICE_AUDIOSYSTEM:
+  case CECDEVICE_PLAYBACKDEVICE1:
+  case CECDEVICE_RECORDINGDEVICE1:
+  case CECDEVICE_TUNER1:
+  case CECDEVICE_TV:
+    bSendPoll = true;
+    break;
+  default:
+    break;
+  }
+
+  return bSendPoll;
+}
+
+cec_bus_device_status CCECBusDevice::GetStatus(bool bForcePoll /* = false */)
 {
   CLockObject lock(&m_mutex);
-  if (m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN)
+  if (m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN || bForcePoll)
   {
-    if (m_processor->PollDevice(m_iLogicalAddress))
-      m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
-    else
-      m_deviceStatus = CEC_DEVICE_STATUS_NOT_PRESENT;
+    lock.Leave();
+    bool bPollAcked(false);
+    if (bForcePoll || NeedsPoll())
+      bPollAcked = m_processor->PollDevice(m_iLogicalAddress);
+
+    lock.Lock();
+    m_deviceStatus = bPollAcked ? CEC_DEVICE_STATUS_PRESENT : CEC_DEVICE_STATUS_NOT_PRESENT;
   }
 
   return m_deviceStatus;
@@ -748,4 +833,43 @@ bool CCECBusDevice::TransmitVendorID(cec_logical_address dest)
     return m_processor->Transmit(command);
   }
 }
+
+bool CCECBusDevice::SendKeypress(cec_user_control_code key, bool bWait /* = false */)
+{
+  {
+    CLockObject lock(&m_transmitMutex);
+    cec_command command;
+    cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_PRESSED);
+    command.parameters.PushBack((uint8_t)key);
+
+    if (bWait)
+    {
+      if (m_processor->Transmit(command))
+        return m_condition.Wait(&m_transmitMutex, 1000);
+      return false;
+    }
+
+    return m_processor->Transmit(command);
+  }
+}
+
+bool CCECBusDevice::SendKeyRelease(bool bWait /* = false */)
+{
+  {
+    CLockObject lock(&m_transmitMutex);
+    cec_command command;
+    cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_RELEASE);
+
+    if (bWait)
+    {
+      if (m_processor->Transmit(command))
+        return m_condition.Wait(&m_transmitMutex, 1000);
+      return false;
+    }
+    else
+    {
+      return m_processor->Transmit(command);
+    }
+  }
+}
 //@}