this solves problem with device dissapearing from TV's menu
[deb_libcec.git] / src / lib / implementations / CECCommandHandler.cpp
index 28cee428128f5caadbc5cf2346fb0c8377c66537..a89ebe6c27ee2bc5fb632a6b26ee29749af3331c 100644 (file)
@@ -257,6 +257,14 @@ int CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command & UNUS
 int CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
 {
   SetVendorId(command);
+
+  if (command.initiator == CECDEVICE_TV)
+  {
+    CCECBusDevice* primary = m_processor->GetPrimaryDevice();
+    if (primary)
+      primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false);
+  }
+
   return COMMAND_HANDLED;
 }
 
@@ -455,6 +463,13 @@ int CCECCommandHandler::HandleReportPhysicalAddress(const cec_command &command)
   {
     uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
     SetPhysicalAddress(command.initiator, iNewAddress);
+
+    if (command.initiator == CECDEVICE_TV)
+    {
+      CCECBusDevice* primary = m_processor->GetPrimaryDevice();
+      if (primary)
+        primary->TransmitPhysicalAddress(false);
+    }
     return COMMAND_HANDLED;
   }
   return CEC_ABORT_REASON_INVALID_OPERAND;
@@ -577,19 +592,18 @@ int CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
     CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress);
     if (device)
     {
-      if (device->IsHandledByLibCEC() && !device->IsActiveSource())
-        device->ActivateSource();
-      else
-        device->MarkAsActiveSource();
+      if (device->IsHandledByLibCEC())
+      {
+        if (!device->IsActiveSource())
+          device->ActivateSource();
+        else
+        {
+          device->MarkAsActiveSource();
+          device->TransmitActiveSource(true);
+        }
+      }
       return COMMAND_HANDLED;
     }
-    else
-    {
-      cec_logical_address previousSource = m_processor->GetActiveSource(false);
-      CCECBusDevice* device = m_processor->GetDevice(previousSource);
-      if (device && device->GetCurrentPhysicalAddress() != iStreamAddress)
-        device->MarkAsInactiveSource();
-    }
   }
 
   return CEC_ABORT_REASON_INVALID_OPERAND;
@@ -756,6 +770,9 @@ void CCECCommandHandler::UnhandledCommand(const cec_command &command, const cec_
   {
     LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending abort with opcode %02x and reason '%s' to %s", command.opcode, ToString(reason), ToString(command.initiator));
     m_processor->TransmitAbort(command.destination, command.initiator, command.opcode, reason);
+
+    if (reason == CEC_ABORT_REASON_INVALID_OPERAND)
+      RequestEmailFromCustomer(command);
   }
 }
 
@@ -914,12 +931,12 @@ bool CCECCommandHandler::TransmitRequestPhysicalAddress(const cec_logical_addres
   return Transmit(command, !bWaitForResponse, false);
 }
 
-bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse /* = true */)
+bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bUpdate, bool bWaitForResponse /* = true */)
 {
   if (iDestination == CECDEVICE_TV)
   {
     int64_t now(GetTimeMs());
-    if (now - m_iPowerStatusRequested < REQUEST_POWER_STATUS_TIMEOUT)
+    if (!bUpdate && now - m_iPowerStatusRequested < REQUEST_POWER_STATUS_TIMEOUT)
       return true;
     m_iPowerStatusRequested = now;
   }
@@ -1211,7 +1228,7 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
     bool bTvPresent = (tv && tv->GetStatus() == CEC_DEVICE_STATUS_PRESENT);
     bool bActiveSourceFailed(false);
     if (bTvPresent)
-      bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
+      bActiveSourceFailed = !tv->PowerOn(m_busDevice->GetLogicalAddress());
     else
       LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV not present, not sending 'image view on'");
 
@@ -1234,6 +1251,14 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
         if (playbackDevice && SendDeckStatusUpdateOnActiveSource())
           bActiveSourceFailed = !playbackDevice->TransmitDeckStatus(CECDEVICE_TV, false);
       }
+
+      // update system audio mode for audiosystem devices
+      if (bTvPresent && !bActiveSourceFailed)
+      {
+        CCECAudioSystem* audioDevice = m_busDevice->AsAudioSystem();
+        if (audioDevice)
+          bActiveSourceFailed = !audioDevice->TransmitSetSystemAudioMode(CECDEVICE_TV, false);
+      }
     }
 
     // retry later
@@ -1265,3 +1290,31 @@ void CCECCommandHandler::ScheduleActivateSource(uint64_t iDelay)
   CLockObject lock(m_mutex);
   m_iActiveSourcePending = GetTimeMs() + iDelay;
 }
+
+void CCECCommandHandler::RequestEmailFromCustomer(const cec_command& command)
+{
+  bool bInserted(false);
+  map<cec_opcode, vector<cec_command> >::iterator it = m_logsRequested.find(command.opcode);
+  if (it != m_logsRequested.end())
+  {
+    for (vector<cec_command>::const_iterator it2 = it->second.begin(); it2 != it->second.end(); it2++)
+    {
+      // we already logged this one
+      if ((*it2).parameters == command.parameters)
+        return;
+    }
+
+    it->second.push_back(command);
+    bInserted = true;
+  }
+
+  if (!bInserted)
+  {
+    vector<cec_command> commands;
+    commands.push_back(command);
+    m_logsRequested.insert(make_pair(command.opcode, commands));
+  }
+
+  LIB_CEC->AddLog(CEC_LOG_NOTICE, "Unmapped code detected. Please send an email to support@pulse-eight.com with the following details, and if you pressed a key, tell us which one you pressed, and we'll add support for this it.\nCEC command: %s\nVendor ID: %s (%06x)", ToString(command).c_str(), ToString(m_vendorId), m_vendorId);
+}
+