cec: delay the 'active source' command for panasonic, until the vendor command that...
authorLars Op den Kamp <lars@opdenkamp.eu>
Tue, 24 Apr 2012 16:17:35 +0000 (18:17 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Tue, 24 Apr 2012 16:53:38 +0000 (18:53 +0200)
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/devices/CECBusDevice.cpp
src/lib/devices/CECBusDevice.h
src/lib/implementations/CECCommandHandler.h
src/lib/implementations/VLCommandHandler.cpp
src/lib/implementations/VLCommandHandler.h

index ea1a353c5ea90a218fab24338ecb0cb1a5b99390..9cf771bda124bda87edc00b93e607c398e29cb6d 100644 (file)
@@ -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;
+}
index 25b0c2aa10f75d627191807155d87bac85fd4847..3bb56fd54ba8cb453ca382c523969b6ec82870e4 100644 (file)
@@ -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:
index 13ba22e75ae36c2cdf38a264cbf1945c11b15797..3d4a20abfb9405b87c34cf3698515774b04c4a09 100644 (file)
@@ -1076,4 +1076,12 @@ void CCECBusDevice::CheckVendorIdRequested(void)
   }
 }
 
+bool CCECBusDevice::TransmitPendingActiveSourceCommands(void)
+{
+  MarkBusy();
+  bool bReturn = m_handler->TransmitPendingActiveSourceCommands();
+  MarkReady();
+  return bReturn;
+}
+
 //@}
index 9db9bd4d03b39c403496d77d3fd7cefe8ac2b3d0..a8c967da0bb0a4a1076b08c2ffee4701f60c1a0c 100644 (file)
@@ -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);
index 93892709ff0fa01534b5d4c7c24b518d6f0387bc..fe9a3f1be191aa9b1de930f91bcdde9d76537604 100644 (file)
@@ -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);
index ad4cf1717fb68a7f0bd0186e5caa54c99ee1f12d..87a3037e432a4bde4f872b7a820ee7c2e04bcf93 100644 (file)
 #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;
+}
index c3b0fe0337b261e5caf978d23076e9b12f929835..18b75070d9531a3ce69d7500955d5eee1d2513c2 100644 (file)
@@ -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;
   };
 };