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