/*
* This file is part of the libCEC(R) library.
*
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
* libCEC(R) is an original work, containing original code.
*
* libCEC(R) is a trademark of Pulse-Eight Limited.
* http://www.pulse-eight.net/
*/
+#include "env.h"
#include "CECClient.h"
+
#include "CECProcessor.h"
#include "LibCEC.h"
+#include "CECTypeUtils.h"
#include "devices/CECPlaybackDevice.h"
#include "devices/CECAudioSystem.h"
#include "devices/CECTV.h"
+#include "implementations/CECCommandHandler.h"
using namespace CEC;
using namespace PLATFORM;
#define LIB_CEC m_processor->GetLib()
-#define ToString(x) LIB_CEC->ToString(x)
+#define ToString(x) CCECTypeUtils::ToString(x)
CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration &configuration) :
m_processor(processor),
m_bInitialised(false),
m_bRegistered(false),
m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
- m_buttontime(0)
+ m_buttontime(0),
+ m_iPreventForwardingPowerOffCommand(0),
+ m_iLastKeypressTime(0)
{
+ m_lastKeypress.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
+ m_lastKeypress.duration = 0;
+ m_configuration.Clear();
// set the initial configuration
SetConfiguration(configuration);
}
// set the physical address
SetPhysicalAddress(m_configuration);
- // ensure that we know the vendor id of the TV, so we are using the correct handler
- m_processor->GetTV()->GetVendorId(GetPrimaryLogicalAdddress());
-
// make the primary device the active source if the option is set
if (m_configuration.bActivateSource == 1)
- GetPrimaryDevice()->ActivateSource();
+ GetPrimaryDevice()->ActivateSource(500);
return true;
}
iPort > CEC_MAX_HDMI_PORTNUMBER)
return bReturn;
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice);
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice);
// update the configuration
{
}
// don't continue if the connection isn't opened
- if (!m_processor->IsRunning() && !bForce)
+ if (!m_processor->CECInitialised() && !bForce)
return true;
// get the PA of the base device
// set the default address when something went wrong
if (!bReturn)
{
- LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
- iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+ uint16_t iEepromAddress = m_processor->GetPhysicalAddressFromEeprom();
+ if (CLibCEC::IsValidPhysicalAddress(iEepromAddress))
+ {
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the value that was persisted in the eeprom, %04X", iPhysicalAddress, iEepromAddress);
+ iPhysicalAddress = iEepromAddress;
+ bReturn = true;
+ }
+ else
+ {
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
+ iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+ }
}
// and set the address
SetDevicePhysicalAddress(iPhysicalAddress);
- ConfigurationChanged(m_configuration);
+ CallbackConfigurationChanged(m_configuration);
return bReturn;
}
void CCECClient::ResetPhysicalAddress(void)
{
- SetPhysicalAddress(m_configuration);
+ SetPhysicalAddress(CEC_DEFAULT_PHYSICAL_ADDRESS);
}
void CCECClient::SetPhysicalAddress(const libcec_configuration &configuration)
{
- // try to autodetect the address
bool bPASet(false);
- if (m_processor->IsRunning() && configuration.bAutodetectAddress == 1)
- bPASet = AutodetectPhysicalAddress();
- // try to use physical address setting
+ // override the physical address from configuration.iPhysicalAddress if it's set
if (!bPASet && CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress))
bPASet = SetPhysicalAddress(configuration.iPhysicalAddress);
+ // try to autodetect the address
+ if (!bPASet && m_processor->CECInitialised())
+ {
+ bPASet = AutodetectPhysicalAddress();
+ m_configuration.bAutodetectAddress = bPASet ? 1 : 0;
+ }
+
// use the base device + hdmi port settings
if (!bPASet)
bPASet = SetHDMIPort(configuration.baseDevice, configuration.iHDMIPort);
bool CCECClient::SetPhysicalAddress(const uint16_t iPhysicalAddress)
{
// update the configuration
+ bool bChanged(true);
{
CLockObject lock(m_mutex);
if (m_configuration.iPhysicalAddress == iPhysicalAddress)
- {
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "physical address unchanged (%04X)", iPhysicalAddress);
- return true;
- }
+ bChanged = false;
else
- {
m_configuration.iPhysicalAddress = iPhysicalAddress;
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting physical address to '%04X'", iPhysicalAddress);
- }
+ }
+ if (!bChanged)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "physical address unchanged (%04X)", iPhysicalAddress);
+ return true;
}
- // persist the new configuration
- if (m_processor->IsRunning())
- m_processor->PersistConfiguration(m_configuration);
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting physical address to '%04X'", iPhysicalAddress);
// set the physical address for each device
SetDevicePhysicalAddress(iPhysicalAddress);
// and send back the updated configuration
- ConfigurationChanged(m_configuration);
+ CallbackConfigurationChanged(m_configuration);
return true;
}
+void CCECClient::SetSupportedDeviceTypes(void)
+{
+ cec_device_type_list types;
+ types.Clear();
+
+ // get the command handler for the tv
+ CCECCommandHandler *tvHandler = m_processor->GetTV()->GetHandler();
+ if (!tvHandler)
+ return;
+
+ // check all device types
+ for (uint8_t iPtr = 0; iPtr < 5; iPtr++)
+ {
+ if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
+ continue;
+
+ // get the supported device type. the handler will replace types it doesn't support by one it does support
+ cec_device_type type = tvHandler->GetReplacementDeviceType(m_configuration.deviceTypes.types[iPtr]);
+ if (!types.IsSet(type))
+ types.Add(type);
+ }
+ m_processor->GetTV()->MarkHandlerReady();
+
+ // set the new type list
+ m_configuration.deviceTypes = types;
+
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
+}
+
bool CCECClient::AllocateLogicalAddresses(void)
{
// reset all previous LAs that were set
m_configuration.logicalAddresses.Clear();
+ // get the supported device types from the command handler of the TV
+ SetSupportedDeviceTypes();
+
// display an error if no device types are set
if (m_configuration.deviceTypes.IsEmpty())
{
m_configuration.logicalAddresses.Set(address);
}
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
+
return true;
}
cec_logical_address retVal(CECDEVICE_UNKNOWN);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'recording device'");
- if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE1))
+ if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE1, m_configuration.cecVersion))
retVal = CECDEVICE_RECORDINGDEVICE1;
- else if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE2))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE2, m_configuration.cecVersion))
retVal = CECDEVICE_RECORDINGDEVICE2;
- else if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE3))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE3, m_configuration.cecVersion))
retVal = CECDEVICE_RECORDINGDEVICE3;
return retVal;
cec_logical_address retVal(CECDEVICE_UNKNOWN);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'tuner'");
- if (m_processor->TryLogicalAddress(CECDEVICE_TUNER1))
+ if (m_processor->TryLogicalAddress(CECDEVICE_TUNER1, m_configuration.cecVersion))
retVal = CECDEVICE_TUNER1;
- else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER2))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER2, m_configuration.cecVersion))
retVal = CECDEVICE_TUNER2;
- else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER3))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER3, m_configuration.cecVersion))
retVal = CECDEVICE_TUNER3;
- else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER4))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER4, m_configuration.cecVersion))
retVal = CECDEVICE_TUNER4;
return retVal;
cec_logical_address retVal(CECDEVICE_UNKNOWN);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'playback device'");
- if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE1))
+ if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE1, m_configuration.cecVersion))
retVal = CECDEVICE_PLAYBACKDEVICE1;
- else if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE2))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE2, m_configuration.cecVersion))
retVal = CECDEVICE_PLAYBACKDEVICE2;
- else if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE3))
+ else if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE3, m_configuration.cecVersion))
retVal = CECDEVICE_PLAYBACKDEVICE3;
return retVal;
cec_logical_address retVal(CECDEVICE_UNKNOWN);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'audiosystem'");
- if (m_processor->TryLogicalAddress(CECDEVICE_AUDIOSYSTEM))
+ if (m_processor->TryLogicalAddress(CECDEVICE_AUDIOSYSTEM, m_configuration.cecVersion))
retVal = CECDEVICE_AUDIOSYSTEM;
return retVal;
bool CCECClient::ChangeDeviceType(const cec_device_type from, const cec_device_type to)
{
- LIB_CEC->AddLog(CEC_LOG_NOTICE, "changing device type '%s' into '%s'", ToString(from), ToString(to));
-
- CLockObject lock(m_mutex);
+ if (from == to)
+ return true;
- // get the previous device that was allocated
- CCECBusDevice *previousDevice = GetDeviceByType(from);
- if (!previousDevice)
- return false;
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, "changing device type '%s' into '%s'", ToString(from), ToString(to));
- // change the type in the device type list
- bool bChanged(false);
- for (uint8_t iPtr = 0; iPtr < 5; iPtr++)
{
- if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
- continue;
+ CLockObject lock(m_mutex);
- if (m_configuration.deviceTypes.types[iPtr] == from)
- {
- bChanged = true;
- m_configuration.deviceTypes.types[iPtr] = to;
- }
- else if (m_configuration.deviceTypes.types[iPtr] == to && bChanged)
+ // get the previous device that was allocated
+ CCECBusDevice *previousDevice = GetDeviceByType(from);
+ if (!previousDevice)
+ return false;
+
+ // change the type in the device type list
+ bool bChanged(false);
+ for (uint8_t iPtr = 0; iPtr < 5; iPtr++)
{
- // ensure that dupes are removed
- m_configuration.deviceTypes.types[iPtr] = CEC_DEVICE_TYPE_RESERVED;
+ if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
+ continue;
+
+ if (m_configuration.deviceTypes.types[iPtr] == from)
+ {
+ bChanged = true;
+ m_configuration.deviceTypes.types[iPtr] = to;
+ }
+ else if (m_configuration.deviceTypes.types[iPtr] == to && bChanged)
+ {
+ // ensure that dupes are removed
+ m_configuration.deviceTypes.types[iPtr] = CEC_DEVICE_TYPE_RESERVED;
+ }
}
}
if (!m_processor->RegisterClient(this))
return false;
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
+
return true;
}
bool CCECClient::SetLogicalAddress(const cec_logical_address iLogicalAddress)
{
- CLockObject lock(m_mutex);
+ bool bReturn(true);
+
if (GetPrimaryLogicalAdddress() != iLogicalAddress)
{
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, "setting primary logical address to %1x", iLogicalAddress);
{
CLockObject lock(m_mutex);
- LIB_CEC->AddLog(CEC_LOG_NOTICE, "<< setting primary logical address to %1x", iLogicalAddress);
m_configuration.logicalAddresses.primary = iLogicalAddress;
m_configuration.logicalAddresses.Set(iLogicalAddress);
}
- return m_processor->RegisterClient(this);
+
+ bReturn = m_processor->RegisterClient(this);
+
+ // persist the new configuration
+ if (bReturn)
+ PersistConfiguration(m_configuration);
}
- return true;
+ return bReturn;
}
-bool CCECClient::Transmit(const cec_command &data)
+bool CCECClient::Transmit(const cec_command &data, bool bIsReply)
{
- return m_processor ? m_processor->Transmit(data) : false;
+ return m_processor ? m_processor->Transmit(data, bIsReply) : false;
}
bool CCECClient::SendPowerOnDevices(const cec_logical_address address /* = CECDEVICE_TV */)
{
- // if the broadcast address if set as destination and the client version >=1.5.0, read the wakeDevices setting
- if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0)
+ // if the broadcast address if set as destination, read the wakeDevices setting
+ if (address == CECDEVICE_BROADCAST)
{
CECDEVICEVEC devices;
m_processor->GetDevices()->GetWakeDevices(m_configuration, devices);
bool CCECClient::SendStandbyDevices(const cec_logical_address address /* = CECDEVICE_BROADCAST */)
{
- // if the broadcast address if set as destination and the client version >=1.5.0, read the standbyDevices setting
- if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0)
+ // if the broadcast address if set as destination, read the standbyDevices setting
+ if (address == CECDEVICE_BROADCAST)
{
CECDEVICEVEC devices;
m_processor->GetDevices()->GetPowerOffDevices(m_configuration, devices);
CCECBusDevice *device = *devices.begin();
// and activate it
- if (!m_processor->IsRunning())
+ if (!m_processor->CECInitialised())
device->MarkAsActiveSource();
else if (device->HasValidPhysicalAddress())
return device->ActivateSource();
// and set the deck control mode if there is a match
device->SetDeckControlMode(mode);
if (bSendUpdate)
- return device->TransmitDeckStatus(CECDEVICE_TV);
+ return device->TransmitDeckStatus(CECDEVICE_TV, false);
return true;
}
// and set the deck status if there is a match
device->SetDeckStatus(info);
if (bSendUpdate)
- return device->AsPlaybackDevice()->TransmitDeckStatus(CECDEVICE_TV);
+ return device->AsPlaybackDevice()->TransmitDeckStatus(CECDEVICE_TV, false);
return true;
}
{
(*it)->SetMenuState(state);
if (bSendUpdate)
- (*it)->TransmitMenuState(CECDEVICE_TV);
+ (*it)->TransmitMenuState(CECDEVICE_TV, false);
}
return true;
{
CCECBusDevice *primary = GetPrimaryDevice();
if (primary)
- return primary->TransmitOSDString(iLogicalAddress, duration, strMessage);
+ return primary->TransmitOSDString(iLogicalAddress, duration, strMessage, false);
return false;
}
(uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
}
-bool CCECClient::SendKeypress(const cec_logical_address iDestination, const cec_user_control_code key, bool bWait /* = true */)
+uint8_t CCECClient::AudioToggleMute(void)
{
CCECBusDevice *device = GetPrimaryDevice();
+ CCECAudioSystem *audio = m_processor->GetAudioSystem();
+
+ return device && audio && audio->IsPresent() ?
+ audio->MuteAudio(device->GetLogicalAddress()) :
+ (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
+}
+
+uint8_t CCECClient::AudioMute(void)
+{
+ CCECBusDevice *device = GetPrimaryDevice();
+ CCECAudioSystem *audio = m_processor->GetAudioSystem();
+ uint8_t iStatus = device && audio && audio->IsPresent() ? audio->GetAudioStatus(device->GetLogicalAddress()) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
+ if ((iStatus & CEC_AUDIO_MUTE_STATUS_MASK) != CEC_AUDIO_MUTE_STATUS_MASK)
+ iStatus = audio->MuteAudio(device->GetLogicalAddress());
+
+ return iStatus;
+}
+
+uint8_t CCECClient::AudioUnmute(void)
+{
+ CCECBusDevice *device = GetPrimaryDevice();
+ CCECAudioSystem *audio = m_processor->GetAudioSystem();
+ uint8_t iStatus = device && audio && audio->IsPresent() ? audio->GetAudioStatus(device->GetLogicalAddress()) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
+ if ((iStatus & CEC_AUDIO_MUTE_STATUS_MASK) == CEC_AUDIO_MUTE_STATUS_MASK)
+ iStatus = audio->MuteAudio(device->GetLogicalAddress());
+
+ return iStatus;
+}
+
+uint8_t CCECClient::AudioStatus(void)
+{
+ CCECBusDevice *device = GetPrimaryDevice();
+ CCECAudioSystem *audio = m_processor->GetAudioSystem();
+ return device && audio && audio->IsPresent() ? audio->GetAudioStatus(device->GetLogicalAddress()) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
+}
+
+bool CCECClient::SendKeypress(const cec_logical_address iDestination, const cec_user_control_code key, bool bWait /* = true */)
+{
CCECBusDevice *dest = m_processor->GetDevice(iDestination);
- return device && dest ?
- device->TransmitKeypress(GetPrimaryLogicalAdddress(), key, bWait) :
+ return dest ?
+ dest->TransmitKeypress(GetPrimaryLogicalAdddress(), key, bWait) :
false;
}
bool CCECClient::SendKeyRelease(const cec_logical_address iDestination, bool bWait /* = true */)
{
- CCECBusDevice *device = GetPrimaryDevice();
CCECBusDevice *dest = m_processor->GetDevice(iDestination);
- return device && dest ?
- device->TransmitKeyRelease(GetPrimaryLogicalAdddress(), bWait) :
+ return dest ?
+ dest->TransmitKeyRelease(GetPrimaryLogicalAdddress(), bWait) :
false;
}
// client version 1.5.0
snprintf(configuration.strDeviceName, 13, "%s", m_configuration.strDeviceName);
- configuration.deviceTypes = m_configuration.deviceTypes;
- configuration.bAutodetectAddress = m_configuration.bAutodetectAddress;
- configuration.iPhysicalAddress = m_configuration.iPhysicalAddress;
- configuration.baseDevice = m_configuration.baseDevice;
- configuration.iHDMIPort = m_configuration.iHDMIPort;
- configuration.clientVersion = m_configuration.clientVersion;
- configuration.serverVersion = m_configuration.serverVersion;
- configuration.tvVendor = m_configuration.tvVendor;
-
- configuration.bGetSettingsFromROM = m_configuration.bGetSettingsFromROM;
- configuration.bUseTVMenuLanguage = m_configuration.bUseTVMenuLanguage;
- configuration.bActivateSource = m_configuration.bActivateSource;
- configuration.wakeDevices = m_configuration.wakeDevices;
- configuration.powerOffDevices = m_configuration.powerOffDevices;
- configuration.bPowerOffScreensaver = m_configuration.bPowerOffScreensaver;
- configuration.bPowerOffOnStandby = m_configuration.bPowerOffOnStandby;
-
- // client version 1.5.1
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_1)
- configuration.bSendInactiveSource = m_configuration.bSendInactiveSource;
-
- // client version 1.5.3
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_3)
- configuration.logicalAddresses = m_configuration.logicalAddresses;
-
- // client version 1.6.0
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_0)
- {
- configuration.iFirmwareVersion = m_configuration.iFirmwareVersion;
- configuration.bPowerOffDevicesOnStandby = m_configuration.bPowerOffDevicesOnStandby;
- configuration.bShutdownOnStandby = m_configuration.bShutdownOnStandby;
- }
+ configuration.deviceTypes = m_configuration.deviceTypes;
+ configuration.bAutodetectAddress = m_configuration.bAutodetectAddress;
+ configuration.iPhysicalAddress = m_configuration.iPhysicalAddress;
+ configuration.baseDevice = m_configuration.baseDevice;
+ configuration.iHDMIPort = m_configuration.iHDMIPort;
+ configuration.clientVersion = m_configuration.clientVersion;
+ configuration.serverVersion = m_configuration.serverVersion;
+ configuration.tvVendor = m_configuration.tvVendor;
+ configuration.bGetSettingsFromROM = m_configuration.bGetSettingsFromROM;
+ configuration.bUseTVMenuLanguage = m_configuration.bUseTVMenuLanguage;
+ configuration.bActivateSource = m_configuration.bActivateSource;
+ configuration.wakeDevices = m_configuration.wakeDevices;
+ configuration.powerOffDevices = m_configuration.powerOffDevices;
+ configuration.bPowerOffScreensaver = m_configuration.bPowerOffScreensaver;
+ configuration.bPowerOnScreensaver = m_configuration.bPowerOnScreensaver;
+ configuration.bPowerOffOnStandby = m_configuration.bPowerOffOnStandby;
+ configuration.bSendInactiveSource = m_configuration.bSendInactiveSource;
+ configuration.logicalAddresses = m_configuration.logicalAddresses;
+ configuration.iFirmwareVersion = m_configuration.iFirmwareVersion;
+ configuration.bPowerOffDevicesOnStandby = m_configuration.bPowerOffDevicesOnStandby;
+ configuration.bShutdownOnStandby = m_configuration.bShutdownOnStandby;
+ memcpy(configuration.strDeviceLanguage, m_configuration.strDeviceLanguage, 3);
+ configuration.iFirmwareBuildDate = m_configuration.iFirmwareBuildDate;
+ configuration.bMonitorOnly = m_configuration.bMonitorOnly;
+ configuration.cecVersion = m_configuration.cecVersion;
+ configuration.adapterType = m_configuration.adapterType;
- // client version 1.6.2
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_2)
- {
- memcpy(configuration.strDeviceLanguage, m_configuration.strDeviceLanguage, 3);
- configuration.iFirmwareBuildDate = m_configuration.iFirmwareBuildDate;
- }
return true;
}
bool CCECClient::SetConfiguration(const libcec_configuration &configuration)
{
- bool bIsRunning(m_processor && m_processor->IsRunning());
+ libcec_configuration defaultSettings;
+ bool bIsRunning(m_processor && m_processor->CECInitialised());
CCECBusDevice *primary = bIsRunning ? GetPrimaryDevice() : NULL;
uint16_t iPA = primary ? primary->GetCurrentPhysicalAddress() : CEC_INVALID_PHYSICAL_ADDRESS;
// just copy these
{
CLockObject lock(m_mutex);
- m_configuration.bUseTVMenuLanguage = configuration.bUseTVMenuLanguage;
- m_configuration.bActivateSource = configuration.bActivateSource;
- m_configuration.bGetSettingsFromROM = configuration.bGetSettingsFromROM;
- m_configuration.wakeDevices = configuration.wakeDevices;
- m_configuration.powerOffDevices = configuration.powerOffDevices;
- m_configuration.bPowerOffScreensaver = configuration.bPowerOffScreensaver;
- m_configuration.bPowerOffOnStandby = configuration.bPowerOffOnStandby;
-
- // client version 1.5.1
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_1)
- m_configuration.bSendInactiveSource = configuration.bSendInactiveSource;
-
- // client version 1.6.0
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_0)
+ m_configuration.bUseTVMenuLanguage = configuration.bUseTVMenuLanguage;
+ m_configuration.bActivateSource = configuration.bActivateSource;
+ m_configuration.bGetSettingsFromROM = configuration.bGetSettingsFromROM;
+ m_configuration.wakeDevices = configuration.wakeDevices;
+ m_configuration.powerOffDevices = configuration.powerOffDevices;
+ m_configuration.bPowerOffScreensaver = configuration.bPowerOffScreensaver;
+ m_configuration.bPowerOffOnStandby = configuration.bPowerOffOnStandby;
+ m_configuration.bSendInactiveSource = configuration.bSendInactiveSource;
+ m_configuration.bPowerOffDevicesOnStandby = configuration.bPowerOffDevicesOnStandby;
+ m_configuration.bShutdownOnStandby = configuration.bShutdownOnStandby;
+ memcpy(m_configuration.strDeviceLanguage, configuration.strDeviceLanguage, 3);
+ m_configuration.bMonitorOnly = configuration.bMonitorOnly;
+ m_configuration.cecVersion = configuration.cecVersion;
+ m_configuration.adapterType = configuration.adapterType;
+ m_configuration.iDoubleTapTimeoutMs = configuration.iDoubleTapTimeoutMs;
+ m_configuration.deviceTypes.Add(configuration.deviceTypes[0]);
+
+ if (m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5)
{
- m_configuration.bPowerOffDevicesOnStandby = configuration.bPowerOffDevicesOnStandby;
- m_configuration.bShutdownOnStandby = configuration.bShutdownOnStandby;
+ m_configuration.comboKey = configuration.comboKey;
+ m_configuration.iComboKeyTimeoutMs = configuration.iComboKeyTimeoutMs;
}
-
- // client version 1.6.2
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_2)
+ else
{
- memcpy(m_configuration.strDeviceLanguage, configuration.strDeviceLanguage, 3);
+ m_configuration.comboKey = defaultSettings.comboKey;
+ m_configuration.iComboKeyTimeoutMs = defaultSettings.iComboKeyTimeoutMs;
}
- // ensure that there is at least 1 device type set
- if (m_configuration.deviceTypes.IsEmpty())
- m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
+ if (m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_1_0)
+ m_configuration.bPowerOnScreensaver = configuration.bPowerOnScreensaver;
+ else
+ m_configuration.bPowerOnScreensaver = defaultSettings.bPowerOnScreensaver;
}
bool bNeedReinit(false);
SetPhysicalAddress(configuration);
}
- if (bIsRunning)
- m_processor->PersistConfiguration(m_configuration);
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
if (!primary)
primary = GetPrimaryDevice();
void CCECClient::AddCommand(const cec_command &command)
{
- CLockObject lock(m_mutex);
-
- LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> %s (%X) -> %s (%X): %s (%2X)", ToString(command.initiator), command.initiator, ToString(command.destination), command.destination, ToString(command.opcode), command.opcode);
+ // don't forward the standby opcode more than once every 10 seconds
+ if (command.opcode == CEC_OPCODE_STANDBY)
+ {
+ CLockObject lock(m_mutex);
+ if (m_iPreventForwardingPowerOffCommand != 0 &&
+ m_iPreventForwardingPowerOffCommand > GetTimeMs())
+ return;
+ else
+ m_iPreventForwardingPowerOffCommand = GetTimeMs() + CEC_FORWARD_STANDBY_MIN_INTERVAL;
+ }
- if (m_configuration.callbacks && m_configuration.callbacks->CBCecCommand)
- m_configuration.callbacks->CBCecCommand(m_configuration.callbackParam, command);
- else if (!m_commandBuffer.Push(command))
- LIB_CEC->AddLog(CEC_LOG_WARNING, "command buffer is full");
+ if (command.destination == CECDEVICE_BROADCAST || GetLogicalAddresses().IsSet(command.destination))
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s (%X) -> %s (%X): %s (%2X)", ToString(command.initiator), command.initiator, ToString(command.destination), command.destination, ToString(command.opcode), command.opcode);
+ CallbackAddCommand(command);
+ }
}
int CCECClient::MenuStateChanged(const cec_menu_state newState)
{
- CLockObject lock(m_mutex);
-
- LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST), ToString(newState));
-
- if (m_configuration.callbacks &&
- m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_2 &&
- m_configuration.callbacks->CBCecMenuStateChanged)
- return m_configuration.callbacks->CBCecMenuStateChanged(m_configuration.callbackParam, newState);
-
- return 0;
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST), ToString(newState));
+ return CallbackMenuStateChanged(newState);
}
-void CCECClient::Alert(const libcec_alert type, const libcec_parameter ¶m)
+void CCECClient::AddKey(bool bSendComboKey /* = false */)
{
- CLockObject lock(m_mutex);
-
- if (m_configuration.callbacks &&
- m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_0 &&
- m_configuration.callbacks->CBCecAlert)
- m_configuration.callbacks->CBCecAlert(m_configuration.callbackParam, type, param);
-}
-
-void CCECClient::AddLog(const cec_log_message &message)
-{
- CLockObject lock(m_logMutex);
- if (m_configuration.callbacks && m_configuration.callbacks->CBCecLogMessage)
- m_configuration.callbacks->CBCecLogMessage(m_configuration.callbackParam, message);
- else
- m_logBuffer.Push(message);
-}
-
-void CCECClient::AddKey(void)
-{
- CLockObject lock(m_mutex);
+ cec_keypress key;
+ key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
- if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
{
- cec_keypress key;
-
- key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
- key.keycode = m_iCurrentButton;
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key released: %1x", key.keycode);
-
- if (m_configuration.callbacks && m_configuration.callbacks->CBCecKeyPress)
- m_configuration.callbacks->CBCecKeyPress(m_configuration.callbackParam, key);
- else
- m_keyBuffer.Push(key);
- m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
+ CLockObject lock(m_mutex);
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
+ {
+ key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
+
+ if (key.duration > m_configuration.iComboKeyTimeoutMs ||
+ m_configuration.iComboKeyTimeoutMs == 0 ||
+ m_iCurrentButton != m_configuration.comboKey ||
+ bSendComboKey)
+ {
+ key.keycode = m_iCurrentButton;
+
+ m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
+ m_buttontime = 0;
+ }
+ }
}
- m_buttontime = 0;
+ if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key released: %s (%1x)", ToString(key.keycode), key.keycode);
+ CallbackAddKey(key);
+ }
}
void CCECClient::AddKey(const cec_keypress &key)
{
- CLockObject lock(m_mutex);
+ if (key.keycode > CEC_USER_CONTROL_CODE_MAX &&
+ key.keycode < CEC_USER_CONTROL_CODE_SELECT)
+ {
+ // send back the previous key if there is one
+ AddKey();
+ return;
+ }
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %1x", key.keycode);
+ cec_keypress transmitKey(key);
+ cec_user_control_code comboKey(m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5 ?
+ m_configuration.comboKey : CEC_USER_CONTROL_CODE_STOP);
- if (m_configuration.callbacks && m_configuration.callbacks->CBCecKeyPress)
- m_configuration.callbacks->CBCecKeyPress(m_configuration.callbackParam, key);
- else
- m_keyBuffer.Push(key);
+ {
+ CLockObject lock(m_mutex);
+ if (m_configuration.iComboKeyTimeoutMs > 0 && m_iCurrentButton == comboKey && key.duration == 0)
+ {
+ // stop + ok -> exit
+ if (key.keycode == CEC_USER_CONTROL_CODE_SELECT)
+ transmitKey.keycode = CEC_USER_CONTROL_CODE_EXIT;
+ // stop + pause -> root menu
+ else if (key.keycode == CEC_USER_CONTROL_CODE_PAUSE)
+ transmitKey.keycode = CEC_USER_CONTROL_CODE_ROOT_MENU;
+ // stop + play -> dot (which is handled as context menu in xbmc)
+ else if (key.keycode == CEC_USER_CONTROL_CODE_PLAY)
+ transmitKey.keycode = CEC_USER_CONTROL_CODE_DOT;
+ // default, send back the previous key
+ else
+ AddKey(true);
+ }
- m_iCurrentButton = key.duration > 0 ? CEC_USER_CONTROL_CODE_UNKNOWN : key.keycode;
- m_buttontime = key.duration > 0 ? 0 : GetTimeMs();
+ if (m_iCurrentButton == key.keycode)
+ {
+ m_buttontime = GetTimeMs();
+ }
+ else
+ {
+ AddKey();
+ if (key.duration == 0)
+ {
+ m_iCurrentButton = transmitKey.keycode;
+ m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs();
+ }
+ }
+ }
+
+ if (key.keycode != comboKey || key.duration > 0)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode);
+ CallbackAddKey(transmitKey);
+ }
}
void CCECClient::SetCurrentButton(const cec_user_control_code iButtonCode)
void CCECClient::CheckKeypressTimeout(void)
{
- if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && GetTimeMs() - m_buttontime > CEC_BUTTON_TIMEOUT)
+ cec_keypress key;
+
{
- AddKey();
- m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
- }
-}
+ CLockObject lock(m_mutex);
+ uint64_t iNow = GetTimeMs();
+ cec_user_control_code comboKey(m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5 ?
+ m_configuration.comboKey : CEC_USER_CONTROL_CODE_STOP);
+ uint32_t iTimeoutMs(m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5 ?
+ m_configuration.iComboKeyTimeoutMs : CEC_DEFAULT_COMBO_TIMEOUT_MS);
+
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
+ ((m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_buttontime > iTimeoutMs) ||
+ (m_iCurrentButton != comboKey && iNow - m_buttontime > CEC_BUTTON_TIMEOUT)))
+ {
+ key.duration = (unsigned int) (iNow - m_buttontime);
+ key.keycode = m_iCurrentButton;
-void CCECClient::ConfigurationChanged(const libcec_configuration &config)
-{
- CLockObject lock(m_mutex);
+ m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
+ m_buttontime = 0;
+ }
+ else
+ {
+ return;
+ }
+ }
- if (m_configuration.callbacks &&
- m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0 &&
- m_configuration.callbacks->CBCecConfigurationChanged &&
- m_processor->CECInitialised())
- m_configuration.callbacks->CBCecConfigurationChanged(m_configuration.callbackParam, config);
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key auto-released: %s (%1x)", ToString(key.keycode), key.keycode);
+ CallbackAddKey(key);
}
bool CCECClient::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks)
{
- CLockObject lock(m_mutex);
+ CLockObject lock(m_cbMutex);
m_configuration.callbackParam = cbParam;
m_configuration.callbacks = callbacks;
return true;
return m_processor ? m_processor->PingAdapter() : false;
}
-bool CCECClient::GetNextLogMessage(cec_log_message *message)
-{
- return (m_logBuffer.Pop(*message));
-}
-
-bool CCECClient::GetNextKeypress(cec_keypress *key)
-{
- return m_keyBuffer.Pop(*key);
-}
-
-bool CCECClient::GetNextCommand(cec_command *command)
-{
- return m_commandBuffer.Pop(*command);
-}
-
-CStdString CCECClient::GetConnectionInfo(void)
+std::string CCECClient::GetConnectionInfo(void)
{
CStdString strLog;
strLog.Format("libCEC version = %s, client version = %s, firmware version = %d", ToString((cec_server_version)m_configuration.serverVersion), ToString((cec_client_version)m_configuration.clientVersion), m_configuration.iFirmwareVersion);
{
time_t buildTime = (time_t)m_configuration.iFirmwareBuildDate;
strLog.AppendFormat(", firmware build date: %s", asctime(gmtime(&buildTime)));
- strLog = strLog.Left((int)strLog.length() - 1); // strip \n added by asctime
+ strLog = strLog.substr(0, strLog.length() > 0 ? (size_t)(strLog.length() - 1) : 0); // strip \n added by asctime
strLog.append(" +0000");
}
if (!CLibCEC::IsValidPhysicalAddress(m_configuration.iPhysicalAddress))
strLog.AppendFormat(", base device: %s (%X), HDMI port number: %d", ToString(m_configuration.baseDevice), m_configuration.baseDevice, m_configuration.iHDMIPort);
- else
- strLog.AppendFormat(", physical address: %04x", m_configuration.iPhysicalAddress);
+ uint16_t iPhysicalAddress = GetPrimaryDevice()->GetPhysicalAddress(GetLogicalAddresses().primary, false);
+ strLog.AppendFormat(", physical address: %x.%x.%x.%x", (iPhysicalAddress >> 12) & 0xF, (iPhysicalAddress >> 8) & 0xF, (iPhysicalAddress >> 4) & 0xF, iPhysicalAddress & 0xF);
+
+ strLog.AppendFormat(", %s", LIB_CEC->GetLibInfo());
- return strLog;
+ std::string strReturn(strLog.c_str());
+ return strReturn;
}
void CCECClient::SetTVVendorOverride(const cec_vendor_id id)
if (tv)
tv->SetVendorId((uint64_t)id);
}
+
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
}
cec_vendor_id CCECClient::GetTVVendorOverride(void)
return (cec_vendor_id)m_configuration.tvVendor;
}
-void CCECClient::SetOSDName(const CStdString &strDeviceName)
+void CCECClient::SetOSDName(const std::string &strDeviceName)
{
{
CLockObject lock(m_mutex);
LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using OSD name '%s'", __FUNCTION__, strDeviceName.c_str());
CCECBusDevice *primary = GetPrimaryDevice();
- if (primary && !primary->GetCurrentOSDName().Equals(strDeviceName))
+ if (primary && !primary->GetCurrentOSDName().Equals(strDeviceName.c_str()))
{
primary->SetOSDName(strDeviceName);
- if (m_processor && m_processor->IsRunning())
- primary->TransmitOSDName(CECDEVICE_TV);
+ if (m_processor && m_processor->CECInitialised())
+ primary->TransmitOSDName(CECDEVICE_TV, false);
}
+
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
}
-CStdString CCECClient::GetOSDName(void)
+std::string CCECClient::GetOSDName(void)
{
CLockObject lock(m_mutex);
- CStdString strOSDName(m_configuration.strDeviceName);
+ std::string strOSDName(m_configuration.strDeviceName);
return strOSDName;
}
void CCECClient::SetWakeDevices(const cec_logical_addresses &addresses)
{
- CLockObject lock(m_mutex);
- m_configuration.wakeDevices = addresses;
+ {
+ CLockObject lock(m_mutex);
+ m_configuration.wakeDevices = addresses;
+ }
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
}
cec_logical_addresses CCECClient::GetWakeDevices(void)
{
CLockObject lock(m_mutex);
- bNeedReinit = m_processor && m_processor->IsRunning() &&
+ bNeedReinit = m_processor && m_processor->CECInitialised() &&
(m_configuration.deviceTypes != deviceTypes);
m_configuration.deviceTypes = deviceTypes;
}
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
+
if (bNeedReinit)
LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using primary device type '%s'", __FUNCTION__, ToString(deviceTypes[0]));
bool CCECClient::SetDevicePhysicalAddress(const uint16_t iPhysicalAddress)
{
if (!CLibCEC::IsValidPhysicalAddress(iPhysicalAddress))
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - not setting invalid physical address %04x", __FUNCTION__, iPhysicalAddress);
return false;
+ }
// reconfigure all devices
cec_logical_address reactivateSource(CECDEVICE_UNKNOWN);
// and transmit it
if (IsInitialised())
- (*it)->TransmitPhysicalAddress();
+ (*it)->TransmitPhysicalAddress(false);
}
// reactivate the previous active source
if (reactivateSource != CECDEVICE_UNKNOWN &&
- m_processor->IsRunning() &&
+ m_processor->CECInitialised() &&
IsInitialised())
{
CCECBusDevice *device = m_processor->GetDevice(reactivateSource);
device->ActivateSource();
}
+ // persist the new configuration
+ PersistConfiguration(m_configuration);
+
return true;
}
if (m_processor)
{
- if (bEnable)
- return m_processor->UnregisterClient(this);
- else
- return m_processor->RegisterClient(this);
+ m_processor->SwitchMonitoring(bEnable);
+ m_configuration.bMonitorOnly = bEnable;
+ return bEnable ? true: m_processor->RegisterClient(this);
}
return false;
CCECBusDevice *primary = GetPrimaryDevice();
// poll the destination, with the primary as source
if (primary)
- return primary->TransmitPoll(iAddress);
+ return primary->TransmitPoll(iAddress, true);
return m_processor ? m_processor->PollDevice(iAddress) : false;
}
bool CCECClient::SetStreamPath(const uint16_t iPhysicalAddress)
{
- return m_processor ? m_processor->SetStreamPath(iPhysicalAddress) : false;
+ bool bReturn(false);
+
+ CCECBusDevice *device = GetDeviceByType(CEC_DEVICE_TYPE_TV);
+ if (device)
+ {
+ device->SetStreamPath(iPhysicalAddress);
+ bReturn = device->GetHandler()->TransmitSetStreamPath(iPhysicalAddress, false);
+ device->MarkHandlerReady();
+ }
+ else
+ {
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "only the TV is allowed to send CEC_OPCODE_SET_STREAM_PATH");
+ }
+
+ return bReturn;
}
cec_logical_addresses CCECClient::GetLogicalAddresses(void)
bool CCECClient::PersistConfiguration(const libcec_configuration &configuration)
{
- return m_processor ? m_processor->PersistConfiguration(configuration) : false;
+ return m_processor && IsRegistered() ?
+ m_processor->PersistConfiguration(configuration) :
+ false;
}
void CCECClient::RescanActiveDevices(void)
cec_logical_address activeSource = m_processor->GetActiveSource();
CCECBusDevice *device = m_processor->GetDevice(activeSource);
if (device)
- bReturn = device->IsHandledByLibCEC();
+ bReturn = device->IsHandledByLibCEC() && !device->GetHandler()->ActiveSourcePending();
}
return bReturn;
}
+
+void CCECClient::SourceActivated(const cec_logical_address logicalAddress)
+{
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source activated: %s (%x)", ToString(logicalAddress), logicalAddress);
+ CallbackSourceActivated(true, logicalAddress);
+}
+
+void CCECClient::SourceDeactivated(const cec_logical_address logicalAddress)
+{
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source deactivated: %s (%x)", ToString(logicalAddress), logicalAddress);
+ CallbackSourceActivated(false, logicalAddress);
+}
+
+void CCECClient::CallbackAddCommand(const cec_command &command)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks && m_configuration.callbacks->CBCecCommand)
+ m_configuration.callbacks->CBCecCommand(m_configuration.callbackParam, command);
+}
+
+void CCECClient::CallbackAddKey(const cec_keypress &key)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks && m_configuration.callbacks->CBCecKeyPress)
+ {
+ // prevent double taps
+ int64_t now = GetTimeMs();
+ if (m_lastKeypress.keycode != key.keycode ||
+ key.duration > 0 ||
+ now - m_iLastKeypressTime >= m_configuration.iDoubleTapTimeoutMs)
+ {
+ // no double tap
+ if (key.duration == 0)
+ m_iLastKeypressTime = now;
+ m_lastKeypress = key;
+ m_configuration.callbacks->CBCecKeyPress(m_configuration.callbackParam, key);
+ }
+ }
+}
+
+void CCECClient::CallbackAddLog(const cec_log_message &message)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks && m_configuration.callbacks->CBCecLogMessage)
+ m_configuration.callbacks->CBCecLogMessage(m_configuration.callbackParam, message);
+}
+
+void CCECClient::CallbackConfigurationChanged(const libcec_configuration &config)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks &&
+ m_configuration.callbacks->CBCecConfigurationChanged &&
+ m_processor->CECInitialised())
+ m_configuration.callbacks->CBCecConfigurationChanged(m_configuration.callbackParam, config);
+}
+
+void CCECClient::CallbackSourceActivated(bool bActivated, const cec_logical_address logicalAddress)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks &&
+ m_configuration.callbacks->CBCecSourceActivated)
+ m_configuration.callbacks->CBCecSourceActivated(m_configuration.callbackParam, logicalAddress, bActivated ? 1 : 0);
+}
+
+void CCECClient::CallbackAlert(const libcec_alert type, const libcec_parameter ¶m)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks &&
+ m_configuration.callbacks->CBCecAlert)
+ m_configuration.callbacks->CBCecAlert(m_configuration.callbackParam, type, param);
+}
+
+int CCECClient::CallbackMenuStateChanged(const cec_menu_state newState)
+{
+ CLockObject lock(m_cbMutex);
+ if (m_configuration.callbacks &&
+ m_configuration.callbacks->CBCecMenuStateChanged)
+ return m_configuration.callbacks->CBCecMenuStateChanged(m_configuration.callbackParam, newState);
+ return 0;
+}