cec: refactor CEC read/write. keep a single lock for all writes, not one per device
authorLars Op den Kamp <lars@opdenkamp.eu>
Mon, 5 Dec 2011 21:59:11 +0000 (22:59 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Mon, 5 Dec 2011 21:59:11 +0000 (22:59 +0100)
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/LibCEC.cpp
src/lib/devices/CECAudioSystem.cpp
src/lib/devices/CECAudioSystem.h
src/lib/devices/CECBusDevice.cpp
src/lib/devices/CECBusDevice.h
src/lib/devices/CECPlaybackDevice.cpp
src/lib/implementations/CECCommandHandler.cpp
src/lib/implementations/CECCommandHandler.h
src/lib/implementations/SLCommandHandler.cpp

index 3db53f62d083b5d42dd0d00e837a76edeacadfec..81f501bf752c0183e906d31fd59ed6adb7818575 100644 (file)
@@ -572,29 +572,29 @@ bool CCECProcessor::PollDevice(cec_logical_address iAddress)
   return false;
 }
 
-uint8_t CCECProcessor::VolumeUp(bool bWait /* = true */)
+uint8_t CCECProcessor::VolumeUp(void)
 {
   uint8_t status = 0;
   if (IsActiveDevice(CECDEVICE_AUDIOSYSTEM))
-    status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeUp(bWait);
+    status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeUp();
 
   return status;
 }
 
-uint8_t CCECProcessor::VolumeDown(bool bWait /* = true */)
+uint8_t CCECProcessor::VolumeDown(void)
 {
   uint8_t status = 0;
   if (IsActiveDevice(CECDEVICE_AUDIOSYSTEM))
-    status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeDown(bWait);
+    status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeDown();
 
   return status;
 }
 
-uint8_t CCECProcessor::MuteAudio(bool bWait /* = true */)
+uint8_t CCECProcessor::MuteAudio(void)
 {
   uint8_t status = 0;
   if (IsActiveDevice(CECDEVICE_AUDIOSYSTEM))
-    status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->MuteAudio(bWait);
+    status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->MuteAudio();
 
   return status;
 }
@@ -952,14 +952,14 @@ bool CCECProcessor::SetAckMask(uint16_t iMask)
   return bReturn;
 }
 
-bool CCECProcessor::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = false */)
+bool CCECProcessor::SendKeypress(cec_logical_address iDestination, cec_user_control_code key)
 {
-  return m_busDevices[iDestination]->SendKeypress(key, bWait);
+  return m_busDevices[iDestination]->SendKeypress(key);
 }
 
-bool CCECProcessor::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = false */)
+bool CCECProcessor::SendKeyRelease(cec_logical_address iDestination)
 {
-  return m_busDevices[iDestination]->SendKeyRelease(bWait);
+  return m_busDevices[iDestination]->SendKeyRelease();
 }
 
 const char *CCECProcessor::ToString(const cec_menu_state state)
index 37a77392f195d8e35318803dbf50792fb1ef693b..2a8a589f92108d057699e6e369cb342fa6d507e5 100644 (file)
@@ -86,11 +86,11 @@ namespace CEC
       virtual bool SetStreamPath(uint16_t iStreamPath);
       virtual bool SwitchMonitoring(bool bEnable);
       virtual bool PollDevice(cec_logical_address iAddress);
-      virtual uint8_t VolumeUp(bool bWait = true);
-      virtual uint8_t VolumeDown(bool bWait = true);
-      virtual uint8_t MuteAudio(bool bWait = true);
-      virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = false);
-      virtual bool SendKeyRelease(cec_logical_address iDestination, bool bWait = false);
+      virtual uint8_t VolumeUp(void);
+      virtual uint8_t VolumeDown(void);
+      virtual uint8_t MuteAudio(void);
+      virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key);
+      virtual bool SendKeyRelease(cec_logical_address iDestination);
       virtual bool EnablePhysicalAddressDetection(void) { return false; };
       void SetStandardLineTimeout(uint8_t iTimeout);
       void SetRetryLineTimeout(uint8_t iTimeout);
@@ -125,6 +125,7 @@ namespace CEC
       virtual bool PingAdapter(void);
 
       CCECBusDevice *m_busDevices[16];
+      CMutex         m_transmitMutex;
 
   private:
       void ScanCECBus(void);
index 4a63051b885ad092949e2169af6bc94df3ec53cd..3ed7ace2b6946491be9ad45ae9dfbe2f6dfcca17 100644 (file)
@@ -262,14 +262,14 @@ bool CLibCEC::IsActiveDeviceType(cec_device_type type)
 uint8_t CLibCEC::VolumeUp(bool bWait /* = true */)
 {
   if (m_cec)
-    return m_cec->VolumeUp(bWait);
+    return m_cec->VolumeUp();
   return 0;
 }
 
 uint8_t CLibCEC::VolumeDown(bool bWait /* = true */)
 {
   if (m_cec)
-    return m_cec->VolumeDown(bWait);
+    return m_cec->VolumeDown();
   return 0;
 }
 
@@ -277,21 +277,21 @@ uint8_t CLibCEC::VolumeDown(bool bWait /* = true */)
 uint8_t CLibCEC::MuteAudio(bool bWait /* = true */)
 {
   if (m_cec)
-    return m_cec->MuteAudio(bWait);
+    return m_cec->MuteAudio();
   return 0;
 }
 
 bool CLibCEC::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = false */)
 {
   if (m_cec)
-    return m_cec->SendKeypress(iDestination, key, bWait);
+    return m_cec->SendKeypress(iDestination, key);
   return false;
 }
 
 bool CLibCEC::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = false */)
 {
   if (m_cec)
-    return m_cec->SendKeyRelease(iDestination, bWait);
+    return m_cec->SendKeyRelease(iDestination);
   return false;
 }
 
index 99b581e3798701a33b15d24a19f965b8796337b6..38bdb47cbea23becd2f89ab61ec0d7748baa4200 100644 (file)
@@ -80,68 +80,68 @@ bool CCECAudioSystem::SetSystemAudioModeStatus(const cec_system_audio_status mod
 
 bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, m_audioStatus);
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_AUDIO_STATUS);
-  command.parameters.PushBack(m_audioStatus);
+  uint8_t state;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, m_audioStatus);
+    AddLog(CEC_LOG_NOTICE, strLog);
+    state = m_audioStatus;
+  }
 
-  return m_processor->Transmit(command);
+  return m_handler->TransmitAudioStatus(m_iLogicalAddress, dest, state);
 }
 
 bool CCECAudioSystem::TransmitSetSystemAudioMode(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %x -> %x: set system audio mode '%2x'", m_iLogicalAddress, dest, m_audioStatus);
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_SYSTEM_AUDIO_MODE);
-  command.parameters.PushBack((uint8_t)m_systemAudioStatus);
+  cec_system_audio_status state;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %x -> %x: set system audio mode '%2x'", m_iLogicalAddress, dest, m_audioStatus);
+    AddLog(CEC_LOG_NOTICE, strLog);
+    state = m_systemAudioStatus;
+  }
 
-  return m_processor->Transmit(command);
+  return m_handler->TransmitSetSystemAudioMode(m_iLogicalAddress, dest, state);
 }
 
 bool CCECAudioSystem::TransmitSystemAudioModeStatus(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, ToString(m_systemAudioStatus));
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS);
-  command.parameters.PushBack((uint8_t) m_systemAudioStatus);
+  cec_system_audio_status state;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, ToString(m_systemAudioStatus));
+    AddLog(CEC_LOG_NOTICE, strLog);
+    state = m_systemAudioStatus;
+  }
 
-  return m_processor->Transmit(command);
+  return m_handler->TransmitSystemAudioModeStatus(m_iLogicalAddress, dest, state);
 }
 
-uint8_t CCECAudioSystem::VolumeUp(bool bWait /* = true */)
+uint8_t CCECAudioSystem::VolumeUp(void)
 {
   if (SendKeypress(CEC_USER_CONTROL_CODE_VOLUME_UP))
-    SendKeyRelease(bWait);
+    SendKeyRelease();
 
   CLockObject lock(&m_mutex);
   return m_audioStatus;
 }
 
-uint8_t CCECAudioSystem::VolumeDown(bool bWait /* = true */)
+uint8_t CCECAudioSystem::VolumeDown(void)
 {
   if (SendKeypress(CEC_USER_CONTROL_CODE_VOLUME_DOWN))
-    SendKeyRelease(bWait);
+    SendKeyRelease();
 
   CLockObject lock(&m_mutex);
   return m_audioStatus;
 }
 
-uint8_t CCECAudioSystem::MuteAudio(bool bWait /* = true */)
+uint8_t CCECAudioSystem::MuteAudio(void)
 {
   if (SendKeypress(CEC_USER_CONTROL_CODE_MUTE))
-    SendKeyRelease(bWait);
+    SendKeyRelease();
 
   CLockObject lock(&m_mutex);
   return m_audioStatus;
index 7f2254952c3f2d760cf9145a8d4efab2c994226d..291b0ecadc09d39bab87f7d9528aaf5452f75136 100644 (file)
@@ -47,9 +47,9 @@ namespace CEC
     virtual bool TransmitSetSystemAudioMode(cec_logical_address dest);
     virtual bool TransmitSystemAudioModeStatus(cec_logical_address dest);
 
-    virtual uint8_t VolumeUp(bool bWait = true);
-    virtual uint8_t VolumeDown(bool bWait = true);
-    virtual uint8_t MuteAudio(bool bWait = true);
+    virtual uint8_t VolumeUp(void);
+    virtual uint8_t VolumeDown(void);
+    virtual uint8_t MuteAudio(void);
 
     virtual bool TransmitActiveSource(void) { return false; }
 
index fc44ebddb2b8294b3b956760074db385c0b55ed5..a794dc0e407b4d5308bb725afd8d79b130cd406b 100644 (file)
@@ -55,8 +55,7 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi
   m_iLastCommandSent(0),
   m_iLastActive(0),
   m_cecVersion(CEC_VERSION_UNKNOWN),
-  m_deviceStatus(CEC_DEVICE_STATUS_UNKNOWN),
-  m_iTransmitTimeout(1000)
+  m_deviceStatus(CEC_DEVICE_STATUS_UNKNOWN)
 {
   m_handler = new CCECCommandHandler(this);
 
@@ -70,7 +69,6 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi
 
 CCECBusDevice::~CCECBusDevice(void)
 {
-  m_condition.Broadcast();
   delete m_handler;
 }
 
@@ -81,20 +79,26 @@ void CCECBusDevice::AddLog(cec_log_level level, const CStdString &strMessage)
 
 bool CCECBusDevice::HandleCommand(const cec_command &command)
 {
-  CLockObject lock(&m_transmitMutex);
-  m_iLastActive = GetTimeMs();
+  {
+    CLockObject lock(&m_writeMutex);
+    m_iLastActive = GetTimeMs();
+  }
+
   m_handler->HandleCommand(command);
-  if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+
   {
-    if (m_deviceStatus != CEC_DEVICE_STATUS_PRESENT)
+    CLockObject lock(&m_writeMutex);
+    if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
     {
-      CStdString strLog;
-      strLog.Format("device %s (%x) status changed to present after command %s", GetLogicalAddressName(), (uint8_t)GetLogicalAddress(), ToString(command.opcode));
-      AddLog(CEC_LOG_DEBUG, strLog);
+      if (m_deviceStatus != CEC_DEVICE_STATUS_PRESENT)
+      {
+        CStdString strLog;
+        strLog.Format("device %s (%x) status changed to present after command %s", GetLogicalAddressName(), (uint8_t)GetLogicalAddress(), ToString(command.opcode));
+        AddLog(CEC_LOG_DEBUG, strLog);
+      }
+      m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
     }
-    m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
   }
-  m_condition.Signal();
   return true;
 }
 
@@ -104,9 +108,7 @@ bool CCECBusDevice::PowerOn(void)
   strLog.Format("<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
 
-  cec_command command;
-  cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_IMAGE_VIEW_ON, m_iTransmitTimeout);
-  if (m_processor->Transmit(command))
+  if (m_handler->TransmitPowerOn(GetMyLogicalAddress(), m_iLogicalAddress))
   {
     {
       CLockObject lock(&m_mutex);
@@ -115,8 +117,8 @@ bool CCECBusDevice::PowerOn(void)
     cec_power_status status = GetPowerStatus();
     if (status == CEC_POWER_STATUS_STANDBY || status == CEC_POWER_STATUS_UNKNOWN)
     {
-      SendKeypress(CEC_USER_CONTROL_CODE_POWER, true);
-      return SendKeyRelease(false);
+      SendKeypress(CEC_USER_CONTROL_CODE_POWER);
+      return SendKeyRelease();
     }
     return true;
   }
@@ -130,10 +132,7 @@ bool CCECBusDevice::Standby(void)
   strLog.Format("<< putting '%s' (%X) in standby mode", GetLogicalAddressName(), m_iLogicalAddress);
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
 
-  cec_command command;
-  cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_STANDBY, m_iTransmitTimeout);
-
-  return m_processor->Transmit(command);
+  return m_handler->TransmitStandby(GetMyLogicalAddress(), m_iLogicalAddress);
 }
 
 /** @name Getters */
@@ -156,11 +155,8 @@ bool CCECBusDevice::RequestCecVersion(void)
     CStdString strLog;
     strLog.Format("<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
-    cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION, m_iTransmitTimeout);
-    CLockObject lock(&m_transmitMutex);
-    if (m_processor->Transmit(command))
-      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+
+    bReturn = m_handler->TransmitRequestCecVersion(GetMyLogicalAddress(), m_iLogicalAddress);
   }
   return bReturn;
 }
@@ -193,11 +189,7 @@ bool CCECBusDevice::RequestMenuLanguage(void)
     CStdString strLog;
     strLog.Format("<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
-    cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_MENU_LANGUAGE, m_iTransmitTimeout);
-    CLockObject lock(&m_transmitMutex);
-    if (m_processor->Transmit(command))
-      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+    bReturn = m_handler->TransmitRequestMenuLanguage(GetMyLogicalAddress(), m_iLogicalAddress);
   }
   return bReturn;
 }
@@ -231,11 +223,7 @@ bool CCECBusDevice::RequestOSDName(void)
     CStdString strLog;
     strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
-    cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_OSD_NAME, m_iTransmitTimeout);
-    CLockObject lock(&m_transmitMutex);
-    if (m_processor->Transmit(command))
-      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+    bReturn = m_handler->TransmitRequestOSDName(GetMyLogicalAddress(), m_iLogicalAddress);
   }
   return bReturn;
 }
@@ -261,11 +249,7 @@ bool CCECBusDevice::RequestPhysicalAddress(void)
     CStdString strLog;
     strLog.Format("<< requesting physical address of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
-    cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS, m_iTransmitTimeout);
-    CLockObject lock(&m_transmitMutex);
-    if (m_processor->Transmit(command))
-      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+    bReturn = m_handler->TransmitRequestPhysicalAddress(GetMyLogicalAddress(), m_iLogicalAddress);
   }
   return bReturn;
 }
@@ -288,11 +272,7 @@ bool CCECBusDevice::RequestPowerStatus(void)
     CStdString strLog;
     strLog.Format("<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
-    cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS, m_iTransmitTimeout);
-    CLockObject lock(&m_transmitMutex);
-    if (m_processor->Transmit(command))
-      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+    bReturn = m_handler->TransmitRequestPowerStatus(GetMyLogicalAddress(), m_iLogicalAddress);
   }
   return bReturn;
 }
@@ -315,12 +295,7 @@ bool CCECBusDevice::RequestVendorId(void)
     CStdString strLog;
     strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
-    cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
-
-    CLockObject lock(&m_transmitMutex);
-    if (m_processor->Transmit(command))
-      bReturn = m_condition.Wait(&m_transmitMutex, 1000);
+    bReturn = m_handler->TransmitRequestVendorId(GetMyLogicalAddress(), m_iLogicalAddress);
   }
   return bReturn;
 }
@@ -566,7 +541,7 @@ void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus)
   }
 }
 
-void CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true */)
+bool CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true */)
 {
   bool bVendorChanged(false);
 
@@ -605,6 +580,8 @@ void CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true
   CStdString strLog;
   strLog.Format("%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_vendor), m_vendor);
   m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+
+  return bVendorChanged;
 }
 //@}
 
@@ -612,135 +589,117 @@ void CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true
 //@{
 bool CCECBusDevice::TransmitActiveSource(void)
 {
-  CLockObject lock(&m_writeMutex);
-  if (m_powerStatus != CEC_POWER_STATUS_ON)
-  {
-    CStdString strLog;
-    strLog.Format("<< %s (%X) is not powered on", GetLogicalAddressName(), m_iLogicalAddress);
-    AddLog(CEC_LOG_DEBUG, strLog);
-  }
-  else if (m_bActiveSource)
-  {
-    CStdString strLog;
-    strLog.Format("<< %s (%X) -> broadcast (F): active source (%4x)", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
-    AddLog(CEC_LOG_NOTICE, strLog);
+  bool bSendActiveSource(false);
 
-    cec_command command;
-    cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE, m_iTransmitTimeout);
-    command.parameters.PushBack((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF));
-    command.parameters.PushBack((uint8_t) (m_iPhysicalAddress & 0xFF));
-
-    lock.Leave();
-    return m_processor->Transmit(command);
-  }
-  else
   {
-    CStdString strLog;
-    strLog.Format("<< %s (%X) is not the active source", GetLogicalAddressName(), m_iLogicalAddress);
-    AddLog(CEC_LOG_DEBUG, strLog);
+    CLockObject lock(&m_writeMutex);
+    if (m_powerStatus != CEC_POWER_STATUS_ON)
+    {
+      CStdString strLog;
+      strLog.Format("<< %s (%X) is not powered on", GetLogicalAddressName(), m_iLogicalAddress);
+      AddLog(CEC_LOG_DEBUG, strLog);
+    }
+    else if (m_bActiveSource)
+    {
+      CStdString strLog;
+      strLog.Format("<< %s (%X) -> broadcast (F): active source (%4x)", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
+      AddLog(CEC_LOG_NOTICE, strLog);
+      bSendActiveSource = true;
+    }
+    else
+    {
+      CStdString strLog;
+      strLog.Format("<< %s (%X) is not the active source", GetLogicalAddressName(), m_iLogicalAddress);
+      AddLog(CEC_LOG_DEBUG, strLog);
+    }
   }
 
-  return false;
+  return bSendActiveSource ? m_handler->TransmitActiveSource(m_iLogicalAddress, m_iPhysicalAddress) : false;
 }
 
 bool CCECBusDevice::TransmitCECVersion(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion));
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_CEC_VERSION, m_iTransmitTimeout);
-  command.parameters.PushBack((uint8_t)m_cecVersion);
+  cec_version version;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion));
+    AddLog(CEC_LOG_NOTICE, strLog);
+    version = m_cecVersion;
+  }
 
-  lock.Leave();
-  return m_processor->Transmit(command);
+  return m_handler->TransmitCECVersion(m_iLogicalAddress, dest, version);
 }
 
 bool CCECBusDevice::TransmitInactiveSource(void)
 {
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> broadcast (F): inactive source", GetLogicalAddressName(), m_iLogicalAddress);
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE, m_iTransmitTimeout);
-  command.parameters.PushBack((m_iPhysicalAddress >> 8) & 0xFF);
-  command.parameters.PushBack(m_iPhysicalAddress & 0xFF);
+  uint16_t iPhysicalAddress;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> broadcast (F): inactive source", GetLogicalAddressName(), m_iLogicalAddress);
+    AddLog(CEC_LOG_NOTICE, strLog);
+    iPhysicalAddress = m_iPhysicalAddress;
+  }
 
-  return m_processor->Transmit(command);
+  return m_handler->TransmitInactiveSource(m_iLogicalAddress, iPhysicalAddress);
 }
 
 bool CCECBusDevice::TransmitMenuState(cec_logical_address dest)
 {
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> %s (%X): menu state '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_menuState));
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_MENU_STATUS, m_iTransmitTimeout);
-  command.parameters.PushBack((uint8_t)m_menuState);
+  cec_menu_state menuState;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> %s (%X): menu state '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_menuState));
+    AddLog(CEC_LOG_NOTICE, strLog);
+    menuState = m_menuState;
+  }
 
-  return m_processor->Transmit(command);
+  return m_handler->TransmitMenuState(m_iLogicalAddress, dest, menuState);
 }
 
 bool CCECBusDevice::TransmitOSDName(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str());
-  AddLog(CEC_LOG_NOTICE, strLog.c_str());
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_NAME, m_iTransmitTimeout);
-  for (unsigned int iPtr = 0; iPtr < m_strDeviceName.length(); iPtr++)
-    command.parameters.PushBack(m_strDeviceName.at(iPtr));
+  CStdString strDeviceName;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str());
+    AddLog(CEC_LOG_NOTICE, strLog.c_str());
+    strDeviceName = m_strDeviceName;
+  }
 
-  lock.Leave();
-  return m_processor->Transmit(command);
+  return m_handler->TransmitOSDName(m_iLogicalAddress, dest, strDeviceName);
 }
 
 bool CCECBusDevice::TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage)
 {
-  CLockObject lock(&m_writeMutex);
   CStdString strLog;
   strLog.Format("<< %s (%X) -> %s (%X): display OSD message '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, strMessage);
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_STRING, m_iTransmitTimeout);
-  command.parameters.PushBack((uint8_t)duration);
-
-  unsigned int iLen = strlen(strMessage);
-  if (iLen > 13) iLen = 13;
-
-  for (unsigned int iPtr = 0; iPtr < iLen; iPtr++)
-    command.parameters.PushBack(strMessage[iPtr]);
-
-  lock.Leave();
-  return m_processor->Transmit(command);
+  return m_handler->TransmitOSDString(m_iLogicalAddress, dest, duration, strMessage);
 }
 
 bool CCECBusDevice::TransmitPhysicalAddress(void)
 {
-  CLockObject lock(&m_writeMutex);
-
-  if (m_iPhysicalAddress == 0xffff)
-    return false;
+  uint16_t iPhysicalAddress;
+  cec_device_type type;
+  {
+    CLockObject lock(&m_writeMutex);
+    if (m_iPhysicalAddress == 0xffff)
+      return false;
 
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> broadcast (F): physical adddress %4x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
-  AddLog(CEC_LOG_NOTICE, strLog.c_str());
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> broadcast (F): physical adddress %4x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
+    AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS, m_iTransmitTimeout);
-  command.parameters.PushBack((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF));
-  command.parameters.PushBack((uint8_t) (m_iPhysicalAddress & 0xFF));
-  command.parameters.PushBack((uint8_t) (m_type));
+    iPhysicalAddress = m_iPhysicalAddress;
+    type = m_type;
+  }
 
-  lock.Leave();
-  return m_processor->Transmit(command);
+  return m_handler->TransmitPhysicalAddress(m_iLogicalAddress, iPhysicalAddress, type);
 }
 
 bool CCECBusDevice::TransmitPoll(cec_logical_address dest)
@@ -749,106 +708,69 @@ bool CCECBusDevice::TransmitPoll(cec_logical_address dest)
   if (dest == CECDEVICE_UNKNOWN)
     dest = m_iLogicalAddress;
 
-  CLockObject lock(&m_writeMutex);
-
   CStdString strLog;
   strLog.Format("<< %s (%X) -> %s (%X): POLL", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_NONE, m_iTransmitTimeout);
-  command.retries = 0;
-
-  {
-    CLockObject lock(&m_transmitMutex);
-    bReturn = m_processor->Transmit(command);
-  }
-
+  bReturn = m_handler->TransmitPoll(m_iLogicalAddress, dest);
   AddLog(CEC_LOG_DEBUG, bReturn ? ">> POLL sent" : ">> POLL not sent");
+
   if (bReturn)
+  {
+    CLockObject lock(&m_writeMutex);
     m_iLastActive = GetTimeMs();
+  }
 
   return bReturn;
 }
 
 bool CCECBusDevice::TransmitPowerState(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus));
-  AddLog(CEC_LOG_NOTICE, strLog.c_str());
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_POWER_STATUS, m_iTransmitTimeout);
-  command.parameters.PushBack((uint8_t) m_powerStatus);
+  cec_power_status state;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus));
+    AddLog(CEC_LOG_NOTICE, strLog.c_str());
+    state = m_powerStatus;
+  }
 
-  lock.Leave();
-  return m_processor->Transmit(command);
+  return m_handler->TransmitPowerState(m_iLogicalAddress, dest, state);
 }
 
 bool CCECBusDevice::TransmitVendorID(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  if (m_vendor == CEC_VENDOR_UNKNOWN)
+  uint64_t iVendorId;
+  {
+    CLockObject lock(&m_writeMutex);
+    iVendorId = (uint64_t)m_vendor;
+  }
+
+  if (iVendorId == CEC_VENDOR_UNKNOWN)
   {
     CStdString strLog;
     strLog.Format("<< %s (%X) -> %s (%X): vendor id feature abort", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
     AddLog(CEC_LOG_NOTICE, strLog);
 
-    lock.Leave();
     m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
     return false;
   }
   else
   {
     CStdString strLog;
-    strLog.Format("<< %s (%X) -> %s (%X): vendor id %s (%x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_vendor), (uint64_t)m_vendor);
+    strLog.Format("<< %s (%X) -> %s (%X): vendor id %s (%x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString((cec_vendor_id)iVendorId), iVendorId);
     AddLog(CEC_LOG_NOTICE, strLog);
 
-    cec_command command;
-    cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
-
-    command.parameters.PushBack((uint8_t) (((uint64_t)m_vendor >> 16) & 0xFF));
-    command.parameters.PushBack((uint8_t) (((uint64_t)m_vendor >> 8) & 0xFF));
-    command.parameters.PushBack((uint8_t) ((uint64_t)m_vendor & 0xFF));
-
-    lock.Leave();
-    return m_processor->Transmit(command);
+    return m_handler->TransmitVendorID(m_iLogicalAddress, iVendorId);
   }
 }
 
-bool CCECBusDevice::SendKeypress(cec_user_control_code key, bool bWait /* = false */)
+bool CCECBusDevice::SendKeypress(cec_user_control_code key)
 {
-  CLockObject lock(&m_transmitMutex);
-  cec_command command;
-  cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_PRESSED, m_iTransmitTimeout);
-  command.parameters.PushBack((uint8_t)key);
-
-  if (bWait)
-  {
-    if (m_processor->Transmit(command))
-      return m_condition.Wait(&m_transmitMutex, 1000);
-    return false;
-  }
-
-  return m_processor->Transmit(command);
+  return m_handler->SendKeypress(m_processor->GetLogicalAddress(), m_iLogicalAddress, key);
 }
 
-bool CCECBusDevice::SendKeyRelease(bool bWait /* = false */)
+bool CCECBusDevice::SendKeyRelease(void)
 {
-  CLockObject lock(&m_transmitMutex);
-  cec_command command;
-  cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_RELEASE, m_iTransmitTimeout);
-
-  if (bWait)
-  {
-    if (m_processor->Transmit(command))
-      return m_condition.Wait(&m_transmitMutex, 1000);
-    return false;
-  }
-  else
-  {
-    return m_processor->Transmit(command);
-  }
+  return m_handler->SendKeyRelease(m_processor->GetLogicalAddress(), m_iLogicalAddress);
 }
 //@}
index eb48b343cea0b96c97141e4fce809bd3e3ee9b3a..98e9431aa8adee0487feb120708cd03da0233f50 100644 (file)
@@ -69,7 +69,6 @@ namespace CEC
     virtual cec_device_type       GetType(void) const { return m_type; }
     virtual cec_vendor_id         GetVendorId(void);
     virtual const char *          GetVendorName(void);
-    virtual int32_t               GetTransmitTimeout(void) const { return m_iTransmitTimeout; }
     virtual bool                  MyLogicalAddressContains(cec_logical_address address) const;
     virtual cec_bus_device_status GetStatus(bool bForcePoll = false);
 
@@ -91,9 +90,8 @@ namespace CEC
     virtual void SetMenuLanguage(const cec_menu_language &menuLanguage);
     virtual void SetOSDName(CStdString strName);
     virtual void SetMenuState(const cec_menu_state state);
-    virtual void SetVendorId(uint64_t iVendorId, bool bInitHandler = true);
+    virtual bool SetVendorId(uint64_t iVendorId, bool bInitHandler = true);
     virtual void SetPowerStatus(const cec_power_status powerStatus);
-    virtual void SetTransmitTimeout(uint32_t iTimeout) { m_iTransmitTimeout = iTimeout; }
 
     virtual bool TransmitActiveSource(void);
     virtual bool TransmitCECVersion(cec_logical_address dest);
@@ -105,8 +103,8 @@ namespace CEC
     virtual bool TransmitPowerState(cec_logical_address dest);
     virtual bool TransmitPoll(cec_logical_address dest);
     virtual bool TransmitVendorID(cec_logical_address dest);
-    virtual bool SendKeypress(cec_user_control_code key, bool bWait = true);
-    virtual bool SendKeyRelease(bool bWait = true);
+    virtual bool SendKeypress(cec_user_control_code key);
+    virtual bool SendKeyRelease(void);
 
   protected:
     bool NeedsPoll(void);
@@ -127,10 +125,7 @@ namespace CEC
     uint64_t              m_iLastActive;
     cec_version           m_cecVersion;
     cec_bus_device_status m_deviceStatus;
-    int32_t               m_iTransmitTimeout;
-    CMutex                m_transmitMutex;
     CMutex                m_writeMutex;
     CMutex                m_mutex;
-    CCondition            m_condition;
   };
 };
index 112ebf778513c45cc3a44bf008ea36ebf8f3f2d4..4c90b9fa470c734e7e617aad2cf97363b6693300 100644 (file)
@@ -86,14 +86,14 @@ void CCECPlaybackDevice::SetDeckControlMode(cec_deck_control_mode mode)
 
 bool CCECPlaybackDevice::TransmitDeckStatus(cec_logical_address dest)
 {
-  CLockObject lock(&m_writeMutex);
-  CStdString strLog;
-  strLog.Format("<< %s (%X) -> %s (%X): deck status '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_deckStatus));
-  AddLog(CEC_LOG_NOTICE, strLog);
-
-  cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_DECK_STATUS);
-  command.PushBack((uint8_t)m_deckStatus);
+  cec_deck_info state;
+  {
+    CLockObject lock(&m_writeMutex);
+    CStdString strLog;
+    strLog.Format("<< %s (%X) -> %s (%X): deck status '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_deckStatus));
+    AddLog(CEC_LOG_NOTICE, strLog);
+    state = m_deckStatus;
+  }
 
-  return m_processor->Transmit(command);
+  return m_handler->TransmitDeckStatus(m_iLogicalAddress, dest, state);
 }
index d1a4855c793364ac65981cf7913d6906f3dfac02..8e62eaa2c7be982c96e504255de9faa99b1f2ee9 100644 (file)
 using namespace CEC;
 using namespace std;
 
-CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice)
+CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice) :
+    m_busDevice(busDevice),
+    m_processor(m_busDevice->GetProcessor()),
+    m_iTransmitTimeout(1000)
 {
-  m_busDevice = busDevice;
-  m_processor = m_busDevice->GetProcessor();
+}
+
+CCECCommandHandler::~CCECCommandHandler(void)
+{
+  m_condition.Broadcast();
 }
 
 bool CCECCommandHandler::HandleCommand(const cec_command &command)
 {
-  bool bHandled(true);
+  bool bHandled(true), bHandlerChanged(false);
 
   CStdString strLog;
   strLog.Format(">> %s (%X) -> %s (%X): %s (%2X)", m_processor->ToString(command.initiator), command.initiator, m_processor->ToString(command.destination), command.destination, m_processor->ToString(command.opcode), command.opcode);
@@ -76,7 +82,7 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command)
     HandleGiveDeviceVendorId(command);
     break;
   case CEC_OPCODE_DEVICE_VENDOR_ID:
-    HandleDeviceVendorId(command);
+    bHandlerChanged = HandleDeviceVendorId(command);
     break;
   case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
     HandleDeviceVendorCommandWithId(command);
@@ -156,6 +162,12 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command)
     break;
   }
 
+  if (bHandled && !bHandlerChanged)
+  {
+    CLockObject lock(&m_processor->m_transmitMutex);
+    m_condition.Signal();
+  }
+
   return bHandled;
 }
 
@@ -204,8 +216,7 @@ bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &comm
 
 bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
 {
-  SetVendorId(command);
-  return true;
+  return SetVendorId(command);
 }
 
 bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command)
@@ -611,12 +622,13 @@ CCECBusDevice *CCECCommandHandler::GetDeviceByType(cec_device_type type) const
   return m_processor->GetDeviceByType(type);
 }
 
-void CCECCommandHandler::SetVendorId(const cec_command &command)
+bool CCECCommandHandler::SetVendorId(const cec_command &command)
 {
+  bool bChanged(false);
   if (command.parameters.size < 3)
   {
     m_busDevice->AddLog(CEC_LOG_WARNING, "invalid vendor ID received");
-    return;
+    return bChanged;
   }
 
   uint64_t iVendorId = ((uint64_t)command.parameters[0] << 16) +
@@ -625,7 +637,8 @@ void CCECCommandHandler::SetVendorId(const cec_command &command)
 
   CCECBusDevice *device = GetDevice((cec_logical_address) command.initiator);
   if (device)
-    device->SetVendorId(iVendorId);
+    bChanged = device->SetVendorId(iVendorId);
+  return bChanged;
 }
 
 void CCECCommandHandler::SetPhysicalAddress(cec_logical_address iAddress, uint16_t iNewAddress)
@@ -656,3 +669,233 @@ bool CCECCommandHandler::HandleReceiveFailed(void)
   /* default = error */
   return true;
 }
+
+bool CCECCommandHandler::TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_IMAGE_VIEW_ON, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitStandby(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_STANDBY, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestCecVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_CEC_VERSION, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestMenuLanguage(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_MENU_LANGUAGE, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_OSD_NAME, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF));
+  command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF));
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitCECVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_version cecVersion)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_CEC_VERSION, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t)cecVersion);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitInactiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE, m_iTransmitTimeout);
+  command.parameters.PushBack((iPhysicalAddress >> 8) & 0xFF);
+  command.parameters.PushBack(iPhysicalAddress & 0xFF);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitMenuState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_menu_state menuState)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_MENU_STATUS, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t)menuState);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, CStdString strDeviceName)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_NAME, m_iTransmitTimeout);
+  for (unsigned int iPtr = 0; iPtr < strDeviceName.length(); iPtr++)
+    command.parameters.PushBack(strDeviceName.at(iPtr));
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitOSDString(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_display_control duration, const char *strMessage)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_STRING, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t)duration);
+
+  unsigned int iLen = strlen(strMessage);
+  if (iLen > 13) iLen = 13;
+
+  for (unsigned int iPtr = 0; iPtr < iLen; iPtr++)
+    command.parameters.PushBack(strMessage[iPtr]);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitPhysicalAddress(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, cec_device_type type)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF));
+  command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF));
+  command.parameters.PushBack((uint8_t) (type));
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitPoll(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_NONE, m_iTransmitTimeout);
+  command.retries = 0;
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_POWER_STATUS, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t) state);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitVendorID(const cec_logical_address iInitiator, uint64_t iVendorId)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
+
+  command.parameters.PushBack((uint8_t) (((uint64_t)iVendorId >> 16) & 0xFF));
+  command.parameters.PushBack((uint8_t) (((uint64_t)iVendorId >> 8) & 0xFF));
+  command.parameters.PushBack((uint8_t) ((uint64_t)iVendorId & 0xFF));
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_AUDIO_STATUS, m_iTransmitTimeout);
+  command.parameters.PushBack(state);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_SYSTEM_AUDIO_MODE, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t)state);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t)state);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_DECK_STATUS, m_iTransmitTimeout);
+  command.PushBack((uint8_t)state);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::SendKeypress(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_user_control_code key)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_PRESSED, m_iTransmitTimeout);
+  command.parameters.PushBack((uint8_t)key);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::SendKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+  cec_command command;
+  cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_RELEASE, m_iTransmitTimeout);
+
+  return Transmit(command);
+}
+
+bool CCECCommandHandler::Transmit(cec_command &command)
+{
+  CLockObject writeLock(&m_processor->m_transmitMutex);
+  if (m_processor->Transmit(command))
+      return m_condition.Wait(&m_processor->m_transmitMutex, m_iTransmitTimeout);
+
+  return false;
+}
index 383a38613b036311951ad744fc6062f0a9980c6b..58dc67e2cd73cf90b783d9a00ce8ce375cb845f4 100644 (file)
@@ -33,6 +33,8 @@
 
 #include <cectypes.h>
 #include <vector>
+#include "../util/StdString.h"
+#include "../platform/threads.h"
 
 namespace CEC
 {
@@ -43,7 +45,7 @@ namespace CEC
   {
   public:
     CCECCommandHandler(CCECBusDevice *busDevice);
-    virtual ~CCECCommandHandler(void) {};
+    virtual ~CCECCommandHandler(void);
 
     virtual bool HandleCommand(const cec_command &command);
     virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; };
@@ -52,6 +54,31 @@ namespace CEC
 
     virtual bool InitHandler(void) { return true; }
 
+    virtual bool TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitStandby(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitRequestCecVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitRequestMenuLanguage(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress);
+    virtual bool TransmitCECVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_version cecVersion);
+    virtual bool TransmitInactiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress);
+    virtual bool TransmitMenuState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_menu_state menuState);
+    virtual bool TransmitOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, CStdString strDeviceName);
+    virtual bool TransmitOSDString(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_display_control duration, const char *strMessage);
+    virtual bool TransmitPhysicalAddress(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, cec_device_type type);
+    virtual bool TransmitPoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+    virtual bool TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state);
+    virtual bool TransmitVendorID(const cec_logical_address iInitiator, uint64_t iVendorId);
+    virtual bool TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state);
+    virtual bool TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state);
+    virtual bool TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state);
+    virtual bool TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state);
+    virtual bool SendKeypress(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_user_control_code key);
+    virtual bool SendKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+
   protected:
     virtual bool HandleActiveSource(const cec_command &command);
     virtual bool HandleDeckControl(const cec_command &command);
@@ -91,10 +118,14 @@ namespace CEC
     virtual CCECBusDevice *GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const;
     virtual CCECBusDevice *GetDeviceByType(cec_device_type type) const;
 
-    virtual void SetVendorId(const cec_command &command);
+    virtual bool SetVendorId(const cec_command &command);
     virtual void SetPhysicalAddress(cec_logical_address iAddress, uint16_t iNewAddress);
 
-    CCECProcessor *m_processor;
+    virtual bool Transmit(cec_command &command);
+
     CCECBusDevice *m_busDevice;
+    CCECProcessor *m_processor;
+    int32_t        m_iTransmitTimeout;
+    CCondition     m_condition;
   };
 };
index e3789c62d07b36bf9c93f92058afe273d5089aa0..bf3ee43006bdf6db6126abc2a3e52012b8d4217e 100644 (file)
@@ -61,11 +61,11 @@ bool CSLCommandHandler::HandleVendorCommand(const cec_command &command)
   {
     /* enable SL */
     cec_command response;
-    cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND, m_busDevice->GetTransmitTimeout());
+    cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND, m_iTransmitTimeout);
     response.PushBack(SL_COMMAND_UNKNOWN_02);
     response.PushBack(SL_COMMAND_UNKNOWN_03);
 
-    m_busDevice->GetProcessor()->Transmit(response);
+    Transmit(response);
     return true;
   }
   else if (command.parameters.size == 2 &&
@@ -73,10 +73,10 @@ bool CSLCommandHandler::HandleVendorCommand(const cec_command &command)
   {
     /* enable SL */
     cec_command response;
-    cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND, m_busDevice->GetTransmitTimeout());
+    cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND, m_iTransmitTimeout);
     response.PushBack(SL_COMMAND_CONNECT_ACCEPT);
     response.PushBack(m_busDevice->GetProcessor()->GetLogicalAddresses().primary);
-    m_busDevice->GetProcessor()->Transmit(response);
+    Transmit(response);
 
     /* set deck status for the playback device */
     TransmitDeckStatus(command.initiator);
@@ -107,12 +107,12 @@ void CSLCommandHandler::TransmitDeckStatus(const cec_logical_address iDestinatio
 bool CSLCommandHandler::TransmitLGVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination)
 {
   cec_command response;
-  cec_command::Format(response, iInitiator, iDestination, CEC_OPCODE_DEVICE_VENDOR_ID, m_busDevice->GetTransmitTimeout());
+  cec_command::Format(response, iInitiator, iDestination, CEC_OPCODE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
   response.parameters.PushBack((uint8_t) (((uint64_t)CEC_VENDOR_LG >> 16) & 0xFF));
   response.parameters.PushBack((uint8_t) (((uint64_t)CEC_VENDOR_LG >> 8) & 0xFF));
   response.parameters.PushBack((uint8_t) ((uint64_t)CEC_VENDOR_LG & 0xFF));
 
-  m_busDevice->GetProcessor()->Transmit(response);
+  Transmit(response);
   return true;
 }
 
@@ -211,8 +211,8 @@ bool CSLCommandHandler::InitHandler(void)
     primary->TransmitPhysicalAddress();
 
     cec_command command;
-    cec_command::Format(command, m_busDevice->GetProcessor()->GetLogicalAddresses().primary, CECDEVICE_TV, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
-    m_busDevice->GetProcessor()->Transmit(command);
+    cec_command::Format(command, m_busDevice->GetProcessor()->GetLogicalAddresses().primary, CECDEVICE_TV, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
+    Transmit(command);
 
     /* LG TVs don't always reply to CEC version requests, so just set it to 1.3a */
     m_busDevice->SetCecVersion(CEC_VERSION_1_3A);
@@ -224,6 +224,9 @@ bool CSLCommandHandler::InitHandler(void)
   snprintf(lang.language, 4, "eng");
   m_busDevice->SetMenuLanguage(lang);
 
+  /* increase the transmit timeout because the tv is keeping the bus busy at times */
+  m_iTransmitTimeout = 5000;
+
   if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
   {
     /* LG TVs only route keypresses when the deck status is set to 0x20 */
@@ -232,9 +235,6 @@ bool CSLCommandHandler::InitHandler(void)
     {
       CCECBusDevice *device = m_busDevice->GetProcessor()->m_busDevices[iPtr];
 
-      /* increase the transmit timeout because the tv is keeping the bus busy at times */
-      device->SetTransmitTimeout(5000);
-
       if (addr[iPtr])
       {
         if (device && (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||