+ CLockObject lock(m_mutex);
+ if (m_unsupportedFeatures.find(opcode) == m_unsupportedFeatures.end())
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "marking opcode '%s' as unsupported feature for device '%s'", ToString(opcode), GetLogicalAddressName());
+ m_unsupportedFeatures.insert(opcode);
+ }
+ }
+
+ // signal threads that are waiting for a reponse
+ MarkBusy();
+ m_handler->SignalOpcode(cec_command::GetResponseOpcode(opcode));
+ MarkReady();
+}
+
+bool CCECBusDevice::IsUnsupportedFeature(cec_opcode opcode)
+{
+ CLockObject lock(m_mutex);
+ bool bUnsupported = (m_unsupportedFeatures.find(opcode) != m_unsupportedFeatures.end());
+ if (bUnsupported)
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "'%s' is marked as unsupported feature for device '%s'", ToString(opcode), GetLogicalAddressName());
+ return bUnsupported;
+}
+
+bool CCECBusDevice::TransmitKeypress(const cec_logical_address initiator, cec_user_control_code key, bool bWait /* = true */)
+{
+ MarkBusy();
+ bool bReturn = m_handler->TransmitKeypress(initiator, m_iLogicalAddress, key, bWait);
+ MarkReady();
+ return bReturn;
+}
+
+bool CCECBusDevice::TransmitKeyRelease(const cec_logical_address initiator, bool bWait /* = true */)
+{
+ MarkBusy();
+ bool bReturn = m_handler->TransmitKeyRelease(initiator, m_iLogicalAddress, bWait);
+ MarkReady();
+ return bReturn;
+}
+
+cec_version CCECBusDevice::GetCecVersion(const cec_logical_address initiator, 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(initiator);
+ RequestCecVersion(initiator);
+ }
+
+ CLockObject lock(m_mutex);
+ return m_cecVersion;
+}
+
+void CCECBusDevice::SetCecVersion(const cec_version newVersion)
+{
+ CLockObject lock(m_mutex);
+ if (m_cecVersion != newVersion)
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): CEC version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(newVersion));
+ m_cecVersion = newVersion;
+}
+
+bool CCECBusDevice::RequestCecVersion(const cec_logical_address initiator, bool bWaitForResponse /* = true */)
+{
+ bool bReturn(false);
+
+ if (!IsHandledByLibCEC() &&
+ !IsUnsupportedFeature(CEC_OPCODE_GET_CEC_VERSION))
+ {
+ MarkBusy();
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, "<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ bReturn = m_handler->TransmitRequestCecVersion(initiator, m_iLogicalAddress, bWaitForResponse);
+ MarkReady();
+ }
+ return bReturn;
+}
+
+bool CCECBusDevice::TransmitCECVersion(const cec_logical_address destination)
+{
+ cec_version version;
+ {
+ CLockObject lock(m_mutex);
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(destination), destination, ToString(m_cecVersion));
+ version = m_cecVersion;
+ }
+
+ MarkBusy();
+ bool bReturn = m_handler->TransmitCECVersion(m_iLogicalAddress, destination, version);
+ MarkReady();
+ return bReturn;
+}
+
+cec_menu_language &CCECBusDevice::GetMenuLanguage(const cec_logical_address initiator, 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(initiator);
+ RequestMenuLanguage(initiator);
+ }
+
+ CLockObject lock(m_mutex);
+ return m_menuLanguage;
+}
+
+void CCECBusDevice::SetMenuLanguage(const char *strLanguage)
+{
+ if (!strLanguage)