From b78b4e339dd201d11c5e6dbfec36534d6bc5fd69 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Tue, 24 Apr 2012 18:17:35 +0200 Subject: [PATCH] cec: delay the 'active source' command for panasonic, until the vendor command that reports that the TV is powered on has been received. bugzid: 723 --- src/lib/CECProcessor.cpp | 10 ++- src/lib/CECProcessor.h | 2 + src/lib/devices/CECBusDevice.cpp | 8 ++ src/lib/devices/CECBusDevice.h | 1 + src/lib/implementations/CECCommandHandler.h | 1 + src/lib/implementations/VLCommandHandler.cpp | 85 +++++++++++++++++++- src/lib/implementations/VLCommandHandler.h | 9 +++ 7 files changed, 112 insertions(+), 4 deletions(-) diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index ea1a353..9cf771b 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -1770,7 +1770,7 @@ bool CCECProcessor::PersistConfiguration(libcec_configuration *configuration) void CCECProcessor::RescanActiveDevices(void) { - for (unsigned int iPtr = 0; iPtr < 16; iPtr++) + for (unsigned int iPtr = 0; iPtr < CECDEVICE_BROADCAST; iPtr++) m_busDevices[iPtr]->GetStatus(true); } @@ -1786,3 +1786,11 @@ bool CCECProcessor::GetDeviceInformation(const char *strPort, libcec_configurati m_communication = NULL; return true; } + +bool CCECProcessor::TransmitPendingActiveSourceCommands(void) +{ + bool bReturn(true); + for (unsigned int iPtr = 0; iPtr < CECDEVICE_BROADCAST; iPtr++) + bReturn &= m_busDevices[iPtr]->TransmitPendingActiveSourceCommands(); + return bReturn; +} diff --git a/src/lib/CECProcessor.h b/src/lib/CECProcessor.h index 25b0c2a..3bb56fd 100644 --- a/src/lib/CECProcessor.h +++ b/src/lib/CECProcessor.h @@ -196,6 +196,8 @@ namespace CEC virtual bool GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs = 10000); + bool TransmitPendingActiveSourceCommands(void); + CCECBusDevice * m_busDevices[16]; private: diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index 13ba22e..3d4a20a 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -1076,4 +1076,12 @@ void CCECBusDevice::CheckVendorIdRequested(void) } } +bool CCECBusDevice::TransmitPendingActiveSourceCommands(void) +{ + MarkBusy(); + bool bReturn = m_handler->TransmitPendingActiveSourceCommands(); + MarkReady(); + return bReturn; +} + //@} diff --git a/src/lib/devices/CECBusDevice.h b/src/lib/devices/CECBusDevice.h index 9db9bd4..a8c967d 100644 --- a/src/lib/devices/CECBusDevice.h +++ b/src/lib/devices/CECBusDevice.h @@ -109,6 +109,7 @@ namespace CEC virtual bool TransmitKeyRelease(bool bWait = true); bool ReplaceHandler(bool bActivateSource = true); + virtual bool TransmitPendingActiveSourceCommands(void); protected: void CheckVendorIdRequested(void); diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index 9389270..fe9a3f1 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -157,6 +157,7 @@ namespace CEC virtual bool TransmitKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWait = true); virtual bool TransmitSetStreamPath(uint16_t iStreamPath); virtual bool SendDeckStatusUpdateOnActiveSource(void) const { return m_bOPTSendDeckStatusUpdateOnActiveSource; }; + virtual bool TransmitPendingActiveSourceCommands(void) { return true; } protected: virtual bool HandleActiveSource(const cec_command &command); diff --git a/src/lib/implementations/VLCommandHandler.cpp b/src/lib/implementations/VLCommandHandler.cpp index ad4cf17..87a3037 100644 --- a/src/lib/implementations/VLCommandHandler.cpp +++ b/src/lib/implementations/VLCommandHandler.cpp @@ -33,11 +33,19 @@ #include "VLCommandHandler.h" #include "../devices/CECBusDevice.h" #include "../CECProcessor.h" +#include "../LibCEC.h" + +#define VL_POWER_CHANGE 0x20 +#define VL_POWERED_UP 0x00 +#define VL_POWERED_DOWN 0x01 using namespace CEC; +using namespace PLATFORM; CVLCommandHandler::CVLCommandHandler(CCECBusDevice *busDevice) : - CCECCommandHandler(busDevice) + CCECCommandHandler(busDevice), + m_bActiveSourcePending(false), + m_bPowerUpEventReceived(false) { m_vendorId = CEC_VENDOR_PANASONIC; } @@ -46,8 +54,79 @@ bool CVLCommandHandler::InitHandler(void) { CCECBusDevice *primary = m_processor->GetPrimaryDevice(); if (primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE) - { return m_processor->ChangeDeviceType(CEC_DEVICE_TYPE_RECORDING_DEVICE, CEC_DEVICE_TYPE_PLAYBACK_DEVICE); - } + return CCECCommandHandler::InitHandler(); } + +bool CVLCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command) +{ + if (command.initiator == CECDEVICE_TV && + command.destination == CECDEVICE_BROADCAST && + command.parameters.At(3) == VL_POWER_CHANGE) + { + if (command.parameters.At(4) == VL_POWERED_UP) + { + CLibCEC::AddLog(CEC_LOG_DEBUG, "TV powered up"); + { + CLockObject lock(m_mutex); + m_bPowerUpEventReceived = true; + } + m_processor->TransmitPendingActiveSourceCommands(); + } + else if (command.parameters.At(4) == VL_POWERED_DOWN) + CLibCEC::AddLog(CEC_LOG_DEBUG, "TV powered down"); + else if (command.parameters.At(4) == VL_POWERED_DOWN) + CLibCEC::AddLog(CEC_LOG_DEBUG, "unknown vendor command"); + + return true; + } + + return CCECCommandHandler::HandleDeviceVendorCommandWithId(command); +} + +bool CVLCommandHandler::TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress) +{ + bool bPowerUpEventReceived(false); + + { + CLockObject lock(m_mutex); + if (!m_bPowerUpEventReceived) + { + // just assume it's been sent when the tv is powered on + cec_power_status powerStatus = m_processor->m_busDevices[CECDEVICE_TV]->GetPowerStatus(); + m_bPowerUpEventReceived = (powerStatus == CEC_POWER_STATUS_ON); + } + bPowerUpEventReceived = m_bPowerUpEventReceived; + } + + if (!bPowerUpEventReceived) + { + CLockObject lock(m_mutex); + // wait until we received the event + m_bActiveSourcePending = true; + return true; + } + else + { + // transmit standard active source message + return CCECCommandHandler::TransmitActiveSource(iInitiator, iPhysicalAddress); + } +} + +bool CVLCommandHandler::TransmitPendingActiveSourceCommands(void) +{ + bool bTransmitCommand(false); + { + CLockObject lock(m_mutex); + bTransmitCommand = m_bActiveSourcePending; + m_bActiveSourcePending = false; + } + + if (bTransmitCommand) + { + CLibCEC::AddLog(CEC_LOG_DEBUG, "transmitting delayed activate source command"); + return CCECCommandHandler::TransmitActiveSource(m_busDevice->GetLogicalAddress(), m_busDevice->GetPhysicalAddress(false, true)); + } + return true; +} diff --git a/src/lib/implementations/VLCommandHandler.h b/src/lib/implementations/VLCommandHandler.h index c3b0fe0..18b7507 100644 --- a/src/lib/implementations/VLCommandHandler.h +++ b/src/lib/implementations/VLCommandHandler.h @@ -41,5 +41,14 @@ namespace CEC CVLCommandHandler(CCECBusDevice *busDevice); virtual ~CVLCommandHandler(void) {}; virtual bool InitHandler(void); + + virtual bool HandleDeviceVendorCommandWithId(const cec_command &command); + virtual bool TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress); + virtual bool TransmitPendingActiveSourceCommands(void); + + private: + PLATFORM::CMutex m_mutex; + bool m_bActiveSourcePending; + bool m_bPowerUpEventReceived; }; }; -- 2.34.1