cec: refactor CEC command handling. split up standard and non-standard CEC implementa...
[deb_libcec.git] / src / lib / LibCEC.cpp
index abc800c19cc528af2ff0029f43b6787a9f9a5625..ecbc55abece3df8350a42574ec23f4350c9045c2 100644 (file)
@@ -42,6 +42,7 @@ using namespace std;
 using namespace CEC;
 
 CLibCEC::CLibCEC(const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */) :
+    m_iStartTime(GetTimeMs()),
     m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
     m_buttontime(0)
 {
@@ -57,9 +58,13 @@ CLibCEC::~CLibCEC(void)
 
   delete m_comm;
   m_comm = NULL;
+
+  m_logBuffer.Clear();
+  m_keyBuffer.Clear();
+  m_commandBuffer.Clear();
 }
 
-bool CLibCEC::Open(const char *strPort, uint64_t iTimeoutMs /* = 10000 */)
+bool CLibCEC::Open(const char *strPort, uint32_t iTimeoutMs /* = 10000 */)
 {
   if (!m_comm)
   {
@@ -73,7 +78,17 @@ bool CLibCEC::Open(const char *strPort, uint64_t iTimeoutMs /* = 10000 */)
     return false;
   }
 
-  if (!m_comm->Open(strPort, 38400, iTimeoutMs))
+  int64_t iNow = GetTimeMs();
+  int64_t iTarget = iNow + iTimeoutMs;
+
+  bool bOpened(false);
+  while (!bOpened && iNow < iTarget)
+  {
+    bOpened = m_comm->Open(strPort, 38400, iTimeoutMs);
+    iNow = GetTimeMs();
+  }
+
+  if (!bOpened)
   {
     AddLog(CEC_LOG_ERROR, "could not open a connection");
     return false;
@@ -96,7 +111,7 @@ void CLibCEC::Close(void)
     m_comm->Close();
 }
 
-int CLibCEC::FindAdapters(std::vector<cec_adapter> &deviceList, const char *strDevicePath /* = NULL */)
+int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
 {
   CStdString strDebug;
   if (strDevicePath)
@@ -105,7 +120,7 @@ int CLibCEC::FindAdapters(std::vector<cec_adapter> &deviceList, const char *strD
     strDebug.Format("trying to autodetect all CEC adapters");
   AddLog(CEC_LOG_DEBUG, strDebug);
 
-  return CAdapterDetection::FindAdapters(deviceList, strDevicePath);
+  return CAdapterDetection::FindAdapters(deviceList, iBufSize, strDevicePath);
 }
 
 bool CLibCEC::PingAdapter(void)
@@ -118,19 +133,19 @@ bool CLibCEC::StartBootloader(void)
   return m_comm ? m_comm->StartBootloader() : false;
 }
 
-int CLibCEC::GetMinVersion(void)
+int8_t CLibCEC::GetMinVersion(void)
 {
   return CEC_MIN_VERSION;
 }
 
-int CLibCEC::GetLibVersion(void)
+int8_t CLibCEC::GetLibVersion(void)
 {
   return CEC_LIB_VERSION;
 }
 
 bool CLibCEC::GetNextLogMessage(cec_log_message *message)
 {
-  return m_logBuffer.Pop(*message);
+  return (m_logBuffer.Pop(*message));
 }
 
 bool CLibCEC::GetNextKeypress(cec_keypress *key)
@@ -143,7 +158,7 @@ bool CLibCEC::GetNextCommand(cec_command *command)
   return m_commandBuffer.Pop(*command);
 }
 
-bool CLibCEC::Transmit(const cec_frame &data, bool bWaitForAck /* = true */)
+bool CLibCEC::Transmit(const cec_command &data, bool bWaitForAck /* = true */)
 {
   return m_cec ? m_cec->Transmit(data, bWaitForAck) : false;
 }
@@ -153,6 +168,11 @@ bool CLibCEC::SetLogicalAddress(cec_logical_address iLogicalAddress)
   return m_cec ? m_cec->SetLogicalAddress(iLogicalAddress) : false;
 }
 
+bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress)
+{
+  return m_cec ? m_cec->SetPhysicalAddress(iPhysicalAddress) : false;
+}
+
 bool CLibCEC::PowerOnDevices(cec_logical_address address /* = CECDEVICE_TV */)
 {
   return m_cec ? m_cec->PowerOnDevices(address) : false;
@@ -173,12 +193,26 @@ bool CLibCEC::SetInactiveView(void)
   return m_cec ? m_cec->SetInactiveView() : false;
 }
 
+bool CLibCEC::SetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage)
+{
+  return m_cec ? m_cec->SetOSDString(iLogicalAddress, duration, strMessage) : false;
+}
+
+bool CLibCEC::SwitchMonitoring(bool bEnable)
+{
+  return m_cec ? m_cec->SwitchMonitoring(bEnable) : false;
+}
+
 void CLibCEC::AddLog(cec_log_level level, const string &strMessage)
 {
-  cec_log_message message;
-  message.level = level;
-  message.message.assign(strMessage.c_str());
-  m_logBuffer.Push(message);
+  if (m_cec)
+  {
+    cec_log_message message;
+    message.level = level;
+    message.time = GetTimeMs() - m_iStartTime;
+    snprintf(message.message, sizeof(message.message), "%s", strMessage.c_str());
+    m_logBuffer.Push(message);
+  }
 }
 
 void CLibCEC::AddKey(void)
@@ -186,6 +220,7 @@ void CLibCEC::AddKey(void)
   if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
   {
     cec_keypress key;
+
     key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
     key.keycode = m_iCurrentButton;
     m_keyBuffer.Push(key);
@@ -194,18 +229,12 @@ void CLibCEC::AddKey(void)
   }
 }
 
-void CLibCEC::AddCommand(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_frame *parameters)
+void CLibCEC::AddCommand(const cec_command &command)
 {
-  cec_command command;
-  command.source       = source;
-  command.destination  = destination;
-  command.opcode       = opcode;
-  if (parameters)
-    command.parameters = *parameters;
   if (m_commandBuffer.Push(command))
   {
     CStdString strDebug;
-    strDebug.Format("stored command '%d' in the command buffer. buffer size = %d", opcode, m_commandBuffer.Size());
+    strDebug.Format("stored command '%2x' in the command buffer. buffer size = %d", command.opcode, m_commandBuffer.Size());
     AddLog(CEC_LOG_DEBUG, strDebug);
   }
   else
@@ -227,9 +256,23 @@ void CLibCEC::SetCurrentButton(cec_user_control_code iButtonCode)
 {
   m_iCurrentButton = iButtonCode;
   m_buttontime = GetTimeMs();
+
+  /* push keypress to the keybuffer with 0 duration.
+     push another press to the keybuffer with the duration set when the button is released */
+  cec_keypress key;
+  key.duration = 0;
+  key.keycode = m_iCurrentButton;
+  m_keyBuffer.Push(key);
 }
 
-DECLSPEC void * CECCreate(const char *strDeviceName, CEC::cec_logical_address iLogicalAddress /*= CEC::CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
+void * CECCreate(const char *strDeviceName, CEC::cec_logical_address iLogicalAddress /*= CEC::CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
 {
   return static_cast< void* > (new CLibCEC(strDeviceName, iLogicalAddress, iPhysicalAddress));
 }
+
+void CECDestroy(CEC::ICECAdapter *instance)
+{
+  CLibCEC *lib = static_cast< CLibCEC* > (instance);
+  if (lib)
+    delete lib;
+}