+bool CCECBusDevice::HandleCommand(const cec_command &command)
+{
+ bool bHandled(false);
+
+ /* update "last active" */
+ {
+ CLockObject lock(m_mutex);
+ m_iLastActive = GetTimeMs();
+
+ /* don't call GetStatus() here, just read the value with the mutex locked */
+ if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+ m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
+
+ MarkBusy();
+ }
+
+ /* handle the command */
+ bHandled = m_handler->HandleCommand(command);
+
+ /* change status to present */
+ if (bHandled)
+ {
+ CLockObject lock(m_mutex);
+ if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+ {
+ if (m_deviceStatus != CEC_DEVICE_STATUS_PRESENT)
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "device %s (%x) status changed to present after command %s", GetLogicalAddressName(), (uint8_t)GetLogicalAddress(), ToString(command.opcode));
+ m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
+ }
+ }
+
+ MarkReady();
+ return bHandled;
+}
+
+bool CCECBusDevice::PowerOn(void)
+{
+ bool bReturn(false);
+ GetVendorId(); // ensure that we got the vendor id, because the implementations vary per vendor
+
+ MarkBusy();
+ cec_power_status currentStatus = GetPowerStatus(false);
+ if (currentStatus != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON &&
+ currentStatus != CEC_POWER_STATUS_ON)
+ {
+ CLibCEC::AddLog(CEC_LOG_NOTICE, "<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ if (m_handler->PowerOn(GetMyLogicalAddress(), m_iLogicalAddress))
+ {
+ SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+ bReturn = true;
+ }
+ }
+ else
+ {
+ CLibCEC::AddLog(CEC_LOG_NOTICE, "'%s' (%X) is already '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(currentStatus));
+ }
+
+ MarkReady();
+ return bReturn;
+}
+
+bool CCECBusDevice::Standby(void)
+{
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "<< putting '%s' (%X) in standby mode", GetLogicalAddressName(), m_iLogicalAddress);
+ MarkBusy();
+ bool bReturn = m_handler->TransmitStandby(GetMyLogicalAddress(), m_iLogicalAddress);
+ MarkReady();
+ return bReturn;
+}
+
+/** @name Getters */
+//@{
+cec_version CCECBusDevice::GetCecVersion(bool bUpdate /* = false */)
+{
+ bool bIsPresent(GetStatus() == CEC_DEVICE_STATUS_PRESENT);
+ bool bRequestUpdate(false);
+ {
+ CLockObject lock(m_mutex);
+ bRequestUpdate = bIsPresent &&
+ (bUpdate || m_cecVersion == CEC_VERSION_UNKNOWN);
+ }
+
+ if (bRequestUpdate)
+ {
+ CheckVendorIdRequested();
+ RequestCecVersion();
+ }
+
+ CLockObject lock(m_mutex);
+ return m_cecVersion;
+}
+
+bool CCECBusDevice::RequestCecVersion(void)
+{
+ bool bReturn(false);
+
+ if (!MyLogicalAddressContains(m_iLogicalAddress) &&
+ !IsUnsupportedFeature(CEC_OPCODE_GET_CEC_VERSION))
+ {
+ MarkBusy();
+ CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+
+ bReturn = m_handler->TransmitRequestCecVersion(GetMyLogicalAddress(), m_iLogicalAddress);
+ MarkReady();
+ }
+ return bReturn;
+}
+
+const char* CCECBusDevice::GetLogicalAddressName(void) const
+{
+ return ToString(m_iLogicalAddress);
+}
+
+cec_menu_language &CCECBusDevice::GetMenuLanguage(bool bUpdate /* = false */)
+{
+ bool bIsPresent(GetStatus() == CEC_DEVICE_STATUS_PRESENT);
+ bool bRequestUpdate(false);
+ {
+ CLockObject lock(m_mutex);
+ bRequestUpdate = (bIsPresent &&
+ (bUpdate || !strcmp(m_menuLanguage.language, "???")));
+ }
+
+ if (bRequestUpdate)
+ {
+ CheckVendorIdRequested();
+ RequestMenuLanguage();
+ }
+
+ CLockObject lock(m_mutex);
+ return m_menuLanguage;
+}
+
+bool CCECBusDevice::RequestMenuLanguage(void)
+{
+ bool bReturn(false);
+
+ if (!MyLogicalAddressContains(m_iLogicalAddress) &&
+ !IsUnsupportedFeature(CEC_OPCODE_GET_MENU_LANGUAGE))
+ {
+ MarkBusy();
+ CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ bReturn = m_handler->TransmitRequestMenuLanguage(GetMyLogicalAddress(), m_iLogicalAddress);
+ MarkReady();
+ }
+ return bReturn;
+}
+
+cec_menu_state CCECBusDevice::GetMenuState(void)
+{
+ CLockObject lock(m_mutex);
+ return m_menuState;
+}
+