cec: buffer up commands that are received while waiting for an ack. only send 'active...
authorLars Op den Kamp <lars@opdenkamp.eu>
Thu, 10 Nov 2011 17:30:00 +0000 (18:30 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Thu, 10 Nov 2011 18:00:22 +0000 (19:00 +0100)
include/cectypes.h
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/devices/CECBusDevice.cpp
src/lib/devices/CECBusDevice.h
src/lib/implementations/CECCommandHandler.cpp
src/lib/implementations/CECCommandHandler.h

index 7778339da99b814914c0cef2124439025d91492d..cb647fd2230300eb848d1635e98173e278ff18c1 100644 (file)
@@ -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;
 
index 9c368a8dd0bdcba69b4ba9f3eeb9bb24ad21490b..c179e82837e12e3113fe5a1fd73fc41da531b9d5 100644 (file)
@@ -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();
index ef4c5195bdac933d9d3d5fc9816bf225afbe03b5..98b265e78077070f8dc4ee8ced8067cd5fb9ebea 100644 (file)
@@ -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<cec_command> m_commandBuffer;
   };
 };
index c2595c3927aff0a07619d8921c9d191ebd6b5a86..0fb3bf3a487bd50a013e6df7ed105d859b29b921 100644 (file)
@@ -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)
index 44b0a2ffcac0699f89fbc8baf5f1ed300d7c3366..0dccfd4632546c3f48dafa7efd693c6be7e5bff5 100644 (file)
@@ -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;
index 2a5b375f6050875709d01f848fc31a3f267b6923..261b63c8d4b6aabaa7bca1114ad6a2115eeeebea 100644 (file)
@@ -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<CCECBusDevice *> 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<CCECBusDevice *> &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;
index 3a80f463823ca1d3ab9d17240d4d5c4181b42375..524fdc2af5e2215aba6a1727423193097f9de4df 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <cectypes.h>
+#include <vector>
 
 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<CCECBusDevice *> &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;
   };