Merge pull request #4240 from MilhouseVH/cec-key-repeat

[libcec] Add repeating key support from popcornmix repo
This commit is contained in:
Stephan Raue 2015-07-22 11:08:47 +02:00
commit cf5efca1c5
3 changed files with 967 additions and 0 deletions

View File

@ -0,0 +1,859 @@
From ec982e9800ae312972d306b67779215a2add6cde Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 24 Oct 2014 13:45:21 +0100
Subject: [PATCH 1/6] Make released key polling wait for exact time until key
gets released
---
src/libcec/CECClient.cpp | 16 ++++++++++++++--
src/libcec/CECClient.h | 2 +-
src/libcec/CECProcessor.cpp | 8 +++++---
src/libcec/LibCEC.cpp | 10 ++++++++--
src/libcec/LibCEC.h | 4 +++-
5 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index 35c2d3e..e307c0e 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -1067,7 +1067,7 @@ void CCECClient::SetCurrentButton(const cec_user_control_code iButtonCode)
AddKey(key);
}
-void CCECClient::CheckKeypressTimeout(void)
+uint16_t CCECClient::CheckKeypressTimeout(void)
{
cec_keypress key;
@@ -1091,12 +1091,24 @@ void CCECClient::CheckKeypressTimeout(void)
}
else
{
- return;
+ // time when this keypress will be released and we'd like to be called again
+ unsigned int timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton == comboKey && iTimeoutMs > 0)
+ timeout = iTimeoutMs - (iNow - m_buttontime) + 1;
+ else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey)
+ timeout = CEC_BUTTON_TIMEOUT - (iNow - m_buttontime) + 1;
+ if (timeout > CEC_PROCESSOR_SIGNAL_WAIT_TIME)
+ {
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "Unexpected timeout: %d (%.3f %.3f %.3f) k:%02x", timeout, iNow*1e-3, m_buttontime*1e-3, CEC_BUTTON_TIMEOUT*1e-3, m_iCurrentButton);
+ timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
+ }
+ return timeout;
}
}
LIB_CEC->AddLog(CEC_LOG_DEBUG, "key auto-released: %s (%1x)", ToString(key.keycode), key.keycode);
QueueAddKey(key);
+ return CEC_PROCESSOR_SIGNAL_WAIT_TIME;
}
bool CCECClient::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks)
diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h
index 12f8a3b..c9ce5e3 100644
--- a/src/libcec/CECClient.h
+++ b/src/libcec/CECClient.h
@@ -272,7 +272,7 @@ namespace CEC
virtual void AddKey(bool bSendComboKey = false);
virtual void AddKey(const cec_keypress &key);
virtual void SetCurrentButton(const cec_user_control_code iButtonCode);
- virtual void CheckKeypressTimeout(void);
+ virtual uint16_t CheckKeypressTimeout(void);
virtual void SourceActivated(const cec_logical_address logicalAddress);
virtual void SourceDeactivated(const cec_logical_address logicalAddress);
diff --git a/src/libcec/CECProcessor.cpp b/src/libcec/CECProcessor.cpp
index 99f71aa..604b950 100644
--- a/src/libcec/CECProcessor.cpp
+++ b/src/libcec/CECProcessor.cpp
@@ -52,7 +52,6 @@
using namespace CEC;
using namespace PLATFORM;
-#define CEC_PROCESSOR_SIGNAL_WAIT_TIME 1000
#define ACTIVE_SOURCE_CHECK_INTERVAL 500
#define TV_PRESENT_CHECK_INTERVAL 30000
@@ -260,6 +259,7 @@ bool CCECProcessor::OnCommandReceived(const cec_command &command)
void *CCECProcessor::Process(void)
{
+ uint16_t timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
if (!m_connCheck)
@@ -274,13 +274,13 @@ void *CCECProcessor::Process(void)
while (!IsStopped() && m_communication->IsOpen())
{
// wait for a new incoming command, and process it
- if (m_inBuffer.Pop(command, CEC_PROCESSOR_SIGNAL_WAIT_TIME))
+ if (m_inBuffer.Pop(command, timeout))
ProcessCommand(command);
if (CECInitialised() && !IsStopped())
{
// check clients for keypress timeouts
- m_libcec->CheckKeypressTimeout();
+ timeout = m_libcec->CheckKeypressTimeout();
// check if we need to replace handlers
ReplaceHandlers();
@@ -311,6 +311,8 @@ void *CCECProcessor::Process(void)
tvPresentCheck.Init(TV_PRESENT_CHECK_INTERVAL);
}
}
+ else
+ timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
}
return NULL;
diff --git a/src/libcec/LibCEC.cpp b/src/libcec/LibCEC.cpp
index af36b79..5ccb8dd 100644
--- a/src/libcec/LibCEC.cpp
+++ b/src/libcec/LibCEC.cpp
@@ -361,11 +361,17 @@ bool CLibCEC::IsValidPhysicalAddress(uint16_t iPhysicalAddress)
iPhysicalAddress <= CEC_MAX_PHYSICAL_ADDRESS;
}
-void CLibCEC::CheckKeypressTimeout(void)
+uint16_t CLibCEC::CheckKeypressTimeout(void)
{
+ uint16_t timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
// check all clients
for (std::vector<CECClientPtr>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
- (*it)->CheckKeypressTimeout();
+ {
+ uint16_t t = (*it)->CheckKeypressTimeout();
+ if (t < timeout)
+ timeout = t;
+ }
+ return timeout;
}
void CLibCEC::AddLog(const cec_log_level level, const char *strFormat, ...)
diff --git a/src/libcec/LibCEC.h b/src/libcec/LibCEC.h
index 6d9a229..d9d1e7b 100644
--- a/src/libcec/LibCEC.h
+++ b/src/libcec/LibCEC.h
@@ -39,6 +39,8 @@
#include "CECTypeUtils.h"
#include <memory>
+#define CEC_PROCESSOR_SIGNAL_WAIT_TIME 1000
+
namespace CEC
{
class CAdapterCommunication;
@@ -125,7 +127,7 @@ namespace CEC
void AddLog(const cec_log_level level, const char *strFormat, ...);
void AddCommand(const cec_command &command);
- void CheckKeypressTimeout(void);
+ uint16_t CheckKeypressTimeout(void);
void Alert(const libcec_alert type, const libcec_parameter &param);
static bool IsValidPhysicalAddress(uint16_t iPhysicalAddress);
--
1.9.1
From 41f0f3ec9ac136da3565c96fd5a7075499f3938d Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 24 Oct 2014 13:51:34 +0100
Subject: [PATCH 2/6] Keep track of time since initial button press and last
button update
---
src/libcec/CECClient.cpp | 44 +++++++++++++++++++++++++++-----------------
src/libcec/CECClient.h | 3 ++-
2 files changed, 29 insertions(+), 18 deletions(-)
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index e307c0e..e7935b9 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -54,7 +54,8 @@ CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration &con
m_bInitialised(false),
m_bRegistered(false),
m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
- m_buttontime(0),
+ m_initialButtontime(0),
+ m_updateButtontime(0),
m_iPreventForwardingPowerOffCommand(0),
m_iLastKeypressTime(0)
{
@@ -981,9 +982,10 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */)
CLockObject lock(m_mutex);
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
{
- key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
+ unsigned int duration = (unsigned int) (GetTimeMs() - m_updateButtontime);
+ key.duration = (unsigned int) (GetTimeMs() - m_initialButtontime);
- if (key.duration > m_configuration.iComboKeyTimeoutMs ||
+ if (duration > m_configuration.iComboKeyTimeoutMs ||
m_configuration.iComboKeyTimeoutMs == 0 ||
m_iCurrentButton != m_configuration.comboKey ||
bSendComboKey)
@@ -991,14 +993,15 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */)
key.keycode = m_iCurrentButton;
m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
- m_buttontime = 0;
+ m_initialButtontime = 0;
+ m_updateButtontime = 0;
}
}
}
if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN)
{
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key released: %s (%1x)", ToString(key.keycode), key.keycode);
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key released: %s (%1x) D:%dms", ToString(key.keycode), key.keycode, key.duration);
QueueAddKey(key);
}
}
@@ -1012,7 +1015,7 @@ void CCECClient::AddKey(const cec_keypress &key)
AddKey();
return;
}
-
+ bool isrepeat = false;
cec_keypress transmitKey(key);
cec_user_control_code comboKey(m_configuration.clientVersion >= LIBCEC_VERSION_TO_UINT(2, 0, 5) ?
m_configuration.comboKey : CEC_USER_CONTROL_CODE_STOP);
@@ -1035,22 +1038,27 @@ void CCECClient::AddKey(const cec_keypress &key)
AddKey(true);
}
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x) current(%lx) duration(%d)", ToString(transmitKey.keycode), transmitKey.keycode, m_iCurrentButton, key.duration);
+
if (m_iCurrentButton == key.keycode)
{
- m_buttontime = GetTimeMs();
+ m_updateButtontime = GetTimeMs();
+ isrepeat = true;
}
else
{
- AddKey();
+ if (m_iCurrentButton != transmitKey.keycode)
+ AddKey();
if (key.duration == 0)
{
m_iCurrentButton = transmitKey.keycode;
- m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs();
+ m_initialButtontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs();
+ m_updateButtontime = m_initialButtontime;
}
}
}
- if (key.keycode != comboKey || key.duration > 0)
+ if (!isrepeat && (key.keycode != comboKey || key.duration > 0))
{
LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode);
QueueAddKey(transmitKey);
@@ -1074,32 +1082,34 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
{
CLockObject lock(m_mutex);
uint64_t iNow = GetTimeMs();
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s T:%.3f", __FUNCTION__, iNow*1e-3);
cec_user_control_code comboKey(m_configuration.clientVersion >= LIBCEC_VERSION_TO_UINT(2, 0, 5) ?
m_configuration.comboKey : CEC_USER_CONTROL_CODE_STOP);
uint32_t iTimeoutMs(m_configuration.clientVersion >= LIBCEC_VERSION_TO_UINT(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)))
+ ((m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_updateButtontime > iTimeoutMs) ||
+ (m_iCurrentButton != comboKey && iNow - m_updateButtontime > CEC_BUTTON_TIMEOUT)))
{
- key.duration = (unsigned int) (iNow - m_buttontime);
+ key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = m_iCurrentButton;
m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
- m_buttontime = 0;
+ m_initialButtontime = 0;
+ m_updateButtontime = 0;
}
else
{
// time when this keypress will be released and we'd like to be called again
unsigned int timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton == comboKey && iTimeoutMs > 0)
- timeout = iTimeoutMs - (iNow - m_buttontime) + 1;
+ timeout = iTimeoutMs - (iNow - m_updateButtontime) + 1;
else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey)
- timeout = CEC_BUTTON_TIMEOUT - (iNow - m_buttontime) + 1;
+ timeout = CEC_BUTTON_TIMEOUT - (iNow - m_updateButtontime) + 1;
if (timeout > CEC_PROCESSOR_SIGNAL_WAIT_TIME)
{
- LIB_CEC->AddLog(CEC_LOG_ERROR, "Unexpected timeout: %d (%.3f %.3f %.3f) k:%02x", timeout, iNow*1e-3, m_buttontime*1e-3, CEC_BUTTON_TIMEOUT*1e-3, m_iCurrentButton);
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "Unexpected timeout: %d (%.3f %.3f %.3f) k:%02x", timeout, iNow*1e-3, m_updateButtontime*1e-3, CEC_BUTTON_TIMEOUT*1e-3, m_iCurrentButton);
timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
}
return timeout;
diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h
index c9ce5e3..611c68b 100644
--- a/src/libcec/CECClient.h
+++ b/src/libcec/CECClient.h
@@ -404,7 +404,8 @@ namespace CEC
PLATFORM::CMutex m_mutex; /**< mutex for changes to this instance */
PLATFORM::CMutex m_cbMutex; /**< mutex that is held when doing anything with callbacks */
cec_user_control_code m_iCurrentButton; /**< the control code of the button that's currently held down (if any) */
- int64_t m_buttontime; /**< the timestamp when the button was pressed (in seconds since epoch), or 0 if none was pressed. */
+ int64_t m_initialButtontime; /**< the timestamp when the button was initially pressed (in seconds since epoch), or 0 if none was pressed. */
+ int64_t m_updateButtontime; /**< the timestamp when the button was updated (in seconds since epoch), or 0 if none was pressed. */
int64_t m_iPreventForwardingPowerOffCommand; /**< prevent forwarding standby commands until this time */
int64_t m_iLastKeypressTime; /**< last time a key press was sent to the client */
cec_keypress m_lastKeypress; /**< the last key press that was sent to the client */
--
1.9.1
From 273ead6980b69eddf98810eb1eb33d94a7d74fce Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 28 Oct 2014 00:09:18 +0000
Subject: [PATCH 3/6] Support repeating button presses with configurable repeat
rate
---
include/cectypes.h | 6 ++
src/libcec/CECClient.cpp | 100 +++++++++++++++++++----
src/libcec/CECClient.h | 6 +-
src/libcec/implementations/CECCommandHandler.cpp | 2 +-
4 files changed, 96 insertions(+), 18 deletions(-)
diff --git a/include/cectypes.h b/include/cectypes.h
index acff259..8f098ef 100644
--- a/include/cectypes.h
+++ b/include/cectypes.h
@@ -1493,6 +1493,8 @@ struct libcec_configuration
XXX changed meaning in 2.2.0 to not break binary compatibility. next major (3.0) release will fix it in a nicer way */
cec_user_control_code comboKey; /*!< key code that initiates combo keys. defaults to CEC_USER_CONTROL_CODE_F1_BLUE. CEC_USER_CONTROL_CODE_UNKNOWN to disable. added in 2.0.5 */
uint32_t iComboKeyTimeoutMs; /*!< timeout until the combo key is sent as normal keypress */
+ uint32_t iButtonRepeatRateMs; /*!< rate at which buttons autorepeat. 0 means rely on CEC device */
+ uint32_t iButtonReleaseDelayMs;/*!< duration after last update until a button is considered released */
#ifdef __cplusplus
libcec_configuration(void) { Clear(); }
@@ -1527,6 +1529,8 @@ struct libcec_configuration
cecVersion == other.cecVersion &&
adapterType == other.adapterType &&
iDoubleTapTimeout50Ms == other.iDoubleTapTimeout50Ms &&
+ iButtonRepeatRateMs == other.iButtonRepeatRateMs &&
+ iButtonReleaseDelayMs == other.iButtonReleaseDelayMs &&
(other.clientVersion <= LIBCEC_VERSION_TO_UINT(2, 0, 4) || comboKey == other.comboKey) &&
(other.clientVersion <= LIBCEC_VERSION_TO_UINT(2, 0, 4) || iComboKeyTimeoutMs == other.iComboKeyTimeoutMs) &&
(other.clientVersion < LIBCEC_VERSION_TO_UINT(2, 1, 0) || bPowerOnScreensaver == other.bPowerOnScreensaver));
@@ -1567,6 +1571,8 @@ struct libcec_configuration
iDoubleTapTimeout50Ms = CEC_DOUBLE_TAP_TIMEOUT_50_MS;
comboKey = CEC_USER_CONTROL_CODE_STOP;
iComboKeyTimeoutMs = CEC_DEFAULT_COMBO_TIMEOUT_MS;
+ iButtonRepeatRateMs = 0;
+ iButtonReleaseDelayMs = CEC_BUTTON_TIMEOUT;
memset(strDeviceName, 0, 13);
deviceTypes.Clear();
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index e7935b9..598628d 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -56,6 +56,10 @@ CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration &con
m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
m_initialButtontime(0),
m_updateButtontime(0),
+ m_repeatButtontime(0),
+ m_releaseButtontime(0),
+ m_pressedButtoncount(0),
+ m_releasedButtoncount(0),
m_iPreventForwardingPowerOffCommand(0),
m_iLastKeypressTime(0)
{
@@ -851,6 +855,9 @@ bool CCECClient::GetCurrentConfiguration(libcec_configuration &configuration)
configuration.bMonitorOnly = m_configuration.bMonitorOnly;
configuration.cecVersion = m_configuration.cecVersion;
configuration.adapterType = m_configuration.adapterType;
+ configuration.iDoubleTapTimeout50Ms = m_configuration.iDoubleTapTimeout50Ms;
+ configuration.iButtonRepeatRateMs = m_configuration.iButtonRepeatRateMs;
+ configuration.iButtonReleaseDelayMs = m_configuration.iButtonReleaseDelayMs;
return true;
}
@@ -894,6 +901,9 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration)
m_configuration.cecVersion = configuration.cecVersion;
m_configuration.adapterType = configuration.adapterType;
m_configuration.iDoubleTapTimeout50Ms = configuration.iDoubleTapTimeout50Ms;
+ m_configuration.iButtonRepeatRateMs = configuration.iButtonRepeatRateMs;
+ m_configuration.iButtonReleaseDelayMs = configuration.iButtonReleaseDelayMs;
+
m_configuration.deviceTypes.Add(configuration.deviceTypes[0]);
if (m_configuration.clientVersion >= LIBCEC_VERSION_TO_UINT(2, 0, 5))
@@ -950,6 +960,7 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration)
primary->ActivateSource();
}
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: %d:%d:%d", __FUNCTION__, DoubleTapTimeoutMS(), m_configuration.iButtonRepeatRateMs, m_configuration.iButtonReleaseDelayMs);
return true;
}
@@ -973,11 +984,15 @@ void CCECClient::AddCommand(const cec_command &command)
}
}
-void CCECClient::AddKey(bool bSendComboKey /* = false */)
+void CCECClient::AddKey(bool bSendComboKey /* = false */, bool bButtonRelease /* = false */)
{
cec_keypress key;
key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
+ // we ignore button releases when supporting repeating keys
+ if (bButtonRelease && m_configuration.iButtonRepeatRateMs && m_configuration.iButtonReleaseDelayMs)
+ return;
+
{
CLockObject lock(m_mutex);
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
@@ -995,6 +1010,10 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */)
m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
m_initialButtontime = 0;
m_updateButtontime = 0;
+ m_repeatButtontime = 0;
+ m_releaseButtontime = 0;
+ m_pressedButtoncount = 0;
+ m_releasedButtoncount = 0;
}
}
}
@@ -1012,6 +1031,7 @@ void CCECClient::AddKey(const cec_keypress &key)
key.keycode < CEC_USER_CONTROL_CODE_SELECT)
{
// send back the previous key if there is one
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "Unexpected key %s (%1x) D:%dms", ToString(key.keycode), key.keycode, key.duration);
AddKey();
return;
}
@@ -1035,7 +1055,10 @@ void CCECClient::AddKey(const cec_keypress &key)
transmitKey.keycode = CEC_USER_CONTROL_CODE_DOT;
// default, send back the previous key
else
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "Combo key %s (%1x) D%dms:", ToString(key.keycode), key.keycode, key.duration);
AddKey(true);
+ }
}
LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x) current(%lx) duration(%d)", ToString(transmitKey.keycode), transmitKey.keycode, m_iCurrentButton, key.duration);
@@ -1043,17 +1066,44 @@ void CCECClient::AddKey(const cec_keypress &key)
if (m_iCurrentButton == key.keycode)
{
m_updateButtontime = GetTimeMs();
- isrepeat = true;
+ m_releaseButtontime = m_updateButtontime + (m_configuration.iButtonReleaseDelayMs ? m_configuration.iButtonReleaseDelayMs : CEC_BUTTON_TIMEOUT);
+ // want to have seen some updated before considering a repeat
+ if (m_configuration.iButtonRepeatRateMs)
+ {
+ if (!m_repeatButtontime && m_pressedButtoncount > 1)
+ m_repeatButtontime = m_initialButtontime + DoubleTapTimeoutMS();
+ isrepeat = true;
+ }
+ m_pressedButtoncount++;
}
else
{
if (m_iCurrentButton != transmitKey.keycode)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "Changed key %s (%1x) D:%dms cur:%lx", ToString(transmitKey.keycode), transmitKey.keycode, transmitKey.duration, m_iCurrentButton);
AddKey();
+ }
if (key.duration == 0)
{
m_iCurrentButton = transmitKey.keycode;
- m_initialButtontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs();
- m_updateButtontime = m_initialButtontime;
+ if (m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN)
+ {
+ m_initialButtontime = 0;
+ m_updateButtontime = 0;
+ m_repeatButtontime = 0;
+ m_releaseButtontime = 0;
+ m_pressedButtoncount = 0;
+ m_releasedButtoncount = 0;
+ }
+ else
+ {
+ m_initialButtontime = GetTimeMs();
+ m_updateButtontime = m_initialButtontime;
+ m_repeatButtontime = 0; // set this on next update
+ m_releaseButtontime = m_initialButtontime + (m_configuration.iButtonReleaseDelayMs ? m_configuration.iButtonReleaseDelayMs : CEC_BUTTON_TIMEOUT);
+ m_pressedButtoncount = 1;
+ m_releasedButtoncount = 0;
+ }
}
}
}
@@ -1072,12 +1122,16 @@ void CCECClient::SetCurrentButton(const cec_user_control_code iButtonCode)
key.duration = 0;
key.keycode = iButtonCode;
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "SetCurrentButton %s (%1x) D:%dms cur:%lx", ToString(key.keycode), key.keycode, key.duration);
AddKey(key);
}
uint16_t CCECClient::CheckKeypressTimeout(void)
{
+ // time when we'd like to be called again
+ unsigned int timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
cec_keypress key;
+ key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
{
CLockObject lock(m_mutex);
@@ -1089,8 +1143,8 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
m_configuration.iComboKeyTimeoutMs : CEC_DEFAULT_COMBO_TIMEOUT_MS);
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
- ((m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_updateButtontime > iTimeoutMs) ||
- (m_iCurrentButton != comboKey && iNow - m_updateButtontime > CEC_BUTTON_TIMEOUT)))
+ ((m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_updateButtontime >= iTimeoutMs) ||
+ (m_iCurrentButton != comboKey && m_releaseButtontime && iNow >= (uint64_t)m_releaseButtontime)))
{
key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = m_iCurrentButton;
@@ -1098,27 +1152,41 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
m_initialButtontime = 0;
m_updateButtontime = 0;
+ m_repeatButtontime = 0;
+ m_releaseButtontime = 0;
+ m_pressedButtoncount = 0;
+ m_releasedButtoncount = 0;
+ }
+ else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
+ (m_iCurrentButton != comboKey && m_repeatButtontime && iNow >= (uint64_t)m_repeatButtontime))
+ {
+ key.duration = 0;
+ key.keycode = m_iCurrentButton;
+ m_repeatButtontime = iNow + m_configuration.iButtonRepeatRateMs;
+ timeout = std::min((uint64_t)timeout, m_repeatButtontime - iNow);
}
else
{
- // time when this keypress will be released and we'd like to be called again
- unsigned int timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton == comboKey && iTimeoutMs > 0)
- timeout = iTimeoutMs - (iNow - m_updateButtontime) + 1;
- else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey)
- timeout = CEC_BUTTON_TIMEOUT - (iNow - m_updateButtontime) + 1;
+ timeout = std::min((uint64_t)timeout, m_updateButtontime - iNow + iTimeoutMs);
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey && m_releaseButtontime)
+ timeout = std::min((uint64_t)timeout, m_releaseButtontime - iNow);
+ if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey && m_repeatButtontime)
+ timeout = std::min((uint64_t)timeout, m_repeatButtontime - iNow);
if (timeout > CEC_PROCESSOR_SIGNAL_WAIT_TIME)
{
- LIB_CEC->AddLog(CEC_LOG_ERROR, "Unexpected timeout: %d (%.3f %.3f %.3f) k:%02x", timeout, iNow*1e-3, m_updateButtontime*1e-3, CEC_BUTTON_TIMEOUT*1e-3, m_iCurrentButton);
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "Unexpected timeout: %d (%.3f %.3f %.3f) k:%02x", timeout, iNow*1e-3, m_updateButtontime*1e-3, m_releaseButtontime*1e-3, m_iCurrentButton);
timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
}
- return timeout;
}
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key %s: %s (%1x) timeout:%dms (rel:%d,rep:%d,prs:%d,rel:%d)", key.keycode == CEC_USER_CONTROL_CODE_UNKNOWN ? "idle" : key.duration ? "released" : "repeated",
+ ToString(m_iCurrentButton), m_iCurrentButton, timeout, (int)(m_releaseButtontime ? m_releaseButtontime - iNow : 0), (int)(m_repeatButtontime ? m_repeatButtontime - iNow : 0), m_pressedButtoncount, m_releasedButtoncount);
}
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key auto-released: %s (%1x)", ToString(key.keycode), key.keycode);
- QueueAddKey(key);
- return CEC_PROCESSOR_SIGNAL_WAIT_TIME;
+ if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN)
+ QueueAddKey(key);
+
+ return timeout;
}
bool CCECClient::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks)
diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h
index 611c68b..adeb5af 100644
--- a/src/libcec/CECClient.h
+++ b/src/libcec/CECClient.h
@@ -269,7 +269,7 @@ namespace CEC
// callbacks
virtual void Alert(const libcec_alert type, const libcec_parameter &param) { QueueAlert(type, param); }
virtual void AddLog(const cec_log_message &message) { QueueAddLog(message); }
- virtual void AddKey(bool bSendComboKey = false);
+ virtual void AddKey(bool bSendComboKey = false, bool bButtonRelease = false);
virtual void AddKey(const cec_keypress &key);
virtual void SetCurrentButton(const cec_user_control_code iButtonCode);
virtual uint16_t CheckKeypressTimeout(void);
@@ -406,6 +406,10 @@ namespace CEC
cec_user_control_code m_iCurrentButton; /**< the control code of the button that's currently held down (if any) */
int64_t m_initialButtontime; /**< the timestamp when the button was initially pressed (in seconds since epoch), or 0 if none was pressed. */
int64_t m_updateButtontime; /**< the timestamp when the button was updated (in seconds since epoch), or 0 if none was pressed. */
+ int64_t m_repeatButtontime; /**< the timestamp when the button will next repeat (in seconds since epoch), or 0 if repeat is disabled. */
+ int64_t m_releaseButtontime; /**< the timestamp when the button will be released (in seconds since epoch), or 0 if none was pressed. */
+ int32_t m_pressedButtoncount; /**< the number of times a button released message has been seen for this press. */
+ int32_t m_releasedButtoncount; /**< the number of times a button pressed message has been seen for this press. */
int64_t m_iPreventForwardingPowerOffCommand; /**< prevent forwarding standby commands until this time */
int64_t m_iLastKeypressTime; /**< last time a key press was sent to the client */
cec_keypress m_lastKeypress; /**< the last key press that was sent to the client */
diff --git a/src/libcec/implementations/CECCommandHandler.cpp b/src/libcec/implementations/CECCommandHandler.cpp
index 6d6244e..d64186f 100644
--- a/src/libcec/implementations/CECCommandHandler.cpp
+++ b/src/libcec/implementations/CECCommandHandler.cpp
@@ -770,7 +770,7 @@ int CCECCommandHandler::HandleUserControlRelease(const cec_command &command)
CECClientPtr client = m_processor->GetClient(command.destination);
if (client)
- client->AddKey();
+ client->AddKey(false, true);
return COMMAND_HANDLED;
}
--
1.9.1
From 3336d0827f7fd159430f3431642b07090c06c869 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 28 Oct 2014 01:21:35 +0000
Subject: [PATCH 4/6] Skip double press removal. It is handled through other
means.
---
src/libcec/CECClient.cpp | 18 +-----------------
src/libcec/CECClient.h | 2 --
2 files changed, 1 insertion(+), 19 deletions(-)
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index 598628d..dccd874 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -60,11 +60,8 @@ CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration &con
m_releaseButtontime(0),
m_pressedButtoncount(0),
m_releasedButtoncount(0),
- m_iPreventForwardingPowerOffCommand(0),
- m_iLastKeypressTime(0)
+ m_iPreventForwardingPowerOffCommand(0)
{
- m_lastKeypress.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
- m_lastKeypress.duration = 0;
m_configuration.Clear();
// set the initial configuration
SetConfiguration(configuration);
@@ -1647,20 +1644,7 @@ 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 >= DoubleTapTimeoutMS())
- {
- // 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)
diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h
index adeb5af..43a713b 100644
--- a/src/libcec/CECClient.h
+++ b/src/libcec/CECClient.h
@@ -411,8 +411,6 @@ namespace CEC
int32_t m_pressedButtoncount; /**< the number of times a button released message has been seen for this press. */
int32_t m_releasedButtoncount; /**< the number of times a button pressed message has been seen for this press. */
int64_t m_iPreventForwardingPowerOffCommand; /**< prevent forwarding standby commands until this time */
- int64_t m_iLastKeypressTime; /**< last time a key press was sent to the client */
- cec_keypress m_lastKeypress; /**< the last key press that was sent to the client */
PLATFORM::SyncedBuffer<CCallbackWrap*> m_callbackCalls;
};
}
--
1.9.1
From 0dd0234f620a546bfa843172648383f83d88088c Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 3 Nov 2014 23:28:04 +0000
Subject: [PATCH 5/6] Pass through duration on all button repeats
---
src/libcec/CECClient.cpp | 34 ++++++++++++++++++++++++----------
1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index dccd874..1946148 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -986,10 +986,6 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */, bool bButtonRelease /*
cec_keypress key;
key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
- // we ignore button releases when supporting repeating keys
- if (bButtonRelease && m_configuration.iButtonRepeatRateMs && m_configuration.iButtonReleaseDelayMs)
- return;
-
{
CLockObject lock(m_mutex);
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
@@ -1015,6 +1011,10 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */, bool bButtonRelease /*
}
}
+ // we don't forward releases when supporting repeating keys
+ if (bButtonRelease && m_configuration.iButtonRepeatRateMs)
+ return;
+
if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN)
{
LIB_CEC->AddLog(CEC_LOG_DEBUG, "key released: %s (%1x) D:%dms", ToString(key.keycode), key.keycode, key.duration);
@@ -1107,7 +1107,7 @@ void CCECClient::AddKey(const cec_keypress &key)
if (!isrepeat && (key.keycode != comboKey || key.duration > 0))
{
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode);
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x, %d)", ToString(transmitKey.keycode), transmitKey.keycode, transmitKey.duration);
QueueAddKey(transmitKey);
}
}
@@ -1129,6 +1129,7 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
unsigned int timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
cec_keypress key;
key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
+ key.duration = 0;
{
CLockObject lock(m_mutex);
@@ -1140,8 +1141,7 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
m_configuration.iComboKeyTimeoutMs : CEC_DEFAULT_COMBO_TIMEOUT_MS);
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
- ((m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_updateButtontime >= iTimeoutMs) ||
- (m_iCurrentButton != comboKey && m_releaseButtontime && iNow >= (uint64_t)m_releaseButtontime)))
+ m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_updateButtontime >= iTimeoutMs)
{
key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = m_iCurrentButton;
@@ -1155,9 +1155,23 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
m_releasedButtoncount = 0;
}
else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
+ m_iCurrentButton != comboKey && m_releaseButtontime && iNow >= (uint64_t)m_releaseButtontime)
+ {
+ key.duration = (unsigned int) (iNow - m_initialButtontime);
+ key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
+
+ m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN;
+ m_initialButtontime = 0;
+ m_updateButtontime = 0;
+ m_repeatButtontime = 0;
+ m_releaseButtontime = 0;
+ m_pressedButtoncount = 0;
+ m_releasedButtoncount = 0;
+ }
+ else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
(m_iCurrentButton != comboKey && m_repeatButtontime && iNow >= (uint64_t)m_repeatButtontime))
{
- key.duration = 0;
+ key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = m_iCurrentButton;
m_repeatButtontime = iNow + m_configuration.iButtonRepeatRateMs;
timeout = std::min((uint64_t)timeout, m_repeatButtontime - iNow);
@@ -1176,8 +1190,8 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
timeout = CEC_PROCESSOR_SIGNAL_WAIT_TIME;
}
}
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "key %s: %s (%1x) timeout:%dms (rel:%d,rep:%d,prs:%d,rel:%d)", key.keycode == CEC_USER_CONTROL_CODE_UNKNOWN ? "idle" : key.duration ? "released" : "repeated",
- ToString(m_iCurrentButton), m_iCurrentButton, timeout, (int)(m_releaseButtontime ? m_releaseButtontime - iNow : 0), (int)(m_repeatButtontime ? m_repeatButtontime - iNow : 0), m_pressedButtoncount, m_releasedButtoncount);
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "Key %s: %s (duration:%d) (%1x) timeout:%dms (rel:%d,rep:%d,prs:%d,rel:%d)", ToString(m_iCurrentButton), key.keycode == CEC_USER_CONTROL_CODE_UNKNOWN ? "idle" : m_repeatButtontime ? "repeated" : "released", key.duration,
+ m_iCurrentButton, timeout, (int)(m_releaseButtontime ? m_releaseButtontime - iNow : 0), (int)(m_repeatButtontime ? m_repeatButtontime - iNow : 0), m_pressedButtoncount, m_releasedButtoncount);
}
if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN)
--
1.9.1
From 1ea01f59d8186d4d53af41961aaccbbc11651115 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 5 Nov 2014 21:04:25 +0000
Subject: [PATCH 6/6] squash: Fix for stop needing to be pressed twice
---
src/libcec/CECClient.cpp | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index 1946148..f4f114b 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -1131,6 +1131,8 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
key.duration = 0;
+ if (m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN)
+ return timeout;
{
CLockObject lock(m_mutex);
uint64_t iNow = GetTimeMs();
@@ -1140,8 +1142,7 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
uint32_t iTimeoutMs(m_configuration.clientVersion >= LIBCEC_VERSION_TO_UINT(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_updateButtontime >= iTimeoutMs)
+ if (m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_updateButtontime >= iTimeoutMs)
{
key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = m_iCurrentButton;
@@ -1154,8 +1155,7 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
m_pressedButtoncount = 0;
m_releasedButtoncount = 0;
}
- else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
- m_iCurrentButton != comboKey && m_releaseButtontime && iNow >= (uint64_t)m_releaseButtontime)
+ else if (m_iCurrentButton != comboKey && m_releaseButtontime && iNow >= (uint64_t)m_releaseButtontime)
{
key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
@@ -1168,8 +1168,7 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
m_pressedButtoncount = 0;
m_releasedButtoncount = 0;
}
- else if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
- (m_iCurrentButton != comboKey && m_repeatButtontime && iNow >= (uint64_t)m_repeatButtontime))
+ else if (m_iCurrentButton != comboKey && m_repeatButtontime && iNow >= (uint64_t)m_repeatButtontime)
{
key.duration = (unsigned int) (iNow - m_initialButtontime);
key.keycode = m_iCurrentButton;
@@ -1178,11 +1177,11 @@ uint16_t CCECClient::CheckKeypressTimeout(void)
}
else
{
- if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton == comboKey && iTimeoutMs > 0)
+ if (m_iCurrentButton == comboKey && iTimeoutMs > 0)
timeout = std::min((uint64_t)timeout, m_updateButtontime - iNow + iTimeoutMs);
- if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey && m_releaseButtontime)
+ if (m_iCurrentButton != comboKey && m_releaseButtontime)
timeout = std::min((uint64_t)timeout, m_releaseButtontime - iNow);
- if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && m_iCurrentButton != comboKey && m_repeatButtontime)
+ if (m_iCurrentButton != comboKey && m_repeatButtontime)
timeout = std::min((uint64_t)timeout, m_repeatButtontime - iNow);
if (timeout > CEC_PROCESSOR_SIGNAL_WAIT_TIME)
{
--
1.9.1

View File

@ -0,0 +1,83 @@
From 486c88dcd90bbbadb5fb5f69a697872adf12c43a Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 28 Oct 2014 00:19:40 +0000
Subject: [PATCH] [cec] Add settings for configuring button repeats
---
addons/resource.language.en_gb/resources/strings.po | 15 +++++++++++++++
system/peripherals.xml | 4 +++-
xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 16 ++++++++++++++++
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index bedbd87..6db61ed 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -16687,3 +16687,18 @@ msgstr ""
msgctxt "#38009"
msgid "%i dB"
msgstr ""
+
+#: system/peripherals.xml
+msgctxt "#38050"
+msgid "Remote button press delay before repeating (ms)"
+msgstr ""
+
+#: system/peripherals.xml
+msgctxt "#38051"
+msgid "Remote button press repeat rate (ms)"
+msgstr ""
+
+#: system/peripherals.xml
+msgctxt "#38052"
+msgid "Remote button press release time (ms)"
+msgstr ""
diff --git a/system/peripherals.xml b/system/peripherals.xml
index a67dc2f..6841bda 100644
--- a/system/peripherals.xml
+++ b/system/peripherals.xml
@@ -30,7 +30,9 @@
<setting key="device_type" type="int" value="1" configurable="0" />
<setting key="wake_devices_advanced" type="string" value="" configurable="0" />
<setting key="standby_devices_advanced" type="string" value="" configurable="0" />
- <setting key="double_tap_timeout_ms" type="int" min="0" value="300" configurable="0" />
+ <setting key="double_tap_timeout_ms" type="int" min="50" max="1000" step="50" value="300" label="38050" order="16" />
+ <setting key="button_repeat_rate_ms" type="int" min="0" max="250" step="10" value="0" label="38051" order="17" />
+ <setting key="button_release_delay_ms" type="int" min="0" max="500" step="50" value="0" label="38052" order="18" />
</peripheral>
<peripheral vendor_product="2548:1001,2548:1002" bus="usb" name="Pulse-Eight CEC Adapter" mapTo="cec">
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
index ea702e5..b5ff693 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
@@ -1267,6 +1267,20 @@ void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configu
m_configuration.bSendInactiveSource = config.bSendInactiveSource;
bChanged |= SetSetting("send_inactive_source", m_configuration.bSendInactiveSource == 1);
+#if defined(CEC_DOUBLE_TAP_TIMEOUT_MS_OLD)
+ m_configuration.iDoubleTapTimeout50Ms = config.iDoubleTapTimeout50Ms;
+ bChanged |= SetSetting("double_tap_timeout_ms", (int)m_configuration.iDoubleTapTimeout50Ms * 50);
+#else
+ m_configuration.iDoubleTapTimeoutMs = config.iDoubleTapTimeoutMs;
+ bChanged |= SetSetting("double_tap_timeout_ms", (int)m_configuration.iDoubleTapTimeoutMs;
+#endif
+
+ m_configuration.iButtonRepeatRateMs = config.iButtonRepeatRateMs;
+ bChanged |= SetSetting("button_repeat_rate_ms", (int)m_configuration.iButtonRepeatRateMs);
+
+ m_configuration.iButtonReleaseDelayMs = config.iButtonReleaseDelayMs;
+ bChanged |= SetSetting("button_release_delay_ms", (int)m_configuration.iButtonReleaseDelayMs);
+
m_configuration.iFirmwareVersion = config.iFirmwareVersion;
m_configuration.bShutdownOnStandby = config.bShutdownOnStandby;
@@ -1371,6 +1385,8 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void)
// backwards compatibility. will be removed once the next major release of libCEC is out
m_configuration.iDoubleTapTimeoutMs = GetSettingInt("double_tap_timeout_ms");
#endif
+ m_configuration.iButtonRepeatRateMs = GetSettingInt("button_repeat_rate_ms");
+ m_configuration.iButtonReleaseDelayMs = GetSettingInt("button_release_delay_ms");
}
void CPeripheralCecAdapter::ReadLogicalAddresses(const std::string &strString, cec_logical_addresses &addresses)

View File

@ -0,0 +1,25 @@
From defea2828a7b4dba7c94c33896c1cd16d1f29f29 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 3 Nov 2014 23:17:46 +0000
Subject: [PATCH] [cec] Don't discard buttons when repeat mode is enabled
---
xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
index b5ff693..6086bf5 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
@@ -767,7 +767,10 @@ void CPeripheralCecAdapter::PushCecKeypress(const CecButtonPress &key)
CLog::Log(LOGDEBUG, "%s - received key %2x duration %d", __FUNCTION__, key.iButton, key.iDuration);
CSingleLock lock(m_critSection);
- if (key.iDuration > 0)
+ // avoid the queue getting too long
+ if (m_configuration.iButtonRepeatRateMs && m_buttonQueue.size() > 5)
+ return;
+ if (m_configuration.iButtonRepeatRateMs == 0 && key.iDuration > 0)
{
if (m_currentButton.iButton == key.iButton && m_currentButton.iDuration == 0)
{