Merge branch 'master' into release
[deb_libcec.git] / src / lib / implementations / VLCommandHandler.cpp
index dfef4a09e75dfa46e8c66572e0dfd663dc58bec1..e8cf7c8c4d01f0aede754d5c2c71f76d94185c50 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
 #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_bOPTSendDeckStatusUpdateOnActiveSource = false;
+  m_vendorId = CEC_VENDOR_PANASONIC;
+
+  /* use the VL commandhandler for the primary device that is handled by libCEC */
+  if (busDevice->GetLogicalAddress() == CECDEVICE_TV)
+  {
+    CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+    if (primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+    {
+      primary->SetVendorId(CEC_VENDOR_PANASONIC);
+      primary->ReplaceHandler(false);
+    }
+  }
 }
 
 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);
+
+  CCECBusDevice *tv = m_processor->m_busDevices[CECDEVICE_TV];
+  if (tv && tv->GetVendorId(false) == CEC_VENDOR_PANASONIC)
+  {
+    CVLCommandHandler *handler = static_cast<CVLCommandHandler *>(tv->GetHandler());
+    bPowerUpEventReceived = handler ? handler->PowerUpEventReceived() : false;
+  }
+
+  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());
+  }
+  return true;
+}
+
+bool CVLCommandHandler::PowerUpEventReceived(void)
+{
+  {
+    CLockObject lock(m_mutex);
+    if (m_bPowerUpEventReceived)
+      return true;
+  }
+
+  cec_power_status powerStatus = m_busDevice->GetPowerStatus();
+
+  CLockObject lock(m_mutex);
+  m_bPowerUpEventReceived = (powerStatus == CEC_POWER_STATUS_ON);
+  return m_bPowerUpEventReceived;
+}