From cc3ae0339faf2b669bee20cb360c526410910f42 Mon Sep 17 00:00:00 2001
From: Lars Op den Kamp <lars@opdenkamp.eu>
Date: Fri, 11 Nov 2016 10:09:36 +0100
Subject: [PATCH 1/4] [cec] bump to libCEC 4.0.0

---
 .../resource.language.en_gb/resources/strings.po   |   5 -
 configure.ac                                       |   4 +-
 project/BuildDependencies/scripts/0_package.list   |   2 +-
 project/cmake/modules/FindCEC.cmake                |   2 +-
 system/peripherals.xml                             |   1 -
 tools/depends/target/Makefile                      |   5 +-
 tools/depends/target/libcec/Makefile               |   4 +-
 tools/depends/target/p8-platform/Makefile          |  34 ++++
 xbmc/peripherals/devices/PeripheralCecAdapter.cpp  | 192 +++++++++------------
 xbmc/peripherals/devices/PeripheralCecAdapter.h    |  17 +-
 10 files changed, 138 insertions(+), 128 deletions(-)
 create mode 100644 tools/depends/target/p8-platform/Makefile

diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index e3f8a37..e482196 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -16376,11 +16376,6 @@ msgctxt "#36021"
 msgid "Physical address (overrules HDMI port)"
 msgstr ""

-#: system/peripherals.xml
-msgctxt "#36022"
-msgid "COM port (leave empty unless needed)"
-msgstr ""
-
 #: xbmc/peripherals/devices/peripheralcecadapter.cpp
 msgctxt "#36023"
 msgid "Configuration updated"
diff --git a/configure.ac b/configure.ac
index e61d4ae..34fe643 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 >= 4.0.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 >= 4.0.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)])
     fi

     if test "x$use_libcec" != "xno"; then
diff --git a/project/BuildDependencies/scripts/0_package.list b/project/BuildDependencies/scripts/0_package.list
index 9a5bccb..7b6ec1a 100644
--- a/project/BuildDependencies/scripts/0_package.list
+++ b/project/BuildDependencies/scripts/0_package.list
@@ -19,7 +19,7 @@ jsonschemabuilder-1.0.0-win32-3.7z
 libass-0.12.1-win32.7z
 libbluray-0.8.1-win32-vc120.7z
 libcdio-0.83-win32-2.7z
-libcec-3.0.0-win32-2.7z
+libcec-4.0.0-win32-vc140.7z
 libexpat_2.0.1-win32.7z
 libflac-1.2.1-win32.7z
 libfribidi-0.19.2-win32.7z
diff --git a/system/peripherals.xml b/system/peripherals.xml
index f939c0b..58a9d24 100644
--- a/system/peripherals.xml
+++ b/system/peripherals.xml
@@ -24,7 +24,6 @@
     <setting key="connected_device" type="enum" label="36019" value="36037" lvalues="36037|36038" order="12" />
     <setting key="cec_hdmi_port" type="int" value="1" min="1" max="15" label="36015" order="13" />
     <setting key="physical_address" type="string" label="36021" value="0" order="14" />
-    <setting key="port" type="string" value="" label="36022" order="15" />

     <setting key="tv_vendor" type="int" value="0" configurable="0" />
     <setting key="device_name" type="string" value="Kodi" configurable="0" />
diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile
index 9bca188..82b378d 100644
--- a/tools/depends/target/Makefile
+++ b/tools/depends/target/Makefile
@@ -15,7 +15,7 @@
 	python26 libshairplay \
 	libplist libcec libbluray boost tinyxml dummy-libxbmc \
 	libamplayer libssh taglib libusb libnfs \
-	pythonmodule-pil libxslt ffmpeg platform crossguid libdcadec giflib
+	pythonmodule-pil libxslt ffmpeg platform crossguid libdcadec giflib p8-platform

 FFMPEG_DEPENDS = gnutls libdcadec

@@ -101,7 +101,8 @@ pythonmodule-setuptools: python27
 libsdl2: $(LINUX_SYSTEM_LIBS)
 libxslt: libgcrypt
 ffmpeg: $(ICONV) $(ZLIB) bzip2 libvorbis $(FFMPEG_DEPENDS)
-libcec: platform
+platform: p8-platform
+libcec: p8-platform
 crossguid: $(CROSSGUID_DEPS)

 .installed-$(PLATFORM): $(DEPENDS)
diff --git a/tools/depends/target/libcec/Makefile b/tools/depends/target/libcec/Makefile
index f54af9e..c75b300 100644
--- a/tools/depends/target/libcec/Makefile
+++ b/tools/depends/target/libcec/Makefile
@@ -3,12 +3,12 @@ DEPS= ../../Makefile.include Makefile

 # lib name, version
 LIBNAME=libcec
-VERSION_MAJOR=3
+VERSION_MAJOR=4
 VERSION_MINOR=0
 VERSION_PATCH=0

 VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
-SOURCE=$(LIBNAME)-$(VERSION)-6
+SOURCE=$(LIBNAME)-$(VERSION)
 ARCHIVE=$(SOURCE).tar.gz

 LIBDYLIB=$(PLATFORM)/build/src/$(LIBNAME).la
diff --git a/tools/depends/target/p8-platform/Makefile b/tools/depends/target/p8-platform/Makefile
new file mode 100644
index 0000000..d5918d7
--- /dev/null
+++ b/tools/depends/target/p8-platform/Makefile
@@ -0,0 +1,34 @@
+include ../../Makefile.include
+DEPS= ../../Makefile.include Makefile
+
+# lib name, version
+LIBNAME=p8-platform
+VERSION=2.1.0.1
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+
+LIBDYLIB=$(PLATFORM)/build/src/$(LIBNAME).a
+
+all: .installed-$(PLATFORM)
+
+$(TARBALLS_LOCATION)/$(ARCHIVE):
+	cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(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)/build; $(CMAKE) -DBUILD_SHARED_LIBS=0 -DCMAKE_INSTALL_LIBDIR=$(PREFIX)/lib ..
+
+$(LIBDYLIB): $(PLATFORM)
+	$(MAKE) -C $(PLATFORM)/build
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+	$(MAKE) -C $(PLATFORM)/build install
+	touch $@
+
+clean:
+	rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
+distclean::
+	rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
index e6bcbce..a71dc4b 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(4, 0, 0)

 /* time in seconds to ignore standby commands from devices after the screensaver has been activated */
 #define SCREENSAVER_TIMEOUT       20
@@ -119,25 +119,30 @@ void CPeripheralCecAdapter::ResetMembers(void)
     m_dll->CECDestroy(m_cecAdapter);
   m_cecAdapter               = NULL;
   delete m_dll;
-  m_dll                      = NULL;
-  m_bStarted                 = false;
-  m_bHasButton               = false;
-  m_bIsReady                 = false;
-  m_bHasConnectedAudioSystem = false;
-  m_strMenuLanguage          = "???";
-  m_lastKeypress             = 0;
-  m_lastChange               = VOLUME_CHANGE_NONE;
-  m_iExitCode                = EXITCODE_QUIT;
-  m_bIsMuted                 = false; // TODO fetch the correct initial value when system audiostatus is implemented in libCEC
-  m_bGoingToStandby          = false;
-  m_bIsRunning               = false;
-  m_bDeviceRemoved           = false;
-  m_bActiveSourcePending     = false;
-  m_bStandbyPending          = false;
+  m_dll                        = NULL;
+  m_bStarted                   = false;
+  m_bHasButton                 = false;
+  m_bIsReady                   = false;
+  m_bHasConnectedAudioSystem   = false;
+  m_strMenuLanguage            = "???";
+  m_lastKeypress               = 0;
+  m_lastChange                 = VOLUME_CHANGE_NONE;
+  m_iExitCode                  = EXITCODE_QUIT;
+  m_bIsMuted                   = false; //! @todo fetch the correct initial value when system audiostatus is implemented in libCEC
+  m_bGoingToStandby            = false;
+  m_bIsRunning                 = false;
+  m_bDeviceRemoved             = false;
+  m_bActiveSourcePending       = false;
+  m_bStandbyPending            = false;
   m_bActiveSourceBeforeStandby = false;
-  m_bOnPlayReceived          = false;
-  m_bPlaybackPaused          = false;
-  m_queryThread              = NULL;
+  m_bOnPlayReceived            = false;
+  m_bPlaybackPaused            = false;
+  m_queryThread                = NULL;
+  m_bPowerOnScreensaver        = false;
+  m_bUseTVMenuLanguage         = false;
+  m_bSendInactiveSource        = false;
+  m_bPowerOffScreensaver       = false;
+  m_bShutdownOnStandby         = false;

   m_currentButton.iButton    = 0;
   m_currentButton.iDuration  = 0;
@@ -166,8 +171,8 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender,
       if (bIgnoreDeactivate)
         CLog::Log(LOGDEBUG, "%s - ignoring OnScreensaverDeactivated for power action", __FUNCTION__);
     }
-    if (m_configuration.bPowerOnScreensaver == 1 && !bIgnoreDeactivate &&
-        m_configuration.bActivateSource == 1)
+    if (m_bPowerOnScreensaver && !bIgnoreDeactivate &&
+        m_configuration.bActivateSource)
     {
       ActivateSource();
     }
@@ -175,7 +180,7 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender,
   else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && m_bIsReady)
   {
     // Don't put devices to standby if application is currently playing
-    if ((!g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) && m_configuration.bPowerOffScreensaver == 1)
+    if (!g_application.m_pPlayer->IsPlaying() && m_bPowerOffScreensaver)
     {
       // only power off when we're the active source
       if (m_cecAdapter->IsLibCECActiveSource())
@@ -241,14 +246,14 @@ bool CPeripheralCecAdapter::InitialiseFeature(const PeripheralFeature feature)

     SetConfigurationFromSettings();
     m_callbacks.Clear();
-    m_callbacks.CBCecLogMessage           = &CecLogMessage;
-    m_callbacks.CBCecKeyPress             = &CecKeyPress;
-    m_callbacks.CBCecCommand              = &CecCommand;
-    m_callbacks.CBCecConfigurationChanged = &CecConfiguration;
-    m_callbacks.CBCecAlert                = &CecAlert;
-    m_callbacks.CBCecSourceActivated      = &CecSourceActivated;
-    m_configuration.callbackParam         = this;
-    m_configuration.callbacks             = &m_callbacks;
+    m_callbacks.logMessage           = &CecLogMessage;
+    m_callbacks.keyPress             = &CecKeyPress;
+    m_callbacks.commandReceived      = &CecCommand;
+    m_callbacks.configurationChanged = &CecConfiguration;
+    m_callbacks.alert                = &CecAlert;
+    m_callbacks.sourceActivated      = &CecSourceActivated;
+    m_configuration.callbackParam    = this;
+    m_configuration.callbacks        = &m_callbacks;

     m_dll = new DllLibCEC;
     if (m_dll->Load() && m_dll->IsLoaded())
@@ -414,7 +419,7 @@ void CPeripheralCecAdapter::Process(void)
         m_standbySent = CDateTime::GetCurrentDateTime();
         m_cecAdapter->StandbyDevices();
       }
-      else if (m_configuration.bSendInactiveSource == 1)
+      else if (m_bSendInactiveSource)
       {
         CLog::Log(LOGDEBUG, "%s - sending inactive source commands", __FUNCTION__);
         m_cecAdapter->SetInactiveView();
@@ -614,43 +619,43 @@ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage)
     CLog::Log(LOGWARNING, "%s - TV menu language set to unknown value '%s'", __FUNCTION__, strLanguage);
 }

-int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command command)
+void CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command* command)
 {
-  CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
+  CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
   if (!adapter)
-    return 0;
+    return;

   if (adapter->m_bIsReady)
   {
-    switch (command.opcode)
+    switch (command->opcode)
     {
     case CEC_OPCODE_STANDBY:
       /* a device was put in standby mode */
-      if (command.initiator == CECDEVICE_TV &&
-          (adapter->m_configuration.bPowerOffOnStandby == 1 || adapter->m_configuration.bShutdownOnStandby == 1) &&
+      if (command->initiator == CECDEVICE_TV &&
+          (adapter->m_configuration.bPowerOffOnStandby == 1 || adapter->m_bShutdownOnStandby) &&
           (!adapter->m_standbySent.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_standbySent > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT)))
       {
         adapter->m_bStarted = false;
         if (adapter->m_configuration.bPowerOffOnStandby == 1)
           g_application.ExecuteXBMCAction("Suspend");
-        else if (adapter->m_configuration.bShutdownOnStandby == 1)
+        else if (adapter->m_bShutdownOnStandby)
           g_application.ExecuteXBMCAction("Shutdown");
       }
       break;
     case CEC_OPCODE_SET_MENU_LANGUAGE:
-      if (adapter->m_configuration.bUseTVMenuLanguage == 1 && command.initiator == CECDEVICE_TV && command.parameters.size == 3)
+      if (adapter->m_bUseTVMenuLanguage == 1 && command->initiator == CECDEVICE_TV && command->parameters.size == 3)
       {
         char strNewLanguage[4];
         for (int iPtr = 0; iPtr < 3; iPtr++)
-          strNewLanguage[iPtr] = command.parameters[iPtr];
+          strNewLanguage[iPtr] = command->parameters[iPtr];
         strNewLanguage[3] = 0;
         adapter->SetMenuLanguage(strNewLanguage);
       }
       break;
     case CEC_OPCODE_DECK_CONTROL:
-      if (command.initiator == CECDEVICE_TV &&
-          command.parameters.size == 1 &&
-          command.parameters[0] == CEC_DECK_CONTROL_MODE_STOP)
+      if (command->initiator == CECDEVICE_TV &&
+          command->parameters.size == 1 &&
+          command->parameters[0] == CEC_DECK_CONTROL_MODE_STOP)
       {
         cec_keypress key;
         key.duration = 500;
@@ -659,17 +664,17 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command command)
       }
       break;
     case CEC_OPCODE_PLAY:
-      if (command.initiator == CECDEVICE_TV &&
-          command.parameters.size == 1)
+      if (command->initiator == CECDEVICE_TV &&
+          command->parameters.size == 1)
       {
-        if (command.parameters[0] == CEC_PLAY_MODE_PLAY_FORWARD)
+        if (command->parameters[0] == CEC_PLAY_MODE_PLAY_FORWARD)
         {
           cec_keypress key;
           key.duration = 500;
           key.keycode = CEC_USER_CONTROL_CODE_PLAY;
           adapter->PushCecKeypress(key);
         }
-        else if (command.parameters[0] == CEC_PLAY_MODE_PLAY_STILL)
+        else if (command->parameters[0] == CEC_PLAY_MODE_PLAY_STILL)
         {
           cec_keypress key;
           key.duration = 500;
@@ -682,25 +687,23 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command command)
       break;
     }
   }
-  return 1;
 }

-int CPeripheralCecAdapter::CecConfiguration(void *cbParam, const libcec_configuration config)
+void CPeripheralCecAdapter::CecConfiguration(void *cbParam, const libcec_configuration* config)
 {
-  CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
+  CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
   if (!adapter)
-    return 0;
+    return;

   CSingleLock lock(adapter->m_critSection);
-  adapter->SetConfigurationFromLibCEC(config);
-  return 1;
+  adapter->SetConfigurationFromLibCEC(*config);
 }

-int CPeripheralCecAdapter::CecAlert(void *cbParam, const libcec_alert alert, const libcec_parameter data)
+void CPeripheralCecAdapter::CecAlert(void *cbParam, const libcec_alert alert, const libcec_parameter data)
 {
-  CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
+  CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
   if (!adapter)
-    return 0;
+    return;

   bool bReopenConnection(false);
   int iAlertString(0);
@@ -743,18 +746,13 @@ int CPeripheralCecAdapter::CecAlert(void *cbParam, const libcec_alert alert, con

   if (bReopenConnection)
     adapter->ReopenConnection();
-
-  return 1;
 }

-int CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress key)
+void CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress* key)
 {
-  CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
-  if (!adapter)
-    return 0;
-
-  adapter->PushCecKeypress(key);
-  return 1;
+  CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
+  if (!!adapter)
+    adapter->PushCecKeypress(*key);
 }

 void CPeripheralCecAdapter::GetNextKey(void)
@@ -1154,7 +1152,7 @@ void CPeripheralCecAdapter::OnSettingChanged(const std::string &strChangedSettin

 void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_logical_address address, const uint8_t activated)
 {
-  CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
+  CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
   if (!adapter)
     return;

@@ -1196,14 +1194,14 @@ void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_log
   }
 }

-int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message message)
+void CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message* message)
 {
-  CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
+  CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
   if (!adapter)
-    return 0;
+    return;

   int iLevel = -1;
-  switch (message.level)
+  switch (message->level)
   {
   case CEC_LOG_ERROR:
     iLevel = LOGERROR;
@@ -1223,9 +1221,7 @@ int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message me
   }

   if (iLevel >= CEC_LOG_NOTICE || (iLevel >= 0 && CLog::IsLogLevelLogged(LOGDEBUG) && g_advancedSettings.CanLogComponent(LOGCEC)))
-    CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message);
-
-  return 1;
+    CLog::Log(iLevel, "%s - %s", __FUNCTION__, message->message);
 }

 void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configuration &config)
@@ -1270,35 +1266,18 @@ void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configu
   bChanged |= WriteLogicalAddresses(config.powerOffDevices, "standby_devices", "standby_devices_advanced");

   // set the boolean settings
-  m_configuration.bUseTVMenuLanguage = config.bUseTVMenuLanguage;
-  bChanged |= SetSetting("use_tv_menu_language", m_configuration.bUseTVMenuLanguage == 1);
-
   m_configuration.bActivateSource = config.bActivateSource;
   bChanged |= SetSetting("activate_source", m_configuration.bActivateSource == 1);

-  m_configuration.bPowerOffScreensaver = config.bPowerOffScreensaver;
-  bChanged |= SetSetting("cec_standby_screensaver", m_configuration.bPowerOffScreensaver == 1);
-
-  m_configuration.bPowerOnScreensaver = config.bPowerOnScreensaver;
-  bChanged |= SetSetting("cec_wake_screensaver", m_configuration.bPowerOnScreensaver == 1);
-
   m_configuration.bPowerOffOnStandby = config.bPowerOffOnStandby;

-  m_configuration.bSendInactiveSource = config.bSendInactiveSource;
-  bChanged |= SetSetting("send_inactive_source", m_configuration.bSendInactiveSource == 1);
-
   m_configuration.iFirmwareVersion = config.iFirmwareVersion;
-  m_configuration.bShutdownOnStandby = config.bShutdownOnStandby;

   memcpy(m_configuration.strDeviceLanguage, config.strDeviceLanguage, 3);
   m_configuration.iFirmwareBuildDate = config.iFirmwareBuildDate;

   SetVersionInfo(m_configuration);

-  bChanged |= SetSetting("standby_pc_on_tv_standby",
-             m_configuration.bPowerOffOnStandby == 1 ? 13011 :
-             m_configuration.bShutdownOnStandby == 1 ? 13005 : 36028);
-
   if (bChanged)
     CLog::Log(LOGDEBUG, "SetConfigurationFromLibCEC - settings updated by libCEC");
 }
@@ -1306,7 +1285,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 = LIBCEC_VERSION_TO_UINT(4, 0, 0);

   // device name 'XBMC'
   snprintf(m_configuration.strDeviceName, 13, "%s", GetSettingString("device_name").c_str());
@@ -1373,16 +1352,16 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void)
     ReadLogicalAddresses(GetSettingInt("standby_devices"), m_configuration.powerOffDevices);

   // read the boolean settings
-  m_configuration.bUseTVMenuLanguage   = GetSettingBool("use_tv_menu_language") ? 1 : 0;
+  m_bUseTVMenuLanguage                 = GetSettingBool("use_tv_menu_language") ? 1 : 0;
   m_configuration.bActivateSource      = GetSettingBool("activate_source") ? 1 : 0;
-  m_configuration.bPowerOffScreensaver = GetSettingBool("cec_standby_screensaver") ? 1 : 0;
-  m_configuration.bPowerOnScreensaver  = GetSettingBool("cec_wake_screensaver") ? 1 : 0;
-  m_configuration.bSendInactiveSource  = GetSettingBool("send_inactive_source") ? 1 : 0;
+  m_bPowerOffScreensaver               = GetSettingBool("cec_standby_screensaver") ? 1 : 0;
+  m_bPowerOnScreensaver                = GetSettingBool("cec_wake_screensaver") ? 1 : 0;
+  m_bSendInactiveSource                = GetSettingBool("send_inactive_source") ? 1 : 0;

   // read the mutually exclusive boolean settings
   int iStandbyAction(GetSettingInt("standby_pc_on_tv_standby"));
   m_configuration.bPowerOffOnStandby = iStandbyAction == 13011 ? 1 : 0;
-  m_configuration.bShutdownOnStandby = iStandbyAction == 13005 ? 1 : 0;
+  m_bShutdownOnStandby = iStandbyAction == 13005;

 #if defined(CEC_DOUBLE_TAP_TIMEOUT_MS_OLD)
   // double tap prevention timeout in ms. libCEC uses 50ms units for this in 2.2.0, so divide by 50
@@ -1529,14 +1508,11 @@ bool CPeripheralCecAdapterUpdateThread::WaitReady(void)
 void CPeripheralCecAdapterUpdateThread::UpdateMenuLanguage(void)
 {
   // request the menu language of the TV
-  if (m_configuration.bUseTVMenuLanguage == 1)
+  if (m_adapter->m_bUseTVMenuLanguage == 1)
   {
     CLog::Log(LOGDEBUG, "%s - requesting the menu language of the TV", __FUNCTION__);
-    cec_menu_language language;
-    if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language))
-      m_adapter->SetMenuLanguage(language.language);
-    else
-      CLog::Log(LOGDEBUG, "%s - unknown menu language", __FUNCTION__);
+    std::string language(m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV));
+    m_adapter->SetMenuLanguage(language.c_str());
   }
   else
   {
@@ -1553,9 +1529,9 @@ std::string CPeripheralCecAdapterUpdateThread::UpdateAudioSystemStatus(void)
   if (m_adapter->m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM))
   {
     // request the OSD name of the amp
-    cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM);
-    CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name);
-    strAmpName += StringUtils::Format("%s", ampName.name);
+    std::string ampName(m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM));
+    CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.c_str());
+    strAmpName += StringUtils::Format("%s", ampName.c_str());

     // set amp present
     m_adapter->SetAudioSystemConnected(true);
@@ -1592,8 +1568,8 @@ bool CPeripheralCecAdapterUpdateThread::SetInitialConfiguration(void)

   // request the OSD name of the TV
   std::string strNotification;
-  cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV);
-  strNotification = StringUtils::Format("%s: %s", g_localizeStrings.Get(36016).c_str(), tvName.name);
+  std::string tvName(m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV));
+  strNotification = StringUtils::Format("%s: %s", g_localizeStrings.Get(36016).c_str(), tvName.c_str());

   std::string strAmpName = UpdateAudioSystemStatus();
   if (!strAmpName.empty())
@@ -1766,7 +1742,7 @@ void CPeripheralCecAdapter::ProcessStandbyDevices(void)
       m_standbySent = CDateTime::GetCurrentDateTime();
       m_cecAdapter->StandbyDevices(CECDEVICE_BROADCAST);
     }
-    else if (m_configuration.bSendInactiveSource == 1)
+    else if (m_bSendInactiveSource == 1)
     {
       CLog::Log(LOGDEBUG, "%s - sending inactive source commands", __FUNCTION__);
       m_cecAdapter->SetInactiveView();
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h
index e7f769f..30b22c9 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h
@@ -146,12 +146,12 @@ namespace PERIPHERALS
     void SetMenuLanguage(const char *strLanguage);

     // callbacks from libCEC
-    static int CecLogMessage(void *cbParam, const CEC::cec_log_message message);
-    static int CecCommand(void *cbParam, const CEC::cec_command command);
-    static int CecConfiguration(void *cbParam, const CEC::libcec_configuration config);
-    static int CecAlert(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter data);
+    static void CecLogMessage(void *cbParam, const CEC::cec_log_message* message);
+    static void CecCommand(void *cbParam, const CEC::cec_command* command);
+    static void CecConfiguration(void *cbParam, const CEC::libcec_configuration* config);
+    static void CecAlert(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter data);
     static void CecSourceActivated(void *param, const CEC::cec_logical_address address, const uint8_t activated);
-    static int CecKeyPress(void *cbParam, const CEC::cec_keypress key);
+    static void CecKeyPress(void *cbParam, const CEC::cec_keypress* key);

     DllLibCEC*                        m_dll;
     CEC::ICECAdapter*                 m_cecAdapter;
@@ -181,7 +181,12 @@ namespace PERIPHERALS
     bool                              m_bActiveSourceBeforeStandby;
     bool                              m_bOnPlayReceived;
     bool                              m_bPlaybackPaused;
-    std::string                        m_strComPort;
+    std::string                       m_strComPort;
+    bool                              m_bPowerOnScreensaver;
+    bool                              m_bUseTVMenuLanguage;
+    bool                              m_bSendInactiveSource;
+    bool                              m_bPowerOffScreensaver;
+    bool                              m_bShutdownOnStandby;
   };

   class CPeripheralCecAdapterUpdateThread : public CThread

From 82fe52deb8c11df31fbdf8c298b28a5e1a1491aa Mon Sep 17 00:00:00 2001
From: Lars Op den Kamp <lars@opdenkamp.eu>
Date: Fri, 11 Nov 2016 10:09:48 +0100
Subject: [PATCH 2/4] [cec] Added advanced settings for action when TV goes
 standby

Added advances settings for action when TV goes standby : Pause
playback, Stop playback, Exit Kodi
---
 system/peripherals.xml                            |  2 +-
 xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 47 ++++++++++++++++++-----
 xbmc/peripherals/devices/PeripheralCecAdapter.h   |  1 +
 3 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/system/peripherals.xml b/system/peripherals.xml
index 58a9d24..1fa31e1 100644
--- a/system/peripherals.xml
+++ b/system/peripherals.xml
@@ -16,7 +16,7 @@
     <setting key="send_inactive_source" type="bool" value="1" label="36025" order="5" />
     <setting key="cec_standby_screensaver" type="bool" value="0" label="36009" order="6" />
     <setting key="cec_wake_screensaver" type="bool" value="1" label="36010" order="7" />
-    <setting key="standby_pc_on_tv_standby" type="enum" value="13011" label="36029" order="8" lvalues="36028|13005|13011" />
+    <setting key="standby_pc_on_tv_standby" type="enum" value="13011" label="36029" order="8" lvalues="36028|13005|13011|13009|36043|36045" />
     <setting key="standby_tv_on_pc_standby" type="bool" value="1" label="36026" order="9" />
     <setting key="use_tv_menu_language" type="bool" value="1" label="36018" order="10" />
     <setting key="pause_playback_on_deactivate" type="bool" value="1" label="36033" configurable="0" />
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
index a71dc4b..1b7c38e 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
@@ -55,6 +55,10 @@ using namespace CEC;
 #define LOCALISED_ID_TV_AVR       36039
 #define LOCALISED_ID_STOP         36044
 #define LOCALISED_ID_PAUSE        36045
+#define LOCALISED_ID_POWEROFF     13005
+#define LOCALISED_ID_SUSPEND      13011
+#define LOCALISED_ID_QUIT         13009
+#define LOCALISED_ID_IGNORE       36028

 #define LOCALISED_ID_NONE         231

@@ -619,6 +623,35 @@ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage)
     CLog::Log(LOGWARNING, "%s - TV menu language set to unknown value '%s'", __FUNCTION__, strLanguage);
 }

+void CPeripheralCecAdapter::OnTvStandby(void)
+{
+  int iActionOnTvStandby = GetSettingInt("standby_pc_on_tv_standby");
+  switch (iActionOnTvStandby)
+  {
+  case LOCALISED_ID_POWEROFF:
+    m_bStarted = false;
+    g_application.ExecuteXBMCAction("Shutdown");
+    break;
+  case LOCALISED_ID_SUSPEND:
+    m_bStarted = false;
+    g_application.ExecuteXBMCAction("Suspend");
+    break;
+  case LOCALISED_ID_QUIT:
+    m_bStarted = false;
+    g_application.ExecuteXBMCAction("Quit");
+    break;
+  case LOCALISED_ID_PAUSE:
+    g_application.OnAction(CAction(ACTION_PAUSE));
+    break;
+  case LOCALISED_ID_STOP:
+    g_application.StopPlaying();
+    break;
+  default:
+    CLog::Log(LOGERROR, "%s - Unexpected [standby_pc_on_tv_standby] setting value", __FUNCTION__);
+    break;
+  }
+}
+
 void CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command* command)
 {
   CPeripheralCecAdapter *adapter = static_cast<CPeripheralCecAdapter *>(cbParam);
@@ -630,16 +663,10 @@ void CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command* command
     switch (command->opcode)
     {
     case CEC_OPCODE_STANDBY:
-      /* a device was put in standby mode */
       if (command->initiator == CECDEVICE_TV &&
-          (adapter->m_configuration.bPowerOffOnStandby == 1 || adapter->m_bShutdownOnStandby) &&
           (!adapter->m_standbySent.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_standbySent > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT)))
       {
-        adapter->m_bStarted = false;
-        if (adapter->m_configuration.bPowerOffOnStandby == 1)
-          g_application.ExecuteXBMCAction("Suspend");
-        else if (adapter->m_bShutdownOnStandby)
-          g_application.ExecuteXBMCAction("Shutdown");
+        adapter->OnTvStandby();
       }
       break;
     case CEC_OPCODE_SET_MENU_LANGUAGE:
@@ -1360,8 +1387,8 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void)

   // read the mutually exclusive boolean settings
   int iStandbyAction(GetSettingInt("standby_pc_on_tv_standby"));
-  m_configuration.bPowerOffOnStandby = iStandbyAction == 13011 ? 1 : 0;
-  m_bShutdownOnStandby = iStandbyAction == 13005;
+  m_configuration.bPowerOffOnStandby = iStandbyAction == LOCALISED_ID_SUSPEND ? 1 : 0;
+  m_bShutdownOnStandby = iStandbyAction == LOCALISED_ID_POWEROFF;

 #if defined(CEC_DOUBLE_TAP_TIMEOUT_MS_OLD)
   // double tap prevention timeout in ms. libCEC uses 50ms units for this in 2.2.0, so divide by 50
@@ -1373,7 +1400,7 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void)

   if (GetSettingBool("pause_playback_on_deactivate"))
   {
-    SetSetting("pause_or_stop_playback_on_deactivate", 36045);
+    SetSetting("pause_or_stop_playback_on_deactivate", LOCALISED_ID_PAUSE);
     SetSetting("pause_playback_on_deactivate", false);
   }
 }
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h
index 30b22c9..9274eab 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h
@@ -144,6 +144,7 @@ namespace PERIPHERALS

     void SetAudioSystemConnected(bool bSetTo);
     void SetMenuLanguage(const char *strLanguage);
+    void OnTvStandby(void);

     // callbacks from libCEC
     static void CecLogMessage(void *cbParam, const CEC::cec_log_message* message);

From f0e1725617e41e841c9c24a20f1fc9b37347c8c3 Mon Sep 17 00:00:00 2001
From: Lars Op den Kamp <lars@opdenkamp.eu>
Date: Fri, 11 Nov 2016 10:09:56 +0100
Subject: [PATCH 3/4] [cec] add CEC IMX adapter as known type and set no
 polling.

that eliminates extensive periodic /sys walkthrough

(this is reused Lars's commit e59d7e028288464e6890141a830e4a83d4b9d065)
---
 xbmc/peripherals/PeripheralTypes.h                | 5 +++++
 xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h
index 34ce2ef..c87242f 100644
--- a/xbmc/peripherals/PeripheralTypes.h
+++ b/xbmc/peripherals/PeripheralTypes.h
@@ -38,7 +38,8 @@
     PERIPHERAL_BUS_USB,
     PERIPHERAL_BUS_PCI,
     PERIPHERAL_BUS_RPI,
-    PERIPHERAL_BUS_CEC
+    PERIPHERAL_BUS_CEC,
+    PERIPHERAL_BUS_IMX
   };

   enum PeripheralFeature
@@ -173,6 +174,8 @@ namespace PERIPHERALS
         return "pci";
       case PERIPHERAL_BUS_RPI:
         return "rpi";
+      case PERIPHERAL_BUS_IMX:
+        return "imx";
       case PERIPHERAL_BUS_CEC:
         return "cec";
       case PERIPHERAL_BUS_ADDON:
@@ -197,6 +200,8 @@ namespace PERIPHERALS
         return PERIPHERAL_BUS_PCI;
       else if (strTypeLowerCase == "rpi")
         return PERIPHERAL_BUS_RPI;
+      else if (strTypeLowerCase == "imx")
+        return PERIPHERAL_BUS_IMX;
       else if (strTypeLowerCase == "cec")
         return PERIPHERAL_BUS_CEC;
       else if (strTypeLowerCase == "addon")
diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp
index b04fe00..abd0a6b 100644
--- a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp
+++ b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp
@@ -102,6 +102,12 @@ bool CPeripheralBusCEC::PerformDeviceScan(PeripheralScanResults &results)
       /** the Pi's adapter cannot be removed, no need to rescan */
       m_bNeedsPolling = false;
       break;
+#if defined(HAS_IMXVPU)
+    case ADAPTERTYPE_IMX:
+      result.m_mappedBusType = PERIPHERAL_BUS_IMX;
+      m_bNeedsPolling = false;
+      break;
+#endif
     default:
       break;
     }

From cfcfb4c98cf1a6d756fc3962e6d803c297917684 Mon Sep 17 00:00:00 2001
From: Lars Op den Kamp <lars@opdenkamp.eu>
Date: Fri, 11 Nov 2016 10:10:07 +0100
Subject: [PATCH 4/4] [cec] added: setting to make libCEC wake up the AVR
 explicitly when activating the source.

ref: https://github.com/Pulse-Eight/libcec/issues/156
---
 addons/resource.language.en_gb/resources/strings.po | 7 ++++++-
 system/peripherals.xml                              | 3 ++-
 xbmc/peripherals/devices/PeripheralCecAdapter.cpp   | 1 +
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/system/peripherals.xml b/system/peripherals.xml
index 1fa31e1..ed707b6 100644
--- a/system/peripherals.xml
+++ b/system/peripherals.xml
@@ -16,7 +16,7 @@
     <setting key="send_inactive_source" type="bool" value="1" label="36025" order="5" />
     <setting key="cec_standby_screensaver" type="bool" value="0" label="36009" order="6" />
     <setting key="cec_wake_screensaver" type="bool" value="1" label="36010" order="7" />
-    <setting key="standby_pc_on_tv_standby" type="enum" value="13011" label="36029" order="8" lvalues="36028|13005|13011|13009|36043|36045" />
+    <setting key="standby_pc_on_tv_standby" type="enum" value="13011" label="36029" order="8" lvalues="36028|13005|13011|13009|36044|36046" />
     <setting key="standby_tv_on_pc_standby" type="bool" value="1" label="36026" order="9" />
     <setting key="use_tv_menu_language" type="bool" value="1" label="36018" order="10" />
     <setting key="pause_playback_on_deactivate" type="bool" value="1" label="36033" configurable="0" />
@@ -24,6 +24,7 @@
     <setting key="connected_device" type="enum" label="36019" value="36037" lvalues="36037|36038" order="12" />
     <setting key="cec_hdmi_port" type="int" value="1" min="1" max="15" label="36015" order="13" />
     <setting key="physical_address" type="string" label="36021" value="0" order="14" />
+    <setting key="power_avr_on_as" type="bool" label="36045" value="0" order="15" />

     <setting key="tv_vendor" type="int" value="0" configurable="0" />
     <setting key="device_name" type="string" value="Kodi" configurable="0" />
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
index 1b7c38e..d032ffd 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
@@ -1384,6 +1384,7 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void)
   m_bPowerOffScreensaver               = GetSettingBool("cec_standby_screensaver") ? 1 : 0;
   m_bPowerOnScreensaver                = GetSettingBool("cec_wake_screensaver") ? 1 : 0;
   m_bSendInactiveSource                = GetSettingBool("send_inactive_source") ? 1 : 0;
+  m_configuration.bAutoWakeAVR         = GetSettingBool("power_avr_on_as") ? 1 : 0;

   // read the mutually exclusive boolean settings
   int iStandbyAction(GetSettingInt("standby_pc_on_tv_standby"));