cec: removed dupe code around delayed activate source commands. check for delayed...
authorLars Op den Kamp <lars@opdenkamp.eu>
Thu, 21 Jun 2012 10:28:03 +0000 (12:28 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Thu, 21 Jun 2012 12:50:18 +0000 (14:50 +0200)
include/cectypes.h
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/devices/CECBusDevice.cpp
src/lib/implementations/CECCommandHandler.cpp
src/lib/implementations/CECCommandHandler.h
src/lib/implementations/VLCommandHandler.cpp
src/lib/implementations/VLCommandHandler.h

index a47a57016f0d08415091ccfc456acec120786842..bb9dc32fa69ce62b73faaa9385901524682ecbc2 100644 (file)
@@ -110,6 +110,8 @@ namespace CEC {
 #define CEC_SERIAL_DEFAULT_BAUDRATE     38400
 #define CEC_CLEAR_INPUT_DEFAULT_WAIT    1000
 
+#define CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS 5000
+
 #define CEC_MIN_LIB_VERSION          1
 #define CEC_LIB_VERSION_MAJOR        1
 #define CEC_LIB_VERSION_MAJOR_STR    "1"
index 848800ec4cbd9985d6dfab27330f9cccc740bfd9..1975421fc9de39c9fdf6dbd491a551ef63d74dd0 100644 (file)
@@ -51,7 +51,7 @@ using namespace std;
 using namespace PLATFORM;
 
 #define CEC_PROCESSOR_SIGNAL_WAIT_TIME 1000
-#define ACTIVE_SOURCE_CHECK_TIMEOUT    15000
+#define ACTIVE_SOURCE_CHECK_INTERVAL   500
 
 #define ToString(x) CCECTypeUtils::ToString(x)
 
@@ -198,20 +198,6 @@ void CCECProcessor::ReplaceHandlers(void)
     it->second->ReplaceHandler(true);
 }
 
-void CCECProcessor::CheckPendingActiveSource(void)
-{
-  if (!CECInitialised())
-    return;
-
-  // check each device
-  for (CECDEVICEMAP::iterator it = m_busDevices->Begin(); it != m_busDevices->End(); it++)
-  {
-    if (it->second->GetHandler()->ActiveSourcePending())
-      it->second->ActivateSource();
-    it->second->MarkHandlerReady();
-  }
-}
-
 bool CCECProcessor::OnCommandReceived(const cec_command &command)
 {
   return m_inBuffer.Push(command);
@@ -222,7 +208,7 @@ void *CCECProcessor::Process(void)
   m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
 
   cec_command command;
-  CTimeout activeSourceCheck(ACTIVE_SOURCE_CHECK_TIMEOUT);
+  CTimeout activeSourceCheck(ACTIVE_SOURCE_CHECK_INTERVAL);
 
   // as long as we're not being stopped and the connection is open
   while (!IsStopped() && m_communication->IsOpen())
@@ -242,8 +228,9 @@ void *CCECProcessor::Process(void)
       // check whether we need to activate a source, if it failed before
       if (activeSourceCheck.TimeLeft() == 0)
       {
-        CheckPendingActiveSource();
-        activeSourceCheck.Init(ACTIVE_SOURCE_CHECK_TIMEOUT);
+        if (CECInitialised())
+          TransmitPendingActiveSourceCommands();
+        activeSourceCheck.Init(ACTIVE_SOURCE_CHECK_INTERVAL);
       }
     }
   }
index 04d84f55ee2f5edab2997a5aec3d51a5df25d316..5f496d2631558506045e645ecf450e4ba37c5995 100644 (file)
@@ -134,7 +134,6 @@ namespace CEC
       void SetCECInitialised(bool bSetTo = true);
 
       void ReplaceHandlers(void);
-      void CheckPendingActiveSource(void);
       bool PhysicalAddressInUse(uint16_t iPhysicalAddress);
       bool SetAckMask(uint16_t iMask);
 
index 3fb30e8a8dff6f6d7a9c75677f121d8cffc05685..47bd53aff566b60bcf98ece20a76867a1539805a 100644 (file)
@@ -1015,7 +1015,7 @@ bool CCECBusDevice::TransmitInactiveSource(void)
 bool CCECBusDevice::TransmitPendingActiveSourceCommands(void)
 {
   MarkBusy();
-  bool bReturn = m_handler->TransmitPendingActiveSourceCommands();
+  bool bReturn = m_handler->ActivateSource(true);
   MarkReady();
   return bReturn;
 }
index 395aacec69f4baa3dc80df13379cf128a9e78d1f..f99d4c078556d4ce5973fce0fa46255400db42f3 100644 (file)
@@ -57,7 +57,7 @@ CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice) :
     m_bOPTSendDeckStatusUpdateOnActiveSource(false),
     m_vendorId(CEC_VENDOR_UNKNOWN),
     m_waitForResponse(new CWaitForResponse),
-    m_bActiveSourcePending(false)
+    m_iActiveSourcePending(0)
 {
 }
 
@@ -1089,38 +1089,64 @@ bool CCECCommandHandler::Transmit(cec_command &command, bool bSuppressWait /* =
   return bReturn;
 }
 
-bool CCECCommandHandler::ActivateSource(void)
+bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = false */)
 {
   if (m_busDevice->IsActiveSource() &&
-    m_busDevice->IsHandledByLibCEC())
+      m_busDevice->IsHandledByLibCEC())
   {
     {
       CLockObject lock(m_mutex);
-      m_bActiveSourcePending = false;
+      // check if we need to send a delayed source switch
+      if (bTransmitDelayedCommandsOnly)
+      {
+        if (m_iActiveSourcePending == 0 || GetTimeMs() < m_iActiveSourcePending)
+          return false;
+
+        LIB_CEC->AddLog(CEC_LOG_DEBUG, "transmitting delayed activate source command");
+      }
+
+      // clear previous pending active source command
+      m_iActiveSourcePending = 0;
     }
 
+    // update the power state and menu state
     m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
-    m_busDevice->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+    m_busDevice->SetMenuState(CEC_MENU_STATE_ACTIVATED); // TODO: LG
+
+    // power on the TV
+    bool bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
 
-    bool bActiveSourceFailed = !m_busDevice->TransmitImageViewOn() ||
-                               !m_busDevice->TransmitActiveSource() ||
-                               !m_busDevice->TransmitMenuState(CECDEVICE_TV);
+    // check if we're allowed to switch sources
+    bool bSourceSwitchAllowed = SourceSwitchAllowed();
+    if (!bSourceSwitchAllowed)
+      LIB_CEC->AddLog(CEC_LOG_DEBUG, "source switch is currently not allowed by command handler");
 
-    if (!bActiveSourceFailed)
+    // switch sources (if allowed)
+    if (!bActiveSourceFailed && bSourceSwitchAllowed)
     {
-      CCECPlaybackDevice *playbackDevice = m_busDevice->AsPlaybackDevice();
-      if (playbackDevice && SendDeckStatusUpdateOnActiveSource())
-        bActiveSourceFailed = !playbackDevice->TransmitDeckStatus(CECDEVICE_TV);
+      bActiveSourceFailed = !m_busDevice->TransmitActiveSource() ||
+                            !m_busDevice->TransmitMenuState(CECDEVICE_TV);
+
+      // update the deck status for playback devices
+      if (!bActiveSourceFailed)
+      {
+        CCECPlaybackDevice *playbackDevice = m_busDevice->AsPlaybackDevice();
+        if (playbackDevice && SendDeckStatusUpdateOnActiveSource())
+          bActiveSourceFailed = !playbackDevice->TransmitDeckStatus(CECDEVICE_TV);
+      }
     }
 
-    if (bActiveSourceFailed)
+    // retry later
+    if (bActiveSourceFailed || !bSourceSwitchAllowed)
     {
       LIB_CEC->AddLog(CEC_LOG_DEBUG, "failed to make '%s' the active source. will retry later", m_busDevice->GetLogicalAddressName());
       CLockObject lock(m_mutex);
-      m_bActiveSourcePending = true;
+      m_iActiveSourcePending = GetTimeMs() + CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS;
       return false;
     }
 
+    // mark the handler as initialised
+    CLockObject lock(m_mutex);
     m_bHandlerInited = true;
   }
   return true;
@@ -1130,9 +1156,3 @@ void CCECCommandHandler::SignalOpcode(cec_opcode opcode)
 {
   m_waitForResponse->Received(opcode);
 }
-
-bool CCECCommandHandler::ActiveSourcePending(void)
-{
-  CLockObject lock(m_mutex);
-  return m_bActiveSourcePending;
-}
index 607a56a9ff276e43840ac5de7f231266761b695a..70ba3096703e88891d044e5673700df46729379f 100644 (file)
@@ -128,7 +128,7 @@ namespace CEC
     static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC;}
 
     virtual bool InitHandler(void) { return true; }
-    virtual bool ActivateSource(void);
+    virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false);
     virtual uint8_t GetTransmitRetries(void) const { return m_iTransmitRetries; }
 
     virtual bool PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
@@ -160,11 +160,9 @@ 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; }
 
     virtual void SignalOpcode(cec_opcode opcode);
 
-    virtual bool ActiveSourcePending(void);
     virtual bool SupportsDeviceType(const cec_device_type UNUSED(type)) const { return true; };
     virtual cec_device_type GetReplacementDeviceType(const cec_device_type type) const { return type; }
 
@@ -217,6 +215,8 @@ namespace CEC
 
     virtual bool Transmit(cec_command &command, bool bSuppressWait = false);
 
+    virtual bool SourceSwitchAllowed(void) { return true; }
+
     CCECBusDevice *                       m_busDevice;
     CCECProcessor *                       m_processor;
     int32_t                               m_iTransmitTimeout;
@@ -226,7 +226,7 @@ namespace CEC
     bool                                  m_bOPTSendDeckStatusUpdateOnActiveSource;
     cec_vendor_id                         m_vendorId;
     CWaitForResponse                     *m_waitForResponse;
-    bool                                  m_bActiveSourcePending;
+    int                                   m_iActiveSourcePending;
     PLATFORM::CMutex                      m_mutex;
   };
 };
index 74b26509569c11db5f853a5c9f07951116483dad..c347649c9c0b9989ca7be74fc82b3fee8713f804 100644 (file)
@@ -32,6 +32,8 @@
 
 #include "VLCommandHandler.h"
 #include "../devices/CECBusDevice.h"
+#include "../devices/CECPlaybackDevice.h"
+#include "../devices/CECTV.h"
 #include "../CECProcessor.h"
 #include "../LibCEC.h"
 #include "../CECClient.h"
@@ -46,10 +48,12 @@ using namespace PLATFORM;
 #define LIB_CEC     m_busDevice->GetProcessor()->GetLib()
 #define ToString(p) LIB_CEC->ToString(p)
 
+// wait this amount of ms before trying to switch sources after receiving the message from the TV that it's powered on
+#define SOURCE_SWITCH_DELAY_MS 1000
+
 CVLCommandHandler::CVLCommandHandler(CCECBusDevice *busDevice) :
     CCECCommandHandler(busDevice),
-    m_bActiveSourcePending(false),
-    m_bPowerUpEventReceived(false)
+    m_iPowerUpEventReceived(0)
 {
   m_vendorId = CEC_VENDOR_PANASONIC;
 }
@@ -71,6 +75,8 @@ bool CVLCommandHandler::InitHandler(void)
 
     if (primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
       return m_processor->GetPrimaryClient()->ChangeDeviceType(CEC_DEVICE_TYPE_RECORDING_DEVICE, CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+
+    m_processor->GetTV()->RequestPowerStatus(primary->GetLogicalAddress(), false);
   }
 
   return CCECCommandHandler::InitHandler();
@@ -89,17 +95,27 @@ int CVLCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &comman
   {
     if (command.parameters.At(4) == VL_POWERED_UP)
     {
-      LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV powered up");
+      // set the power up event time
       {
         CLockObject lock(m_mutex);
-        m_bPowerUpEventReceived = true;
+        if (m_iPowerUpEventReceived == 0)
+          m_iPowerUpEventReceived = GetTimeMs();
       }
-      m_processor->TransmitPendingActiveSourceCommands();
+      // mark the TV as powered on
+      m_processor->GetTV()->SetPowerStatus(CEC_POWER_STATUS_ON);
     }
     else if (command.parameters.At(4) == VL_POWERED_DOWN)
-      LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV powered down");
-    else if (command.parameters.At(4) == VL_POWERED_DOWN)
-      LIB_CEC->AddLog(CEC_LOG_DEBUG, "unknown vendor command");
+    {
+      // reset the power up event time
+      {
+        CLockObject lock(m_mutex);
+        m_iPowerUpEventReceived = 0;
+      }
+      // mark the TV as powered off
+      m_processor->GetTV()->SetPowerStatus(CEC_POWER_STATUS_STANDBY);
+    }
+    else
+      LIB_CEC->AddLog(CEC_LOG_DEBUG, "skipping unknown vendor command");
 
     return COMMAND_HANDLED;
   }
@@ -107,68 +123,48 @@ int CVLCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &comman
   return CCECCommandHandler::HandleDeviceVendorCommandWithId(command);
 }
 
-bool CVLCommandHandler::TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress)
+bool CVLCommandHandler::PowerUpEventReceived(void)
 {
-  bool bPowerUpEventReceived(false);
+  bool bPowerUpEventReceived(true);
 
-  CCECBusDevice *tv = m_processor->GetDevice(CECDEVICE_TV);
-  if (tv && tv->GetCurrentVendorId() == CEC_VENDOR_PANASONIC)
+  if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV)
   {
-    CVLCommandHandler *handler = static_cast<CVLCommandHandler *>(tv->GetHandler());
-    bPowerUpEventReceived = handler ? handler->PowerUpEventReceived() : false;
-    tv->MarkHandlerReady();
-  }
-
-  if (!bPowerUpEventReceived)
-  {
-    CLockObject lock(m_mutex);
-    // wait until we received the event
-    m_bActiveSourcePending = true;
-    return true;
+    // get the status from the TV
+    CCECBusDevice *tv = m_processor->GetTV();
+    if (tv && tv->GetCurrentVendorId() == CEC_VENDOR_PANASONIC)
+    {
+      CVLCommandHandler *handler = static_cast<CVLCommandHandler *>(tv->GetHandler());
+      bPowerUpEventReceived = handler ? handler->PowerUpEventReceived() : false;
+      tv->MarkHandlerReady();
+    }
   }
   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)
-  {
-    LIB_CEC->AddLog(CEC_LOG_DEBUG, "transmitting delayed activate source command");
-    return CCECCommandHandler::TransmitActiveSource(m_busDevice->GetLogicalAddress(), m_busDevice->GetCurrentPhysicalAddress()) &&
-        TransmitMenuState(m_busDevice->GetLogicalAddress(), CECDEVICE_TV, CEC_MENU_STATE_ACTIVATED);
-  }
-  return true;
-}
+    // get the current status
+    {
+      CLockObject lock(m_mutex);
+      bPowerUpEventReceived = m_iPowerUpEventReceived > 0 &&
+                              GetTimeMs() - m_iPowerUpEventReceived > SOURCE_SWITCH_DELAY_MS;
+    }
 
-bool CVLCommandHandler::PowerUpEventReceived(void)
-{
-  {
-    CLockObject lock(m_mutex);
-    if (m_bPowerUpEventReceived)
-      return true;
+    // if we didn't receive the event, check if the TV is already marked as powered on
+    if (!bPowerUpEventReceived && m_busDevice->GetCurrentPowerStatus() == CEC_POWER_STATUS_ON)
+    {
+      CLockObject lock(m_mutex);
+      m_iPowerUpEventReceived = GetTimeMs();
+      bPowerUpEventReceived = true;
+    }
   }
 
-  CLockObject lock(m_mutex);
-  m_bPowerUpEventReceived = (m_busDevice->GetCurrentPowerStatus() == CEC_POWER_STATUS_ON);
-  return m_bPowerUpEventReceived;
+  return bPowerUpEventReceived;
 }
 
 int CVLCommandHandler::HandleStandby(const cec_command &command)
 {
+  // reset the power up event time
   {
     CLockObject lock(m_mutex);
-    m_bPowerUpEventReceived = false;
+    m_iPowerUpEventReceived = 0;
   }
 
   return CCECCommandHandler::HandleStandby(command);
@@ -195,3 +191,7 @@ int CVLCommandHandler::HandleVendorCommand(const cec_command &command)
   return CEC_ABORT_REASON_INVALID_OPERAND;
 }
 
+bool CVLCommandHandler::SourceSwitchAllowed(void)
+{
+  return PowerUpEventReceived();
+}
index 699ef40330be4618302679635a333614281dc63b..433a3944427fa06b4a59c99752a00965e6343e8e 100644 (file)
@@ -45,17 +45,16 @@ namespace CEC
 
     int HandleDeviceVendorCommandWithId(const cec_command &command);
     int HandleStandby(const cec_command &command);
-    bool TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress);
-    bool TransmitPendingActiveSourceCommands(void);
 
     int HandleVendorCommand(const cec_command &command);
     bool PowerUpEventReceived(void);
     bool SupportsDeviceType(const cec_device_type type) const { return type != CEC_DEVICE_TYPE_RECORDING_DEVICE; };
     cec_device_type GetReplacementDeviceType(const cec_device_type type) const { return type == CEC_DEVICE_TYPE_RECORDING_DEVICE ? CEC_DEVICE_TYPE_PLAYBACK_DEVICE : type; }
 
+    bool SourceSwitchAllowed(void);
+
   private:
     PLATFORM::CMutex m_mutex;
-    bool             m_bActiveSourcePending;
-    bool             m_bPowerUpEventReceived;
+    uint64_t         m_iPowerUpEventReceived;
   };
 };