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