From 8747dd4fbf6aca45c49391ba754f013f28ca3806 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Thu, 10 Nov 2011 18:30:00 +0100 Subject: [PATCH] cec: buffer up commands that are received while waiting for an ack. only send 'active source' message for the actual active source --- include/cectypes.h | 1 + src/lib/CECProcessor.cpp | 23 +++++++++------ src/lib/CECProcessor.h | 20 +++++++------ src/lib/devices/CECBusDevice.cpp | 28 +++++++++++++------ src/lib/devices/CECBusDevice.h | 1 + src/lib/implementations/CECCommandHandler.cpp | 27 +++++++++++++++--- src/lib/implementations/CECCommandHandler.h | 6 ++-- 7 files changed, 75 insertions(+), 31 deletions(-) diff --git a/include/cectypes.h b/include/cectypes.h index 7778339..cb647fd 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -556,6 +556,7 @@ typedef struct cec_logical_addresses } bool isset(cec_logical_address address) const { return addresses[(int) address] == 1; } + bool operator[](uint8_t pos) const { return pos < 16 ? isset((cec_logical_address) pos) : false; } #endif } cec_logical_addresses; diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 9c368a8..c179e82 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -148,9 +148,12 @@ bool CCECProcessor::TryLogicalAddress(cec_logical_address address, const char *s strLog.Format("using logical address '%s'", strLabel); AddLog(CEC_LOG_NOTICE, strLog); - /* only set our OSD name for the primary device */ + /* only set our OSD name and active source for the primary device */ if (m_logicalAddresses.empty()) + { m_busDevices[address]->m_strDeviceName = m_strDeviceName; + m_busDevices[address]->m_bActiveSource = true; + } m_busDevices[address]->m_powerStatus = (m_types[0] == m_busDevices[address]->m_type) ? CEC_POWER_STATUS_ON : CEC_POWER_STATUS_STANDBY; m_busDevices[address]->m_cecVersion = CEC_VERSION_1_3A; m_logicalAddresses.set(address); @@ -226,6 +229,7 @@ bool CCECProcessor::FindLogicalAddresses(void) void *CCECProcessor::Process(void) { + bool bParseFrame(false); cec_command command; CCECAdapterMessage msg; @@ -250,24 +254,26 @@ void *CCECProcessor::Process(void) while (!IsStopped()) { - bool bParseFrame(false); command.clear(); msg.clear(); { CLockObject lock(&m_mutex); - if (m_communication->IsOpen() && m_communication->Read(msg, 50)) + if (m_commandBuffer.Pop(command)) + { + bParseFrame = true; + } + else if (m_communication->IsOpen() && m_communication->Read(msg, 50)) { m_controller->AddLog(msg.is_error() ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString()); - bParseFrame = ParseMessage(msg) && !IsStopped(); + if ((bParseFrame = (ParseMessage(msg) && !IsStopped()))) + command = m_currentframe; } - - if (bParseFrame) - command = m_currentframe; } if (bParseFrame) ParseCommand(command); + bParseFrame = false; Sleep(5); @@ -477,7 +483,8 @@ bool CCECProcessor::WaitForTransmitSucceeded(uint8_t iLength, uint32_t iTimeout bError = !bTransmitSucceeded; break; default: - ParseMessage(msg); + if (ParseMessage(msg)) + m_commandBuffer.Push(m_currentframe); } iNow = GetTimeMs(); diff --git a/src/lib/CECProcessor.h b/src/lib/CECProcessor.h index ef4c519..98b265e 100644 --- a/src/lib/CECProcessor.h +++ b/src/lib/CECProcessor.h @@ -56,15 +56,16 @@ namespace CEC virtual bool Start(void); virtual void *Process(void); - virtual bool IsMonitoring(void) const { return m_bMonitor; } - virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress); - virtual bool GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language); - virtual const std::string & GetDeviceName(void) { return m_strDeviceName; } - virtual uint64_t GetDeviceVendorId(cec_logical_address iAddress); - virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress); - virtual cec_logical_address GetLogicalAddress(void) const { return m_logicalAddresses.primary; } - virtual bool HasLogicalAddress(cec_logical_address address) const { return m_logicalAddresses.isset(address); } - virtual uint16_t GetPhysicalAddress(void) const; + virtual bool IsMonitoring(void) const { return m_bMonitor; } + virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress); + virtual bool GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language); + virtual const std::string & GetDeviceName(void) { return m_strDeviceName; } + virtual uint64_t GetDeviceVendorId(cec_logical_address iAddress); + virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress); + virtual cec_logical_address GetLogicalAddress(void) const { return m_logicalAddresses.primary; } + virtual cec_logical_addresses GetLogicalAddresses(void) const { return m_logicalAddresses; } + virtual bool HasLogicalAddress(cec_logical_address address) const { return m_logicalAddresses.isset(address); } + virtual uint16_t GetPhysicalAddress(void) const; virtual bool SetActiveView(void); virtual bool SetInactiveView(void); @@ -110,5 +111,6 @@ namespace CEC CAdapterCommunication* m_communication; CLibCEC* m_controller; bool m_bMonitor; + CecBuffer m_commandBuffer; }; }; diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index c2595c3..0fb3bf3 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -47,6 +47,7 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi m_powerStatus(CEC_POWER_STATUS_UNKNOWN), m_processor(processor), m_bMenuActive(true), + m_bActiveSource(false), m_iVendorClass(CEC_VENDOR_UNKNOWN), m_iLastActive(0), m_cecVersion(CEC_VERSION_UNKNOWN) @@ -349,16 +350,27 @@ void CCECBusDevice::SetVendorId(uint64_t iVendorId, uint8_t iVendorClass /* = 0 //@{ bool CCECBusDevice::TransmitActiveSource(void) { - CStdString strLog; - strLog.Format("<< %x -> broadcast: active source (%4x)", m_iLogicalAddress, m_iPhysicalAddress); - AddLog(CEC_LOG_NOTICE, strLog); + if (m_bActiveSource) + { + CStdString strLog; + strLog.Format("<< %x -> broadcast: active source (%4x)", m_iLogicalAddress, m_iPhysicalAddress); + AddLog(CEC_LOG_NOTICE, strLog); - cec_command command; - cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); - command.parameters.push_back((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF)); - command.parameters.push_back((uint8_t) (m_iPhysicalAddress & 0xFF)); + cec_command command; + cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); + command.parameters.push_back((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF)); + command.parameters.push_back((uint8_t) (m_iPhysicalAddress & 0xFF)); - return m_processor->Transmit(command); + return m_processor->Transmit(command); + } + else + { + CStdString strLog; + strLog.Format("<< %x is not the active source", m_iLogicalAddress); + AddLog(CEC_LOG_DEBUG, strLog); + } + + return false; } bool CCECBusDevice::TransmitActiveView(void) diff --git a/src/lib/devices/CECBusDevice.h b/src/lib/devices/CECBusDevice.h index 44b0a2f..0dccfd4 100644 --- a/src/lib/devices/CECBusDevice.h +++ b/src/lib/devices/CECBusDevice.h @@ -103,6 +103,7 @@ namespace CEC CCECCommandHandler *m_handler; cec_vendor m_vendor; bool m_bMenuActive; + bool m_bActiveSource; uint8_t m_iVendorClass; uint64_t m_iLastActive; cec_version m_cecVersion; diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index 2a5b375..261b63c 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -36,6 +36,7 @@ #include "../CECProcessor.h" using namespace CEC; +using namespace std; CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice) { @@ -271,10 +272,11 @@ bool CCECCommandHandler::HandleRequestActiveSource(const cec_command &command) CStdString strLog; strLog.Format(">> %i requests active source", (uint8_t) command.initiator); m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str()); - CCECBusDevice *device = m_busDevice->GetProcessor()->m_busDevices[m_busDevice->GetMyLogicalAddress()]; - if (device) - return device->TransmitActiveSource(); - return false; + + vector devices; + for (int iDevicePtr = (int)GetMyDevices(devices)-1; iDevicePtr >=0; iDevicePtr--) + devices[iDevicePtr]->TransmitActiveSource(); + return true; } bool CCECCommandHandler::HandleRoutingChange(const cec_command &command) @@ -375,6 +377,23 @@ void CCECCommandHandler::UnhandledCommand(const cec_command &command) m_busDevice->AddLog(CEC_LOG_DEBUG, strLog); } +unsigned int CCECCommandHandler::GetMyDevices(vector &devices) const +{ + unsigned int iReturn(0); + + cec_logical_addresses addresses = m_busDevice->GetProcessor()->GetLogicalAddresses(); + for (unsigned int iPtr = 0; iPtr < 16; iPtr++) + { + if (addresses[iPtr]) + { + devices.push_back(GetDevice((cec_logical_address) iPtr)); + ++iReturn; + } + } + + return iReturn; +} + CCECBusDevice *CCECCommandHandler::GetDevice(cec_logical_address iLogicalAddress) const { CCECBusDevice *device = NULL; diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index 3a80f46..524fdc2 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -32,6 +32,7 @@ */ #include +#include namespace CEC { @@ -46,6 +47,8 @@ namespace CEC virtual bool HandleCommand(const cec_command &command); virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; }; + static const char* ToString(const cec_opcode opcode); + protected: virtual bool HandleDeviceCecVersion(const cec_command &command); virtual bool HandleDeviceVendorCommandWithId(const cec_command &command); @@ -69,11 +72,10 @@ namespace CEC virtual bool HandleUserControlRelease(const cec_command &command); virtual void UnhandledCommand(const cec_command &command); + virtual unsigned int GetMyDevices(std::vector &devices) const; virtual CCECBusDevice *GetDevice(cec_logical_address iLogicalAddress) const; virtual CCECBusDevice *GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const; - static const char* ToString(const cec_opcode opcode); - virtual void SetVendorId(const cec_command &command); CCECBusDevice *m_busDevice; }; -- 2.34.1