2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "PowerManager.h"
12 #include "PowerTypes.h"
13 #include "ServiceBroker.h"
14 #include "application/AppParams.h"
15 #include "application/Application.h"
16 #include "application/ApplicationComponents.h"
17 #include "application/ApplicationPlayer.h"
18 #include "application/ApplicationPowerHandling.h"
19 #include "application/ApplicationStackHelper.h"
20 #include "cores/AudioEngine/Interfaces/AE.h"
21 #include "dialogs/GUIDialogBusyNoCancel.h"
22 #include "dialogs/GUIDialogKaiToast.h"
23 #include "guilib/GUIComponent.h"
24 #include "guilib/GUIWindowManager.h"
25 #include "guilib/LocalizeStrings.h"
26 #include "interfaces/AnnouncementManager.h"
27 #include "network/Network.h"
28 #include "pvr/PVRManager.h"
29 #include "settings/Settings.h"
30 #include "settings/SettingsComponent.h"
31 #include "settings/lib/Setting.h"
32 #include "settings/lib/SettingDefinitions.h"
33 #include "settings/lib/SettingsManager.h"
34 #include "utils/log.h"
35 #include "weather/WeatherManager.h"
40 #if defined(TARGET_WINDOWS_DESKTOP)
44 CPowerManager::CPowerManager() : m_settings(CServiceBroker::GetSettingsComponent()->GetSettings())
46 m_settings
->GetSettingsManager()->RegisterSettingOptionsFiller("shutdownstates", SettingOptionsShutdownStatesFiller
);
49 CPowerManager::~CPowerManager() = default;
51 void CPowerManager::Initialize()
53 m_instance
.reset(IPowerSyscall::CreateInstance());
56 void CPowerManager::SetDefaults()
58 auto setting
= m_settings
->GetSetting(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE
);
61 CLog::Log(LOGERROR
, "Failed to load setting for: {}",
62 CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE
);
66 int defaultShutdown
= m_settings
->GetInt(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE
);
68 switch (defaultShutdown
)
71 case POWERSTATE_MINIMIZE
:
72 // assume we can shutdown if --standalone is passed
73 if (CServiceBroker::GetAppParams()->IsStandAlone())
74 defaultShutdown
= POWERSTATE_SHUTDOWN
;
76 case POWERSTATE_HIBERNATE
:
77 if (!CServiceBroker::GetPowerManager().CanHibernate())
79 if (CServiceBroker::GetPowerManager().CanSuspend())
80 defaultShutdown
= POWERSTATE_SUSPEND
;
82 defaultShutdown
= CServiceBroker::GetPowerManager().CanPowerdown() ? POWERSTATE_SHUTDOWN
: POWERSTATE_QUIT
;
85 case POWERSTATE_SUSPEND
:
86 if (!CServiceBroker::GetPowerManager().CanSuspend())
88 if (CServiceBroker::GetPowerManager().CanHibernate())
89 defaultShutdown
= POWERSTATE_HIBERNATE
;
91 defaultShutdown
= CServiceBroker::GetPowerManager().CanPowerdown() ? POWERSTATE_SHUTDOWN
: POWERSTATE_QUIT
;
94 case POWERSTATE_SHUTDOWN
:
95 if (!CServiceBroker::GetPowerManager().CanPowerdown())
97 if (CServiceBroker::GetPowerManager().CanSuspend())
98 defaultShutdown
= POWERSTATE_SUSPEND
;
100 defaultShutdown
= CServiceBroker::GetPowerManager().CanHibernate() ? POWERSTATE_HIBERNATE
: POWERSTATE_QUIT
;
105 std::static_pointer_cast
<CSettingInt
>(setting
)->SetDefault(defaultShutdown
);
108 bool CPowerManager::Powerdown()
110 if (CanPowerdown() && m_instance
->Powerdown())
112 CGUIDialogBusyNoCancel
* dialog
=
113 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogBusyNoCancel
>(
114 WINDOW_DIALOG_BUSY_NOCANCEL
);
124 bool CPowerManager::Suspend()
126 return (CanSuspend() && m_instance
->Suspend());
129 bool CPowerManager::Hibernate()
131 return (CanHibernate() && m_instance
->Hibernate());
134 bool CPowerManager::Reboot()
136 bool success
= CanReboot() ? m_instance
->Reboot() : false;
140 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System
, "OnRestart");
142 CGUIDialogBusyNoCancel
* dialog
=
143 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogBusyNoCancel
>(
144 WINDOW_DIALOG_BUSY_NOCANCEL
);
152 bool CPowerManager::CanPowerdown()
154 return m_instance
? m_instance
->CanPowerdown() : false;
156 bool CPowerManager::CanSuspend()
158 return m_instance
? m_instance
->CanSuspend() : false;
160 bool CPowerManager::CanHibernate()
162 return m_instance
? m_instance
->CanHibernate() : false;
164 bool CPowerManager::CanReboot()
166 return m_instance
? m_instance
->CanReboot() : false;
168 int CPowerManager::BatteryLevel()
170 return m_instance
? m_instance
->BatteryLevel() : 0;
172 void CPowerManager::ProcessEvents()
177 static int nesting
= 0;
180 m_instance
->PumpPowerEvents(this);
185 void CPowerManager::OnSleep()
187 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System
, "OnSleep");
189 CGUIDialogBusyNoCancel
* dialog
=
190 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogBusyNoCancel
>(
191 WINDOW_DIALOG_BUSY_NOCANCEL
);
195 CLog::Log(LOGINFO
, "{}: Running sleep jobs", __FUNCTION__
);
199 g_application
.StopPlaying();
200 CServiceBroker::GetPVRManager().OnSleep();
201 auto& components
= CServiceBroker::GetAppComponents();
202 const auto appPower
= components
.GetComponent
<CApplicationPowerHandling
>();
203 appPower
->StopShutdownTimer();
204 appPower
->StopScreenSaverTimer();
205 g_application
.CloseNetworkShares();
206 CServiceBroker::GetActiveAE()->Suspend();
209 void CPowerManager::OnWake()
211 CLog::Log(LOGINFO
, "{}: Running resume jobs", __FUNCTION__
);
213 CServiceBroker::GetNetwork().WaitForNet();
216 auto& components
= CServiceBroker::GetAppComponents();
217 const auto appPower
= components
.GetComponent
<CApplicationPowerHandling
>();
218 appPower
->ResetShutdownTimers();
220 CGUIDialogBusyNoCancel
* dialog
=
221 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogBusyNoCancel
>(
222 WINDOW_DIALOG_BUSY_NOCANCEL
);
224 dialog
->Close(true); // force close. no closing animation, sound etc at this early stage
226 #if defined(TARGET_DARWIN_OSX) || defined(TARGET_WINDOWS)
227 if (CServiceBroker::GetWinSystem()->IsFullScreen())
229 #if defined(TARGET_WINDOWS_DESKTOP)
230 ShowWindow(g_hWnd
, SW_RESTORE
);
231 SetForegroundWindow(g_hWnd
);
234 appPower
->ResetScreenSaver();
237 CServiceBroker::GetActiveAE()->Resume();
238 g_application
.UpdateLibraries();
239 CServiceBroker::GetWeatherManager().Refresh();
240 CServiceBroker::GetPVRManager().OnWake();
241 RestorePlayerState();
243 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System
, "OnWake");
246 void CPowerManager::OnLowBattery()
248 CLog::Log(LOGINFO
, "{}: Running low battery jobs", __FUNCTION__
);
250 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning
, g_localizeStrings
.Get(13050), "");
252 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System
, "OnLowBattery");
255 void CPowerManager::StorePlayerState()
257 auto& components
= CServiceBroker::GetAppComponents();
258 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
259 if (appPlayer
->IsPlaying())
261 m_lastUsedPlayer
= appPlayer
->GetCurrentPlayer();
262 m_lastPlayedFileItem
= std::make_unique
<CFileItem
>(g_application
.CurrentFileItem());
263 // set the actual offset instead of store and load it from database
264 m_lastPlayedFileItem
->SetStartOffset(appPlayer
->GetTime());
265 // in case of regular stack, correct the start offset by adding current part start time
266 const auto stackHelper
= components
.GetComponent
<CApplicationStackHelper
>();
267 if (stackHelper
->IsPlayingRegularStack())
268 m_lastPlayedFileItem
->SetStartOffset(m_lastPlayedFileItem
->GetStartOffset() +
269 stackHelper
->GetCurrentStackPartStartTimeMs());
270 // in case of iso stack, keep track of part number
271 m_lastPlayedFileItem
->m_lStartPartNumber
=
272 stackHelper
->IsPlayingISOStack() ? stackHelper
->GetCurrentPartNumber() + 1 : 1;
273 // for iso and iso stacks, keep track of playerstate
274 m_lastPlayedFileItem
->SetProperty("savedplayerstate", appPlayer
->GetPlayerState());
276 "CPowerManager::StorePlayerState - store last played item (startOffset: {} ms)",
277 m_lastPlayedFileItem
->GetStartOffset());
281 m_lastUsedPlayer
.clear();
282 m_lastPlayedFileItem
.reset();
286 void CPowerManager::RestorePlayerState()
288 if (!m_lastPlayedFileItem
)
292 "CPowerManager::RestorePlayerState - resume last played item (startOffset: {} ms)",
293 m_lastPlayedFileItem
->GetStartOffset());
294 g_application
.PlayFile(*m_lastPlayedFileItem
, m_lastUsedPlayer
);
297 void CPowerManager::SettingOptionsShutdownStatesFiller(const SettingConstPtr
& setting
,
298 std::vector
<IntegerSettingOption
>& list
,
302 if (CServiceBroker::GetPowerManager().CanPowerdown())
303 list
.emplace_back(g_localizeStrings
.Get(13005), POWERSTATE_SHUTDOWN
);
304 if (CServiceBroker::GetPowerManager().CanHibernate())
305 list
.emplace_back(g_localizeStrings
.Get(13010), POWERSTATE_HIBERNATE
);
306 if (CServiceBroker::GetPowerManager().CanSuspend())
307 list
.emplace_back(g_localizeStrings
.Get(13011), POWERSTATE_SUSPEND
);
308 if (!CServiceBroker::GetAppParams()->IsStandAlone())
310 list
.emplace_back(g_localizeStrings
.Get(13009), POWERSTATE_QUIT
);
311 #if !defined(TARGET_DARWIN_EMBEDDED)
312 list
.emplace_back(g_localizeStrings
.Get(13014), POWERSTATE_MINIMIZE
);