X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fdevices%2FCECBusDevice.cpp;h=91dd83538c90ee213310c22c93ed648548ea1861;hb=ebefc26c10d68ba9ced2a30c896dccc81c6c2eeb;hp=d68aa1f38d3ab0fa5ed21843901aea80b72ed7e4;hpb=60c28d825a9439721d83129781a480ecef4f0577;p=deb_libcec.git diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index d68aa1f..91dd835 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -32,12 +32,15 @@ #include "CECBusDevice.h" #include "../CECProcessor.h" +#include "../CECClient.h" #include "../implementations/ANCommandHandler.h" #include "../implementations/CECCommandHandler.h" #include "../implementations/SLCommandHandler.h" #include "../implementations/VLCommandHandler.h" #include "../LibCEC.h" +#include "../CECTypeUtils.h" #include "../platform/util/timeutils.h" +#include "../platform/util/util.h" #include "CECAudioSystem.h" #include "CECPlaybackDevice.h" @@ -50,7 +53,7 @@ using namespace CEC; using namespace PLATFORM; #define LIB_CEC m_processor->GetLib() -#define ToString(p) LIB_CEC->ToString(p) +#define ToString(p) CCECTypeUtils::ToString(p) CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress /* = CEC_INVALID_PHYSICAL_ADDRESS */) : m_type (CEC_DEVICE_TYPE_RESERVED), @@ -69,7 +72,8 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi m_deviceStatus (CEC_DEVICE_STATUS_UNKNOWN), m_iHandlerUseCount (0), m_bAwaitingReceiveFailed(false), - m_bVendorIdRequested (false) + m_bVendorIdRequested (false), + m_waitForResponse (new CWaitForResponse) { m_handler = new CCECCommandHandler(this); @@ -83,7 +87,8 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi CCECBusDevice::~CCECBusDevice(void) { - delete m_handler; + DELETE_AND_NULL(m_handler); + DELETE_AND_NULL(m_waitForResponse); } bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) @@ -105,21 +110,27 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) if (CCECCommandHandler::HasSpecificHandler(m_vendor)) { LIB_CEC->AddLog(CEC_LOG_DEBUG, "replacing the command handler for device '%s' (%x)", GetLogicalAddressName(), GetLogicalAddress()); - delete m_handler; + + int32_t iTransmitTimeout = m_handler->m_iTransmitTimeout; + int32_t iTransmitWait = m_handler->m_iTransmitWait; + int8_t iTransmitRetries = m_handler->m_iTransmitRetries; + int64_t iActiveSourcePending = m_handler->m_iActiveSourcePending; + + DELETE_AND_NULL(m_handler); switch (m_vendor) { case CEC_VENDOR_SAMSUNG: - m_handler = new CANCommandHandler(this); + m_handler = new CANCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_LG: - m_handler = new CSLCommandHandler(this); + m_handler = new CSLCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_PANASONIC: - m_handler = new CVLCommandHandler(this); + m_handler = new CVLCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; default: - m_handler = new CCECCommandHandler(this); + m_handler = new CCECCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; } @@ -131,10 +142,14 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) if (bInitHandler) { - m_handler->InitHandler(); + CCECBusDevice *primary = GetProcessor()->GetPrimaryDevice(); + if (primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED) + { + m_handler->InitHandler(); - if (bActivateSource && IsHandledByLibCEC() && IsActiveSource()) - m_handler->ActivateSource(); + if (bActivateSource && IsHandledByLibCEC() && IsActiveSource()) + m_handler->ActivateSource(); + } } MarkReady(); @@ -142,6 +157,13 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) return true; } +CCECCommandHandler *CCECBusDevice::GetHandler(void) +{ + ReplaceHandler(false); + MarkBusy(); + return m_handler; +} + bool CCECBusDevice::HandleCommand(const cec_command &command) { bool bHandled(false); @@ -217,7 +239,7 @@ void CCECBusDevice::SetUnsupportedFeature(cec_opcode opcode) // signal threads that are waiting for a reponse MarkBusy(); - m_handler->SignalOpcode(cec_command::GetResponseOpcode(opcode)); + SignalOpcode(cec_command::GetResponseOpcode(opcode)); MarkReady(); } @@ -741,15 +763,9 @@ void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus) CLockObject lock(m_mutex); switch (newStatus) { - case CEC_DEVICE_STATUS_UNKNOWN: - if (m_deviceStatus != newStatus) - LIB_CEC->AddLog(CEC_LOG_DEBUG, "device status of %s changed into 'unknown'", ToString(m_iLogicalAddress)); - ResetDeviceStatus(); - m_deviceStatus = newStatus; - break; case CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC: if (m_deviceStatus != newStatus) - LIB_CEC->AddLog(CEC_LOG_DEBUG, "device status of %s changed into 'handled by libCEC'", ToString(m_iLogicalAddress)); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): device status changed into 'handled by libCEC'", GetLogicalAddressName(), m_iLogicalAddress); SetPowerStatus (CEC_POWER_STATUS_ON); SetVendorId (CEC_VENDOR_UNKNOWN); SetMenuState (CEC_MENU_STATE_ACTIVATED); @@ -761,17 +777,20 @@ void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus) break; case CEC_DEVICE_STATUS_PRESENT: if (m_deviceStatus != newStatus) - LIB_CEC->AddLog(CEC_LOG_DEBUG, "device status of %s changed into 'present'", ToString(m_iLogicalAddress)); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): device status changed into 'present'", GetLogicalAddressName(), m_iLogicalAddress); m_deviceStatus = newStatus; break; case CEC_DEVICE_STATUS_NOT_PRESENT: if (m_deviceStatus != newStatus) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "device status of %s changed into 'not present'", ToString(m_iLogicalAddress)); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): device status changed into 'not present'", GetLogicalAddressName(), m_iLogicalAddress); ResetDeviceStatus(); m_deviceStatus = newStatus; } break; + default: + ResetDeviceStatus(); + break; } } } @@ -786,9 +805,15 @@ void CCECBusDevice::ResetDeviceStatus(void) SetStreamPath (CEC_INVALID_PHYSICAL_ADDRESS); SetOSDName (ToString(m_iLogicalAddress)); MarkAsInactiveSource(); + m_iLastActive = 0; m_bVendorIdRequested = false; m_unsupportedFeatures.clear(); + m_waitForResponse->Clear(); + + if (m_deviceStatus != CEC_DEVICE_STATUS_UNKNOWN) + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): device status changed into 'unknown'", GetLogicalAddressName(), m_iLogicalAddress); + m_deviceStatus = CEC_DEVICE_STATUS_UNKNOWN; } bool CCECBusDevice::TransmitPoll(const cec_logical_address dest) @@ -874,12 +899,21 @@ bool CCECBusDevice::TransmitMenuState(const cec_logical_address dest) return bReturn; } -bool CCECBusDevice::ActivateSource(void) +bool CCECBusDevice::ActivateSource(uint64_t iDelay /* = 0 */) { MarkAsActiveSource(); - LIB_CEC->AddLog(CEC_LOG_DEBUG, "activating source '%s'", ToString(m_iLogicalAddress)); MarkBusy(); - bool bReturn = m_handler->ActivateSource(); + bool bReturn(true); + if (iDelay == 0) + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending active source message for '%s'", ToString(m_iLogicalAddress)); + bReturn = m_handler->ActivateSource(); + } + else + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "scheduling active source message for '%s'", ToString(m_iLogicalAddress)); + m_handler->ScheduleActivateSource(iDelay); + } MarkReady(); return bReturn; } @@ -901,38 +935,76 @@ bool CCECBusDevice::RequestActiveSource(bool bWaitForResponse /* = true */) void CCECBusDevice::MarkAsActiveSource(void) { - CLockObject lock(m_mutex); - if (!m_bActiveSource) - LIB_CEC->AddLog(CEC_LOG_DEBUG, "making %s (%x) the active source", GetLogicalAddressName(), m_iLogicalAddress); - else - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%x) was already marked as active source", GetLogicalAddressName(), m_iLogicalAddress); + bool bWasActivated(false); + + // set the power status to powered on + SetPowerStatus(CEC_POWER_STATUS_ON); + + // mark this device as active source + { + CLockObject lock(m_mutex); + if (!m_bActiveSource) + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "making %s (%x) the active source", GetLogicalAddressName(), m_iLogicalAddress); + bWasActivated = true; + } + else + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%x) was already marked as active source", GetLogicalAddressName(), m_iLogicalAddress); + m_bActiveSource = true; + } + + // mark other devices as inactive sources CECDEVICEVEC devices; m_processor->GetDevices()->Get(devices); for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++) if ((*it)->GetLogicalAddress() != m_iLogicalAddress) (*it)->MarkAsInactiveSource(); - m_bActiveSource = true; - SetPowerStatus(CEC_POWER_STATUS_ON); + if (bWasActivated) + { + CCECClient *client = GetClient(); + if (client) + client->SourceActivated(m_iLogicalAddress); + } } void CCECBusDevice::MarkAsInactiveSource(void) { + bool bWasDeactivated(false); { CLockObject lock(m_mutex); if (m_bActiveSource) + { LIB_CEC->AddLog(CEC_LOG_DEBUG, "marking %s (%X) as inactive source", GetLogicalAddressName(), m_iLogicalAddress); + bWasDeactivated = true; + } m_bActiveSource = false; } + + if (bWasDeactivated) + { + CCECClient *client = GetClient(); + if (client) + client->SourceDeactivated(m_iLogicalAddress); + } } bool CCECBusDevice::TransmitActiveSource(void) { bool bSendActiveSource(false); + uint16_t iPhysicalAddress(CEC_INVALID_PHYSICAL_ADDRESS); { CLockObject lock(m_mutex); + if (!HasValidPhysicalAddress()) + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X) has an invalid physical address (%04x), not sending active source commands", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress); + return false; + } + + iPhysicalAddress = m_iPhysicalAddress; + if (m_powerStatus != CEC_POWER_STATUS_ON && m_powerStatus != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON) LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %s (%X) is not powered on", GetLogicalAddressName(), m_iLogicalAddress); else if (m_bActiveSource) @@ -944,15 +1016,15 @@ bool CCECBusDevice::TransmitActiveSource(void) LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %s (%X) is not the active source", GetLogicalAddressName(), m_iLogicalAddress); } + bool bActiveSourceSent(false); if (bSendActiveSource) { MarkBusy(); - m_handler->TransmitActiveSource(m_iLogicalAddress, m_iPhysicalAddress); + bActiveSourceSent = m_handler->TransmitActiveSource(m_iLogicalAddress, iPhysicalAddress); MarkReady(); - return true; } - return false; + return bActiveSourceSent; } bool CCECBusDevice::TransmitImageViewOn(void) @@ -966,10 +1038,11 @@ bool CCECBusDevice::TransmitImageViewOn(void) } } + bool bImageViewOnSent(false); MarkBusy(); - m_handler->TransmitImageViewOn(m_iLogicalAddress, CECDEVICE_TV); + bImageViewOnSent = m_handler->TransmitImageViewOn(m_iLogicalAddress, CECDEVICE_TV); MarkReady(); - return true; + return bImageViewOnSent; } bool CCECBusDevice::TransmitInactiveSource(void) @@ -990,7 +1063,7 @@ bool CCECBusDevice::TransmitInactiveSource(void) bool CCECBusDevice::TransmitPendingActiveSourceCommands(void) { MarkBusy(); - bool bReturn = m_handler->TransmitPendingActiveSourceCommands(); + bool bReturn = m_handler->ActivateSource(true); MarkReady(); return bReturn; } @@ -1227,3 +1300,13 @@ CCECClient *CCECBusDevice::GetClient(void) { return m_processor->GetClient(m_iLogicalAddress); } + +void CCECBusDevice::SignalOpcode(cec_opcode opcode) +{ + m_waitForResponse->Received(opcode); +} + +bool CCECBusDevice::WaitForOpcode(cec_opcode opcode) +{ + return m_waitForResponse->Wait(opcode); +}