fixed - message response signaling and logging
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 34ffed58db84902d286a2532b78223f3b58af9c8..409b30b1cdde68d6f4ff79304a9fecc32a7d1316 100644 (file)
@@ -63,13 +63,17 @@ CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_iStandardLineTimeout(3),
     m_iRetryLineTimeout(3),
     m_iLastTransmission(0),
-    m_bMonitor(true)
+    m_bMonitor(true),
+    m_addrAllocator(NULL),
+    m_bStallCommunication(false)
 {
   m_busDevices = new CCECDeviceMap(this);
 }
 
 CCECProcessor::~CCECProcessor(void)
 {
+  m_bStallCommunication = false;
+  DELETE_AND_NULL(m_addrAllocator);
   Close();
   DELETE_AND_NULL(m_busDevices);
 }
@@ -410,6 +414,9 @@ bool CCECProcessor::Transmit(const cec_command &data, bool bIsReply)
     }
   }
 
+  // wait until we finished allocating a new LA if it got lost
+  while (m_bStallCommunication) Sleep(5);
+
   {
     CLockObject lock(m_mutex);
     m_iLastTransmission = GetTimeMs();
@@ -430,7 +437,9 @@ bool CCECProcessor::Transmit(const cec_command &data, bool bIsReply)
     iLineTimeout = m_iRetryLineTimeout;
   }
 
-  return adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+  return bIsReply ?
+      adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED || adapterState == ADAPTER_MESSAGE_STATE_SENT || adapterState == ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT :
+      adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED;
 }
 
 void CCECProcessor::TransmitAbort(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_abort_reason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */)
@@ -684,6 +693,9 @@ bool CCECProcessor::AllocateLogicalAddresses(CCECClient* client)
   // set the new ackmask
   SetLogicalAddresses(GetLogicalAddresses());
 
+  // resume outgoing communication
+  m_bStallCommunication = false;
+
   return true;
 }
 
@@ -914,18 +926,30 @@ void CCECProcessor::SwitchMonitoring(bool bSwitchTo)
     UnregisterClients();
 }
 
-void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress, cec_logical_address newAddress)
+void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress)
 {
-  m_libcec->AddLog(CEC_LOG_NOTICE, "logical address %x was taken by another device, changed to %x", oldAddress, newAddress);
+  // stall outgoing messages until we know our new LA
+  m_bStallCommunication = true;
+
+  m_libcec->AddLog(CEC_LOG_NOTICE, "logical address %x was taken by another device, allocating a new address", oldAddress);
   CCECClient* client = GetClient(oldAddress);
   if (client)
   {
-    if (newAddress == CECDEVICE_UNKNOWN)
-      UnregisterClient(client);
-    else
-    {
-      client->m_configuration.logicalAddresses.Unset(oldAddress);
-      client->m_configuration.logicalAddresses.Set(newAddress);
-    }
+    if (m_addrAllocator)
+      while (m_addrAllocator->IsRunning()) Sleep(5);
+    delete m_addrAllocator;
+
+    m_addrAllocator = new CCECAllocateLogicalAddress(this, client);
+    m_addrAllocator->CreateThread();
   }
 }
+
+CCECAllocateLogicalAddress::CCECAllocateLogicalAddress(CCECProcessor* processor, CCECClient* client) :
+    m_processor(processor),
+    m_client(client) { }
+
+void* CCECAllocateLogicalAddress::Process(void)
+{
+  m_processor->AllocateLogicalAddresses(m_client);
+  return NULL;
+}