fixed - philips TVs ignore 'image view on' right after they were sent into standby...
authorLars Op den Kamp <lars@opdenkamp.eu>
Wed, 14 Nov 2012 02:43:14 +0000 (03:43 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Wed, 14 Nov 2012 09:24:45 +0000 (10:24 +0100)
src/lib/devices/CECBusDevice.cpp
src/lib/implementations/PHCommandHandler.cpp
src/lib/implementations/PHCommandHandler.h

index b304cb9c3e1a902b9a0ae2c0652fa93857bbb8ac..3e44752cc7dd2adfabbbc4319857d4d7b41b5f6f 100644 (file)
@@ -643,6 +643,8 @@ bool CCECBusDevice::RequestPowerStatus(const cec_logical_address initiator, bool
   {
     MarkBusy();
     bReturn = m_handler->TransmitRequestPowerStatus(initiator, m_iLogicalAddress, bWaitForResponse);
+    if (!bReturn)
+      SetPowerStatus(CEC_POWER_STATUS_UNKNOWN);
     MarkReady();
   }
   return bReturn;
index f8505c7c883c7068bff6663d9129ba93c34dd70d..0d9f010800b5775fb905f717cb1109453eb9b6e6 100644 (file)
 #include "lib/CECClient.h"
 
 using namespace CEC;
+using namespace PLATFORM;
 
 #define LIB_CEC     m_busDevice->GetProcessor()->GetLib()
 #define ToString(p) LIB_CEC->ToString(p)
 
+#define TV_ON_CHECK_TIME_MS 5000
+
+CImageViewOnCheck::~CImageViewOnCheck(void)
+{
+  StopThread(-1);
+  m_event.Broadcast();
+  StopThread();
+}
+
+void* CImageViewOnCheck::Process(void)
+{
+  CCECBusDevice* tv = m_handler->m_processor->GetDevice(CECDEVICE_TV);
+  cec_power_status status(CEC_POWER_STATUS_UNKNOWN);
+  while (status != CEC_POWER_STATUS_ON)
+  {
+    m_event.Wait(TV_ON_CHECK_TIME_MS);
+    if (!IsRunning())
+      return NULL;
+
+    status = tv->GetPowerStatus(m_handler->m_busDevice->GetLogicalAddress());
+
+    if (status != CEC_POWER_STATUS_ON &&
+        status != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON)
+    {
+      CLockObject lock(m_handler->m_mutex);
+      tv->OnImageViewOnSent(false);
+      m_handler->m_iActiveSourcePending = GetTimeMs();
+    }
+  }
+  return NULL;
+}
+
 CPHCommandHandler::CPHCommandHandler(CCECBusDevice *busDevice,
                                      int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */,
                                      int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */,
@@ -51,9 +84,49 @@ CPHCommandHandler::CPHCommandHandler(CCECBusDevice *busDevice,
     CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending),
     m_iLastKeyCode(CEC_USER_CONTROL_CODE_UNKNOWN)
 {
+  m_imageViewOnCheck = new CImageViewOnCheck(this);
   m_vendorId = CEC_VENDOR_PHILIPS;
 }
 
+CPHCommandHandler::~CPHCommandHandler(void)
+{
+  delete m_imageViewOnCheck;
+}
+
+bool CPHCommandHandler::InitHandler(void)
+{
+  CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+  if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
+  {
+    //XXX hack to use this handler for the primary device
+    if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV &&
+        primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+    {
+      primary->SetVendorId(CEC_VENDOR_PHILIPS);
+      primary->ReplaceHandler(false);
+    }
+  }
+
+  return CCECCommandHandler::InitHandler();
+}
+
+bool CPHCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = false */)
+{
+
+  CCECBusDevice* tv = m_processor->GetDevice(CECDEVICE_TV);
+  if (m_busDevice->IsActiveSource() &&
+      m_busDevice->IsHandledByLibCEC() &&
+      tv && tv->GetCurrentPowerStatus() != CEC_POWER_STATUS_ON &&
+      !bTransmitDelayedCommandsOnly)
+  {
+    // tv sometimes ignores image view on. check the power status of the tv in 5 seconds, and retry when it failed to power up
+    if (m_imageViewOnCheck && !m_imageViewOnCheck->IsRunning())
+      m_imageViewOnCheck->CreateThread(false);
+  }
+
+  return CCECCommandHandler::ActivateSource(bTransmitDelayedCommandsOnly);
+}
+
 int CPHCommandHandler::HandleUserControlPressed(const cec_command& command)
 {
   // tv keeps sending these until a button is pressed
@@ -72,3 +145,16 @@ int CPHCommandHandler::HandleUserControlRelease(const cec_command& command)
 
   return CCECCommandHandler::HandleUserControlRelease(command);
 }
+
+int CPHCommandHandler::HandleDeviceVendorId(const cec_command& command)
+{
+  m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
+  return CCECCommandHandler::HandleDeviceVendorId(command);
+}
+
+int CPHCommandHandler::HandleGiveDeviceVendorId(const cec_command& command)
+{
+  LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %s (%X) -> %s (%X): vendor id feature abort", ToString(command.destination), command.destination, ToString(command.initiator), command.initiator);
+  m_processor->TransmitAbort(command.destination, command.initiator, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+  return COMMAND_HANDLED;
+}
index 85338b46d695422b60c714fcf8b48ccb530b3859..a40d7b58179d2abc2e1b1bd09c79015981d57703 100644 (file)
  */
 
 #include "CECCommandHandler.h"
+#include "platform/threads/threads.h"
 
 namespace CEC
 {
+  class CPHCommandHandler;
+
+  class CImageViewOnCheck : public PLATFORM::CThread
+  {
+  public:
+    CImageViewOnCheck(CPHCommandHandler* handler):
+      m_handler(handler) {}
+    virtual ~CImageViewOnCheck(void);
+
+    void* Process(void);
+
+  private:
+    CPHCommandHandler* m_handler;
+    PLATFORM::CEvent   m_event;
+  };
+
   class CPHCommandHandler : public CCECCommandHandler
   {
+    friend class CImageViewOnCheck;
   public:
     CPHCommandHandler(CCECBusDevice *busDevice,
                       int32_t iTransmitTimeout = CEC_DEFAULT_TRANSMIT_TIMEOUT,
                       int32_t iTransmitWait = CEC_DEFAULT_TRANSMIT_WAIT,
                       int8_t iTransmitRetries = CEC_DEFAULT_TRANSMIT_RETRIES,
                       int64_t iActiveSourcePending = 0);
-    virtual ~CPHCommandHandler(void) {};
+    virtual ~CPHCommandHandler(void);
+
+    bool InitHandler(void);
 
   protected:
+    virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false);
     virtual int HandleUserControlPressed(const cec_command& command);
     virtual int HandleUserControlRelease(const cec_command& command);
-    uint8_t m_iLastKeyCode;
+    virtual int HandleGiveDeviceVendorId(const cec_command& command);
+    virtual int HandleDeviceVendorId(const cec_command& command);
+    uint8_t            m_iLastKeyCode;
+    CImageViewOnCheck* m_imageViewOnCheck;
   };
 };