MythTV  master
mythpower.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "mythcorecontext.h"
3 #include "mythpower.h"
4 
5 #ifdef USING_DBUS
7 #endif
8 
9 #ifdef Q_OS_DARWIN
10 #include "platforms/mythpowerosx.h"
11 #endif
12 
13 #define LOC QString("Power: ")
14 
15 QRecursiveMutex MythPower::s_lock;
16 
71 MythPower* MythPower::AcquireRelease(void *Reference, bool Acquire, std::chrono::seconds MinimumDelay)
72 {
73  static MythPower* s_instance = nullptr;
74  static QHash<void*,std::chrono::seconds> s_delays;
75 
76  QMutexLocker locker(&s_lock);
77  if (Acquire)
78  {
79  // Upref or create
80  if (s_instance)
81  {
82  s_instance->IncrRef();
83  }
84  else
85  {
86 #ifdef Q_OS_DARWIN
87  // NB OSX may have DBUS but it won't help here
88  s_instance = new MythPowerOSX();
89 #elif defined(USING_DBUS)
91  s_instance = new MythPowerDBus();
92 #endif
93  // default no functionality
94  if (!s_instance)
95  s_instance = new MythPower();
96  }
97  // Append additional feature delay request
98  s_delays.insert(Reference, MinimumDelay);
99  }
100  else
101  {
102  // Remove requested delay
103  s_delays.remove(Reference);
104 
105  // Decref and ensure nulled on last use
106  if (s_instance)
107  if (s_instance->DecrRef() == 0)
108  s_instance = nullptr;
109  }
110 
111  if (s_instance)
112  {
113  // Update the maximum requested delay
114  std::chrono::seconds max = std::max_element(s_delays.cbegin(), s_delays.cend()).value();
115  s_instance->SetRequestedDelay(max);
116  }
117  return s_instance;
118 }
119 
121  : ReferenceCounter("Power")
122 {
123  m_featureTimer.setSingleShot(true);
125 }
126 
127 void MythPower::Init(void)
128 {
129  QStringList supported = GetFeatureList();
130  if (supported.isEmpty())
131  supported << "None";
132  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Supported actions: %1").arg(supported.join(",")));
133 }
134 
135 void MythPower::SetRequestedDelay(std::chrono::seconds Delay)
136 {
137  m_maxRequestedDelay = Delay;
138 }
139 
140 MythPower::Features MythPower::GetFeatures(void)
141 {
142  Features result = FeatureNone;
143  s_lock.lock();
144  result = m_features;
145  s_lock.unlock();
146  return result;
147 }
148 
149 QStringList MythPower::GetFeatureList(void)
150 {
151  QStringList supported;
152  MythPower::Features features = GetFeatures();
153  if (features.testFlag(FeatureSuspend)) supported << FeatureToString(FeatureSuspend);
154  if (features.testFlag(FeatureHibernate)) supported << FeatureToString(FeatureHibernate);
155  if (features.testFlag(FeatureRestart)) supported << FeatureToString(FeatureRestart);
156  if (features.testFlag(FeatureShutdown)) supported << FeatureToString(FeatureShutdown);
157  if (features.testFlag(FeatureHybridSleep)) supported << FeatureToString(FeatureHybridSleep);
158  return supported;
159 }
160 
162 {
163  bool result = false;
164  s_lock.lock();
165  result = ((m_features & Supported) != 0U);
166  s_lock.unlock();
167  return result;
168 }
169 
171 {
172  int result = UnknownPower;
173  s_lock.lock();
174  result = m_powerLevel;
175  s_lock.unlock();
176  return result;
177 }
178 
180 {
181  QMutexLocker locker(&s_lock);
182 
183  if ((Request == FeatureNone) || !(m_features & Request))
184  return false;
185 
186  // N.B Always check for a new user delay value as this class is persistent.
187  // Default is user preference, limited by the maximum supported system value
188  // and possibly overriden by the maximum delay requested by other Myth classes.
189  auto user = gCoreContext->GetDurSetting<std::chrono::seconds>("EXIT_SHUTDOWN_DELAY", 3s);
190  auto delay = std::clamp(user, m_maxRequestedDelay, m_maxSupportedDelay);
191 
192  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("Delay: %1 User: %2 Requested: %3 Supported: %4")
193  .arg(Delay).arg(user.count()).arg(m_maxRequestedDelay.count())
194  .arg(m_maxSupportedDelay.count()));
195 
196  if (!Delay || delay < 1s)
197  {
199  DoFeature();
200  }
201 
202  if (!ScheduleFeature(Request, delay))
203  return false;
204 
205  auto remaining = m_featureTimer.remainingTimeAsDuration();
206  switch (Request)
207  {
208  case FeatureSuspend: emit WillSuspend(remaining); break;
209  case FeatureShutdown: emit WillShutDown(remaining); break;
210  case FeatureRestart: emit WillRestart(remaining); break;
211  case FeatureHibernate: emit WillHibernate(remaining); break;
212  case FeatureHybridSleep: emit WillHybridSleep(remaining); break;
213  default: break;
214  }
215  return true;
216 }
217 
220 {
221  QMutexLocker locker(&s_lock);
222 
223  if (!m_featureTimer.isActive() || !m_scheduledFeature)
224  LOG(VB_GENERAL, LOG_WARNING, LOC + "No power request to cancel");
225  else
226  {
227  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Cancelling %1 request with %2 seconds remaining")
228  .arg(FeatureToString(m_scheduledFeature)).arg(m_featureTimer.remainingTime() / 1000));
229  DidWakeUp();
230  }
232  m_featureTimer.stop();
233 }
234 
236 {
237  DoFeature();
238 }
239 
241 {
242  switch (Type)
243  {
244  case FeatureRestart: return tr("Restart");
245  case FeatureSuspend: return tr("Suspend");
246  case FeatureShutdown: return tr("Shutdown");
247  case FeatureHibernate: return tr("Hibernate");
248  case FeatureHybridSleep: return tr("HybridSleep");
249  case FeatureNone: break;
250  }
251  return "Unknown";
252 }
253 
255 {
256  bool suspend = Second == FeatureSuspend || Second == FeatureHibernate ||
257  Second == FeatureHybridSleep;
258  bool poweroff = Second == FeatureRestart || Second == FeatureShutdown;
259  switch (First)
260  {
261  case FeatureNone: return Second == FeatureNone;
262  case FeatureSuspend:
263  case FeatureHibernate:
264  case FeatureHybridSleep: return suspend;
265  case FeatureRestart:
266  case FeatureShutdown: return poweroff;
267  }
268  return false;
269 }
270 
271 bool MythPower::ScheduleFeature(enum Feature Type, std::chrono::seconds Delay)
272 {
273  if (Type == FeatureNone || Delay > MAXIMUM_SHUTDOWN_WAIT)
274  return false;
275 
276  if (m_featureTimer.isActive() || m_scheduledFeature)
277  {
278  LOG(VB_GENERAL, LOG_ERR, LOC +
279  QString("Ignoring %1 request: %2 pending in %3 seconds")
281  .arg(m_featureTimer.remainingTime() / 1000));
282  return false;
283  }
284 
285  m_scheduledFeature = Type;
286  m_featureTimer.start(Delay);
287  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Will %1 in %2 seconds")
288  .arg(FeatureToString(Type)).arg(Delay.count()));
289  return true;
290 }
291 
299 {
300  if (FeatureNone != Spontaneous)
301  {
302  m_scheduledFeature = Spontaneous;
303  m_isSpontaneous = true;
304  }
305 
306  if (!m_scheduledFeature)
307  return;
308 
309  m_sleepTime = QDateTime::currentDateTime();
310  LOG(VB_GENERAL, LOG_INFO, LOC + QString("About to: %1 %2")
312  m_isSpontaneous ? QString("(System notification)") : ""));
313 
314  switch (m_scheduledFeature)
315  {
316  case FeatureSuspend: emit Suspending(); break;
317  case FeatureShutdown: emit ShuttingDown(); break;
318  case FeatureRestart: emit Restarting(); break;
319  case FeatureHibernate: emit Hibernating(); break;
320  case FeatureHybridSleep: emit HybridSleeping(); break;
321  case FeatureNone: break;
322  }
323 }
324 
326 {
327  QMutexLocker locker(&s_lock);
328 
330  m_isSpontaneous = false;
331  m_featureTimer.stop();
332  static constexpr qint64 kSecsInDay { 24LL * 60 * 60 };
333  QDateTime now = QDateTime::currentDateTime();
334  qint64 secs = m_sleepTime.secsTo(now);
335  qint64 days = secs / kSecsInDay;
336  QTime time = QTime(0, 0).addSecs(secs % kSecsInDay);
337  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Woke up after %1days %2hours %3minutes and %4seconds")
338  .arg(days).arg(time.hour()).arg(time.minute()).arg(time.second()));
339  emit WokeUp(std::chrono::seconds(m_sleepTime.secsTo(now)));
340 }
341 
343 {
344  if (Level == m_powerLevel)
345  return;
346 
347  if (Level == ACPower)
348  {
349  m_warnForLowBattery = true;
350  LOG(VB_GENERAL, LOG_INFO, LOC + "On AC power");
351  }
352  else if (Level == UPS)
353  {
354  m_warnForLowBattery = true;
355  LOG(VB_GENERAL, LOG_INFO, LOC + "On UPS");
356  }
357  else if (Level < UnknownPower)
358  {
359  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Battery at %1%").arg(Level));
360  if (Level <= BatteryLow)
361  {
363  {
364  m_warnForLowBattery = false;
365  LOG(VB_GENERAL, LOG_INFO, LOC + "Low battery!");
366  emit LowBattery();
367  }
368  }
369  else
370  {
371  m_warnForLowBattery = true;
372  }
373  }
374  else
375  {
376  LOG(VB_GENERAL, LOG_INFO, LOC + "Unknown power source");
377  }
378 
379  m_powerLevel = Level;
380 }
MythPowerOSX
Definition: mythpowerosx.h:15
MythPower::ACPower
@ ACPower
Definition: mythpower.h:27
MythPower::MythPower
MythPower()
Definition: mythpower.cpp:120
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
MythPower::ShuttingDown
void ShuttingDown(void)
MythPower
Definition: mythpower.h:19
MythPower::FeatureSuspend
@ FeatureSuspend
Definition: mythpower.h:39
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
MythPower::FeatureToString
static QString FeatureToString(enum Feature Type)
Definition: mythpower.cpp:240
MythPower::m_scheduledFeature
Feature m_scheduledFeature
Definition: mythpower.h:92
MythPower::UnknownPower
@ UnknownPower
Definition: mythpower.h:31
MythPower::FeatureHappening
virtual void FeatureHappening(Feature Spontaneous=FeatureNone)
Signal to the rest of MythTV that the given feature will happen now.
Definition: mythpower.cpp:298
MythPower::FeatureNone
@ FeatureNone
Definition: mythpower.h:37
musicbrainzngs.musicbrainz.user
string user
Definition: musicbrainz.py:287
MythPower::FeatureIsEquivalent
static bool FeatureIsEquivalent(Feature First, Feature Second)
Definition: mythpower.cpp:254
MythPowerDBus
Definition: mythpowerdbus.h:12
MythPower::FeatureShutdown
@ FeatureShutdown
Definition: mythpower.h:38
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythPower::m_maxRequestedDelay
std::chrono::seconds m_maxRequestedDelay
Definition: mythpower.h:94
MythPower::WillSuspend
void WillSuspend(std::chrono::milliseconds MilliSeconds=0ms)
MythPower::m_maxSupportedDelay
std::chrono::seconds m_maxSupportedDelay
Definition: mythpower.h:95
MythPower::GetFeatures
Features GetFeatures(void)
Definition: mythpower.cpp:140
MythPower::IsFeatureSupported
bool IsFeatureSupported(Feature Supported)
Definition: mythpower.cpp:161
LOC
#define LOC
Definition: mythpower.cpp:13
MythPower::Hibernating
void Hibernating(void)
MythPower::m_sleepTime
QDateTime m_sleepTime
Definition: mythpower.h:97
MythPower::WillRestart
void WillRestart(std::chrono::milliseconds MilliSeconds=0ms)
MythPower::ScheduleFeature
virtual bool ScheduleFeature(enum Feature Type, std::chrono::seconds Delay)
Definition: mythpower.cpp:271
MythPower::Restarting
void Restarting(void)
MythPowerDBus::IsAvailable
static bool IsAvailable(void)
Static check for DBus interfaces that support some form of power management.
Definition: mythpowerdbus.cpp:46
mythpowerdbus.h
MythPower::AcquireRelease
static MythPower * AcquireRelease(void *Reference, bool Acquire, std::chrono::seconds MinimumDelay=0s)
Definition: mythpower.cpp:71
MythCoreContext::GetDurSetting
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
Definition: mythcorecontext.h:168
MythPower::FeatureHibernate
@ FeatureHibernate
Definition: mythpower.h:40
MythPower::PowerLevelChanged
void PowerLevelChanged(int Level)
Definition: mythpower.cpp:342
MythPower::RequestFeature
virtual bool RequestFeature(Feature Request, bool Delay=true)
Definition: mythpower.cpp:179
mythpowerosx.h
MythPower::BatteryLow
@ BatteryLow
Definition: mythpower.h:29
MythPower::FeatureTimeout
void FeatureTimeout(void)
Definition: mythpower.cpp:235
MythPower::m_features
Features m_features
Definition: mythpower.h:91
MythPower::m_isSpontaneous
bool m_isSpontaneous
Definition: mythpower.h:93
MythPower::WillHibernate
void WillHibernate(std::chrono::milliseconds MilliSeconds=0ms)
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythPower::GetFeatureList
QStringList GetFeatureList(void)
Definition: mythpower.cpp:149
MythPower::CancelFeature
virtual void CancelFeature(void)
This is untested as it is currently not clear whether it is useful.
Definition: mythpower.cpp:219
MythPower::Feature
Feature
Definition: mythpower.h:35
hardwareprofile.distros.mythtv_data.request.Request
def Request(url=None)
Definition: distros/mythtv_data/request.py:62
MythPower::s_lock
static QRecursiveMutex s_lock
Definition: mythpower.h:76
std::chrono::days
duration< CHRONO_TYPE, ratio< 86400 > > days
Definition: mythchrono.h:25
MythPower::LowBattery
void LowBattery(void)
MythPower::DoFeature
virtual bool DoFeature(bool=false)
Definition: mythpower.h:82
mythcorecontext.h
MythPower::WillHybridSleep
void WillHybridSleep(std::chrono::milliseconds MilliSeconds=0ms)
MythPower::FeatureRestart
@ FeatureRestart
Definition: mythpower.h:41
MythPower::SetRequestedDelay
void SetRequestedDelay(std::chrono::seconds Delay)
Definition: mythpower.cpp:135
MAXIMUM_SHUTDOWN_WAIT
static constexpr std::chrono::seconds MAXIMUM_SHUTDOWN_WAIT
Definition: mythpower.h:17
MythPower::WillShutDown
void WillShutDown(std::chrono::milliseconds MilliSeconds=0ms)
MythPower::HybridSleeping
void HybridSleeping(void)
MythPower::m_featureTimer
QTimer m_featureTimer
Definition: mythpower.h:96
MythPower::FeatureHybridSleep
@ FeatureHybridSleep
Definition: mythpower.h:42
MythPower::DidWakeUp
virtual void DidWakeUp(void)
Definition: mythpower.cpp:325
MythPower::UPS
@ UPS
Definition: mythpower.h:26
mythpower.h
MythPower::GetPowerLevel
int GetPowerLevel(void) const
Definition: mythpower.cpp:170
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
MythPower::m_warnForLowBattery
bool m_warnForLowBattery
Definition: mythpower.h:99
MythPower::WokeUp
void WokeUp(std::chrono::seconds SecondsAsleep)
MythPower::m_powerLevel
int m_powerLevel
Definition: mythpower.h:98
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
MythPower::Suspending
void Suspending(void)
MythPower::Init
virtual void Init(void)
Definition: mythpower.cpp:127