#include "env.h"
#include "CECAudioSystem.h"
#include "CECProcessor.h"
#include "implementations/CECCommandHandler.h"
#include "LibCEC.h"
#include "CECTypeUtils.h"
using namespace CEC;
using namespace P8PLATFORM;
#define LIB_CEC m_processor->GetLib()
#define ToString(p) CCECTypeUtils::ToString(p)
CCECAudioSystem::CCECAudioSystem(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress ) :
CCECBusDevice(processor, address, iPhysicalAddress),
m_iLastAudioStatusUpdate(0),
m_systemAudioModeStatus(CEC_SYSTEM_AUDIO_STATUS_UNKNOWN),
m_audioStatus(CEC_AUDIO_VOLUME_STATUS_UNKNOWN)
{
m_type = CEC_DEVICE_TYPE_AUDIO_SYSTEM;
}
bool CCECAudioSystem::SetAudioStatus(uint8_t status)
{
CLockObject lock(m_mutex);
if (m_audioStatus != status)
{
m_iLastAudioStatusUpdate = GetTimeMs();
LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s (%X): audio status changed from %2x to %2x", GetLogicalAddressName(), m_iLogicalAddress, m_audioStatus, status);
m_audioStatus = status;
return true;
}
return false;
}
bool CCECAudioSystem::SetSystemAudioModeStatus(const cec_system_audio_status mode)
{
CLockObject lock(m_mutex);
if (m_systemAudioModeStatus != mode)
{
LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s (%X): system audio mode changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, ToString((cec_system_audio_status)m_systemAudioModeStatus), ToString(mode));
m_systemAudioModeStatus = mode;
return true;
}
return false;
}
bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest, bool bIsReply)
{
uint8_t state;
{
CLockObject lock(m_mutex);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, m_audioStatus);
state = m_audioStatus;
}
return m_handler->TransmitAudioStatus(m_iLogicalAddress, dest, state, bIsReply);
}
bool CCECAudioSystem::TransmitSetSystemAudioMode(cec_logical_address dest, bool bIsReply)
{
cec_system_audio_status state;
{
CLockObject lock(m_mutex);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %x -> %x: set system audio mode '%d'", m_iLogicalAddress, dest, m_systemAudioModeStatus);
state = (cec_system_audio_status)m_systemAudioModeStatus;
}
return m_handler->TransmitSetSystemAudioMode(m_iLogicalAddress, dest, state, bIsReply);
}
bool CCECAudioSystem::TransmitSystemAudioModeStatus(cec_logical_address dest, bool bIsReply)
{
cec_system_audio_status state;
{
CLockObject lock(m_mutex);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, ToString((cec_system_audio_status)m_systemAudioModeStatus));
state = (cec_system_audio_status)m_systemAudioModeStatus;
}
return m_handler->TransmitSystemAudioModeStatus(m_iLogicalAddress, dest, state, bIsReply);
}
uint8_t CCECAudioSystem::VolumeUp(const cec_logical_address source, bool bSendRelease )
{
TransmitVolumeUp(source, bSendRelease);
CLockObject lock(m_mutex);
return m_audioStatus;
}
uint8_t CCECAudioSystem::VolumeDown(const cec_logical_address source, bool bSendRelease )
{
TransmitVolumeDown(source, bSendRelease);
CLockObject lock(m_mutex);
return m_audioStatus;
}
uint8_t CCECAudioSystem::MuteAudio(const cec_logical_address source)
{
TransmitMuteAudio(source);
return GetAudioStatus(source, true);
}
bool CCECAudioSystem::RequestAudioStatus(const cec_logical_address initiator, bool bWaitForResponse )
{
bool bReturn(false);
if (!IsHandledByLibCEC() &&
!IsUnsupportedFeature(CEC_OPCODE_GIVE_AUDIO_STATUS))
{
MarkBusy();
LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< requesting audio status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
bReturn = m_handler->TransmitRequestAudioStatus(initiator, m_iLogicalAddress, bWaitForResponse);
MarkReady();
}
return bReturn;
}
bool CCECAudioSystem::RequestSystemAudioModeStatus(const cec_logical_address initiator, bool bWaitForResponse )
{
bool bReturn(false);
if (!IsHandledByLibCEC() &&
!IsUnsupportedFeature(CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS))
{
MarkBusy();
LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< requesting system audio mode status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
bReturn = m_handler->TransmitRequestSystemAudioModeStatus(initiator, m_iLogicalAddress, bWaitForResponse);
MarkReady();
}
return bReturn;
}
uint8_t CCECAudioSystem::GetAudioStatus(const cec_logical_address initiator, bool bUpdate )
{
bool bIsPresent(GetStatus() == CEC_DEVICE_STATUS_PRESENT);
bool bRequestUpdate(false);
{
CLockObject lock(m_mutex);
bRequestUpdate = bIsPresent &&
(bUpdate || m_audioStatus == CEC_AUDIO_VOLUME_STATUS_UNKNOWN ||
GetTimeMs() - m_iLastAudioStatusUpdate >= CEC_AUDIO_STATUS_REFRESH_TIME);
}
if (bRequestUpdate)
{
CheckVendorIdRequested(initiator);
RequestAudioStatus(initiator);
}
CLockObject lock(m_mutex);
return m_audioStatus;
}
uint8_t CCECAudioSystem::GetSystemAudioModeStatus(const cec_logical_address initiator, bool bUpdate )
{
bool bIsPresent(GetStatus() == CEC_DEVICE_STATUS_PRESENT);
bool bRequestUpdate(false);
{
CLockObject lock(m_mutex);
bRequestUpdate = bIsPresent &&
(bUpdate || m_systemAudioModeStatus == CEC_SYSTEM_AUDIO_STATUS_UNKNOWN);
}
if (bRequestUpdate)
{
CheckVendorIdRequested(initiator);
RequestSystemAudioModeStatus(initiator);
}
CLockObject lock(m_mutex);
return m_systemAudioModeStatus;
}
bool CCECAudioSystem::AudioEnable(CCECBusDevice* device, bool bEnable )
{
cec_logical_address iLogicalAddress = device->GetLogicalAddress() ?
device->GetLogicalAddress() : CECDEVICE_UNKNOWN;
uint16_t physicalAddress = bEnable ? device->GetCurrentPhysicalAddress() :
CEC_INVALID_PHYSICAL_ADDRESS;
return m_handler->TransmitSystemAudioModeRequest(iLogicalAddress, physicalAddress);
}