Kodi Community Forum

Full Version: Enabling Shutdown Timer menu display - PowerManager.cpp validation override
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

I'm about to run Kodi 18.8 on Raspberry Pi boards and looking for a way to enable the Shutdown Timer for a user that doesn't have the right to shutdown the system.
There should be an "Exit Timer" enabled by default in such a case, when the user can't shutdown the system, but that's something that will take time & will to implement.
My use case is simple, I'm trying to turn Kodi into an actual MediaCenter and not only use it as a playback application. Shutting down the system running Kodi is really dumb IMO, because you need to power it back on manually after this and the remote control won't help.

I managed to get this done in Kodi 17.x by hacking the /xbmc/powermanagement/PowerManager.cpp, setting all validations on true, but the code in Kodi 17.x was simpler.
I'm starting Kodi 17.x with the help of lircd and irexec (launching a script) and keeping the underlying Linux system always on. The simple script (it lacks a check to figure if Kodi is already running):
Code:
#turning HDMI on - will bring the Monitor/TV on
/opt/vc/bin/vcgencmd display_power 1
#starting Kodi
/usr/bin/kodi
#turning HDMI off - will bring the Monitor/TV down
/opt/vc/bin/vcgencmd display_power 0
When Kodi exits (even triggered by the Shutdown Timer), the lircd & irexec remain active and waiting for my remote control input to start Kodi again. This way I managed to have an actual Media Center that I'm controlling with the help of my remote control.

Now, Kodi 18.8 has some new, enhanced, PowerManagement code and I'm failing to hack it, that's override the checks for identifying if the user with which kodi was launched has shutdown permissions and set the validation on true by default and get the ShutDown Timer menu option displayed (active).
This is what I tried so far and failed - I only get the Exit menu option.
Original file:
https://github.com/xbmc/xbmc/blob/Leia/x...anager.cpp
My hacking attempt - diff -u PowerManager-orig.cpp PowerManager.cpp
cpp:

--- PowerManager-orig.cpp       2020-09-24 21:35:46.725570076 +0300
+++ PowerManager.cpp    2020-09-24 21:37:30.495570037 +0300
@@ -52,14 +52,15 @@

 void CPowerManager::SetDefaults()
 {
-  int defaultShutdown = m_settings->GetInt(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE);
+  int defaultShutdown = POWERSTATE_SHUTDOWN;

   switch (defaultShutdown)
   {
     case POWERSTATE_QUIT:
     case POWERSTATE_MINIMIZE:
       // assume we can shutdown if --standalone is passed
-      if (g_application.IsStandAlone())
+// comment this to enable shutdown menu
+//      if (g_application.IsStandAlone())
         defaultShutdown = POWERSTATE_SHUTDOWN;
     break;
     case POWERSTATE_HIBERNATE:
@@ -81,13 +82,16 @@
       }
     break;
     case POWERSTATE_SHUTDOWN:
-      if (!CServiceBroker::GetPowerManager().CanPowerdown())
-      {
-        if (CServiceBroker::GetPowerManager().CanSuspend())
-          defaultShutdown = POWERSTATE_SUSPEND;
-        else
-          defaultShutdown = CServiceBroker::GetPowerManager().CanHibernate() ? POWERSTATE_HIBERNATE : POWERSTATE_QUIT;
-      }
+// add this to enable shutdown menu
+        defaultShutdown = POWERSTATE_SHUTDOWN;
+// comment this to enable shutdown menu
+//      if (!CServiceBroker::GetPowerManager().CanPowerdown())
+//      {
+//        if (CServiceBroker::GetPowerManager().CanSuspend())
+//          defaultShutdown = POWERSTATE_SUSPEND;
+//        else
+//          defaultShutdown = CServiceBroker::GetPowerManager().CanHibernate() ? POWERSTATE_HIBERNATE : POWERSTATE_QUIT;
+//      }
     break;
   }

@@ -96,7 +100,12 @@

 bool CPowerManager:Tongueowerdown()
 {
-  if (CanPowerdown() && m_instance->Powerdown())
+// comment this to enable shutdown menu
+//  if (CanPowerdown() && m_instance->Powerdown())
+// add :
+ bool blabla = true;
+ if (blabla)
+// done add
   {
     CGUIDialogBusy* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusy>(WINDOW_DIALOG_BUSY);
     if (dialog)
@@ -118,6 +127,7 @@
   return (CanHibernate() && m_instance->Hibernate());
 }

+
 bool CPowerManager::Reboot()
 {
   bool success = CanReboot() ? m_instance->Reboot() : false;
@@ -136,7 +146,7 @@

 bool CPowerManager::CanPowerdown()
 {
-  return m_instance ? m_instance->CanPowerdown() : false;
+  return m_instance ? m_instance->CanPowerdown() : true;
 }
 bool CPowerManager::CanSuspend()
 {

I'm not very good in coding,  failing to understand the logic in PowerManager.cpp and would be very thankful if some of the Kodi devs could help me with a simple way to override the shutdown validations/checks for the user that launched Kodi and get ShutDown Timer menu option displayed.

Many thanks in advance!
Went a little postal in my latest attempt and commented out a lot of conditional statements. Didn't help, after building Kodi 18.8 I still only got the Exit Menu Option.
Code:
--- PowerManager-orig.cpp       2020-09-24 23:35:46.725570076 +0300
+++ PowerManager.cpp    2020-09-26 01:44:49.235206351 +0300
@@ -52,51 +52,60 @@

 void CPowerManager::SetDefaults()
 {
-  int defaultShutdown = m_settings->GetInt(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE);
+  int defaultShutdown = POWERSTATE_SHUTDOWN;

-  switch (defaultShutdown)
-  {
-    case POWERSTATE_QUIT:
-    case POWERSTATE_MINIMIZE:
+//  switch (defaultShutdown)
+//  {
+//    case POWERSTATE_QUIT:
+//    case POWERSTATE_MINIMIZE:
       // assume we can shutdown if --standalone is passed
-      if (g_application.IsStandAlone())
-        defaultShutdown = POWERSTATE_SHUTDOWN;
-    break;
-    case POWERSTATE_HIBERNATE:
-      if (!CServiceBroker::GetPowerManager().CanHibernate())
-      {
-        if (CServiceBroker::GetPowerManager().CanSuspend())
-          defaultShutdown = POWERSTATE_SUSPEND;
-        else
-          defaultShutdown = CServiceBroker::GetPowerManager().CanPowerdown() ? POWERSTATE_SHUTDOWN : POWERSTATE_QUIT;
-      }
-    break;
-    case POWERSTATE_SUSPEND:
-      if (!CServiceBroker::GetPowerManager().CanSuspend())
-      {
-        if (CServiceBroker::GetPowerManager().CanHibernate())
-          defaultShutdown = POWERSTATE_HIBERNATE;
-        else
-          defaultShutdown = CServiceBroker::GetPowerManager().CanPowerdown() ? POWERSTATE_SHUTDOWN : POWERSTATE_QUIT;
-      }
-    break;
-    case POWERSTATE_SHUTDOWN:
-      if (!CServiceBroker::GetPowerManager().CanPowerdown())
-      {
-        if (CServiceBroker::GetPowerManager().CanSuspend())
-          defaultShutdown = POWERSTATE_SUSPEND;
-        else
-          defaultShutdown = CServiceBroker::GetPowerManager().CanHibernate() ? POWERSTATE_HIBERNATE : POWERSTATE_QUIT;
-      }
-    break;
-  }
+// comment this to enable shutdown menu
+//      if (g_application.IsStandAlone())
+//        defaultShutdown = POWERSTATE_SHUTDOWN;
+//    break;
+//    case POWERSTATE_HIBERNATE:
+//      if (!CServiceBroker::GetPowerManager().CanHibernate())
+//      {
+//        if (CServiceBroker::GetPowerManager().CanSuspend())
+//          defaultShutdown = POWERSTATE_SUSPEND;
+//        else
+//          defaultShutdown = CServiceBroker::GetPowerManager().CanPowerdown() ? POWERSTATE_SHUTDOWN : POWERSTATE_QUIT;
+//      }
+//    break;
+//    case POWERSTATE_SUSPEND:
+//      if (!CServiceBroker::GetPowerManager().CanSuspend())
+//      {
+//        if (CServiceBroker::GetPowerManager().CanHibernate())
+//          defaultShutdown = POWERSTATE_HIBERNATE;
+//        else
+//          defaultShutdown = CServiceBroker::GetPowerManager().CanPowerdown() ? POWERSTATE_SHUTDOWN : POWERSTATE_QUIT;
+//      }
+//    break;
+//    case POWERSTATE_SHUTDOWN:
+// add this to enable shutdown menu
+//        defaultShutdown = POWERSTATE_SHUTDOWN;
+// comment this to enable shutdown menu
+//      if (!CServiceBroker::GetPowerManager().CanPowerdown())
+//      {
+//        if (CServiceBroker::GetPowerManager().CanSuspend())
+//          defaultShutdown = POWERSTATE_SUSPEND;
+//        else
+//          defaultShutdown = CServiceBroker::GetPowerManager().CanHibernate() ? POWERSTATE_HIBERNATE : POWERSTATE_QUIT;
+//      }
+//    break;
+// }

   std::static_pointer_cast<CSettingInt>(m_settings->GetSetting(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE))->SetDefault(defaultShutdown);
 }

 bool CPowerManager::Powerdown()
 {
-  if (CanPowerdown() && m_instance->Powerdown())
+// comment this to enable shutdown menu
+//  if (CanPowerdown() && m_instance->Powerdown())
+// add :
+ bool blabla = true;
+ if (blabla)
+// done add
   {
     CGUIDialogBusy* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusy>(WINDOW_DIALOG_BUSY);
     if (dialog)
@@ -105,7 +114,7 @@
     return true;
   }

-  return false;
+  return true;
 }

 bool CPowerManager::Suspend()
@@ -118,6 +127,7 @@
   return (CanHibernate() && m_instance->Hibernate());
 }

+
 bool CPowerManager::Reboot()
 {
   bool success = CanReboot() ? m_instance->Reboot() : false;
@@ -136,7 +146,7 @@

 bool CPowerManager::CanPowerdown()
 {
-  return m_instance ? m_instance->CanPowerdown() : false;
+  return m_instance ? m_instance->CanPowerdown() : true;
 }
 bool CPowerManager::CanSuspend()
 {
@@ -264,17 +274,17 @@

 void CPowerManager::SettingOptionsShutdownStatesFiller(SettingConstPtr setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
 {
-  if (CServiceBroker::GetPowerManager().CanPowerdown())
+//  if (CServiceBroker::GetPowerManager().CanPowerdown())
     list.push_back(make_pair(g_localizeStrings.Get(13005), POWERSTATE_SHUTDOWN));
-  if (CServiceBroker::GetPowerManager().CanHibernate())
-    list.push_back(make_pair(g_localizeStrings.Get(13010), POWERSTATE_HIBERNATE));
-  if (CServiceBroker::GetPowerManager().CanSuspend())
-    list.push_back(make_pair(g_localizeStrings.Get(13011), POWERSTATE_SUSPEND));
-  if (!g_application.IsStandAlone())
-  {
+//  if (CServiceBroker::GetPowerManager().CanHibernate())
+//    list.push_back(make_pair(g_localizeStrings.Get(13010), POWERSTATE_HIBERNATE));
+//  if (CServiceBroker::GetPowerManager().CanSuspend())
+//    list.push_back(make_pair(g_localizeStrings.Get(13011), POWERSTATE_SUSPEND));
+//  if (!g_application.IsStandAlone())
+//  {
     list.push_back(make_pair(g_localizeStrings.Get(13009), POWERSTATE_QUIT));
-#if !defined(TARGET_DARWIN_IOS)
-    list.push_back(make_pair(g_localizeStrings.Get(13014), POWERSTATE_MINIMIZE));
-#endif
-  }
+// #if !defined(TARGET_DARWIN_IOS)
+//    list.push_back(make_pair(g_localizeStrings.Get(13014), POWERSTATE_MINIMIZE));
+// #endif
+//  }
 }

Any help appreciated.
Still stuck with this. Apparently I'll need some help from any of the more knowledgeable - according to github: 41 contributors:
https://github.com/xbmc/xbmc/blob/Leia/x...anager.cpp
bump

No one really has a clue / is willing to help?
bump!

Just wondering, is the logic for the population of the exit menu only in PowerManager.cpp in Kodi 18.x ? Still failing to hack it.

I also don't know how to cheat on system level (Linux) - giving the user with which I start kodi apparent rights to shutdown, in order for Kodi to validate that the user can shutdown.

I so much love Kodi but I soooo much hate that nobody gave a thought to make it actually usable as a media player system (as it pretends to be). As it stands, it's a feature rich video/audio/streaming player only. What's the bloody point to shutdown a media player ?

Shutdown Timer -  instead of Exit/ Suspend / StopPlayback&TurnOffMonitor Timer
https://github.com/xbmc/xbmc/blob/2e1c0f...cation.cpp
- at line 1711:
Code:
// built in functions : execute the built-in
  if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
  {
    if (!CBuiltins::GetInstance().IsSystemPowerdownCommand(action.GetName()) ||
        CServiceBroker::GetPVRManager().GUIActions()->CanSystemPowerdown())
    {
      CBuiltins::GetInstance().Execute(action.GetName());
      m_navigationTimer.StartZero();
    }
    return true;
  }

Another check "CanSystemPowerdown" ? Redundant?
(2021-11-11, 05:03)abga Wrote: [ -> ]There should be an "Exit Timer" enabled by default in such a case, when the user can't shutdown the system, but that's something that will take time & will to implement.
IMHO there should be no "power off, shutdown,  etc" in the exit menu att all (at least not as default settings). Regarding PowerManager.cpp and most of the old src code in Kodi, it's unfortunately undocumented and the only way try to find out the logic is to dive into the source code yourself. Good luck!