File indexing completed on 2024-04-28 16:55:13
0001 /*************************************************************************** 0002 * Copyright (C) 2010 by Dario Freddi <drf@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify * 0005 * it under the terms of the GNU General Public License as published by * 0006 * the Free Software Foundation; either version 2 of the License, or * 0007 * (at your option) any later version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, * 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0012 * GNU General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU General Public License * 0015 * along with this program; if not, write to the * 0016 * Free Software Foundation, Inc., * 0017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 0018 ***************************************************************************/ 0019 0020 #include "powerdevilbackendinterface.h" 0021 #include "powerdevilscreenbrightnesslogic.h" 0022 #include "powerdevilkeyboardbrightnesslogic.h" 0023 #include "powerdevil_debug.h" 0024 #include <QDebug> 0025 0026 namespace PowerDevil 0027 { 0028 0029 /** 0030 * Filter data along one dimension using exponential moving average. 0031 */ 0032 double emafilter(const double last, const double update, double weight) 0033 { 0034 double current = last * (1 - weight) + update * weight; 0035 0036 return current; 0037 } 0038 0039 class BackendInterface::Private 0040 { 0041 public: 0042 Private() 0043 : acAdapterState(UnknownAcAdapterState) 0044 , batteryRemainingTime(0) 0045 , isReady(false) 0046 , isError(false) 0047 , isLidClosed(false) 0048 , isLidPresent(false) 0049 { 0050 } 0051 ~Private() {} 0052 0053 AcAdapterState acAdapterState; 0054 0055 qulonglong batteryRemainingTime; 0056 qulonglong smoothedBatteryRemainingTime = 0; 0057 qulonglong lastRateTimestamp = 0; 0058 double batteryEnergyFull = 0; 0059 double batteryEnergy = 0; 0060 double smoothedBatteryDischargeRate = 0; 0061 0062 QHash< BrightnessControlType, BrightnessLogic* > brightnessLogic; 0063 BrightnessControlsList brightnessControlsAvailable; 0064 Capabilities capabilities; 0065 SuspendMethods suspendMethods; 0066 QString errorString; 0067 bool isReady; 0068 bool isError; 0069 bool isLidClosed; 0070 bool isLidPresent; 0071 QHash< QString, uint > capacities; 0072 }; 0073 0074 BackendInterface::BackendInterface(QObject* parent) 0075 : QObject(parent) 0076 , d(new Private) 0077 { 0078 d->brightnessLogic[Screen] = new ScreenBrightnessLogic(); 0079 d->brightnessLogic[Keyboard] = new KeyboardBrightnessLogic(); 0080 } 0081 0082 BackendInterface::~BackendInterface() 0083 { 0084 delete d->brightnessLogic[Keyboard]; 0085 delete d->brightnessLogic[Screen]; 0086 delete d; 0087 } 0088 0089 BackendInterface::AcAdapterState BackendInterface::acAdapterState() const 0090 { 0091 return d->acAdapterState; 0092 } 0093 0094 qulonglong BackendInterface::batteryRemainingTime() const 0095 { 0096 return d->batteryRemainingTime; 0097 } 0098 0099 qulonglong BackendInterface::smoothedBatteryRemainingTime() const 0100 { 0101 return d->smoothedBatteryRemainingTime; 0102 } 0103 0104 void BackendInterface::setBrightness(int brightness, BackendInterface::BrightnessControlType type) 0105 { 0106 if (type == Screen) { 0107 qCDebug(POWERDEVIL) << "set screen brightness: " << brightness; 0108 } else { 0109 qCDebug(POWERDEVIL) << "set kbd backlight: " << brightness; 0110 } 0111 0112 d->brightnessLogic.value(type)->setValue(brightness); 0113 } 0114 0115 int BackendInterface::brightness(BackendInterface::BrightnessControlType type) const 0116 { 0117 return d->brightnessLogic.value(type)->value(); 0118 } 0119 0120 int BackendInterface::brightnessMax(BackendInterface::BrightnessControlType type) const 0121 { 0122 return d->brightnessLogic.value(type)->valueMax(); 0123 } 0124 0125 int BackendInterface::brightnessSteps(BackendInterface::BrightnessControlType type) const 0126 { 0127 BrightnessLogic *logic = d->brightnessLogic.value(type); 0128 logic->setValueMax(brightnessMax(type)); 0129 return logic->steps(); 0130 } 0131 0132 BackendInterface::BrightnessControlsList BackendInterface::brightnessControlsAvailable() const 0133 { 0134 return d->brightnessControlsAvailable; 0135 } 0136 0137 QHash< QString, uint > BackendInterface::capacities() const 0138 { 0139 return d->capacities; 0140 } 0141 0142 BackendInterface::SuspendMethods BackendInterface::supportedSuspendMethods() const 0143 { 0144 return d->suspendMethods; 0145 } 0146 0147 bool BackendInterface::isLidClosed() const 0148 { 0149 return d->isLidClosed; 0150 } 0151 0152 bool BackendInterface::isLidPresent() const 0153 { 0154 return d->isLidPresent; 0155 } 0156 0157 void BackendInterface::setLidPresent(bool present) 0158 { 0159 d->isLidPresent = present; 0160 } 0161 0162 void BackendInterface::setAcAdapterState(PowerDevil::BackendInterface::AcAdapterState state) 0163 { 0164 d->acAdapterState = state; 0165 Q_EMIT acAdapterStateChanged(state); 0166 } 0167 0168 void BackendInterface::setBackendHasError(const QString& errorDetails) 0169 { 0170 Q_UNUSED(errorDetails) 0171 } 0172 0173 void BackendInterface::setBackendIsReady(const BrightnessControlsList &availableBrightnessControls, 0174 BackendInterface::SuspendMethods supportedSuspendMethods) 0175 { 0176 d->brightnessControlsAvailable = availableBrightnessControls; 0177 d->suspendMethods = supportedSuspendMethods; 0178 d->isReady = true; 0179 0180 Q_EMIT backendReady(); 0181 } 0182 0183 void BackendInterface::setBatteryEnergyFull(const double energy) 0184 { 0185 d->batteryEnergyFull = energy; 0186 } 0187 0188 void BackendInterface::setBatteryEnergy(const double energy) 0189 { 0190 d->batteryEnergy = energy; 0191 } 0192 0193 void BackendInterface::setBatteryRate(const double rate, qulonglong timestamp) 0194 { 0195 // remaining time in milliseconds 0196 qulonglong time = 0; 0197 0198 if (rate > 0) { 0199 // Energy and rate are in Watt*hours resp. Watt 0200 time = 3600 * 1000 * (d->batteryEnergyFull - d->batteryEnergy) / rate; 0201 } else if (rate < 0) { 0202 time = 3600 * 1000 * (0.0 - d->batteryEnergy) / rate; 0203 } 0204 0205 if (d->batteryRemainingTime != time) { 0206 d->batteryRemainingTime = time; 0207 Q_EMIT batteryRemainingTimeChanged(time); 0208 } 0209 0210 // Charging or full 0211 if ((rate > 0) || (time == 0)) { 0212 if (d->smoothedBatteryRemainingTime != time) { 0213 d->smoothedBatteryRemainingTime = time; 0214 Q_EMIT smoothedBatteryRemainingTimeChanged(time); 0215 } 0216 return; 0217 } 0218 0219 double oldRate = d->smoothedBatteryDischargeRate; 0220 if (oldRate == 0) { 0221 d->smoothedBatteryDischargeRate = rate; 0222 } else { 0223 // To have a time constant independent from the update frequency 0224 // the weight must be scaled 0225 double weight = 0.005 * std::min<qulonglong>(60, timestamp - d->lastRateTimestamp); 0226 d->lastRateTimestamp = timestamp; 0227 d->smoothedBatteryDischargeRate = emafilter(oldRate, rate, weight); 0228 } 0229 0230 time = 3600 * 1000 * (0.0 - d->batteryEnergy) / d->smoothedBatteryDischargeRate; 0231 0232 if (d->smoothedBatteryRemainingTime != time) { 0233 d->smoothedBatteryRemainingTime = time; 0234 Q_EMIT smoothedBatteryRemainingTimeChanged(d->smoothedBatteryRemainingTime); 0235 } 0236 } 0237 0238 void BackendInterface::setButtonPressed(PowerDevil::BackendInterface::ButtonType type) 0239 { 0240 if (type == LidClose && !d->isLidClosed) { 0241 d->isLidClosed = true; 0242 Q_EMIT lidClosedChanged(true); 0243 } else if (type == LidOpen && d->isLidClosed) { 0244 d->isLidClosed = false; 0245 Q_EMIT lidClosedChanged(false); 0246 } 0247 Q_EMIT buttonPressed(type); 0248 } 0249 0250 void BackendInterface::setCapacityForBattery(const QString& batteryId, uint percent) 0251 { 0252 d->capacities.insert(batteryId, percent); 0253 } 0254 0255 void BackendInterface::onBrightnessChanged(BrightnessControlType type, int value, int valueMax) 0256 { 0257 BrightnessLogic *logic = d->brightnessLogic.value(type); 0258 logic->setValueMax(valueMax); 0259 logic->setValue(value); 0260 0261 Q_EMIT brightnessChanged(logic->info(), type); 0262 } 0263 0264 BackendInterface::Capabilities BackendInterface::capabilities() const 0265 { 0266 return d->capabilities; 0267 } 0268 0269 void BackendInterface::setCapabilities(BackendInterface::Capabilities capabilities) 0270 { 0271 d->capabilities = capabilities; 0272 } 0273 0274 int BackendInterface::calculateNextStep(int value, int valueMax, BrightnessControlType controlType, BrightnessLogic::BrightnessKeyType keyType) 0275 { 0276 BrightnessLogic *logic = d->brightnessLogic.value(controlType); 0277 logic->setValueMax(valueMax); 0278 logic->setValue(value); 0279 0280 return logic->action(keyType); 0281 } 0282 0283 }