11#include <QDBusUnixFileDescriptor>
13#define LOC QString("PowerDBus: ")
15#define FREE_SERVICE (QString("org.freedesktop."))
16#define FREE_PATH (QString("/org/freedesktop/"))
17#define UPOWER (QString("UPower"))
18#define LOGIN1 (QString("login1"))
19#define UPOWER_SERVICE (FREE_SERVICE + UPOWER)
20#define UPOWER_PATH (FREE_PATH + UPOWER)
21#define UPOWER_INTERFACE (UPOWER_SERVICE)
22#define LOGIN1_SERVICE (FREE_SERVICE + LOGIN1)
23#define LOGIN1_PATH (FREE_PATH + LOGIN1)
24#define LOGIN1_INTERFACE (LOGIN1_SERVICE + QString(".Manager"))
48 QMutexLocker locker(&
s_lock);
49 static bool s_available =
false;
50 static bool s_checked =
false;
54 auto* upower =
new QDBusInterface(
56 auto* login1 =
new QDBusInterface(
58 s_available = upower->isValid() || login1->isValid();
77 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Closing interfaces");
107 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No UPower interface. Unable to monitor battery state");
109 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"No login1 interface. Cannot change system power state");
120 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to listen for sleep events");
125 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to listen for shutdown events");
132 QDBusReply<QList<QDBusObjectPath> > response =
134 if (response.isValid())
136 QList devices = response.value();
137 for (
const auto& device : std::as_const(devices))
143 LOG(VB_GENERAL, LOG_ERR,
"Failed to register for Changed");
149 LOG(VB_GENERAL, LOG_ERR,
"Failed to register for DeviceChanged");
155 LOG(VB_GENERAL, LOG_ERR,
"Failed to register for DeviceAdded");
161 LOG(VB_GENERAL, LOG_ERR,
"Failed to register for DeviceRemoved");
229 if (property.isValid() && property.toBool())
235 if (property.isValid() && property.toBool())
255 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Trying to delay system %1 for %2 seconds")
271 QMutexLocker locker(&
s_lock);
303 auto time = nowAsDuration<std::chrono::milliseconds>();
306 std::chrono::milliseconds millisecs = time + Delay;
314 QDBusReply<void> reply =
316 static_cast<qint64
>(millisecs.count()));
318 if (reply.isValid() && !reply.error().isValid())
322 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"%1 scheduled via logind")
328 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
329 QString(
"Failed to schedule %1 - falling back to default behaviour")
331 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Error %1 Message %2")
332 .arg(reply.error().name(), reply.error().message()));
350 QMutexLocker locker(&
s_lock);
359 QMutexLocker locker(&
s_lock);
367 QMutexLocker locker(&
s_lock);
372 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Added UPower.Device '%1'").arg(
Device.path()));
379 QMutexLocker locker(&
s_lock);
384 LOG(VB_GENERAL, LOG_INFO, QString(
"Removed UPower.Device '%1'").arg(
Device.path()));
396 QMutexLocker locker(&
s_lock);
411 QDBusReply<QString> cansuspend =
m_logindInterface->call(QLatin1String(
"CanSuspend"));
412 if (cansuspend.isValid() && cansuspend.value() ==
"yes")
414 QDBusReply<QString> canshutdown =
m_logindInterface->call(QLatin1String(
"CanPowerOff"));
415 if (canshutdown.isValid() && canshutdown.value() ==
"yes")
417 QDBusReply<QString> canrestart =
m_logindInterface->call(QLatin1String(
"CanReboot"));
418 if (canrestart.isValid() && canrestart.value() ==
"yes")
420 QDBusReply<QString> canhibernate =
m_logindInterface->call(QLatin1String(
"CanHibernate"));
421 if (canhibernate.isValid() && canhibernate.value() ==
"yes")
423 QDBusReply<QString> canhybrid =
m_logindInterface->call(QLatin1String(
"CanHybridSleep"));
424 if (canhybrid.isValid() && canhybrid.value() ==
"yes")
430 auto value = std::chrono::microseconds(delay.toUInt());
432 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Max inhibit delay: %1seconds")
444 QMutexLocker locker(&
s_lock);
452 if (level >= 0 && level <= 100)
455 total +=
static_cast<qreal
>(level);
460 newlevel = lround(total / count);
466 if (acpower.isValid() && acpower.toBool())
477 if (interface.isValid())
479 QVariant battery = interface.property(
"IsRechargeable");
480 if (battery.isValid() && battery.toBool())
482 QVariant percent = interface.property(
"Percentage");
483 if (percent.isValid())
485 int result =
static_cast<int>(lroundf(percent.toFloat() * 100.0F));
486 if (result >= 0 && result <= 100)
495 QVariant
type = interface.property(
"Type");
498 QString typestr =
type.toString();
499 if (typestr ==
"Line Power")
501 if (typestr ==
"Ups")
522 QMutexLocker locker(&
s_lock);
526 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Already hold delay lock");
535 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unknown delay requests");
539 QDBusReply<QDBusUnixFileDescriptor> reply =
541 QLatin1String(
"MythTV"), QLatin1String(
""), QLatin1String(
"delay"));
542 if (!reply.isValid())
544 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Failed to delay %1: %2")
545 .arg(
types.join(
","), reply.error().message()));
561 QMutexLocker locker(&
s_lock);
568 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Releasing delay FD: %1").arg(
m_lockHandle));
static const std::array< featureStruct, 7 > feature
A device containing images (ie. USB stick, CD, storage group etc)
void CancelFeature(void) override
This is untested.
void UpdateProperties(void)
QDBusInterface * m_upowerInterface
void DidWakeUp(void) override
void DBusShuttingDown(bool Stopping)
void DeviceChanged(const QDBusObjectPath &Device)
Update power device state.
void AcquireLock(Features Types)
Acquire an inhibition lock for logind power events.
void DBusSuspending(bool Stopping)
bool ScheduleFeature(enum Feature Type, std::chrono::seconds Delay) override
Schedule a MythTV initiated power feature.
void DeviceAdded(const QDBusObjectPath &Device)
void ReleaseLock(void)
Release our inhibition lock.
static bool IsAvailable(void)
Static check for DBus interfaces that support some form of power management.
void DeviceRemoved(const QDBusObjectPath &Device)
int RetrieveBatteryLevel(const QString &Path)
bool DoFeature(bool Delayed=false) override
~MythPowerDBus() override
QMap< QString, int > m_batteries
QDBusInterface * m_logindInterface
std::chrono::seconds m_maxRequestedDelay
static QRecursiveMutex s_lock
void WillSuspend(std::chrono::milliseconds MilliSeconds=0ms)
virtual void FeatureHappening(Feature Spontaneous=FeatureNone)
Signal to the rest of MythTV that the given feature will happen now.
virtual void DidWakeUp(void)
Feature m_scheduledFeature
static bool FeatureIsEquivalent(Feature First, Feature Second)
void PowerLevelChanged(int Level)
static QString FeatureToString(enum Feature Type)
virtual void CancelFeature(void)
This is untested as it is currently not clear whether it is useful.
std::chrono::seconds m_maxSupportedDelay
void WillShutDown(std::chrono::milliseconds MilliSeconds=0ms)
virtual bool ScheduleFeature(enum Feature Type, std::chrono::seconds Delay)
static const struct wl_interface * types[]
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static eu8 clamp(eu8 value, eu8 low, eu8 high)