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