#include "powerprofiles.hpp" #include #include #include #include #include #include #include #include #include #include #include #include "../../dbus/bus.hpp" #include "../../dbus/properties.hpp" namespace qs::service::upower { namespace { Q_LOGGING_CATEGORY(logPowerProfiles, "quickshell.service.powerprofiles", QtWarningMsg); } QString PowerProfile::toString(PowerProfile::Enum profile) { switch (profile) { case PowerProfile::PowerSaver: return QStringLiteral("PowerSaver"); case PowerProfile::Balanced: return QStringLiteral("Balanced"); case PowerProfile::Performance: return QStringLiteral("Performance"); default: return QStringLiteral("Invalid"); } } QString PerformanceDegradationReason::toString(PerformanceDegradationReason::Enum reason) { switch (reason) { case PerformanceDegradationReason::LapDetected: return QStringLiteral("LapDetected"); case PerformanceDegradationReason::HighTemperature: return QStringLiteral("HighTemperature"); default: return QStringLiteral("Invalid"); } } bool PowerProfileHold::operator==(const PowerProfileHold& other) const { return other.profile == this->profile && other.applicationId == this->applicationId && other.reason == this->reason; } QDebug& operator<<(QDebug& debug, const PowerProfileHold& hold) { auto saver = QDebugStateSaver(debug); debug.nospace(); debug << "PowerProfileHold(profile=" << hold.profile << ", applicationId=" << hold.applicationId << ", reason=" << hold.reason << ')'; return debug; } PowerProfiles::PowerProfiles() { qDBusRegisterMetaType>(); this->bHasPerformanceProfile.setBinding([this]() { return this->bProfiles.value().contains(PowerProfile::Performance); }); qCDebug(logPowerProfiles) << "Starting PowerProfiles Service."; auto bus = QDBusConnection::systemBus(); if (!bus.isConnected()) { qCWarning(logPowerProfiles ) << "Could not connect to DBus. PowerProfiles services will not work."; } this->service = new QDBusInterface( "org.freedesktop.UPower.PowerProfiles", "/org/freedesktop/UPower/PowerProfiles", "org.freedesktop.UPower.PowerProfiles", bus, this ); if (!this->service->isValid()) { qCDebug(logPowerProfiles ) << "PowerProfilesDaemon is not currently running, attempting to start it."; dbus::tryLaunchService(this, bus, "org.freedesktop.UPower.PowerProfiles", [this](bool success) { if (success) { qCDebug(logPowerProfiles) << "Successfully launched PowerProfiles service."; this->init(); } else { qCWarning(logPowerProfiles) << "Could not start PowerProfilesDaemon. The PowerProfiles service will not work."; } }); } else { this->init(); } } void PowerProfiles::init() { this->properties.setInterface(this->service); this->properties.updateAllViaGetAll(); } void PowerProfiles::setProfile(PowerProfile::Enum profile) { if (!this->properties.isConnected()) { qCCritical(logPowerProfiles ) << "Cannot set power profile: power-profiles-daemon not accessible or not running"; return; } if (profile == PowerProfile::Performance && !this->bHasPerformanceProfile) { qCCritical(logPowerProfiles ) << "Cannot request performance profile as it is not present for this device."; return; } else if (profile < PowerProfile::PowerSaver || profile > PowerProfile::Performance) { qCCritical(logPowerProfiles) << "Tried to request invalid power profile" << profile; return; } this->bProfile = profile; this->pProfile.write(); } PowerProfiles* PowerProfiles::instance() { static auto* instance = new PowerProfiles(); // NOLINT return instance; } PowerProfilesQml::PowerProfilesQml(QObject* parent): QObject(parent) { auto* instance = PowerProfiles::instance(); this->bProfile.setBinding([instance]() { return instance->bProfile.value(); }); this->bHasPerformanceProfile.setBinding([instance]() { return instance->bHasPerformanceProfile.value(); }); this->bDegradationReason.setBinding([instance]() { return instance->bDegradationReason.value(); } ); this->bHolds.setBinding([instance]() { return instance->bHolds.value(); }); } } // namespace qs::service::upower namespace qs::dbus { using namespace qs::service::upower; DBusResult DBusDataTransform::fromWire(const Wire& wire) { if (wire == QStringLiteral("power-saver")) { return PowerProfile::PowerSaver; } else if (wire == QStringLiteral("balanced")) { return PowerProfile::Balanced; } else if (wire == QStringLiteral("performance")) { return PowerProfile::Performance; } else { return QDBusError(QDBusError::InvalidArgs, QString("Invalid PowerProfile: %1").arg(wire)); } } QString DBusDataTransform::toWire(Data data) { switch (data) { case PowerProfile::PowerSaver: return QStringLiteral("power-saver"); case PowerProfile::Balanced: return QStringLiteral("balanced"); case PowerProfile::Performance: return QStringLiteral("performance"); } } DBusResult> DBusDataTransform>::fromWire(const Wire& wire) { QList profiles; for (const auto& entry: wire) { auto profile = DBusDataTransform::fromWire(entry.value("Profile").value()); if (!profile.isValid()) return profile.error; profiles.append(profile.value); } return profiles; } DBusResult DBusDataTransform::fromWire(const Wire& wire) { if (wire.isEmpty()) { return PerformanceDegradationReason::None; } else if (wire == QStringLiteral("lap-detected")) { return PerformanceDegradationReason::LapDetected; } else if (wire == QStringLiteral("high-operating-temperature")) { return PerformanceDegradationReason::HighTemperature; } else { return QDBusError( QDBusError::InvalidArgs, QString("Invalid PerformanceDegradationReason: %1").arg(wire) ); } } DBusResult> DBusDataTransform>::fromWire(const Wire& wire) { QList holds; for (const auto& entry: wire) { auto profile = DBusDataTransform::fromWire(entry.value("Profile").value()); if (!profile.isValid()) return profile.error; auto applicationId = entry.value("ApplicationId").value(); auto reason = entry.value("Reason").value(); holds.append(PowerProfileHold(profile.value, applicationId, reason)); } return holds; } } // namespace qs::dbus