From 8670c97085f27ad5d7f3fc218247f32332462b1d Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Thu, 16 Feb 2012 10:07:23 +0100 Subject: [PATCH] cec: moved the autodetect address api call to libcec_configuration. only send power up commands to non-tv devices when the power state is not on/transition->on. let players call the power up/power down command. --- include/cec.h | 1 + include/cectypes.h | 8 +- src/LibCecSharp/CecSharpTypes.h | 2 + src/LibCecSharp/LibCecSharp.cpp | 21 +++-- src/lib/CECProcessor.cpp | 92 +++++++++++++++----- src/lib/CECProcessor.h | 2 +- src/lib/adapter/AdapterCommunication.h | 5 ++ src/lib/adapter/USBCECAdapterCommunication.h | 1 + src/lib/devices/CECBusDevice.cpp | 17 +++- 9 files changed, 112 insertions(+), 37 deletions(-) diff --git a/include/cec.h b/include/cec.h index 1d36eb9..cbc8346 100644 --- a/include/cec.h +++ b/include/cec.h @@ -146,6 +146,7 @@ namespace CEC virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS) = 0; /*! + * @deprecated Use libcec_configuration instead. * @brief Enable physical address detection (if the connected adapter supports this). * @return True when physical address detection was enabled, false otherwise. */ diff --git a/include/cectypes.h b/include/cectypes.h index fe8678f..ca02f09 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -952,9 +952,10 @@ typedef struct libcec_configuration cec_client_version clientVersion; /*!< the version of the client that is connecting */ char strDeviceName[13]; /*!< how to name the device on the CEC bus */ cec_device_type_list deviceTypes; /*!< the CEC device types to emulate */ - uint16_t iPhysicalAddress; /*!< the physical address of the CEC adapter */ - cec_logical_address baseDevice; /*!< the logical address of the device to which the adapter is connected. only used when iPhysicalAddress = 0 */ - uint8_t iHDMIPort; /*!< the HDMI port to which the adapter is connected. only used when iPhysicalAddress = 0 */ + uint8_t bAutodetectAddress; /*!< try to autodetect the physical address when 1 */ + uint16_t iPhysicalAddress; /*!< the physical address of the CEC adapter. only used when bAutodetectAddress = 0 or when the adapter doesn't support autodetection */ + cec_logical_address baseDevice; /*!< the logical address of the device to which the adapter is connected. only used when iPhysicalAddress = 0 and bAutodetectAddress = 0 or when the adapter doesn't support autodetection */ + uint8_t iHDMIPort; /*!< the HDMI port to which the adapter is connected. only used when iPhysicalAddress = 0 and bAutodetectAddress = 0 or when the adapter doesn't support autodetection */ cec_vendor_id tvVendor; /*!< override the vendor ID of the TV. leave this untouched to autodetect */ cec_logical_addresses wakeDevices; /*!< wake these CEC devices when initialising libCEC or when calling PowerOnDevices() without any parameter */ cec_logical_addresses powerOffDevices; /*!< power off these devices when calling StandbyDevices() without any parameter */ @@ -982,6 +983,7 @@ typedef struct libcec_configuration wakeDevices.Clear(); powerOffDevices.Clear(); + bAutodetectAddress = 1; bGetSettingsFromROM = 0; bUseTVMenuLanguage = CEC_DEFAULT_SETTING_USE_TV_MENU_LANGUAGE; bActivateSource = CEC_DEFAULT_SETTING_ACTIVATE_SOURCE; diff --git a/src/LibCecSharp/CecSharpTypes.h b/src/LibCecSharp/CecSharpTypes.h index f385cda..135eecf 100644 --- a/src/LibCecSharp/CecSharpTypes.h +++ b/src/LibCecSharp/CecSharpTypes.h @@ -519,6 +519,7 @@ namespace CecSharp { DeviceName = ""; DeviceTypes = gcnew CecDeviceTypeList(); + AutodetectAddress = true; PhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS; BaseDevice = (CecLogicalAddress)CEC_DEFAULT_BASE_DEVICE; HDMIPort = CEC_DEFAULT_HDMI_PORT; @@ -548,6 +549,7 @@ namespace CecSharp property System::String ^ DeviceName; property CecDeviceTypeList ^ DeviceTypes; + property bool AutodetectAddress; property uint16_t PhysicalAddress; property CecLogicalAddress BaseDevice; property uint8_t HDMIPort; diff --git a/src/LibCecSharp/LibCecSharp.cpp b/src/LibCecSharp/LibCecSharp.cpp index c02c4ea..4bf39f0 100644 --- a/src/LibCecSharp/LibCecSharp.cpp +++ b/src/LibCecSharp/LibCecSharp.cpp @@ -93,12 +93,13 @@ namespace CecSharp for (unsigned int iPtr = 0; iPtr < 5; iPtr++) config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr]; + config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0; config.iPhysicalAddress = netConfig->PhysicalAddress; config.baseDevice = (cec_logical_address)netConfig->BaseDevice; config.iHDMIPort = netConfig->HDMIPort; config.clientVersion = (cec_client_version)netConfig->ClientVersion; - config.bGetSettingsFromROM = netConfig->GetSettingsFromROM; - config.bActivateSource = netConfig->ActivateSource; + config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0; + config.bActivateSource = netConfig->ActivateSource ? 1 : 0; config.tvVendor = (cec_vendor_id)netConfig->TvVendor; config.wakeDevices.Clear(); for (int iPtr = 0; iPtr < 16; iPtr++) @@ -112,8 +113,8 @@ namespace CecSharp if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr)) config.powerOffDevices.Set((cec_logical_address)iPtr); } - config.bPowerOffScreensaver = netConfig->PowerOffScreensaver; - config.bPowerOffOnStandby = netConfig->PowerOffOnStandby; + config.bPowerOffScreensaver = netConfig->PowerOffScreensaver ? 1 : 0; + config.bPowerOffOnStandby = netConfig->PowerOffOnStandby ? 1 : 0; config.callbacks = &g_cecCallbacks; } @@ -146,12 +147,17 @@ namespace CecSharp } void Close(void) + { + DisableCallbacks(); + m_libCec->Close(); + } + + virtual void DisableCallbacks(void) override { // delete the callbacks, since these might already have been destroyed in .NET CecCallbackMethods::DisableCallbacks(); - m_libCec->EnableCallbacks(NULL, NULL); - m_libCec->StandbyDevices(); - m_libCec->Close(); + if (m_libCec) + m_libCec->EnableCallbacks(NULL, NULL); } virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override @@ -430,6 +436,7 @@ namespace CecSharp if (m_libCec->GetCurrentConfiguration(&config)) { + configuration->AutodetectAddress = config.bAutodetectAddress == 1; configuration->BaseDevice = (CecLogicalAddress)config.baseDevice; configuration->DeviceName = gcnew String(config.strDeviceName); configuration->HDMIPort = config.iHDMIPort; diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 918d4e9..98be0c4 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -228,8 +228,6 @@ bool CCECProcessor::Initialise(void) else if (m_configuration.iPhysicalAddress == 0 && (bReturn = SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort, true)) == false) CLibCEC::AddLog(CEC_LOG_ERROR, "unable to set HDMI port %d on %s (%x)", m_configuration.iHDMIPort, ToString(m_configuration.baseDevice), (uint8_t)m_configuration.baseDevice); - PowerOnDevices(); - SetInitialised(bReturn); CLibCEC::ConfigurationChanged(m_configuration); @@ -510,6 +508,7 @@ void CCECProcessor::SetRetryLineTimeout(uint8_t iTimeout) bool CCECProcessor::SetActiveView(void) { + CLibCEC::AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__); return SetActiveSource(m_configuration.deviceTypes.IsEmpty() ? CEC_DEVICE_TYPE_RESERVED : m_configuration.deviceTypes[0]); } @@ -548,10 +547,14 @@ bool CCECProcessor::SetDeckInfo(cec_deck_info info, bool bSendUpdate /* = true * bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce /* = false */) { bool bReturn(false); - CLockObject lock(m_mutex); - m_configuration.baseDevice = iBaseDevice; - m_configuration.iHDMIPort = iPort; + { + CLockObject lock(m_mutex); + m_configuration.baseDevice = iBaseDevice; + m_configuration.iHDMIPort = iPort; + m_configuration.bAutodetectAddress = false; + } + if (!IsRunning() && !bForce) return true; @@ -560,9 +563,7 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, uint16_t iPhysicalAddress(0); if (iBaseDevice > CECDEVICE_TV) { - lock.Unlock(); iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress(); - lock.Lock(); } if (iPhysicalAddress < 0xffff) @@ -582,10 +583,7 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, if (!bReturn) CLibCEC::AddLog(CEC_LOG_ERROR, "failed to set the physical address"); else - { - lock.Unlock(); SetPhysicalAddress(iPhysicalAddress); - } return bReturn; } @@ -660,6 +658,11 @@ bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress, bool bSendUpda { CLockObject lock(m_mutex); m_configuration.iPhysicalAddress = iPhysicalAddress; + if (m_configuration.bAutodetectAddress) + { + m_configuration.baseDevice = CECDEVICE_UNKNOWN; + m_configuration.iHDMIPort = 0; + } if (!m_logicalAddresses.IsEmpty()) { @@ -953,6 +956,21 @@ bool CCECProcessor::TransmitKeyRelease(cec_logical_address iDestination, bool bW return m_busDevices[iDestination]->TransmitKeyRelease(bWait); } +bool CCECProcessor::EnablePhysicalAddressDetection(void) +{ + CLibCEC::AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__); + uint16_t iPhysicalAddress = m_communication->GetPhysicalAddress(); + if (iPhysicalAddress != 0) + { + m_configuration.bAutodetectAddress = 1; + m_configuration.iPhysicalAddress = iPhysicalAddress; + m_configuration.baseDevice = CECDEVICE_UNKNOWN; + m_configuration.iHDMIPort = 0; + return SetPhysicalAddress(iPhysicalAddress); + } + return false; +} + bool CCECProcessor::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */) { if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0) @@ -1416,9 +1434,6 @@ bool CCECProcessor::SetStreamPath(uint16_t iPhysicalAddress) bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration) { bool bReinit(false); - bool bPhysicalAddressChanged(false); - bool bHdmiPortChanged(false); - bool bDeviceTypeChanged(false); CCECBusDevice *primary = IsRunning() ? GetPrimaryDevice() : NULL; cec_device_type oldPrimaryType = primary ? primary->GetType() : CEC_DEVICE_TYPE_RECORDING_DEVICE; m_configuration.clientVersion = configuration->clientVersion; @@ -1426,22 +1441,54 @@ bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration) // client version 1.5.0 // device types - bDeviceTypeChanged |= IsRunning () && m_configuration.deviceTypes != configuration->deviceTypes; + bool bDeviceTypeChanged = IsRunning () && m_configuration.deviceTypes != configuration->deviceTypes; m_configuration.deviceTypes = configuration->deviceTypes; + // autodetect address + uint16_t iPhysicalAddress = IsRunning() && configuration->bAutodetectAddress ? m_communication->GetPhysicalAddress() : 0; + bool bPhysicalAutodetected = IsRunning() && configuration->bAutodetectAddress && iPhysicalAddress != m_configuration.iPhysicalAddress && iPhysicalAddress != 0; + if (bPhysicalAutodetected) + { + m_configuration.iPhysicalAddress = iPhysicalAddress; + m_configuration.bAutodetectAddress = true; + } + else + { + m_configuration.bAutodetectAddress = false; + } + // physical address - bPhysicalAddressChanged |= IsRunning() && m_configuration.iPhysicalAddress != configuration->iPhysicalAddress; - m_configuration.iPhysicalAddress = configuration->iPhysicalAddress; + bool bPhysicalAddressChanged(false); + if (!bPhysicalAutodetected) + { + bPhysicalAddressChanged = IsRunning() && m_configuration.iPhysicalAddress != configuration->iPhysicalAddress; + m_configuration.iPhysicalAddress = configuration->iPhysicalAddress; + } // base device - bHdmiPortChanged |= IsRunning() && m_configuration.baseDevice != configuration->baseDevice; - m_configuration.baseDevice = configuration->baseDevice; + bool bHdmiPortChanged(false); + if (!bPhysicalAutodetected && !bPhysicalAddressChanged) + { + bHdmiPortChanged = IsRunning() && m_configuration.baseDevice != configuration->baseDevice; + m_configuration.baseDevice = configuration->baseDevice; + } + else + { + m_configuration.baseDevice = CECDEVICE_UNKNOWN; + } // hdmi port - bHdmiPortChanged |= IsRunning() && m_configuration.iHDMIPort != configuration->iHDMIPort; - m_configuration.iHDMIPort = configuration->iHDMIPort; + if (!bPhysicalAutodetected && !bPhysicalAddressChanged) + { + bHdmiPortChanged |= IsRunning() && m_configuration.iHDMIPort != configuration->iHDMIPort; + m_configuration.iHDMIPort = configuration->iHDMIPort; + } + else + { + m_configuration.iHDMIPort = 0; + } - bReinit = bPhysicalAddressChanged || bHdmiPortChanged || bDeviceTypeChanged; + bReinit = bPhysicalAddressChanged || bHdmiPortChanged || bDeviceTypeChanged || bPhysicalAutodetected; // device name snprintf(m_configuration.strDeviceName, 13, "%s", configuration->strDeviceName); @@ -1483,7 +1530,7 @@ bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration) return ChangeDeviceType(oldPrimaryType, m_configuration.deviceTypes[0]); else if (bPhysicalAddressChanged) return SetPhysicalAddress(m_configuration.iPhysicalAddress); - else + else return SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort); } @@ -1496,6 +1543,7 @@ bool CCECProcessor::GetCurrentConfiguration(libcec_configuration *configuration) configuration->clientVersion = m_configuration.clientVersion; snprintf(configuration->strDeviceName, 13, "%s", m_configuration.strDeviceName); configuration->deviceTypes = m_configuration.deviceTypes; + configuration->bAutodetectAddress = m_configuration.bAutodetectAddress; configuration->iPhysicalAddress = m_configuration.iPhysicalAddress; configuration->baseDevice = m_configuration.baseDevice; configuration->iHDMIPort = m_configuration.iHDMIPort; diff --git a/src/lib/CECProcessor.h b/src/lib/CECProcessor.h index 2fc12e0..9a6f842 100644 --- a/src/lib/CECProcessor.h +++ b/src/lib/CECProcessor.h @@ -105,7 +105,7 @@ namespace CEC virtual uint8_t MuteAudio(bool bSendRelease = true); virtual bool TransmitKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = true); virtual bool TransmitKeyRelease(cec_logical_address iDestination, bool bWait = true); - virtual bool EnablePhysicalAddressDetection(void) { return false; }; + virtual bool EnablePhysicalAddressDetection(void); void SetStandardLineTimeout(uint8_t iTimeout); void SetRetryLineTimeout(uint8_t iTimeout); virtual bool GetCurrentConfiguration(libcec_configuration *configuration); diff --git a/src/lib/adapter/AdapterCommunication.h b/src/lib/adapter/AdapterCommunication.h index 98ecd2e..9ee2951 100644 --- a/src/lib/adapter/AdapterCommunication.h +++ b/src/lib/adapter/AdapterCommunication.h @@ -148,5 +148,10 @@ namespace CEC * @return The name of the port */ virtual CStdString GetPortName(void) = 0; + + /*! + * @return The physical address, if the adapter supports this. 0 otherwise. + */ + virtual uint16_t GetPhysicalAddress(void) = 0; }; }; diff --git a/src/lib/adapter/USBCECAdapterCommunication.h b/src/lib/adapter/USBCECAdapterCommunication.h index 3a9ba51..fc9e16c 100644 --- a/src/lib/adapter/USBCECAdapterCommunication.h +++ b/src/lib/adapter/USBCECAdapterCommunication.h @@ -68,6 +68,7 @@ namespace CEC virtual bool SetControlledMode(bool controlled); virtual bool PersistConfiguration(libcec_configuration * UNUSED(configuration)) { return false; } // TODO virtual CStdString GetPortName(void); + virtual uint16_t GetPhysicalAddress(void) { return 0; } void *Process(void); private: diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index a5d884e..3f82da6 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -117,11 +117,20 @@ bool CCECBusDevice::PowerOn(void) GetVendorId(); // ensure that we got the vendor id, because the implementations vary per vendor MarkBusy(); - CLibCEC::AddLog(CEC_LOG_NOTICE, "<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress); - if (m_handler->PowerOn(GetMyLogicalAddress(), m_iLogicalAddress)) + cec_power_status currentStatus = GetPowerStatus(false); + if (currentStatus != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON && + currentStatus != CEC_POWER_STATUS_ON) { - SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON); - bReturn = true; + 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(); -- 2.34.1