m_bRegistered(false),
m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
m_buttontime(0),
- m_iPreventForwardingPowerOffCommand(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 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
if (GetPrimaryLogicalAdddress() != iLogicalAddress)
{
- LIB_CEC->AddLog(CEC_LOG_NOTICE, "<< setting primary logical address to %1x", iLogicalAddress);
+ LIB_CEC->AddLog(CEC_LOG_NOTICE, "setting primary logical address to %1x", iLogicalAddress);
{
CLockObject lock(m_mutex);
m_configuration.logicalAddresses.primary = iLogicalAddress;
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);
// 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;
- }
-
- // 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;
- }
-
- // client version 1.6.3
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_3)
- {
- configuration.bMonitorOnly = m_configuration.bMonitorOnly;
- }
-
- // client version 1.8.0
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_0)
- configuration.cecVersion = m_configuration.cecVersion;
-
- // client version 1.8.2
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_2)
- configuration.adapterType = m_configuration.adapterType;
+ 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;
+ 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;
return true;
}
// 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.bPowerOffDevicesOnStandby = configuration.bPowerOffDevicesOnStandby;
- m_configuration.bShutdownOnStandby = configuration.bShutdownOnStandby;
- }
-
- // client version 1.6.2
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_2)
- {
- memcpy(m_configuration.strDeviceLanguage, configuration.strDeviceLanguage, 3);
- }
-
- // client version 1.6.3
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_3)
- {
- m_configuration.bMonitorOnly = configuration.bMonitorOnly;
- }
-
- // client version 1.8.0
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_0)
- m_configuration.cecVersion = configuration.cecVersion;
-
- // client version 1.8.2
- if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_2)
- m_configuration.adapterType = configuration.adapterType;
-
- // ensure that there is at least 1 device type set
- if (m_configuration.deviceTypes.IsEmpty())
- m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
+ 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.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
}
bool bNeedReinit(false);
if (command.destination == CECDEVICE_BROADCAST || GetLogicalAddresses().IsSet(command.destination))
{
- 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);
+ 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)
{
- LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST), ToString(newState));
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST), ToString(newState));
return CallbackMenuStateChanged(newState);
}
// send back the previous key if there is one
AddKey();
+ if (key.keycode > CEC_USER_CONTROL_CODE_MAX &&
+ key.keycode < CEC_USER_CONTROL_CODE_SELECT)
+ return;
+
cec_keypress transmitKey(key);
{
CLockObject lock(m_mutex);
- if (key.duration > 0 || key.keycode > CEC_USER_CONTROL_CODE_MAX)
- {
- transmitKey.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
- }
- else if (m_iCurrentButton == COMBO_KEY)
+ if (m_iCurrentButton == COMBO_KEY && 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_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)
AddKey(true);
}
- m_iCurrentButton = transmitKey.keycode;
- m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs();
+ if (key.duration == 0)
+ {
+ m_iCurrentButton = transmitKey.keycode;
+ m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs();
+ }
}
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode);
- CallbackAddKey(transmitKey);
+ if (key.keycode != COMBO_KEY || 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)
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);
-}
-
std::string CCECClient::GetConnectionInfo(void)
{
CStdString strLog;
{
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());
CCECBusDevice *primary = GetPrimaryDevice();
// poll the destination, with the primary as source
if (primary)
- return primary->TransmitPoll(iAddress, false);
+ return primary->TransmitPoll(iAddress, true);
return m_processor ? m_processor->PollDevice(iAddress) : false;
}
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::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);
- return;
- }
- }
- m_commandBuffer.Push(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)
{
- 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);
- return;
}
}
- m_keyBuffer.Push(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);
- return;
- }
- }
- m_logBuffer.Push(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.clientVersion >= CEC_CLIENT_VERSION_1_5_0 &&
m_configuration.callbacks->CBCecConfigurationChanged &&
m_processor->CECInitialised())
m_configuration.callbacks->CBCecConfigurationChanged(m_configuration.callbackParam, config);
{
CLockObject lock(m_cbMutex);
if (m_configuration.callbacks &&
- m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_7_1 &&
m_configuration.callbacks->CBCecSourceActivated)
m_configuration.callbacks->CBCecSourceActivated(m_configuration.callbackParam, logicalAddress, bActivated ? 1 : 0);
}
{
CLockObject lock(m_cbMutex);
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);
}
{
CLockObject lock(m_cbMutex);
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;