add more spacing
[personal-kdebase.git] / workspace / solid / hal / halpower.cpp
blob88b266313d3c5e535a19370f1563cccf123ee439
1 /* This file is part of the KDE project
2 Copyright (C) 2006 Kevin Ottens <ervin@kde.org>
3 Copyright (C) 2008 Dario Freddi <drf54321@gmail.com>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include "halpower.h"
23 #include <QtDBus/QDBusReply>
25 #include <kdebug.h>
27 #include "halsuspendjob.h"
29 #include <solid/deviceinterface.h>
30 #include <solid/acadapter.h>
31 #include <solid/battery.h>
32 #include <solid/button.h>
33 #include <solid/genericinterface.h>
35 HalPower::HalPower(QObject *parent, const QStringList & /*args */)
36 : PowerManager(parent),
37 m_halComputer("org.freedesktop.Hal",
38 "/org/freedesktop/Hal/devices/computer",
39 "org.freedesktop.Hal.Device",
40 QDBusConnection::systemBus()),
41 m_halPowerManagement("org.freedesktop.Hal",
42 "/org/freedesktop/Hal/devices/computer",
43 "org.freedesktop.Hal.Device.SystemPowerManagement",
44 QDBusConnection::systemBus()),
45 m_halCpuFreq("org.freedesktop.Hal",
46 "/org/freedesktop/Hal/devices/computer",
47 "org.freedesktop.Hal.Device.CPUFreq",
48 QDBusConnection::systemBus()),
49 m_halManager("org.freedesktop.Hal",
50 "/org/freedesktop/Hal/Manager",
51 "org.freedesktop.Hal.Manager",
52 QDBusConnection::systemBus())
54 connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString &)),
55 this, SLOT(slotDeviceRemoved(const QString &)));
56 connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString &)),
57 this, SLOT(slotDeviceAdded(const QString &)));
59 m_pluggedAdapterCount = 0;
60 computeAcAdapters();
62 computeBatteries();
63 updateBatteryStats();
65 computeButtons();
68 HalPower::~HalPower()
70 qDeleteAll(m_acAdapters);
71 qDeleteAll(m_batteries);
72 qDeleteAll(m_buttons);
75 QStringList HalPower::supportedSchemes() const
77 return QStringList() << "performance" << "powersaving";
80 QString HalPower::schemeDescription(const QString &schemeName) const
82 if (schemeName=="performance")
84 return "Use all the performances of the system";
86 else if (schemeName=="powersaving")
88 return "Try to keep as much power as possible to improve battery life";
90 else
92 return QString();
95 return QString();
98 QString HalPower::scheme() const
100 // FIXME: We miss an accessor in HAL to make scheme management useful
101 return QString();
104 bool HalPower::setScheme(const QString &name)
106 bool powersave;
108 if (name=="powersaving")
110 powersave = true;
112 else if (name=="performance")
114 powersave = false;
116 else
118 return false;
121 QDBusReply<int> reply = m_halPowerManagement.call("SetPowerSave", powersave);
123 if (reply.isValid())
125 int code = reply;
126 return code==0;
128 else
130 return false;
134 Solid::Control::PowerManager::BatteryState HalPower::batteryState() const
136 if (m_batteries.size()==0)
138 return Solid::Control::PowerManager::NoBatteryState;
140 else if (m_currentBatteryCharge <= m_criticalBatteryCharge)
142 return Solid::Control::PowerManager::Critical;
144 else if (m_currentBatteryCharge <= m_lowBatteryCharge)
146 return Solid::Control::PowerManager::Low;
148 else if (m_currentBatteryCharge <= m_warningBatteryCharge)
150 return Solid::Control::PowerManager::Warning;
152 else
154 return Solid::Control::PowerManager::Normal;
158 int HalPower::batteryChargePercent() const
160 if (!m_maxBatteryCharge) return 0;
162 return (m_currentBatteryCharge *100)/m_maxBatteryCharge;
165 int HalPower::batteryRemainingTime() const
167 return m_estimatedBatteryTime;
170 Solid::Control::PowerManager::AcAdapterState HalPower::acAdapterState() const
172 if (m_acAdapters.size()==0)
174 return Solid::Control::PowerManager::UnknownAcAdapterState;
176 else if (m_pluggedAdapterCount==0)
178 return Solid::Control::PowerManager::Unplugged;
180 else
182 return Solid::Control::PowerManager::Plugged;
186 Solid::Control::PowerManager::SuspendMethods HalPower::supportedSuspendMethods() const
188 Solid::Control::PowerManager::SuspendMethods supported = Solid::Control::PowerManager::UnknownSuspendMethod;
190 QDBusReply<bool> reply = m_halComputer.call("GetPropertyBoolean", "power_management.can_suspend");
192 if (reply.isValid())
194 bool can_suspend = reply;
195 if (can_suspend)
197 supported |= Solid::Control::PowerManager::ToRam;
200 else
202 kDebug() << reply.error().name() << ": " << reply.error().message();
205 reply = m_halComputer.call("GetPropertyBoolean", "power_management.can_hibernate");
207 if (reply.isValid())
209 bool can_hibernate = reply;
210 if (can_hibernate)
212 supported |= Solid::Control::PowerManager::ToDisk;
215 else
217 kDebug() << reply.error().name() << ": " << reply.error().message();
220 return supported;
223 KJob *HalPower::suspend(Solid::Control::PowerManager::SuspendMethod method) const
225 return new HalSuspendJob(m_halPowerManagement,
226 method, supportedSuspendMethods());
229 Solid::Control::PowerManager::CpuFreqPolicies HalPower::supportedCpuFreqPolicies() const
231 QDBusReply<QStringList> reply = m_halCpuFreq.call("GetCPUFreqAvailableGovernors");
233 if (!reply.isValid())
235 return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
237 else
239 QStringList governors = reply;
240 Solid::Control::PowerManager::CpuFreqPolicies policies = Solid::Control::PowerManager::UnknownCpuFreqPolicy;
242 foreach (const QString& governor, governors)
244 if (governor == "ondemand")
246 policies|= Solid::Control::PowerManager::OnDemand;
248 else if (governor == "userspace")
250 policies|= Solid::Control::PowerManager::Userspace;
252 else if (governor == "powersave")
254 policies|= Solid::Control::PowerManager::Powersave;
256 else if (governor == "performance")
258 policies|= Solid::Control::PowerManager::Performance;
260 else if (governor == "conservative")
262 policies|= Solid::Control::PowerManager::Conservative;
264 else
266 kWarning() << "Unknown governor: " << governor ;
270 return policies;
274 Solid::Control::PowerManager::CpuFreqPolicy HalPower::cpuFreqPolicy() const
276 QDBusReply<QString> reply = m_halCpuFreq.call("GetCPUFreqGovernor");
278 if (!reply.isValid())
280 return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
282 else
284 QString governor = reply;
286 if (governor == "ondemand")
288 return Solid::Control::PowerManager::OnDemand;
290 else if (governor == "userspace")
292 return Solid::Control::PowerManager::Userspace;
294 else if (governor == "powersave")
296 return Solid::Control::PowerManager::Powersave;
298 else if (governor == "performance")
300 return Solid::Control::PowerManager::Performance;
302 else if (governor == "conservative")
304 return Solid::Control::PowerManager::Conservative;
306 else
308 return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
313 bool HalPower::setCpuFreqPolicy(Solid::Control::PowerManager::CpuFreqPolicy newPolicy)
315 QString governor;
317 switch(newPolicy)
319 case Solid::Control::PowerManager::OnDemand:
320 governor = "ondemand";
321 break;
322 case Solid::Control::PowerManager::Userspace:
323 governor = "userspace";
324 break;
325 case Solid::Control::PowerManager::Powersave:
326 governor = "powersave";
327 break;
328 case Solid::Control::PowerManager::Performance:
329 governor = "performance";
330 break;
331 case Solid::Control::PowerManager::Conservative:
332 governor = "conservative";
333 break;
334 default:
335 return false;
338 QDBusReply<int> reply = m_halCpuFreq.call("SetCPUFreqGovernor", governor);
340 if (reply.isValid())
342 int code = reply;
343 return code==0;
345 else
347 return false;
351 bool HalPower::canDisableCpu(int /*cpuNum */) const
353 return false;
356 bool HalPower::setCpuEnabled(int /*cpuNum */, bool /*enabled */)
358 return false;
361 Solid::Control::PowerManager::BrightnessControlsList HalPower::brightnessControlsAvailable()
363 Solid::Control::PowerManager::BrightnessControlsList deviceList;
364 foreach(const QString &name, m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList())
366 deviceList.insert(name, Solid::Control::PowerManager::Screen);
368 foreach(const QString &name, m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList())
370 deviceList.insert(name, Solid::Control::PowerManager::Keyboard);
372 return deviceList;
375 float HalPower::brightness(const QString &device)
377 float brightness;
378 if(m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList().contains(device))
380 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.LaptopPanel", QDBusConnection::systemBus());
381 brightness = deviceInterface.call("GetBrightness").arguments().at(0).toDouble();
382 if(deviceInterface.lastError().isValid())
384 return 0;
386 else
388 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
389 int levels = propertyInterface.call("GetProperty", "laptop_panel.num_levels").arguments().at(0).toInt();
390 return (float)(100*(brightness/(levels-1)));
393 if(m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList().contains(device))
395 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.KeyboardBacklight", QDBusConnection::systemBus()); //TODO - I do not have a backlight enabled keyboard, so I'm guessing a bit here. Could someone please check this.
396 brightness = deviceInterface.call("GetBrightness").arguments().at(0).toDouble();
397 if(deviceInterface.lastError().isValid())
399 return 0;
401 else
403 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
404 int levels = propertyInterface.call("GetProperty", "keyboard_backlight.num_levels").arguments().at(0).toInt();
405 return (float)(100*(brightness/(levels-1)));
408 return 0;
411 bool HalPower::setBrightness(float brightness, const QString &device)
413 if(m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList().contains(device))
415 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
416 int levels = propertyInterface.call("GetProperty", "laptop_panel.num_levels").arguments().at(0).toInt();
417 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.LaptopPanel", QDBusConnection::systemBus());
418 deviceInterface.call("SetBrightness", qRound((levels-1)*(brightness/100.0))); // .0? The right way? Feels hackish.
419 if(!deviceInterface.lastError().isValid())
421 emit(brightnessChanged(brightness));
422 return true;
425 if(m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList().contains(device))
427 QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
428 int levels = propertyInterface.call("GetProperty", "keyboard_backlight.num_levels").arguments().at(0).toInt();
429 QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.KeyboardBacklight", QDBusConnection::systemBus()); //TODO - I do not have a backlight enabled keyboard, so I'm guessing a bit here. Could someone please check this.
430 deviceInterface.call("SetBrightness", qRound((levels-1)*(brightness/100.0)));
431 if(!deviceInterface.lastError().isValid())
433 emit(brightnessChanged(brightness));
434 return true;
437 return false;
440 void HalPower::computeAcAdapters()
442 QList<Solid::Device> adapters
443 = Solid::Device::listFromType(Solid::DeviceInterface::AcAdapter);
445 foreach (Solid::Device adapter, adapters)
447 m_acAdapters[adapter.udi()] = new Solid::Device(adapter);
448 connect(m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>(), SIGNAL(plugStateChanged(bool, const QString &)),
449 this, SLOT(slotPlugStateChanged(bool)));
451 if (m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>()!=0
452 && m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>()->isPlugged())
454 m_pluggedAdapterCount++;
459 void HalPower::computeBatteries()
461 QList<Solid::Device> batteries
462 = Solid::Device::listFromQuery("Battery.type == 'PrimaryBattery'");
464 foreach (Solid::Device battery, batteries)
466 m_batteries[battery.udi()] = new Solid::Device(battery);
467 connect(m_batteries[battery.udi()]->as<Solid::Battery>(), SIGNAL(chargePercentChanged(int, const QString &)),
468 this, SLOT(updateBatteryStats()));
469 connect(m_batteries[battery.udi()]->as<Solid::GenericInterface>(), SIGNAL(propertyChanged(const QMap<QString,int> &)),
470 this, SLOT(slotBatteryPropertyChanged(const QMap<QString,int> &)));
473 updateBatteryStats();
476 void HalPower::computeButtons()
478 QList<Solid::Device> buttons
479 = Solid::Device::listFromType(Solid::DeviceInterface::Button);
481 foreach (Solid::Device button, buttons)
483 m_buttons[button.udi()] = new Solid::Device(button);
484 connect(m_buttons[button.udi()]->as<Solid::Button>(), SIGNAL(pressed(Solid::Button::ButtonType, const QString &)),
485 this, SLOT(slotButtonPressed(Solid::Button::ButtonType)));
489 void HalPower::updateBatteryStats()
491 m_currentBatteryCharge = 0;
492 m_maxBatteryCharge = 0;
493 m_warningBatteryCharge = 0;
494 m_lowBatteryCharge = 0;
495 m_criticalBatteryCharge = 0;
496 m_estimatedBatteryTime = 0;
498 foreach (Solid::Device *d, m_batteries)
500 Solid::GenericInterface *interface = d->as<Solid::GenericInterface>();
502 if (interface == 0) continue;
504 m_currentBatteryCharge+= interface->property("battery.charge_level.current").toInt();
505 m_maxBatteryCharge+= interface->property("battery.charge_level.last_full").toInt();
506 m_warningBatteryCharge+= interface->property("battery.charge_level.warning").toInt();
507 m_lowBatteryCharge+= interface->property("battery.charge_level.low").toInt();
508 m_estimatedBatteryTime+= interface->property("battery.remaining_time").toInt() * 1000;
511 m_criticalBatteryCharge = m_lowBatteryCharge/2;
514 void HalPower::slotPlugStateChanged(bool newState)
516 if (newState)
518 if(m_pluggedAdapterCount == 0)
520 emit acAdapterStateChanged(Solid::Control::PowerManager::Plugged);
522 m_pluggedAdapterCount++;
524 else
526 if(m_pluggedAdapterCount == 1)
528 emit acAdapterStateChanged(Solid::Control::PowerManager::Unplugged);
530 m_pluggedAdapterCount--;
534 void HalPower::slotButtonPressed(Solid::Button::ButtonType type)
536 Solid::Button *button = qobject_cast<Solid::Button *>(sender());
538 if (button == 0) return;
540 switch(type)
542 case Solid::Button::PowerButton:
543 emit buttonPressed(Solid::Control::PowerManager::PowerButton);
544 break;
545 case Solid::Button::SleepButton:
546 emit buttonPressed(Solid::Control::PowerManager::SleepButton);
547 break;
548 case Solid::Button::LidButton:
549 if (button->stateValue())
551 emit buttonPressed(Solid::Control::PowerManager::LidClose);
553 else
555 emit buttonPressed(Solid::Control::PowerManager::LidOpen);
557 break;
558 default:
559 kWarning() << "Unknown button type" ;
560 break;
564 void HalPower::slotDeviceAdded(const QString &udi)
566 Solid::Device *device = new Solid::Device(udi);
567 if (device->is<Solid::AcAdapter>())
569 m_acAdapters[udi] = device;
570 connect(m_acAdapters[udi]->as<Solid::AcAdapter>(), SIGNAL(plugStateChanged(bool, const QString &)),
571 this, SLOT(slotPlugStateChanged(bool)));
573 if (m_acAdapters[udi]->as<Solid::AcAdapter>()!=0
574 && m_acAdapters[udi]->as<Solid::AcAdapter>()->isPlugged())
576 m_pluggedAdapterCount++;
579 else if (device->is<Solid::Battery>())
581 m_batteries[udi] = device;
582 connect(m_batteries[udi]->as<Solid::Battery>(), SIGNAL(chargePercentChanged(int, const QString &)),
583 this, SLOT(updateBatteryStats()));
584 connect(m_batteries[udi]->as<Solid::GenericInterface>(), SIGNAL(propertyChanged(const QMap<QString,int> &)),
585 this, SLOT(slotBatteryPropertyChanged(const QMap<QString,int> &)));
587 else if (device->is<Solid::Button>())
589 m_buttons[udi] = device;
590 connect(m_buttons[udi]->as<Solid::Button>(), SIGNAL(pressed(int, const QString &)),
591 this, SLOT(slotButtonPressed(int)));
593 else
595 delete device;
599 void HalPower::slotDeviceRemoved(const QString &udi)
601 Solid::Device *device = 0;
603 device = m_acAdapters.take(udi);
605 if (device!=0)
607 delete device;
609 m_pluggedAdapterCount = 0;
611 foreach (Solid::Device *d, m_acAdapters)
613 if (d->as<Solid::AcAdapter>()!=0
614 && d->as<Solid::AcAdapter>()->isPlugged())
616 m_pluggedAdapterCount++;
620 return;
623 device = m_batteries.take(udi);
625 if (device!=0)
627 delete device;
628 updateBatteryStats();
629 return;
632 device = m_buttons.take(udi);
634 if (device!=0)
636 delete device;
637 return;
641 void HalPower::slotBatteryPropertyChanged(const QMap<QString,int> &changes)
643 /* This slot catches property changes on battery devices. At
644 * the moment it is used to find out remaining time on batteries.
647 if (changes.contains("battery.remaining_time")) {
648 updateBatteryStats();
649 emit batteryRemainingTimeChanged(batteryRemainingTime());
653 #include "halpower.moc"