X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fdevices%2FCECBusDevice.cpp;h=2a0dc89b552476061e8ff47e2f9d89e0766c96a1;hb=1fcf5a3f2cab008b87b648a3f4a71391a54e70f9;hp=75862b702179f2ad0314c9d348e8e15db8dfcfdc;hpb=8d84e2c0857878d0391aee40190919cf57d689e7;p=deb_libcec.git diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index 75862b7..2a0dc89 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -42,16 +42,52 @@ using namespace CEC; CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress) : m_iPhysicalAddress(iPhysicalAddress), m_iLogicalAddress(iLogicalAddress), + m_powerStatus(CEC_POWER_STATUS_UNKNOWN), m_processor(processor), - m_iVendorId(0), m_iVendorClass(CEC_VENDOR_UNKNOWN), - m_iLastActive(0) + m_iLastActive(0), + m_cecVersion(CEC_VERSION_UNKNOWN) { m_handler = new CCECCommandHandler(this); + for (unsigned int iPtr = 0; iPtr < 4; iPtr++) + m_menuLanguage.language[iPtr] = '?'; + m_menuLanguage.language[3] = 0; + m_menuLanguage.device = iLogicalAddress; + m_vendor.vendor = CEC_VENDOR_UNKNOWN; + + switch(iLogicalAddress) + { + case CECDEVICE_AUDIOSYSTEM: + m_type = CEC_DEVICE_TYPE_AUDIO_SYSTEM; + m_strDeviceName = "Audio"; + case CECDEVICE_PLAYBACKDEVICE1: + case CECDEVICE_PLAYBACKDEVICE2: + case CECDEVICE_PLAYBACKDEVICE3: + m_type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE; + m_strDeviceName = "Player"; + case CECDEVICE_RECORDINGDEVICE1: + case CECDEVICE_RECORDINGDEVICE2: + case CECDEVICE_RECORDINGDEVICE3: + m_type = CEC_DEVICE_TYPE_RECORDING_DEVICE; + m_strDeviceName = "Recorder"; + case CECDEVICE_TUNER1: + case CECDEVICE_TUNER2: + case CECDEVICE_TUNER3: + case CECDEVICE_TUNER4: + m_type = CEC_DEVICE_TYPE_TUNER; + m_strDeviceName = "Tuner"; + case CECDEVICE_TV: + m_type = CEC_DEVICE_TYPE_TV; + m_strDeviceName = "TV"; + default: + m_type = CEC_DEVICE_TYPE_RESERVED; + m_strDeviceName = "Unknown"; + } } CCECBusDevice::~CCECBusDevice(void) { + m_condition.Broadcast(); delete m_handler; } @@ -60,6 +96,11 @@ cec_logical_address CCECBusDevice::GetMyLogicalAddress(void) const return m_processor->GetLogicalAddress(); } +bool CCECBusDevice::MyLogicalAddressContains(cec_logical_address address) const +{ + return m_processor->HasLogicalAddress(address); +} + uint16_t CCECBusDevice::GetMyPhysicalAddress(void) const { return m_processor->GetPhysicalAddress(); @@ -70,6 +111,55 @@ void CCECBusDevice::AddLog(cec_log_level level, const CStdString &strMessage) m_processor->AddLog(level, strMessage); } +void CCECBusDevice::SetMenuLanguage(const cec_menu_language &language) +{ + if (language.device == m_iLogicalAddress) + { + CStdString strLog; + strLog.Format("device %d menu language set to '%s'", m_iLogicalAddress, language.language); + m_processor->AddLog(CEC_LOG_DEBUG, strLog); + m_menuLanguage = language; + } +} + +void CCECBusDevice::SetCecVersion(const cec_version newVersion) +{ + CStdString strLog; + m_cecVersion = newVersion; + + switch (newVersion) + { + case CEC_VERSION_1_2: + strLog.Format("device %d reports CEC version 1.2", m_iLogicalAddress); + break; + case CEC_VERSION_1_2A: + strLog.Format("device %d reports CEC version 1.2a", m_iLogicalAddress); + break; + case CEC_VERSION_1_3: + strLog.Format("device %d reports CEC version 1.3", m_iLogicalAddress); + break; + case CEC_VERSION_1_3A: + strLog.Format("device %d reports CEC version 1.3a", m_iLogicalAddress); + break; + default: + strLog.Format("device %d reports an unknown CEC version", m_iLogicalAddress); + m_cecVersion = CEC_VERSION_UNKNOWN; + break; + } + AddLog(CEC_LOG_DEBUG, strLog); +} + +void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus) +{ + if (m_powerStatus != powerStatus) + { + CStdString strLog; + strLog.Format("device %d power status changed from %2x to %2x", m_iLogicalAddress, m_powerStatus, powerStatus); + m_processor->AddLog(CEC_LOG_DEBUG, strLog); + m_powerStatus = powerStatus; + } +} + void CCECBusDevice::SetVendorId(const cec_datapacket &data) { if (data.size < 3) @@ -87,7 +177,7 @@ void CCECBusDevice::SetVendorId(const cec_datapacket &data) void CCECBusDevice::SetVendorId(uint64_t iVendorId, uint8_t iVendorClass /* = 0 */) { - m_iVendorId = iVendorId; + m_vendor.vendor = (cec_vendor_id)iVendorId; m_iVendorClass = iVendorClass; switch (iVendorId) @@ -125,32 +215,52 @@ bool CCECBusDevice::HandleCommand(const cec_command &command) CLockObject lock(&m_mutex); m_iLastActive = GetTimeMs(); m_handler->HandleCommand(command); + m_condition.Signal(); return true; } +const cec_vendor &CCECBusDevice::GetVendor(void) +{ + if (m_vendor.vendor == CEC_VENDOR_UNKNOWN) + { + AddLog(CEC_LOG_NOTICE, "<< requesting vendor ID"); + cec_command command; + cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); + CLockObject lock(&m_mutex); + + if (m_processor->Transmit(command)) + m_condition.Wait(&m_mutex, 1000); + } + + return m_vendor; +} + void CCECBusDevice::PollVendorId(void) { CLockObject lock(&m_mutex); if (m_iLastActive > 0 && m_iLogicalAddress != CECDEVICE_BROADCAST && - m_iVendorId == CEC_VENDOR_UNKNOWN && + m_vendor.vendor == CEC_VENDOR_UNKNOWN && GetTimeMs() - m_iLastActive > 5000) { m_iLastActive = GetTimeMs(); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), GetLogicalAddress(), CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); - command.ack_timeout = 0; - m_processor->Transmit(command); + cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); + if (m_processor->Transmit(command)) + m_condition.Wait(&m_mutex, 1000); } } void CCECBusDevice::SetPhysicalAddress(uint16_t iNewAddress, uint16_t iOldAddress /* = 0 */) { - CStdString strLog; - strLog.Format(">> %i changed physical address from %04x to %04x", GetLogicalAddress(), m_iPhysicalAddress, iNewAddress); - AddLog(CEC_LOG_DEBUG, strLog.c_str()); + if (iNewAddress > 0) + { + CStdString strLog; + strLog.Format(">> %i changed physical address from %04x to %04x", m_iLogicalAddress, m_iPhysicalAddress, iNewAddress); + AddLog(CEC_LOG_DEBUG, strLog.c_str()); - m_iPhysicalAddress = iNewAddress; + m_iPhysicalAddress = iNewAddress; + } } bool CCECBusDevice::PowerOn(void) @@ -193,26 +303,26 @@ bool CCECBusDevice::SetOSDString(cec_display_control duration, const char *strMe return m_processor->Transmit(command); } -bool CCECBusDevice::ReportCECVersion(void) +bool CCECBusDevice::ReportCECVersion(cec_logical_address dest) { AddLog(CEC_LOG_NOTICE, "<< reporting CEC version as 1.3a"); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_CEC_VERSION); + cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_CEC_VERSION); command.parameters.push_back(CEC_VERSION_1_3A); return m_processor->Transmit(command); } -bool CCECBusDevice::ReportDeckStatus(void) +bool CCECBusDevice::ReportDeckStatus(cec_logical_address dest) { // need to support opcodes play and deck control before doing anything with this AddLog(CEC_LOG_NOTICE, "<< deck status requested, feature abort"); - m_processor->TransmitAbort(m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); + m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); return false; } -bool CCECBusDevice::ReportMenuState(bool bActive /* = true */) +bool CCECBusDevice::ReportMenuState(cec_logical_address dest, bool bActive /* = true */) { if (bActive) AddLog(CEC_LOG_NOTICE, "<< reporting menu state as active"); @@ -220,13 +330,13 @@ bool CCECBusDevice::ReportMenuState(bool bActive /* = true */) AddLog(CEC_LOG_NOTICE, "<< reporting menu state as inactive"); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_MENU_STATUS); + cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_MENU_STATUS); command.parameters.push_back(bActive ? (uint8_t) CEC_MENU_STATE_ACTIVATED : (uint8_t) CEC_MENU_STATE_DEACTIVATED); return m_processor->Transmit(command); } -bool CCECBusDevice::ReportOSDName(void) +bool CCECBusDevice::ReportOSDName(cec_logical_address dest) { const char *osdname = m_processor->GetDeviceName().c_str(); CStdString strLog; @@ -234,31 +344,29 @@ bool CCECBusDevice::ReportOSDName(void) AddLog(CEC_LOG_NOTICE, strLog.c_str()); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_SET_OSD_NAME); + cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_NAME); for (unsigned int iPtr = 0; iPtr < strlen(osdname); iPtr++) command.parameters.push_back(osdname[iPtr]); return m_processor->Transmit(command); } -bool CCECBusDevice::ReportPowerState(bool bOn /* = true */) +bool CCECBusDevice::ReportPowerState(cec_logical_address dest) { - if (bOn) - AddLog(CEC_LOG_NOTICE, "<< reporting \"On\" power status"); - else - AddLog(CEC_LOG_NOTICE, "<< reporting \"Off\" power status"); + AddLog(CEC_LOG_NOTICE, "<< reporting \"On\" power status"); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_REPORT_POWER_STATUS); - command.parameters.push_back(bOn ? (uint8_t) CEC_POWER_STATUS_ON : (uint8_t) CEC_POWER_STATUS_STANDBY); + cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_POWER_STATUS); +// command.parameters.push_back(bOn ? (uint8_t) CEC_POWER_STATUS_ON : (uint8_t) CEC_POWER_STATUS_STANDBY); + command.parameters.push_back((uint8_t) CEC_POWER_STATUS_ON); return m_processor->Transmit(command); } -bool CCECBusDevice::ReportVendorID(void) +bool CCECBusDevice::ReportVendorID(cec_logical_address dest) { AddLog(CEC_LOG_NOTICE, "<< vendor ID requested, feature abort"); - m_processor->TransmitAbort(m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); + m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); return false; } @@ -267,7 +375,7 @@ bool CCECBusDevice::BroadcastActiveView(void) AddLog(CEC_LOG_DEBUG, "<< setting active view"); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); + cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); command.parameters.push_back((m_iPhysicalAddress >> 8) & 0xFF); command.parameters.push_back(m_iPhysicalAddress & 0xFF); @@ -279,7 +387,7 @@ bool CCECBusDevice::BroadcastInactiveView(void) AddLog(CEC_LOG_DEBUG, "<< setting inactive view"); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), CECDEVICE_BROADCAST, CEC_OPCODE_INACTIVE_SOURCE); + cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_INACTIVE_SOURCE); command.parameters.push_back((m_iPhysicalAddress >> 8) & 0xFF); command.parameters.push_back(m_iPhysicalAddress & 0xFF); @@ -293,7 +401,7 @@ bool CCECBusDevice::BroadcastPhysicalAddress(void) AddLog(CEC_LOG_NOTICE, strLog.c_str()); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS); + cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS); command.parameters.push_back((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF)); command.parameters.push_back((uint8_t) (m_iPhysicalAddress & 0xFF)); command.parameters.push_back((uint8_t) (CEC_DEVICE_TYPE_PLAYBACK_DEVICE)); @@ -306,22 +414,74 @@ bool CCECBusDevice::BroadcastActiveSource(void) AddLog(CEC_LOG_NOTICE, "<< broadcasting active source"); cec_command command; - cec_command::format(command, GetMyLogicalAddress(), CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); + cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); command.parameters.push_back((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF)); command.parameters.push_back((uint8_t) (m_iPhysicalAddress & 0xFF)); return m_processor->Transmit(command); } -const char *CCECBusDevice::CECVendorIdToString(const uint64_t iVendorId) +cec_version CCECBusDevice::GetCecVersion(bool bRefresh /* = true */) { - switch (iVendorId) + if (bRefresh || m_cecVersion == CEC_VERSION_UNKNOWN) { - case CEC_VENDOR_SAMSUNG: - return "Samsung"; - case CEC_VENDOR_LG: - return "LG"; - default: - return "Unknown"; + AddLog(CEC_LOG_NOTICE, "<< requesting CEC version"); + cec_command command; + cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION); + CLockObject lock(&m_mutex); + if (m_processor->Transmit(command)) + m_condition.Wait(&m_mutex, 1000); + } + + return m_cecVersion; +} + +cec_menu_language &CCECBusDevice::GetMenuLanguage(bool bRefresh /* = true */) +{ + if (bRefresh || !strcmp(m_menuLanguage.language, "???")) + { + AddLog(CEC_LOG_NOTICE, "<< requesting menu language"); + cec_command command; + cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_MENU_LANGUAGE); + CLockObject lock(&m_mutex); + if (m_processor->Transmit(command)) + m_condition.Wait(&m_mutex, 1000); } + + return m_menuLanguage; +} + +cec_power_status CCECBusDevice::GetPowerStatus(bool bRefresh /* = true */) +{ + if (bRefresh || m_powerStatus == CEC_POWER_STATUS_UNKNOWN) + { + AddLog(CEC_LOG_NOTICE, "<< requesting power status"); + cec_command command; + cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS); + CLockObject lock(&m_mutex); + if (m_processor->Transmit(command)) + m_condition.Wait(&m_mutex, 1000); + } + + return m_powerStatus; +} + +bool CCECBusDevice::PollDevice(cec_logical_address source /* = CECDEVICE_UNKNOWN */) +{ + bool bReturn(false); + + if (source == CECDEVICE_UNKNOWN) + source = GetMyLogicalAddress(); + + CStdString strLog; + strLog.Format("<< sending POLL from device %1x to device %1x", (int8_t)source, m_iLogicalAddress); + AddLog(CEC_LOG_DEBUG, strLog); + + cec_command command; + cec_command::format(command, source, m_iLogicalAddress, CEC_OPCODE_NONE); + CLockObject lock(&m_mutex); + + bReturn = m_processor->Transmit(command); + AddLog(CEC_LOG_DEBUG, bReturn ? ">> POLL sent" : ">> POLL not sent"); + return bReturn; }