Merge branch 'development'
authorLars Op den Kamp <lars@opdenkamp.eu>
Thu, 11 Oct 2012 14:55:12 +0000 (16:55 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Thu, 11 Oct 2012 14:55:12 +0000 (16:55 +0200)
22 files changed:
ChangeLog
debian/changelog
include/cec.h
include/cectypes.h
project/cec-config.rc
project/libcec.rc
project/testclient.rc
src/CecSharpTester/Properties/AssemblyInfo.cs
src/LibCecSharp/AssemblyInfo.cpp
src/LibCecSharp/CecSharpTypes.h
src/LibCecTray/Properties/AssemblyInfo.cs
src/lib/CECClient.cpp
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/CECTypeUtils.h
src/lib/adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp
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
src/testclient/main.cpp

index 82e7880280cb5dadf683dfe67a390b3763e8b1b2..ccb10d2260ee9077ea1df76bb94783544b90d558 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+libcec (2.0.2-1) unstable; urgency=low
+
+  * changed/added:
+    * missing from the previous changelog: added support for the CuBox TDA995x
+      credits: warped-rudi
+    * lower retry timeout for source switches
+    * cec-client: wait for the source switch to finish when cec-client is
+      called with the -s switch
+    * request the power status of the TV directly after registering a new
+      client
+  * fixed:
+    * don't keep trying to send 'image view on' commands to the TV when no TV
+      is connected, and just send the 'set active source' command. fixes source
+      switch and debug log spam for people without a TV connected
+    * don't keep waiting for an updated power status from the TV for Panasonic,
+      but request a status update once every 5 seconds, or we can possibly wait
+      forever for the tv to send it
+    * log what we received exactly when logging FIXME
+    * typo in CVLCommandHandler::VendorPreActivateSourceHook. bugzid: 1087
+    * if we failed to get the physical address of the device that we are
+      connected to in the config, then try to use the address that was
+      persisted in the eeprom before resetting to the default value, 1.0.0.0.
+      closes #50.
+    * don't update the device status of unregistered/broadcast
+    * log all device status changes
+    * CCECClient::IsLibCECActiveSource returns false now while the active
+      source command is pending
+    * log failed acks and other errors in the debug log again
+    * don't send 'image view on' when the TV is already powering up
+    * reset the delayed source switch timeout properly, so we don't spam
+      commands every second
+    * don't change the device status when sending a delayed source switch
+    * don't send out commands to a device that is marked as not present or
+      handled by libCEC
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Thu, 11 Oct 2012 15:48:00 +0100
+
 libcec (2.0.1-1) unstable; urgency=low
 
   * changed/added:
index 82e7880280cb5dadf683dfe67a390b3763e8b1b2..ccb10d2260ee9077ea1df76bb94783544b90d558 100644 (file)
@@ -1,3 +1,40 @@
+libcec (2.0.2-1) unstable; urgency=low
+
+  * changed/added:
+    * missing from the previous changelog: added support for the CuBox TDA995x
+      credits: warped-rudi
+    * lower retry timeout for source switches
+    * cec-client: wait for the source switch to finish when cec-client is
+      called with the -s switch
+    * request the power status of the TV directly after registering a new
+      client
+  * fixed:
+    * don't keep trying to send 'image view on' commands to the TV when no TV
+      is connected, and just send the 'set active source' command. fixes source
+      switch and debug log spam for people without a TV connected
+    * don't keep waiting for an updated power status from the TV for Panasonic,
+      but request a status update once every 5 seconds, or we can possibly wait
+      forever for the tv to send it
+    * log what we received exactly when logging FIXME
+    * typo in CVLCommandHandler::VendorPreActivateSourceHook. bugzid: 1087
+    * if we failed to get the physical address of the device that we are
+      connected to in the config, then try to use the address that was
+      persisted in the eeprom before resetting to the default value, 1.0.0.0.
+      closes #50.
+    * don't update the device status of unregistered/broadcast
+    * log all device status changes
+    * CCECClient::IsLibCECActiveSource returns false now while the active
+      source command is pending
+    * log failed acks and other errors in the debug log again
+    * don't send 'image view on' when the TV is already powering up
+    * reset the delayed source switch timeout properly, so we don't spam
+      commands every second
+    * don't change the device status when sending a delayed source switch
+    * don't send out commands to a device that is marked as not present or
+      handled by libCEC
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Thu, 11 Oct 2012 15:48:00 +0100
+
 libcec (2.0.1-1) unstable; urgency=low
 
   * changed/added:
index 1b0019bea193a912c165fabaccb0a2d1229c3c3c..d10f4339ff6b775372154abcda37b2226b6602f3 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "cectypes.h"
 
-#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_2_0_0
+#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_2_0_1
 
 namespace CEC
 {
index 2af86437c726152708000c6cb77b3b8422aa2d11..f68007b507e4477619c5d8e2f7346e343b4c887d 100644 (file)
@@ -257,7 +257,7 @@ namespace CEC {
 /*!
  * wait this amount of milliseconds before retrying when libCEC failed to make itself the active source
  */
-#define CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS 5000
+#define CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS 1000
 
 /*!
  * don't forward any power off command to the client application for this amount of milliseconds after sending a power off command
@@ -1374,6 +1374,7 @@ typedef enum cec_client_version
   CEC_CLIENT_VERSION_1_9_0   = 0x1900,
   CEC_CLIENT_VERSION_1_99_0  = 0x1990,
   CEC_CLIENT_VERSION_2_0_0   = 0x2000,
+  CEC_CLIENT_VERSION_2_0_1   = 0x2001,
 } cec_client_version;
 
 typedef enum cec_server_version
@@ -1396,6 +1397,7 @@ typedef enum cec_server_version
   CEC_SERVER_VERSION_1_9_0   = 0x1900,
   CEC_SERVER_VERSION_1_99_0  = 0x1990,
   CEC_SERVER_VERSION_2_0_0   = 0x2000,
+  CEC_SERVER_VERSION_2_0_1   = 0x2001,
 } cec_server_version;
 
 struct libcec_configuration
index 8927346fb6504637f061b04a5451ced071ca5c9c..bc1299da66e7e33e3d1a4130ad1735bddef5d756 100644 (file)
Binary files a/project/cec-config.rc and b/project/cec-config.rc differ
index 579649fd32745d1e49a76be7227dc27f9c25b76d..2f85a67abc451b26408f9ce922ce4dbbf160af07 100644 (file)
Binary files a/project/libcec.rc and b/project/libcec.rc differ
index b7f8c08cf5572dde4344636fcda3dcc91567f987..1d6382b69816b2092cbb7248fbed00136a96c25c 100644 (file)
Binary files a/project/testclient.rc and b/project/testclient.rc differ
index 2b249ff4d4c91c5822f3b93182bfe2bb83901a31..799111ddc3ddbad6d642ec9d1ee7a1797bd11fea 100644 (file)
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyVersion("2.0.1.0")]
+[assembly: AssemblyFileVersion("2.0.1.0")]
index ed06b3b3ba74c9aa3b3866cd669024bbe97a0e9f..bb64ab4413f9244c083a2ba4b9c16a20eeda8a41 100644 (file)
@@ -13,7 +13,7 @@ using namespace System::Security::Permissions;
 [assembly:AssemblyTrademarkAttribute("")];
 [assembly:AssemblyCultureAttribute("")];
 
-[assembly:AssemblyVersionAttribute("2.0.0.0")];
+[assembly:AssemblyVersionAttribute("2.0.1.0")];
 
 [assembly:ComVisible(false)];
 [assembly:CLSCompliantAttribute(true)];
index fb14a54dba9cc00c6ac50d1b695fcacb29656507..908b3fc767633d51389f1fc71cdbee9481c73135 100644 (file)
@@ -1163,7 +1163,11 @@ namespace CecSharp
     /// <summary>
     /// v2.0.0
     /// </summary>
-    Version2_0_0   = 0x2000
+    Version2_0_0   = 0x2000,
+    /// <summary>
+    /// v2.0.1
+    /// </summary>
+    Version2_0_1   = 0x2001
   };
 
   /// <summary>
@@ -1242,7 +1246,11 @@ namespace CecSharp
     /// <summary>
     /// v2.0.0
     /// </summary>
-    Version2_0_0   = 0x2000
+    Version2_0_0   = 0x2000,
+    /// <summary>
+    /// v2.0.1
+    /// </summary>
+    Version2_0_1   = 0x2001
   };
 
   /// <summary>
index 8c25663917ba4dd7d6066cb856ef9a6516d05105..80c33c6276723cfd9e361f1ad3a2f7f3b70e54d4 100644 (file)
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.7.2.0")]
-[assembly: AssemblyFileVersion("1.7.2.0")]
+[assembly: AssemblyVersion("2.0.1.0")]
+[assembly: AssemblyFileVersion("2.0.1.0")]
index d6f8100dec9daa25b26b7e55986eeaf8e85f6858..f85a53c2a6cae81bae6d17134ffa6b2fc3313f6e 100644 (file)
@@ -184,8 +184,18 @@ bool CCECClient::SetHDMIPort(const cec_logical_address iBaseDevice, const uint8_
   // set the default address when something went wrong
   if (!bReturn)
   {
-    LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
-    iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+    uint16_t iEepromAddress = m_processor->GetPhysicalAddressFromEeprom();
+    if (CLibCEC::IsValidPhysicalAddress(iEepromAddress))
+    {
+      LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the value that was persisted in the eeprom, %04X", iPhysicalAddress, iEepromAddress);
+      iPhysicalAddress = iEepromAddress;
+      bReturn = true;
+    }
+    else
+    {
+      LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
+      iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+    }
   }
 
   // and set the address
@@ -1344,7 +1354,7 @@ bool CCECClient::IsLibCECActiveSource(void)
     cec_logical_address activeSource = m_processor->GetActiveSource();
     CCECBusDevice *device = m_processor->GetDevice(activeSource);
     if (device)
-      bReturn = device->IsHandledByLibCEC();
+      bReturn = device->IsHandledByLibCEC() && !device->GetHandler()->ActiveSourcePending();
   }
   return bReturn;
 }
index 824744cc061d9e52bfd11c69099508d050b81575..cc6adda8bf4826bfb0c28f63975bae66e60bfd94 100644 (file)
@@ -701,6 +701,14 @@ bool CCECProcessor::AllocateLogicalAddresses(CCECClient* client)
   return true;
 }
 
+uint16_t CCECProcessor::GetPhysicalAddressFromEeprom(void)
+{
+  libcec_configuration config; config.Clear();
+  if (m_communication)
+    m_communication->GetConfiguration(config);
+  return config.iPhysicalAddress;
+}
+
 bool CCECProcessor::RegisterClient(CCECClient *client)
 {
   if (!client)
@@ -730,13 +738,22 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   // ensure that controlled mode is enabled
   m_communication->SetControlledMode(true);
 
+  // source logical address for requests
+  cec_logical_address sourceAddress(CECDEVICE_UNREGISTERED);
+  if (!m_communication->SupportsSourceLogicalAddress(CECDEVICE_UNREGISTERED))
+  {
+    if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE))
+      sourceAddress = CECDEVICE_FREEUSE;
+    else
+    {
+      m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: both unregistered and free use are not supported by the device");
+      return false;
+    }
+  }
+
   // ensure that we know the vendor id of the TV
   CCECBusDevice *tv = GetTV();
-  cec_vendor_id tvVendor = CEC_VENDOR_UNKNOWN;
-  if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_UNREGISTERED))
-    tvVendor = tv->GetVendorId(CECDEVICE_UNREGISTERED);
-  else if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE))
-    tvVendor = tv->GetVendorId(CECDEVICE_FREEUSE);
+  cec_vendor_id tvVendor(tv->GetVendorId(sourceAddress));
 
   // wait until the handler is replaced, to avoid double registrations
   if (tvVendor != CEC_VENDOR_UNKNOWN &&
@@ -786,6 +803,8 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   // mark the client as registered
   client->SetRegistered(true);
 
+  sourceAddress = client->GetPrimaryLogicalAdddress();
+
   // initialise the client
   bool bReturn = client->OnRegister();
 
@@ -813,6 +832,9 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
     GetTV()->MarkHandlerReady();
   }
 
+  // request the power status of the TV
+  tv->RequestPowerStatus(sourceAddress, true);
+
   return bReturn;
 }
 
index dff892e8b9ee2b1e5e588640705a451ff9977605..5593a2cc99e5be970756bd2d778df3f91e27ba50 100644 (file)
@@ -77,6 +77,7 @@ namespace CEC
       bool RegisterClient(CCECClient *client);
       bool UnregisterClient(CCECClient *client);
       void UnregisterClients(void);
+      uint16_t GetPhysicalAddressFromEeprom(void);
       CCECClient *GetPrimaryClient(void);
       CCECClient *GetClient(const cec_logical_address address);
 
index 6662182f50802be831d67e4f6174686fa842b766..5d34b466e92580ddfaa85a270792d1abe125edc6 100644 (file)
@@ -557,6 +557,8 @@ namespace CEC
         return "2.0.0-pre";
       case CEC_CLIENT_VERSION_2_0_0:
         return "2.0.0";
+      case CEC_CLIENT_VERSION_2_0_1:
+        return "2.0.1";
       default:
         return "Unknown";
       }
@@ -602,6 +604,8 @@ namespace CEC
         return "2.0.0-pre";
       case CEC_CLIENT_VERSION_2_0_0:
         return "2.0.0";
+      case CEC_CLIENT_VERSION_2_0_1:
+        return "2.0.1";
       default:
         return "Unknown";
       }
index 1b14f445f30e9bfc43afbef5304296d3277cb619..9fca017c05020f3366afc69599257e72716464bc 100644 (file)
@@ -169,7 +169,7 @@ bool CCECAdapterMessageQueueEntry::IsResponse(const CCECAdapterMessage &msg)
 
   if (!m_message->IsTranmission())
   {
-    m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_WARNING, "FIXME! not a transmission");
+    m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_WARNING, "FIXME! not a transmission: %s", msg.ToString().c_str());
     return false;
   }
 
@@ -262,6 +262,9 @@ bool CCECAdapterMessageQueueEntry::MessageReceivedResponse(const CCECAdapterMess
     CLockObject lock(m_mutex);
 #ifdef CEC_DEBUGGING
     m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_DEBUG, "%s - received response - %s", ToString(), message.ToString().c_str());
+#else
+    if (message.IsError())
+      m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_DEBUG, "%s - received response - %s", ToString(), message.ToString().c_str());
 #endif
     m_message->response = message.packet;
     if (m_message->IsTranmission())
@@ -462,7 +465,7 @@ bool CCECAdapterMessageQueue::Write(CCECAdapterMessage *msg)
       m_messages.erase(iEntryId);
     }
 
-    if (msg->ReplyIsError())
+    if (msg->ReplyIsError() && msg->state != ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED)
       msg->state = ADAPTER_MESSAGE_STATE_ERROR;
 
     delete entry;
index e3d4cfdeea8876a2d2d36d87f1d85aadab57d717..b42230dd41201913a0331e18f3b9c57aee874ec7 100644 (file)
@@ -174,11 +174,6 @@ bool CCECBusDevice::HandleCommand(const cec_command &command)
   {
     CLockObject lock(m_mutex);
     m_iLastActive = GetTimeMs();
-
-    /* don't call GetStatus() here, just read the value with the mutex locked */
-    if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC && command.opcode_set == 1)
-      m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
-
     MarkBusy();
   }
 
@@ -764,6 +759,9 @@ cec_bus_device_status CCECBusDevice::GetStatus(bool bForcePoll /* = false */, bo
 
 void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus, cec_version libCECSpecVersion /* = CEC_VERSION_1_4 */)
 {
+  if (m_iLogicalAddress == CECDEVICE_UNREGISTERED)
+    return;
+
   {
     CLockObject lock(m_mutex);
     switch (newStatus)
@@ -841,10 +839,10 @@ bool CCECBusDevice::TransmitPoll(const cec_logical_address dest, bool bIsReply)
   if (bReturn)
   {
     m_iLastActive = GetTimeMs();
-    destDevice->m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
+    SetDeviceStatus(CEC_DEVICE_STATUS_PRESENT);
   }
   else
-    destDevice->m_deviceStatus = CEC_DEVICE_STATUS_NOT_PRESENT;
+    SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
 
   MarkReady();
   return bReturn;
index 269cbde0d183fbdef4411fa4cc1f975c05869337..8dcc2559dbad3eb8e57cec211dfcef8ad6453132 100644 (file)
@@ -1077,6 +1077,23 @@ bool CCECCommandHandler::Transmit(cec_command &command, bool bSuppressWait, bool
     return bReturn;
   }
 
+  // check whether the destination is not marked as not present or handled by libCEC
+  if (command.destination != CECDEVICE_BROADCAST && command.opcode_set)
+  {
+    CCECBusDevice* destinationDevice = m_processor->GetDevice(command.destination);
+    cec_bus_device_status status = destinationDevice ? destinationDevice->GetStatus() : CEC_DEVICE_STATUS_NOT_PRESENT;
+    if (status == CEC_DEVICE_STATUS_NOT_PRESENT)
+    {
+      LIB_CEC->AddLog(CEC_LOG_DEBUG, "not sending command '%s': destination device '%s' marked as not present", ToString(command.opcode),ToString(command.destination));
+      return bReturn;
+    }
+    else if (status == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+    {
+      LIB_CEC->AddLog(CEC_LOG_DEBUG, "not sending command '%s': destination device '%s' marked as handled by libCEC", ToString(command.opcode),ToString(command.destination));
+      return bReturn;
+    }
+  }
+
   {
     uint8_t iTries(0), iMaxTries(!command.opcode_set ? 1 : m_iTransmitRetries + 1);
     while (!bReturn && ++iTries <= iMaxTries && !m_busDevice->IsUnsupportedFeature(command.opcode))
@@ -1114,14 +1131,26 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
     }
 
     // update the power state and menu state
-    m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
-    m_busDevice->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+    if (!bTransmitDelayedCommandsOnly)
+    {
+      m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
+      m_busDevice->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+    }
 
     // vendor specific hook
     VendorPreActivateSourceHook();
 
     // power on the TV
-    bool bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
+    CCECBusDevice* tv = m_processor->GetDevice(CECDEVICE_TV);
+    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();
+    }
+    else
+      LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV not present, not sending 'image view on'");
 
     // check if we're allowed to switch sources
     bool bSourceSwitchAllowed = SourceSwitchAllowed();
@@ -1131,11 +1160,12 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
     // switch sources (if allowed)
     if (!bActiveSourceFailed && bSourceSwitchAllowed)
     {
-      bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false) ||
-                            !m_busDevice->TransmitMenuState(CECDEVICE_TV, false);
+      bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false);
+      if (bTvPresent && !bActiveSourceFailed)
+        bActiveSourceFailed = !m_busDevice->TransmitMenuState(CECDEVICE_TV, false);
 
       // update the deck status for playback devices
-      if (!bActiveSourceFailed)
+      if (bTvPresent && !bActiveSourceFailed)
       {
         CCECPlaybackDevice *playbackDevice = m_busDevice->AsPlaybackDevice();
         if (playbackDevice && SendDeckStatusUpdateOnActiveSource())
@@ -1147,9 +1177,10 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
     if (bActiveSourceFailed || !bSourceSwitchAllowed)
     {
       LIB_CEC->AddLog(CEC_LOG_DEBUG, "failed to make '%s' the active source. will retry later", m_busDevice->GetLogicalAddressName());
+      int64_t now(GetTimeMs());
       CLockObject lock(m_mutex);
-      if (m_iActiveSourcePending == 0)
-        m_iActiveSourcePending = GetTimeMs() + (int64_t)CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS;
+      if (m_iActiveSourcePending == 0 || m_iActiveSourcePending < now)
+        m_iActiveSourcePending = now + (int64_t)CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS;
       return false;
     }
     else
index 61f9f47d5e722f2d2edb68a3ffc23167469239fd..fca8a966fa6aca7a4809cce9c9fad9727bf863f8 100644 (file)
@@ -97,6 +97,7 @@ namespace CEC
 
     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; }
+    virtual bool ActiveSourcePending(void) const { return m_iActiveSourcePending != 0; }
 
   protected:
     virtual int HandleActiveSource(const cec_command &command);
index 227d8a0aa3b67e25ebe4ec8f71a4f51c85a22d1a..90e87778c4c0a7dd11daa9f55534e5bebfcec95a 100644 (file)
@@ -45,6 +45,8 @@
 #define VL_POWERED_DOWN 0x01
 #define VL_UNKNOWN1     0x06
 
+#define VL_REQUEST_POWER_STATUS_TIMEOUT 5000
+
 using namespace CEC;
 using namespace PLATFORM;
 
@@ -62,7 +64,7 @@ CVLCommandHandler::CVLCommandHandler(CCECBusDevice *busDevice,
     CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending),
     m_iPowerUpEventReceived(0),
     m_bCapabilitiesSent(false),
-    m_bPowerStatusRequested(false)
+    m_iPowerStatusRequested(0)
 {
   m_vendorId = CEC_VENDOR_PANASONIC;
 }
@@ -162,8 +164,11 @@ bool CVLCommandHandler::PowerUpEventReceived(void)
 
   if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV)
   {
+    CCECBusDevice* tv = m_processor->GetTV();
+    if (tv && tv->GetStatus() != CEC_DEVICE_STATUS_PRESENT)
+      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());
@@ -208,7 +213,7 @@ void CVLCommandHandler::VendorPreActivateSourceHook(void)
   bool bTransmit(false);
   {
     CLockObject lock(m_mutex);
-    bTransmit = m_bCapabilitiesSent;
+    bTransmit = !m_bCapabilitiesSent;
   }
   if (bTransmit)
     SendVendorCommandCapabilities(m_processor->GetLogicalAddress(), CECDEVICE_TV);
@@ -249,13 +254,14 @@ int CVLCommandHandler::HandleVendorCommand(const cec_command &command)
 
 bool CVLCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse /* = true */)
 {
-  m_bPowerStatusRequested = true;
+  m_iPowerStatusRequested = GetTimeMs();
   return CCECCommandHandler::TransmitRequestPowerStatus(iInitiator, iDestination, bWaitForResponse);
 }
 
 bool CVLCommandHandler::SourceSwitchAllowed(void)
 {
-  if (!PowerUpEventReceived() && !m_bPowerStatusRequested)
+  int64_t now(GetTimeMs());
+  if (!PowerUpEventReceived() && now - m_iPowerStatusRequested > VL_REQUEST_POWER_STATUS_TIMEOUT)
     TransmitRequestPowerStatus(m_processor->GetPrimaryDevice()->GetLogicalAddress(), CECDEVICE_TV, false);
 
   return PowerUpEventReceived();
index ae6b9f60d63a291b3d34c5449ed87ffd91e10c67..b878ca97bee17da48f243a1d40db99920f12a03d 100644 (file)
@@ -67,6 +67,6 @@ namespace CEC
     PLATFORM::CMutex m_mutex;
     uint64_t         m_iPowerUpEventReceived;
     bool             m_bCapabilitiesSent;
-    bool             m_bPowerStatusRequested;
+    int64_t          m_iPowerStatusRequested;
   };
 };
index d170bfa44a791be7606384ef6f2bc8cbfb7d5c8b..24ddde594eb7b9abd67503c6ee3fd453c65012ed 100644 (file)
@@ -48,7 +48,7 @@ using namespace CEC;
 using namespace std;
 using namespace PLATFORM;
 
-#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_2_0_0;
+#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_2_0_1;
 
 #include "../../include/cecloader.h"
 
@@ -537,6 +537,18 @@ bool ProcessCommandAS(ICECAdapter *parser, const string &command, string & UNUSE
   if (command == "as")
   {
     parser->SetActiveSource();
+    // wait for the source switch to finish for 15 seconds tops
+    if (g_bSingleCommand)
+    {
+      CTimeout timeout(15000);
+      bool bActiveSource(false);
+      while (timeout.TimeLeft() > 0 && !bActiveSource)
+      {
+        bActiveSource = parser->IsLibCECActiveSource();
+        if (!bActiveSource)
+          CEvent::Sleep(100);
+      }
+    }
     return true;
   }