X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2FCECClient.cpp;h=b0d7e188da38fd98a138214b6f5cb79c59e34f3c;hb=ebefc26c10d68ba9ced2a30c896dccc81c6c2eeb;hp=24f196f49287008800a01c1b88f76ff4d0463259;hpb=cc938f166e50b0c9e4fdccf55e0a8cffb2c56602;p=deb_libcec.git diff --git a/src/lib/CECClient.cpp b/src/lib/CECClient.cpp index 24f196f..b0d7e18 100644 --- a/src/lib/CECClient.cpp +++ b/src/lib/CECClient.cpp @@ -33,23 +33,27 @@ #include "CECClient.h" #include "CECProcessor.h" #include "LibCEC.h" +#include "CECTypeUtils.h" #include "devices/CECPlaybackDevice.h" #include "devices/CECAudioSystem.h" #include "devices/CECTV.h" +#include "implementations/CECCommandHandler.h" using namespace CEC; using namespace PLATFORM; #define LIB_CEC m_processor->GetLib() -#define ToString(x) LIB_CEC->ToString(x) +#define ToString(x) CCECTypeUtils::ToString(x) CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration &configuration) : m_processor(processor), m_bInitialised(false), m_bRegistered(false), m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN), - m_buttontime(0) + m_buttontime(0), + m_iPreventForwardingPowerOffCommand(0) { + m_configuration.Clear(); // set the initial configuration SetConfiguration(configuration); } @@ -119,12 +123,9 @@ bool CCECClient::OnRegister(void) // set the physical address SetPhysicalAddress(m_configuration); - // ensure that we know the vendor id of the TV, so we are using the correct handler - m_processor->GetTV()->GetVendorId(GetPrimaryLogicalAdddress()); - // make the primary device the active source if the option is set if (m_configuration.bActivateSource == 1) - GetPrimaryDevice()->ActivateSource(); + GetPrimaryDevice()->ActivateSource(500); return true; } @@ -138,7 +139,7 @@ bool CCECClient::SetHDMIPort(const cec_logical_address iBaseDevice, const uint8_ iPort > CEC_MAX_HDMI_PORTNUMBER) return bReturn; - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice); + LIB_CEC->AddLog(CEC_LOG_NOTICE, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice); // update the configuration { @@ -194,15 +195,19 @@ void CCECClient::ResetPhysicalAddress(void) void CCECClient::SetPhysicalAddress(const libcec_configuration &configuration) { - // try to autodetect the address bool bPASet(false); - if (m_processor->CECInitialised() && configuration.bAutodetectAddress == 1) - bPASet = AutodetectPhysicalAddress(); - // try to use physical address setting + // override the physical address from configuration.iPhysicalAddress if it's set if (!bPASet && CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress)) bPASet = SetPhysicalAddress(configuration.iPhysicalAddress); + // try to autodetect the address + if (!bPASet && m_processor->CECInitialised()) + { + bPASet = AutodetectPhysicalAddress(); + m_configuration.bAutodetectAddress = bPASet ? 1 : 0; + } + // use the base device + hdmi port settings if (!bPASet) bPASet = SetHDMIPort(configuration.baseDevice, configuration.iHDMIPort); @@ -245,11 +250,41 @@ bool CCECClient::SetPhysicalAddress(const uint16_t iPhysicalAddress) return true; } +void CCECClient::SetSupportedDeviceTypes(void) +{ + cec_device_type_list types; + types.Clear(); + + // get the command handler for the tv + CCECCommandHandler *tvHandler = m_processor->GetTV()->GetHandler(); + if (!tvHandler) + return; + + // check all device types + for (uint8_t iPtr = 0; iPtr < 5; iPtr++) + { + if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED) + continue; + + // get the supported device type. the handler will replace types it doesn't support by one it does support + cec_device_type type = tvHandler->GetReplacementDeviceType(m_configuration.deviceTypes.types[iPtr]); + if (!types.IsSet(type)) + types.Add(type); + } + m_processor->GetTV()->MarkHandlerReady(); + + // set the new type list + m_configuration.deviceTypes = types; +} + bool CCECClient::AllocateLogicalAddresses(void) { // reset all previous LAs that were set m_configuration.logicalAddresses.Clear(); + // get the supported device types from the command handler of the TV + SetSupportedDeviceTypes(); + // display an error if no device types are set if (m_configuration.deviceTypes.IsEmpty()) { @@ -678,21 +713,19 @@ uint8_t CCECClient::SendMuteAudio(void) bool CCECClient::SendKeypress(const cec_logical_address iDestination, const cec_user_control_code key, bool bWait /* = true */) { - CCECBusDevice *device = GetPrimaryDevice(); CCECBusDevice *dest = m_processor->GetDevice(iDestination); - return device && dest ? - device->TransmitKeypress(GetPrimaryLogicalAdddress(), key, bWait) : + return dest ? + dest->TransmitKeypress(GetPrimaryLogicalAdddress(), key, bWait) : false; } bool CCECClient::SendKeyRelease(const cec_logical_address iDestination, bool bWait /* = true */) { - CCECBusDevice *device = GetPrimaryDevice(); CCECBusDevice *dest = m_processor->GetDevice(iDestination); - return device && dest ? - device->TransmitKeyRelease(GetPrimaryLogicalAdddress(), bWait) : + return dest ? + dest->TransmitKeyRelease(GetPrimaryLogicalAdddress(), bWait) : false; } @@ -851,14 +884,28 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) void CCECClient::AddCommand(const cec_command &command) { - CLockObject lock(m_mutex); + // don't forward the standby opcode more than once every 10 seconds + if (command.opcode == CEC_OPCODE_STANDBY) + { + CLockObject lock(m_mutex); + if (m_iPreventForwardingPowerOffCommand != 0 && + m_iPreventForwardingPowerOffCommand > GetTimeMs()) + return; + else + m_iPreventForwardingPowerOffCommand = GetTimeMs() + CEC_FORWARD_STANDBY_MIN_INTERVAL; + } + + if (command.destination == CECDEVICE_BROADCAST || GetLogicalAddresses().IsSet(command.destination)) + { + CLockObject lock(m_mutex); - LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> %s (%X) -> %s (%X): %s (%2X)", ToString(command.initiator), command.initiator, ToString(command.destination), command.destination, ToString(command.opcode), command.opcode); + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> %s (%X) -> %s (%X): %s (%2X)", ToString(command.initiator), command.initiator, ToString(command.destination), command.destination, ToString(command.opcode), command.opcode); - if (m_configuration.callbacks && m_configuration.callbacks->CBCecCommand) - m_configuration.callbacks->CBCecCommand(m_configuration.callbackParam, command); - else if (!m_commandBuffer.Push(command)) - LIB_CEC->AddLog(CEC_LOG_WARNING, "command buffer is full"); + if (m_configuration.callbacks && m_configuration.callbacks->CBCecCommand) + m_configuration.callbacks->CBCecCommand(m_configuration.callbackParam, command); + else if (!m_commandBuffer.Push(command)) + LIB_CEC->AddLog(CEC_LOG_WARNING, "command buffer is full"); + } } int CCECClient::MenuStateChanged(const cec_menu_state newState) @@ -875,6 +922,30 @@ int CCECClient::MenuStateChanged(const cec_menu_state newState) return 0; } +void CCECClient::SourceActivated(const cec_logical_address logicalAddress) +{ + CLockObject lock(m_mutex); + + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source activated: %s (%x)", ToString(logicalAddress), logicalAddress); + + if (m_configuration.callbacks && + m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_7_1 && + m_configuration.callbacks->CBCecSourceActivated) + m_configuration.callbacks->CBCecSourceActivated(m_configuration.callbackParam, logicalAddress, 1); +} + +void CCECClient::SourceDeactivated(const cec_logical_address logicalAddress) +{ + CLockObject lock(m_mutex); + + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source deactivated: %s (%x)", ToString(logicalAddress), logicalAddress); + + if (m_configuration.callbacks && + m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_7_1 && + m_configuration.callbacks->CBCecSourceActivated) + m_configuration.callbacks->CBCecSourceActivated(m_configuration.callbackParam, logicalAddress, 0); +} + void CCECClient::Alert(const libcec_alert type, const libcec_parameter ¶m) { CLockObject lock(m_mutex); @@ -1142,7 +1213,10 @@ cec_device_type_list CCECClient::GetDeviceTypes(void) bool CCECClient::SetDevicePhysicalAddress(const uint16_t iPhysicalAddress) { if (!CLibCEC::IsValidPhysicalAddress(iPhysicalAddress)) + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - not setting invalid physical address %04x", __FUNCTION__, iPhysicalAddress); return false; + } // reconfigure all devices cec_logical_address reactivateSource(CECDEVICE_UNKNOWN);