From c77ae55125886d20a9dc5d4f6bbffa9bad1f4e82 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 10 Aug 2014 16:45:16 +0100 Subject: [PATCH 05/73] filesystem: Make support of browsing into archives optional The ability to browse, scan and play content in archives can cause problems on low powered/low memory devices. It's quite common to see reports of a large rar file that causes xbmc to crash with an out-of-memory error when browsing or scanning. It also can be slow as any archive in the directory is opened and extracted. This causes issues for people who scan library with archives disabled, then subsequently enable it. The library has the .rar files in which don't play without removing and re-adding. We'll let people who don't use archives disable it manually --- addons/resource.language.en_gb/resources/strings.po | 9 +++++++++ system/settings/rbp.xml | 11 +++++++++++ xbmc/Util.cpp | 4 ++-- xbmc/filesystem/FileDirectoryFactory.cpp | 4 ++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 5d2af8d8705ecf61dc5b7c91f0517b8d1e1e640a..488e590d5a48467b19e27d01863487f51442b130 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -19333,6 +19333,15 @@ msgstr "" #: system/settings/rbp.xml msgctxt "#38010" msgid "GPU accelerated" + +#: system/settings/settings.xml +msgctxt "#38040" +msgid "Support browsing into archives" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#38041" +msgid "Allow viewing and playing files in archives (e.g. zip, rar)" msgstr "" #. Setting #38011 "Show All Items entry" diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml index 62e9c8ed2199f8c57a640b06b0216ee4c8f0ca1e..e8b0d3d472b02fd161a4b51e957b9129e3cb9792 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -102,4 +102,15 @@ +
+ + + + 1 + true + + + + +
diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index c3567941192c724f2600494a8d7e355584b57b52..da1508dcedbd196789988d895e64548a08439d8f 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -1899,7 +1899,7 @@ void CUtil::ScanPathsForAssociatedItems(const std::string& videoName, URIUtils::RemoveExtension(strCandidate); if (StringUtils::StartsWithNoCase(strCandidate, videoName)) { - if (URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath())) + if (CSettings::GetInstance().GetBool("filelists.browsearchives") && (URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath()))) CUtil::ScanArchiveForAssociatedItems(pItem->GetPath(), "", item_exts, associatedFiles); else { @@ -1909,7 +1909,7 @@ void CUtil::ScanPathsForAssociatedItems(const std::string& videoName, } else { - if (URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath())) + if (CSettings::GetInstance().GetBool("filelists.browsearchives") && (URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath()))) CUtil::ScanArchiveForAssociatedItems(pItem->GetPath(), videoName, item_exts, associatedFiles); } } diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp index a0fd0a9011e71f4af1535110c696b6ea5c4b37db..688b71a297c7c617c6764bfe6be157d727eb49d3 100644 --- a/xbmc/filesystem/FileDirectoryFactory.cpp +++ b/xbmc/filesystem/FileDirectoryFactory.cpp @@ -40,6 +40,7 @@ #include "playlists/PlayListFactory.h" #include "Directory.h" #include "File.h" +#include "settings/Settings.h" #include "FileItem.h" #include "utils/StringUtils.h" #include "URL.h" @@ -116,6 +117,8 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, return NULL; } #endif + if (CSettings::GetInstance().GetBool("filelists.browsearchives")) + { if (url.IsFileType("zip")) { CURL zipURL = URIUtils::CreateArchivePath("zip", url); @@ -189,6 +192,7 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, } return NULL; } + } if (url.IsFileType("xbt")) { CURL xbtUrl = URIUtils::CreateArchivePath("xbt", url); From 859c87e3ac2360ecaa7eb846c24ae565228b9d85 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 24 Sep 2014 23:13:52 +0100 Subject: [PATCH 08/73] [audio] Add settings option to boost centre channel when downmixing This allows a dB volume increase to be added to centre channel. This can help improve dialgue in the presence of background music/effects. It can go up to 30dB for testing purposes, but value of 6 is probably more reasonable. It is recommended to ensure "Normalise levels on downmix" is enabled when boosting by large values to avoid clipping. Should work with Pi Sink (dvdplayer/paplayer) and omxplayer --- addons/resource.language.en_gb/resources/strings.po | 15 +++++++++++++++ system/settings/settings.xml | 12 ++++++++++++ .../Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp | 7 +++++++ .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 ++++++ xbmc/cores/omxplayer/OMXAudio.cpp | 6 ++++++ 5 files changed, 46 insertions(+) diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 488e590d5a48467b19e27d01863487f51442b130..a867d3205bbad13ac4f3b0862911f04c694e0f07 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -19531,6 +19531,21 @@ msgstr "" #empty strings from id 38047 to 38099 +#: system/settings/settings.xml +msgctxt "#38007" +msgid "Boost centre channel when downmixing" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#38008" +msgid "Increase this value to make the dialogue louder compared to background sounds when downmixing multichannel audio" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#38009" +msgid "%i dB" +msgstr "" + #. Description of section #14200 "Player"" #: system/settings/settings.xml msgctxt "#38100" diff --git a/system/settings/settings.xml b/system/settings/settings.xml index 6ff6b4c63fdb49ebe02f63b93c6995e0ddd21d40..52f7d29eaa509c8d648c2cf2e125b9e7e4b90f3b 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -2361,6 +2361,18 @@ + + 2 + 0 + + 0 + 1 + 30 + + + 38009 + + HAS_AE_QUALITY_LEVELS 2 diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp index af5bf93116543bd282953b01d0c5bcef93bb3a84..d7165dedd242abdfa7c0607eee332451c3187298 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp @@ -20,6 +20,7 @@ #include "cores/AudioEngine/Utils/AEUtil.h" #include "ActiveAEResampleFFMPEG.h" +#include "settings/Settings.h" #include "utils/log.h" extern "C" { @@ -104,6 +105,12 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i { av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); } + int boost_center = CSettings::GetInstance().GetInt("audiooutput.boostcenter"); + if (boost_center) + { + float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); + av_opt_set_double(m_pContext, "center_mix_level", gain, 0); + } if (remapLayout) { diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp index 78071493fca4756c6741d7085e35cbe2f27038e6..698a6ae1e2bc0cc9256caec42c0dcfb0893301b5 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp @@ -164,6 +164,12 @@ bool CActiveAEResamplePi::Init(uint64_t dst_chan_layout, int dst_channels, int d { av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); } + int boost_center = CSettings::GetInstance().GetInt("audiooutput.boostcenter"); + if (boost_center) + { + float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); + av_opt_set_double(m_pContext, "center_mix_level", gain, 0); + } if (remapLayout) { diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp index f16b822ed7b4aebe18b5d339b3f71ee66e97c23f..993d4b33a294e88c2c004b7943895ba55558c2d0 100644 --- a/xbmc/cores/omxplayer/OMXAudio.cpp +++ b/xbmc/cores/omxplayer/OMXAudio.cpp @@ -633,6 +633,12 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo { av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); } + int boost_center = CSettings::GetInstance().GetInt("audiooutput.boostcenter"); + if (boost_center) + { + float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); + av_opt_set_double(m_pContext, "center_mix_level", gain, 0); + } // stereo upmix if (upmix && m_src_channels == 2 && m_dst_channels > 2) From 5b64f68afe3f41097e46b278f02db69190d2628d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 27 Oct 2014 15:23:51 +0000 Subject: [PATCH 09/73] [rbp] Default extract thumbnails to false It can take 80 seconds for a single file on a Pi. It can cause crashes with out-of-memory errors. It genereates a lot of support issues. Best to default to disabled and let users enable it if they must --- system/settings/rbp.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml index e8b0d3d472b02fd161a4b51e957b9129e3cb9792..289dc55ec41aa44848519a05f8ee1ccc72740085 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -43,6 +43,12 @@ false + + false + + + false + From 7552084189bbac0c9b2a443fa071b1ebe85b1cf3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 10 Feb 2015 15:29:16 +0000 Subject: [PATCH 51/73] [libcec] Add repeating keypress patch from popcornmix' repo --- tools/depends/target/libcec/Makefile | 1 + tools/depends/target/libcec/popcornmix.patch | 859 +++++++++++++++++++++++++++ 2 files changed, 860 insertions(+) create mode 100644 tools/depends/target/libcec/popcornmix.patch diff --git a/tools/depends/target/libcec/Makefile b/tools/depends/target/libcec/Makefile index f54af9e7ed3d0a9bef922517728c8b8db51d9d75..ddf996361ad5b46dd2b33fb035b2ed133914a612 100644 --- a/tools/depends/target/libcec/Makefile +++ b/tools/depends/target/libcec/Makefile @@ -21,6 +21,7 @@ $(TARBALLS_LOCATION)/$(ARCHIVE): $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) rm -rf $(PLATFORM); mkdir -p $(PLATFORM)/build cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../popcornmix.patch cd $(PLATFORM)/build; $(CMAKE) -DBUILD_SHARED_LIBS=1 -DSKIP_PYTHON_WRAPPER:STRING=1 -DCMAKE_INSTALL_LIBDIR=$(PREFIX)/lib .. $(LIBDYLIB): $(PLATFORM) diff --git a/tools/depends/target/libcec/popcornmix.patch b/tools/depends/target/libcec/popcornmix.patch new file mode 100644 index 0000000000000000000000000000000000000000..8366a696562a934144cc9a21ea6f2cab3c69e655 --- /dev/null +++ b/tools/depends/target/libcec/popcornmix.patch @@ -0,0 +1,859 @@ +From ec982e9800ae312972d306b67779215a2add6cde Mon Sep 17 00:00:00 2001 +From: popcornmix +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::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 + ++#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 ¶m); + + static bool IsValidPhysicalAddress(uint16_t iPhysicalAddress); +-- +1.9.1 + + +From 41f0f3ec9ac136da3565c96fd5a7075499f3938d Mon Sep 17 00:00:00 2001 +From: popcornmix +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 +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 ¶m) { 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 +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 m_callbackCalls; + }; + } +-- +1.9.1 + + +From 0dd0234f620a546bfa843172648383f83d88088c Mon Sep 17 00:00:00 2001 +From: popcornmix +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 +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 + From 32d910f5fb777a2d18b2d81b8242e0abd48e6388 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 19 Mar 2016 17:15:29 +0000 Subject: [PATCH 52/73] cec: hack: pretend bump to 3.1.0 --- tools/depends/target/libcec/Makefile | 1 + tools/depends/target/libcec/bump.patch | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tools/depends/target/libcec/bump.patch diff --git a/tools/depends/target/libcec/Makefile b/tools/depends/target/libcec/Makefile index ddf996361ad5b46dd2b33fb035b2ed133914a612..39ba882d0c7e270b4d1d1d566027cbaffb76b587 100644 --- a/tools/depends/target/libcec/Makefile +++ b/tools/depends/target/libcec/Makefile @@ -22,6 +22,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) rm -rf $(PLATFORM); mkdir -p $(PLATFORM)/build cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) cd $(PLATFORM); patch -p1 < ../popcornmix.patch + cd $(PLATFORM); patch -p1 < ../bump.patch cd $(PLATFORM)/build; $(CMAKE) -DBUILD_SHARED_LIBS=1 -DSKIP_PYTHON_WRAPPER:STRING=1 -DCMAKE_INSTALL_LIBDIR=$(PREFIX)/lib .. $(LIBDYLIB): $(PLATFORM) diff --git a/tools/depends/target/libcec/bump.patch b/tools/depends/target/libcec/bump.patch new file mode 100644 index 0000000000000000000000000000000000000000..9e55e51068e7befd9d4ff003156ce1ff4cc56c0e --- /dev/null +++ b/tools/depends/target/libcec/bump.patch @@ -0,0 +1,21 @@ +commit 49a1728feabca68b8424a8b22abec9ee87b9aa99 +Author: Lars Op den Kamp +Date: Wed Jan 20 01:06:50 2016 +0100 + + bump to 3.1.0 + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 23d71fc..173f625 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -2,8 +2,8 @@ project(libcec) + cmake_minimum_required(VERSION 2.8.9) + + set(LIBCEC_VERSION_MAJOR 3) +-set(LIBCEC_VERSION_MINOR 0) +-set(LIBCEC_VERSION_PATCH 0) ++set(LIBCEC_VERSION_MINOR 1) ++set(LIBCEC_VERSION_PATCH 0) + + # cec-client + add_subdirectory(src/cec-client) From 2e98d936f34bb32d80b7edfc86f10e4cd6073a85 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 28 Oct 2014 00:19:40 +0000 Subject: [PATCH 53/73] [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 7ace950c83e1497b4d96a31b33b524e7eafb1783..bdc5953503cf382091706240505c850084d84d94 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -19714,3 +19714,18 @@ msgstr "" msgctxt "#38206" msgid "Max" 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 f939c0b685d96d022856544e7eb31a71338d9ba4..a4b8f7add4d915c1749628d62a9cbe9afe97d063 100644 --- a/system/peripherals.xml +++ b/system/peripherals.xml @@ -31,7 +31,9 @@ - + + + diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index e6bcbce6911a1714e129ecd5aceead94769231f4..19b3c37bc18fcab30920b12902e8c3397a69dccc 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -1287,6 +1287,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; @@ -1391,6 +1405,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"); if (GetSettingBool("pause_playback_on_deactivate")) { From 4b033455b05332c157035752984e7c8da9ddce20 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Nov 2014 23:17:46 +0000 Subject: [PATCH 54/73] [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 19b3c37bc18fcab30920b12902e8c3397a69dccc..f859f44f6d5379154317b5760d7df720f0894e0d 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -778,7 +778,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) { From 6e8d828760fc9a98acb6d7599926b9bc33ff4f4e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 4 Nov 2014 18:50:00 +0000 Subject: [PATCH 55/73] [cec] Temp - more logging --- xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index f859f44f6d5379154317b5760d7df720f0894e0d..f1c3a6d242183507c4ce9ebf4651b0c0f7e9c5c9 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -775,12 +775,15 @@ void CPeripheralCecAdapter::GetNextKey(void) void CPeripheralCecAdapter::PushCecKeypress(const CecButtonPress &key) { - CLog::Log(LOGDEBUG, "%s - received key %2x duration %d", __FUNCTION__, key.iButton, key.iDuration); + CLog::Log(LOGDEBUG, "%s - received key %2x duration %d (rep:%d size:%d)", __FUNCTION__, key.iButton, key.iDuration, m_configuration.iButtonRepeatRateMs, m_buttonQueue.size()); CSingleLock lock(m_critSection); // avoid the queue getting too long if (m_configuration.iButtonRepeatRateMs && m_buttonQueue.size() > 5) + { + CLog::Log(LOGDEBUG, "%s - discarded key %2x", __FUNCTION__, key.iButton); return; + } if (m_configuration.iButtonRepeatRateMs == 0 && key.iDuration > 0) { if (m_currentButton.iButton == key.iButton && m_currentButton.iDuration == 0) @@ -789,6 +792,7 @@ void CPeripheralCecAdapter::PushCecKeypress(const CecButtonPress &key) if (m_bHasButton) m_currentButton.iDuration = key.iDuration; // ignore this one, since it's already been handled by xbmc + CLog::Log(LOGDEBUG, "%s - ignored key %2x", __FUNCTION__, key.iButton); return; } // if we received a keypress with a duration set, try to find the same one without a duration set, and replace it @@ -799,6 +803,7 @@ void CPeripheralCecAdapter::PushCecKeypress(const CecButtonPress &key) if ((*it).iDuration == 0) { // replace this entry + CLog::Log(LOGDEBUG, "%s - replaced key %2x", __FUNCTION__, key.iButton); (*it).iDuration = key.iDuration; return; } @@ -808,6 +813,7 @@ void CPeripheralCecAdapter::PushCecKeypress(const CecButtonPress &key) } } + CLog::Log(LOGDEBUG, "%s - added key %2x", __FUNCTION__, key.iButton); m_buttonQueue.push_back(key); } From f422270e1333ba02c8c2321538ae171572e9879d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 22 Jan 2016 12:29:41 +0000 Subject: [PATCH 56/73] [cec] Update for libcec 3.1.0 --- configure.ac | 4 ++-- xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 3df753bde53593ecea534455056268f9f8a24c1a..738d23e3272cd56b095cef821a3993bb9aa69b55 100644 --- a/configure.ac +++ b/configure.ac @@ -1453,9 +1453,9 @@ if test "x$use_libcec" != "xno"; then # libcec is dyloaded, so we need to check for its headers and link any depends. if test "x$use_libcec" != "xno"; then if test "x$use_libcec" != "xauto"; then - PKG_CHECK_MODULES([CEC],[libcec >= 3.0.0],,[use_libcec="no";AC_MSG_ERROR($libcec_disabled)]) + PKG_CHECK_MODULES([CEC],[libcec >= 3.1.0],,[use_libcec="no";AC_MSG_ERROR($libcec_disabled)]) else - PKG_CHECK_MODULES([CEC],[libcec >= 3.0.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) + PKG_CHECK_MODULES([CEC],[libcec >= 3.1.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) fi if test "x$use_libcec" != "xno"; then diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index f1c3a6d242183507c4ce9ebf4651b0c0f7e9c5c9..28a6a8148810da940f977976a627018c59a719db 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -43,7 +43,7 @@ using namespace PERIPHERALS; using namespace ANNOUNCEMENT; using namespace CEC; -#define CEC_LIB_SUPPORTED_VERSION LIBCEC_VERSION_TO_UINT(3, 0, 0) +#define CEC_LIB_SUPPORTED_VERSION LIBCEC_VERSION_TO_UINT(3, 1, 0) /* time in seconds to ignore standby commands from devices after the screensaver has been activated */ #define SCREENSAVER_TIMEOUT 20 @@ -1329,7 +1329,7 @@ void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configu void CPeripheralCecAdapter::SetConfigurationFromSettings(void) { // client version matches the version of libCEC that we originally used the API from - m_configuration.clientVersion = LIBCEC_VERSION_TO_UINT(3, 0, 0); + m_configuration.clientVersion = CEC_LIB_SUPPORTED_VERSION; // device name 'XBMC' snprintf(m_configuration.strDeviceName, 13, "%s", GetSettingString("device_name").c_str()); From 2748fd05bec256b540214e0e3e4cbbacac5aea31 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 19 Mar 2016 14:46:41 +0000 Subject: [PATCH 57/73] libcec: use system audio mode request instead of power on to start AVR reliable --- tools/depends/target/libcec/208.patch | 38 +++++++++++++++++++++++++++++++++++ tools/depends/target/libcec/Makefile | 1 + 2 files changed, 39 insertions(+) create mode 100644 tools/depends/target/libcec/208.patch diff --git a/tools/depends/target/libcec/208.patch b/tools/depends/target/libcec/208.patch new file mode 100644 index 0000000000000000000000000000000000000000..3dc5adf022e80c3337ad69b7c7d7346daafbfdd3 --- /dev/null +++ b/tools/depends/target/libcec/208.patch @@ -0,0 +1,38 @@ +From f70c4d76e1d9c0219a3927b6b66090b7575e7933 Mon Sep 17 00:00:00 2001 +From: Gerald Dachs +Date: Thu, 17 Mar 2016 12:12:51 +0100 +Subject: [PATCH] use system audio mode request instead of power on to start + AVR reliable + +--- + src/libcec/devices/CECBusDevice.cpp | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/libcec/devices/CECBusDevice.cpp b/src/libcec/devices/CECBusDevice.cpp +index 55939d1..e2d5ea3 100644 +--- a/src/libcec/devices/CECBusDevice.cpp ++++ b/src/libcec/devices/CECBusDevice.cpp +@@ -1025,14 +1025,19 @@ bool CCECBusDevice::ActivateSource(uint64_t iDelay /* = 0 */) + bool bReturn(true); + if (iDelay == 0) + { +- /** some AVRs fail to be powered up by the TV when it powers up. power up the AVR explicitly */ ++ /** send system audio mode request if AVR exists */ + if (m_iLogicalAddress != CECDEVICE_AUDIOSYSTEM) + { + CCECBusDevice* audioSystem(m_processor->GetDevice(CECDEVICE_AUDIOSYSTEM)); +- if (audioSystem && audioSystem->IsPresent() && audioSystem->GetPowerStatus(m_iLogicalAddress) != CEC_POWER_STATUS_ON) ++ if (audioSystem && audioSystem->IsPresent()) + { +- LIB_CEC->AddLog(CEC_LOG_DEBUG, "powering up the AVR"); +- audioSystem->PowerOn(m_iLogicalAddress); ++ cec_command command; ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending system audio mode request for '%s'", ToString(m_iLogicalAddress)); ++ cec_command::Format(command, m_iLogicalAddress, CECDEVICE_AUDIOSYSTEM, CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST); ++ command.parameters.PushBack((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF)); ++ command.parameters.PushBack((uint8_t) (m_iPhysicalAddress & 0xFF)); ++ bReturn = m_handler->Transmit(command, false, false); + } + } + diff --git a/tools/depends/target/libcec/Makefile b/tools/depends/target/libcec/Makefile index 39ba882d0c7e270b4d1d1d566027cbaffb76b587..4565dc9f6fc0b3e6b49133443c19e10767d475eb 100644 --- a/tools/depends/target/libcec/Makefile +++ b/tools/depends/target/libcec/Makefile @@ -23,6 +23,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) cd $(PLATFORM); patch -p1 < ../popcornmix.patch cd $(PLATFORM); patch -p1 < ../bump.patch + cd $(PLATFORM); patch -p1 < ../208.patch cd $(PLATFORM)/build; $(CMAKE) -DBUILD_SHARED_LIBS=1 -DSKIP_PYTHON_WRAPPER:STRING=1 -DCMAKE_INSTALL_LIBDIR=$(PREFIX)/lib .. $(LIBDYLIB): $(PLATFORM) From 25e789e48fd92bd81c780834328846abde00c69f Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Tue, 22 Mar 2016 09:51:52 +0100 Subject: [PATCH 58/73] python: use kodi provided cert if available --- xbmc/interfaces/python/XBPython.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp index bc84af9411ef55eaf5ba71a320b5cbfec5f49548..ff4ed7db26845905108ea0ae504e4f589f9c7d0f 100644 --- a/xbmc/interfaces/python/XBPython.cpp +++ b/xbmc/interfaces/python/XBPython.cpp @@ -595,6 +595,12 @@ bool XBPython::OnScriptInitialized(ILanguageInvoker *invoker) CEnvironment::putenv(buf); #endif +#if !defined(TARGET_WINDOWS) + // use Kodi provided cert if available + if (XFILE::CFile::Exists("special://xbmc/system/certs/cacert.pem")) + setenv("SSL_CERT_FILE", CSpecialProtocol::TranslatePath("special://xbmc/system/certs/cacert.pem").c_str(), 1); +#endif + if (PyEval_ThreadsInitialized()) PyEval_AcquireLock(); else