ensure that we only send 'image view on' when needed
[deb_libcec.git] / src / lib / implementations / CECCommandHandler.cpp
index 831825da263fdeb2167e890583fd50070cdaeed3..d1af939188fbf86386295827a6652d1a065f2613 100644 (file)
@@ -209,12 +209,13 @@ int CCECCommandHandler::HandleActiveSource(const cec_command &command)
   if (command.parameters.size == 2)
   {
     uint16_t iAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+    m_processor->GetDevices()->SetActiveSource(iAddress);
     CCECBusDevice *device = m_processor->GetDeviceByPhysicalAddress(iAddress);
     if (device)
-    {
       device->MarkAsActiveSource();
-      return COMMAND_HANDLED;
-    }
+
+    m_processor->GetDevices()->SignalAll(command.opcode);
+    return COMMAND_HANDLED;
   }
 
   return CEC_ABORT_REASON_INVALID_OPERAND;
@@ -384,12 +385,14 @@ int CCECCommandHandler::HandleGiveSystemAudioModeStatus(const cec_command &comma
 int CCECCommandHandler::HandleImageViewOn(const cec_command &command)
 {
   CCECBusDevice *device = GetDevice(command.destination);
-  if (device && (device->GetCurrentStatus() == CEC_DEVICE_STATUS_PRESENT ||
-      device->GetCurrentStatus() == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC))
+  if (device && device->GetCurrentStatus() == CEC_DEVICE_STATUS_PRESENT)
   {
     if (device->GetCurrentPowerStatus() == CEC_POWER_STATUS_STANDBY ||
         device->GetCurrentPowerStatus() == CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY)
       device->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+    CCECBusDevice* tv = GetDevice(CECDEVICE_TV);
+    if (tv)
+      tv->OnImageViewOnSent(false);
   }
   return COMMAND_HANDLED;
 }
@@ -488,13 +491,11 @@ int CCECCommandHandler::HandleRoutingChange(const cec_command &command)
 {
   if (command.parameters.size == 4)
   {
-    uint16_t iOldAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
-    uint16_t iNewAddress = ((uint16_t)command.parameters[2] << 8) | ((uint16_t)command.parameters[3]);
-
     CCECBusDevice *device = GetDevice(command.initiator);
     if (device)
     {
-      device->SetStreamPath(iNewAddress, iOldAddress);
+      uint16_t iNewAddress = ((uint16_t)command.parameters[2] << 8) | ((uint16_t)command.parameters[3]);
+      device->SetActiveRoute(iNewAddress);
       return COMMAND_HANDLED;
     }
   }
@@ -506,11 +507,11 @@ int CCECCommandHandler::HandleRoutingInformation(const cec_command &command)
 {
   if (command.parameters.size == 2)
   {
-    uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
-    CCECBusDevice *device = m_processor->GetDeviceByPhysicalAddress(iNewAddress);
+    CCECBusDevice *device = GetDevice(command.initiator);
     if (device)
     {
-      device->MarkAsActiveSource();
+      uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+      device->SetActiveRoute(iNewAddress);
       return COMMAND_HANDLED;
     }
   }
@@ -570,9 +571,6 @@ int CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
     uint16_t iStreamAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
     LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s (%x) sets stream path to physical address %04x", ToString(command.initiator), command.initiator, iStreamAddress);
 
-    // a device will only change the stream path when it's powered on
-    m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
-
     /* one of the device handled by libCEC has been made active */
     CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress);
     if (device && device->IsHandledByLibCEC())
@@ -678,13 +676,15 @@ int CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
     client->SetCurrentButton((cec_user_control_code) command.parameters[0]);
 
   if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER ||
-      command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION)
+      command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION||
+      command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION)
   {
     bool bPowerOn(true);
 
-    // CEC_USER_CONTROL_CODE_POWER operates as a toggle
+    // CEC_USER_CONTROL_CODE_POWER and CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION operate as a toggle
     // assume CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION does not
-    if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER)
+    if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER ||
+        command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION)
     {
       cec_power_status status = device->GetCurrentPowerStatus();
       bPowerOn = !(status == CEC_POWER_STATUS_ON || status == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
@@ -701,6 +701,12 @@ int CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
       device->SetMenuState(CEC_MENU_STATE_DEACTIVATED);
     }
   }
+  else if (command.parameters[0] != CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION)
+  {
+    // we're not marked as active source, but the tv sends keypresses to us, so assume it forgot to activate us
+    if (!device->IsActiveSource() && command.initiator == CECDEVICE_TV)
+      device->ActivateSource();
+  }
 
   return COMMAND_HANDLED;
 }
@@ -723,6 +729,15 @@ int CCECCommandHandler::HandleVendorCommand(const cec_command & UNUSED(command))
   return CEC_ABORT_REASON_INVALID_OPERAND;
 }
 
+int CCECCommandHandler::HandleVendorRemoteButtonDown(const cec_command& command)
+{
+  if (command.parameters.size == 0)
+    return CEC_ABORT_REASON_INVALID_OPERAND;
+
+  LIB_CEC->AddLog(CEC_LOG_NOTICE, "unhandled vendor remote button received with keycode %x", command.parameters[0]);
+  return COMMAND_HANDLED;
+}
+
 void CCECCommandHandler::UnhandledCommand(const cec_command &command, const cec_abort_reason reason)
 {
   if (m_processor->IsHandledByLibCEC(command.destination))
@@ -817,7 +832,14 @@ bool CCECCommandHandler::TransmitImageViewOn(const cec_logical_address iInitiato
   cec_command command;
   cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_IMAGE_VIEW_ON);
 
-  return Transmit(command, false, false);
+  if (Transmit(command, false, false))
+  {
+    CCECBusDevice* dest = m_processor->GetDevice(iDestination);
+    if (dest && dest->GetCurrentPowerStatus() != CEC_POWER_STATUS_ON)
+      dest->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+    return true;
+  }
+  return false;
 }
 
 bool CCECCommandHandler::TransmitStandby(const cec_logical_address iInitiator, const cec_logical_address iDestination)
@@ -1161,10 +1183,7 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
     bool bTvPresent = (tv && tv->GetStatus() == CEC_DEVICE_STATUS_PRESENT);
     bool bActiveSourceFailed(false);
     if (bTvPresent)
-    {
-      if (tv->GetCurrentPowerStatus() != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON)
-        bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
-    }
+      bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
     else
       LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV not present, not sending 'image view on'");