cec: add a Close() method to the interface
authorLars Op den Kamp <lars@opdenkamp.eu>
Thu, 29 Sep 2011 21:27:28 +0000 (23:27 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Thu, 29 Sep 2011 21:27:28 +0000 (23:27 +0200)
include/CECExportsC.h
include/CECExportsCpp.h
src/lib/CECParser.cpp
src/lib/CECParser.h
src/lib/CECParserC.cpp
src/lib/util/threads.cpp

index 5d278f4c63dcae14b3cc3fe4ebc4b48f84f72a7d..8d91fe26ad9010d964a061c45694a84e28c7eba6 100644 (file)
@@ -52,12 +52,6 @@ extern DECLSPEC bool cec_init(const char *strDeviceName, CEC::cec_logical_addres
 extern DECLSPEC bool cec_init(const char *strDeviceName, cec_logical_address iLogicalAddress = CECDEVICE_PLAYBACKDEVICE1, int iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
 #endif
 
-/*!
- * @brief Close the CEC adapter connection.
- * @return True when the device was closed, false otherwise.
- */
-extern DECLSPEC bool cec_close(void);
-
 /*!
  * @brief Open a connection to the CEC adapter.
  * @param strPort The path to the port.
@@ -66,6 +60,12 @@ extern DECLSPEC bool cec_close(void);
  */
 extern DECLSPEC bool cec_open(const char *strPort, int iTimeout);
 
+/*!
+ * @brief Close the connection to the CEC adapter.
+ * @param iTimeout Timeout in ms
+ */
+extern DECLSPEC bool cec_close(int iTimeout);
+
 /*!
  * @brief Ping the CEC adapter.
  * @return True when the ping was succesful, false otherwise.
index fd4ea9fa078c8f99501c93930ffa7d3230c73826..ac00190571599ea9510396faa83f489b25b79cb4 100644 (file)
@@ -41,6 +41,11 @@ namespace CEC
      */
     virtual bool Open(const char *strPort, int iTimeoutMs = 10000) = 0;
 
+    /*!
+     * @see cec_close
+     */
+    virtual bool Close(int iTimeoutMs = 2000) = 0;
+
     /*!
      * @see cec_find_devices
      */
index 547d6268116576529553a8c34d5c2df2e637453e..dad7a0d038a31340caeed08329afcfd58d6645d3 100644 (file)
@@ -67,8 +67,7 @@ CCECParser::CCECParser(const char *strDeviceName, cec_logical_address iLogicalAd
 
 CCECParser::~CCECParser(void)
 {
-  m_bRunning = false;
-  pthread_join(m_thread, NULL);
+  Close(0);
   m_serialport->Close();
   delete m_serialport;
 }
@@ -112,6 +111,24 @@ bool CCECParser::Open(const char *strPort, int iTimeoutMs /* = 10000 */)
   return bReturn;
 }
 
+bool CCECParser::Close(int iTimeoutMs /* = 2000 */)
+{
+  m_bRunning = false;
+  bool bExit(false);
+  if (iTimeoutMs > 0)
+  {
+    bExit = m_exitCondition.Wait(&m_mutex, iTimeoutMs);
+    m_mutex.Unlock();
+  }
+  else
+  {
+    pthread_join(m_thread, NULL);
+    bExit = true;
+  }
+
+  return bExit;
+}
+
 void *CCECParser::ThreadHandler(CCECParser *parser)
 {
   if (parser)
@@ -145,11 +162,15 @@ bool CCECParser::Process(void)
 
   AddLog(CEC_LOG_DEBUG, "reader thread terminated");
   m_bRunning = false;
+  m_exitCondition.Signal();
   return true;
 }
 
 bool CCECParser::Ping(void)
 {
+  if (!m_bRunning)
+    return false;
+
   AddLog(CEC_LOG_DEBUG, "sending ping");
   cec_frame output;
   output.push_back(MSGSTART);
@@ -170,6 +191,9 @@ bool CCECParser::Ping(void)
 
 bool CCECParser::StartBootloader(void)
 {
+  if (!m_bRunning)
+    return false;
+
   AddLog(CEC_LOG_DEBUG, "starting the bootloader");
   cec_frame output;
   output.push_back(MSGSTART);
@@ -193,6 +217,9 @@ uint8_t CCECParser::GetSourceDestination(cec_logical_address destination /* = CE
 
 bool CCECParser::PowerOffDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
 {
+  if (!m_bRunning)
+    return false;
+
   CStdString strLog;
   strLog.Format("powering off devices with logical address %d", (int8_t)address);
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
@@ -204,6 +231,9 @@ bool CCECParser::PowerOffDevices(cec_logical_address address /* = CECDEVICE_BROA
 
 bool CCECParser::PowerOnDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
 {
+  if (!m_bRunning)
+    return false;
+
   CStdString strLog;
   strLog.Format("powering on devices with logical address %d", (int8_t)address);
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
@@ -215,6 +245,9 @@ bool CCECParser::PowerOnDevices(cec_logical_address address /* = CECDEVICE_BROAD
 
 bool CCECParser::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
 {
+  if (!m_bRunning)
+    return false;
+
   CStdString strLog;
   strLog.Format("putting all devices with logical address %d in standby mode", (int8_t)address);
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
@@ -226,6 +259,9 @@ bool CCECParser::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROAD
 
 bool CCECParser::SetActiveView(void)
 {
+  if (!m_bRunning)
+    return false;
+
   AddLog(CEC_LOG_DEBUG, "setting active view");
   cec_frame frame;
   frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
@@ -237,6 +273,9 @@ bool CCECParser::SetActiveView(void)
 
 bool CCECParser::SetInactiveView(void)
 {
+  if (!m_bRunning)
+    return false;
+
   AddLog(CEC_LOG_DEBUG, "setting inactive view");
   cec_frame frame;
   frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
@@ -248,17 +287,17 @@ bool CCECParser::SetInactiveView(void)
 
 bool CCECParser::GetNextLogMessage(cec_log_message *message)
 {
-  return m_logBuffer.Pop(*message);
+  return m_bRunning ? m_logBuffer.Pop(*message) : false;
 }
 
 bool CCECParser::GetNextKeypress(cec_keypress *key)
 {
-  return m_keyBuffer.Pop(*key);
+  return m_bRunning ? m_keyBuffer.Pop(*key) : false;
 }
 
 bool CCECParser::GetNextCommand(cec_command *command)
 {
-  return m_commandBuffer.Pop(*command);
+  return m_bRunning ? m_commandBuffer.Pop(*command) : false;
 }
 //@}
 
@@ -517,7 +556,7 @@ bool CCECParser::ReadFromDevice(int iTimeout)
 void CCECParser::ProcessMessages(void)
 {
   cec_frame msg;
-  while (GetMessage(msg))
+  while (m_bRunning && GetMessage(msg))
     ParseMessage(msg);
 }
 
index 1eca99c5e7fe3f4af940bea2a417862d0dbfc292..be958553cb8ea9b22502d5ac44594064521ca199 100644 (file)
@@ -52,6 +52,7 @@ namespace CEC
       virtual ~CCECParser(void);
 
       virtual bool Open(const char *strPort, int iTimeout = 10000);
+      virtual bool Close(int iTimeoutMs = 2000);
       virtual int  FindDevices(std::vector<cec_device> &deviceList, const char *strDevicePath = NULL);
       virtual bool Ping(void);
       virtual bool StartBootloader(void);
@@ -116,6 +117,7 @@ namespace CEC
       std::string                m_strDeviceName;
       pthread_t                  m_thread;
       CMutex                     m_mutex;
+      CCondition                 m_exitCondition;
       bool                       m_bRunning;
   };
 };
index a4841a0a69b0dec55860b17e65bd3e496338c6d3..b21f1c0b461a3d17358983e3dfdda9afd8ec4821 100644 (file)
@@ -47,13 +47,6 @@ bool cec_init(const char *strDeviceName, cec_logical_address iLogicalAddress /*
   return (cec_parser != NULL);
 }
 
-bool cec_close(void)
-{
-  delete cec_parser;
-  cec_parser = NULL;
-  return true;
-}
-
 bool cec_open(const char *strPort, int iTimeout)
 {
   if (cec_parser)
@@ -61,6 +54,17 @@ bool cec_open(const char *strPort, int iTimeout)
   return false;
 }
 
+bool cec_close(int iTimeout)
+{
+  bool bReturn = false;
+  if (cec_parser)
+    bReturn = cec_parser->Close(iTimeout);
+
+  delete cec_parser;
+  cec_parser = NULL;
+  return bReturn;
+}
+
 bool cec_ping(void)
 {
   if (cec_parser)
index 3bfc1bd75e0cbb96f81f1a99a62836ea4f65490d..3e40c2ba0370288cb668662514a91f52b3f10405 100644 (file)
@@ -115,6 +115,8 @@ bool CCondition::Wait(CMutex *mutex, int64_t iTimeout)
     abstime.tv_sec  = now.tv_sec + (time_t)(iTimeout / 1000);
     abstime.tv_nsec = (long)((iTimeout % (unsigned long)1000) * (unsigned long)1000000);
     m_bSignaled     = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0);
+    if (!m_bSignaled)
+      pthread_mutex_unlock(&mutex->m_mutex);
   }
 
   bool bReturn = m_bSignaled;