summaryrefslogtreecommitdiffstats
path: root/xbmc/powermanagement/PowerManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/powermanagement/PowerManager.cpp')
-rw-r--r--xbmc/powermanagement/PowerManager.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp
new file mode 100644
index 0000000..3c30817
--- /dev/null
+++ b/xbmc/powermanagement/PowerManager.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "PowerManager.h"
+
+#include "FileItem.h"
+#include "PowerTypes.h"
+#include "ServiceBroker.h"
+#include "application/AppParams.h"
+#include "application/Application.h"
+#include "application/ApplicationComponents.h"
+#include "application/ApplicationPlayer.h"
+#include "application/ApplicationPowerHandling.h"
+#include "application/ApplicationStackHelper.h"
+#include "cores/AudioEngine/Interfaces/AE.h"
+#include "dialogs/GUIDialogBusyNoCancel.h"
+#include "dialogs/GUIDialogKaiToast.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "interfaces/AnnouncementManager.h"
+#include "network/Network.h"
+#include "pvr/PVRManager.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "settings/lib/Setting.h"
+#include "settings/lib/SettingDefinitions.h"
+#include "settings/lib/SettingsManager.h"
+#include "utils/log.h"
+#include "weather/WeatherManager.h"
+
+#include <list>
+#include <memory>
+
+#if defined(TARGET_WINDOWS_DESKTOP)
+extern HWND g_hWnd;
+#endif
+
+CPowerManager::CPowerManager() : m_settings(CServiceBroker::GetSettingsComponent()->GetSettings())
+{
+ m_settings->GetSettingsManager()->RegisterSettingOptionsFiller("shutdownstates", SettingOptionsShutdownStatesFiller);
+}
+
+CPowerManager::~CPowerManager() = default;
+
+void CPowerManager::Initialize()
+{
+ m_instance.reset(IPowerSyscall::CreateInstance());
+}
+
+void CPowerManager::SetDefaults()
+{
+ auto setting = m_settings->GetSetting(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE);
+ if (!setting)
+ {
+ CLog::Log(LOGERROR, "Failed to load setting for: {}",
+ CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE);
+ return;
+ }
+
+ int defaultShutdown = m_settings->GetInt(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE);
+
+ switch (defaultShutdown)
+ {
+ case POWERSTATE_QUIT:
+ case POWERSTATE_MINIMIZE:
+ // assume we can shutdown if --standalone is passed
+ if (CServiceBroker::GetAppParams()->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;
+ }
+
+ std::static_pointer_cast<CSettingInt>(setting)->SetDefault(defaultShutdown);
+}
+
+bool CPowerManager::Powerdown()
+{
+ if (CanPowerdown() && m_instance->Powerdown())
+ {
+ CGUIDialogBusyNoCancel* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusyNoCancel>(
+ WINDOW_DIALOG_BUSY_NOCANCEL);
+ if (dialog)
+ dialog->Open();
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CPowerManager::Suspend()
+{
+ return (CanSuspend() && m_instance->Suspend());
+}
+
+bool CPowerManager::Hibernate()
+{
+ return (CanHibernate() && m_instance->Hibernate());
+}
+
+bool CPowerManager::Reboot()
+{
+ bool success = CanReboot() ? m_instance->Reboot() : false;
+
+ if (success)
+ {
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System, "OnRestart");
+
+ CGUIDialogBusyNoCancel* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusyNoCancel>(
+ WINDOW_DIALOG_BUSY_NOCANCEL);
+ if (dialog)
+ dialog->Open();
+ }
+
+ return success;
+}
+
+bool CPowerManager::CanPowerdown()
+{
+ return m_instance ? m_instance->CanPowerdown() : false;
+}
+bool CPowerManager::CanSuspend()
+{
+ return m_instance ? m_instance->CanSuspend() : false;
+}
+bool CPowerManager::CanHibernate()
+{
+ return m_instance ? m_instance->CanHibernate() : false;
+}
+bool CPowerManager::CanReboot()
+{
+ return m_instance ? m_instance->CanReboot() : false;
+}
+int CPowerManager::BatteryLevel()
+{
+ return m_instance ? m_instance->BatteryLevel() : 0;
+}
+void CPowerManager::ProcessEvents()
+{
+ if (!m_instance)
+ return;
+
+ static int nesting = 0;
+
+ if (++nesting == 1)
+ m_instance->PumpPowerEvents(this);
+
+ nesting--;
+}
+
+void CPowerManager::OnSleep()
+{
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System, "OnSleep");
+
+ CGUIDialogBusyNoCancel* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusyNoCancel>(
+ WINDOW_DIALOG_BUSY_NOCANCEL);
+ if (dialog)
+ dialog->Open();
+
+ CLog::Log(LOGINFO, "{}: Running sleep jobs", __FUNCTION__);
+
+ StorePlayerState();
+
+ g_application.StopPlaying();
+ CServiceBroker::GetPVRManager().OnSleep();
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPower = components.GetComponent<CApplicationPowerHandling>();
+ appPower->StopShutdownTimer();
+ appPower->StopScreenSaverTimer();
+ g_application.CloseNetworkShares();
+ CServiceBroker::GetActiveAE()->Suspend();
+}
+
+void CPowerManager::OnWake()
+{
+ CLog::Log(LOGINFO, "{}: Running resume jobs", __FUNCTION__);
+
+ CServiceBroker::GetNetwork().WaitForNet();
+
+ // reset out timers
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPower = components.GetComponent<CApplicationPowerHandling>();
+ appPower->ResetShutdownTimers();
+
+ CGUIDialogBusyNoCancel* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusyNoCancel>(
+ WINDOW_DIALOG_BUSY_NOCANCEL);
+ if (dialog)
+ dialog->Close(true); // force close. no closing animation, sound etc at this early stage
+
+#if defined(TARGET_DARWIN_OSX) || defined(TARGET_WINDOWS)
+ if (CServiceBroker::GetWinSystem()->IsFullScreen())
+ {
+#if defined(TARGET_WINDOWS_DESKTOP)
+ ShowWindow(g_hWnd, SW_RESTORE);
+ SetForegroundWindow(g_hWnd);
+#endif
+ }
+ appPower->ResetScreenSaver();
+#endif
+
+ CServiceBroker::GetActiveAE()->Resume();
+ g_application.UpdateLibraries();
+ CServiceBroker::GetWeatherManager().Refresh();
+ CServiceBroker::GetPVRManager().OnWake();
+ RestorePlayerState();
+
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System, "OnWake");
+}
+
+void CPowerManager::OnLowBattery()
+{
+ CLog::Log(LOGINFO, "{}: Running low battery jobs", __FUNCTION__);
+
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(13050), "");
+
+ CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System, "OnLowBattery");
+}
+
+void CPowerManager::StorePlayerState()
+{
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ if (appPlayer->IsPlaying())
+ {
+ m_lastUsedPlayer = appPlayer->GetCurrentPlayer();
+ m_lastPlayedFileItem.reset(new CFileItem(g_application.CurrentFileItem()));
+ // set the actual offset instead of store and load it from database
+ m_lastPlayedFileItem->SetStartOffset(appPlayer->GetTime());
+ // in case of regular stack, correct the start offset by adding current part start time
+ const auto stackHelper = components.GetComponent<CApplicationStackHelper>();
+ if (stackHelper->IsPlayingRegularStack())
+ m_lastPlayedFileItem->SetStartOffset(m_lastPlayedFileItem->GetStartOffset() +
+ stackHelper->GetCurrentStackPartStartTimeMs());
+ // in case of iso stack, keep track of part number
+ m_lastPlayedFileItem->m_lStartPartNumber =
+ stackHelper->IsPlayingISOStack() ? stackHelper->GetCurrentPartNumber() + 1 : 1;
+ // for iso and iso stacks, keep track of playerstate
+ m_lastPlayedFileItem->SetProperty("savedplayerstate", appPlayer->GetPlayerState());
+ CLog::Log(LOGDEBUG,
+ "CPowerManager::StorePlayerState - store last played item (startOffset: {} ms)",
+ m_lastPlayedFileItem->GetStartOffset());
+ }
+ else
+ {
+ m_lastUsedPlayer.clear();
+ m_lastPlayedFileItem.reset();
+ }
+}
+
+void CPowerManager::RestorePlayerState()
+{
+ if (!m_lastPlayedFileItem)
+ return;
+
+ CLog::Log(LOGDEBUG,
+ "CPowerManager::RestorePlayerState - resume last played item (startOffset: {} ms)",
+ m_lastPlayedFileItem->GetStartOffset());
+ g_application.PlayFile(*m_lastPlayedFileItem, m_lastUsedPlayer);
+}
+
+void CPowerManager::SettingOptionsShutdownStatesFiller(const SettingConstPtr& setting,
+ std::vector<IntegerSettingOption>& list,
+ int& current,
+ void* data)
+{
+ if (CServiceBroker::GetPowerManager().CanPowerdown())
+ list.emplace_back(g_localizeStrings.Get(13005), POWERSTATE_SHUTDOWN);
+ if (CServiceBroker::GetPowerManager().CanHibernate())
+ list.emplace_back(g_localizeStrings.Get(13010), POWERSTATE_HIBERNATE);
+ if (CServiceBroker::GetPowerManager().CanSuspend())
+ list.emplace_back(g_localizeStrings.Get(13011), POWERSTATE_SUSPEND);
+ if (!CServiceBroker::GetAppParams()->IsStandAlone())
+ {
+ list.emplace_back(g_localizeStrings.Get(13009), POWERSTATE_QUIT);
+#if !defined(TARGET_DARWIN_EMBEDDED)
+ list.emplace_back(g_localizeStrings.Get(13014), POWERSTATE_MINIMIZE);
+#endif
+ }
+}