updated copyright messages for 2013
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 409b30b1cdde68d6f4ff79304a9fecc32a7d1316..84a46d635e01823a7fb7bcff25adcb666fcdf36b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -104,6 +104,8 @@ void CCECProcessor::Close(void)
   SetCECInitialised(false);
 
   // stop the processor
+  StopThread(-1);
+  m_inBuffer.Broadcast();
   StopThread();
 
   // close the connection
@@ -222,7 +224,7 @@ void *CCECProcessor::Process(void)
     if (m_inBuffer.Pop(command, CEC_PROCESSOR_SIGNAL_WAIT_TIME))
       ProcessCommand(command);
 
-    if (CECInitialised())
+    if (CECInitialised() && !IsStopped())
     {
       // check clients for keypress timeouts
       m_libcec->CheckKeypressTimeout();
@@ -258,6 +260,12 @@ bool CCECProcessor::ActivateSource(uint16_t iStreamPath)
   return bReturn;
 }
 
+void CCECProcessor::SetActiveSource(bool bSetTo, bool bClientUnregistered)
+{
+  if (m_communication)
+    m_communication->SetActiveSource(bSetTo, bClientUnregistered);
+}
+
 void CCECProcessor::SetStandardLineTimeout(uint8_t iTimeout)
 {
   CLockObject lock(m_mutex);
@@ -313,11 +321,11 @@ bool CCECProcessor::PollDevice(cec_logical_address iAddress)
   CCECBusDevice *primary = GetPrimaryDevice();
   // poll the destination, with the primary as source
   if (primary)
-    return primary->TransmitPoll(iAddress, false);
+    return primary->TransmitPoll(iAddress, true);
 
   CCECBusDevice *device = m_busDevices->At(CECDEVICE_UNREGISTERED);
   if (device)
-    return device->TransmitPoll(iAddress, false);
+    return device->TransmitPoll(iAddress, true);
 
   return false;
 }
@@ -615,6 +623,8 @@ bool CCECProcessor::GetDeviceInformation(const char *strPort, libcec_configurati
   config->iFirmwareBuildDate = m_communication->GetFirmwareBuildDate();
   config->adapterType        = m_communication->GetAdapterType();
 
+  Close();
+
   return true;
 }
 
@@ -699,6 +709,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)
@@ -706,7 +724,13 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
 
   libcec_configuration &configuration = *client->GetConfiguration();
 
-  if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_3 && configuration.bMonitorOnly == 1)
+  if (configuration.clientVersion < CEC_CLIENT_VERSION_2_0_0)
+  {
+    m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: client version %s is no longer supported", ToString((cec_client_version)configuration.clientVersion));
+    return false;
+  }
+
+  if (configuration.bMonitorOnly == 1)
     return true;
 
   if (!CECInitialised())
@@ -721,14 +745,24 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
 
   // ensure that controlled mode is enabled
   m_communication->SetControlledMode(true);
+  m_bMonitor = false;
+
+  // 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 &&
@@ -778,6 +812,8 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   // mark the client as registered
   client->SetRegistered(true);
 
+  sourceAddress = client->GetPrimaryLogicalAdddress();
+
   // initialise the client
   bool bReturn = client->OnRegister();
 
@@ -805,6 +841,12 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
     GetTV()->MarkHandlerReady();
   }
 
+  // report our OSD name to the TV, since some TVs don't request it
+  client->GetPrimaryDevice()->TransmitOSDName(CECDEVICE_TV, false);
+
+  // request the power status of the TV
+  tv->RequestPowerStatus(sourceAddress, true);
+
   return bReturn;
 }
 
@@ -833,7 +875,7 @@ bool CCECProcessor::UnregisterClient(CCECClient *client)
         m_clients.erase(entry);
 
       // reset the device status
-      (*it)->ResetDeviceStatus();
+      (*it)->ResetDeviceStatus(true);
     }
   }
 
@@ -853,7 +895,7 @@ bool CCECProcessor::UnregisterClient(CCECClient *client)
 
 void CCECProcessor::UnregisterClients(void)
 {
-  m_libcec->AddLog(CEC_LOG_NOTICE, "unregistering all CEC clients");
+  m_libcec->AddLog(CEC_LOG_DEBUG, "unregistering all CEC clients");
 
   vector<CCECClient *> clients = m_libcec->GetClients();
   for (vector<CCECClient *>::iterator client = clients.begin(); client != clients.end(); client++)
@@ -933,6 +975,8 @@ void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress)
 
   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)
+    client = GetPrimaryClient();
   if (client)
   {
     if (m_addrAllocator)
@@ -944,6 +988,24 @@ void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress)
   }
 }
 
+void CCECProcessor::HandlePhysicalAddressChanged(uint16_t iNewAddress)
+{
+  m_libcec->AddLog(CEC_LOG_NOTICE, "physical address changed to %04x", iNewAddress);
+  CCECClient* client = GetPrimaryClient();
+  if (client)
+    client->SetPhysicalAddress(iNewAddress);
+}
+
+uint16_t CCECProcessor::GetAdapterVendorId(void) const
+{
+  return m_communication ? m_communication->GetAdapterVendorId() : 0;
+}
+
+uint16_t CCECProcessor::GetAdapterProductId(void) const
+{
+  return m_communication ? m_communication->GetAdapterProductId() : 0;
+}
+
 CCECAllocateLogicalAddress::CCECAllocateLogicalAddress(CCECProcessor* processor, CCECClient* client) :
     m_processor(processor),
     m_client(client) { }