xbmc: add PR2971

Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
Stephan Raue 2013-08-05 10:42:33 +02:00
parent 3a130cd500
commit 7e8e0f9712

View File

@ -0,0 +1,582 @@
diff -Naur xbmc-12.2-e40d13d/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp
--- xbmc-12.2-e40d13d/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp 1970-01-01 01:00:00.000000000 +0100
+++ xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp 2013-08-05 10:02:45.904395105 +0200
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2012 Denis Yantarev
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "system.h"
+#include "LogindUPowerSyscall.h"
+#include "utils/log.h"
+
+#ifdef HAS_DBUS
+
+// logind DBus interface specification:
+// http://www.freedesktop.org/wiki/Software/Logind/logind
+//
+// Inhibitor Locks documentation:
+// http://www.freedesktop.org/wiki/Software/Logind/inhibit/
+
+#define LOGIND_DEST "org.freedesktop.login1"
+#define LOGIND_PATH "/org/freedesktop/login1"
+#define LOGIND_IFACE "org.freedesktop.login1.Manager"
+
+CLogindUPowerSyscall::CLogindUPowerSyscall()
+{
+ CLog::Log(LOGINFO, "Selected Logind/UPower as PowerSyscall");
+
+ // Check if we have UPower. If not, we avoid any battery related operations.
+ CDBusMessage message("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "EnumerateDevices");
+ m_hasUPower = message.SendSystem() != NULL;
+
+ if (!m_hasUPower)
+ CLog::Log(LOGINFO, "LogindUPowerSyscall - UPower not found, battery information will not be available");
+
+ m_canPowerdown = LogindCheckCapability("CanPowerOff");
+ m_canReboot = LogindCheckCapability("CanReboot");
+ m_canHibernate = LogindCheckCapability("CanHibernate");
+ m_canSuspend = LogindCheckCapability("CanSuspend");
+
+ InhibitDelayLock();
+
+ m_batteryLevel = 0;
+ if (m_hasUPower)
+ UpdateBatteryLevel();
+
+ DBusError error;
+ dbus_error_init(&error);
+ m_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+
+ if (dbus_error_is_set(&error))
+ {
+ CLog::Log(LOGERROR, "LogindUPowerSyscall: Failed to get dbus connection: %s", error.message);
+ dbus_connection_close(m_connection);
+ dbus_connection_unref(m_connection);
+ m_connection = NULL;
+ dbus_error_free(&error);
+ return;
+ }
+
+ dbus_connection_set_exit_on_disconnect(m_connection, false);
+ dbus_bus_add_match(m_connection, "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'", NULL);
+
+ if (m_hasUPower)
+ dbus_bus_add_match(m_connection, "type='signal',interface='org.freedesktop.UPower',member='DeviceChanged'", NULL);
+
+ dbus_connection_flush(m_connection);
+ dbus_error_free(&error);
+}
+
+CLogindUPowerSyscall::~CLogindUPowerSyscall()
+{
+ if (m_connection)
+ {
+ dbus_connection_close(m_connection);
+ dbus_connection_unref(m_connection);
+ }
+
+ ReleaseDelayLock();
+}
+
+bool CLogindUPowerSyscall::Powerdown()
+{
+ return LogindSetPowerState("PowerOff");
+}
+
+bool CLogindUPowerSyscall::Reboot()
+{
+ return LogindSetPowerState("Reboot");
+}
+
+bool CLogindUPowerSyscall::Suspend()
+{
+ return LogindSetPowerState("Suspend");
+}
+
+bool CLogindUPowerSyscall::Hibernate()
+{
+ return LogindSetPowerState("Hibernate");
+}
+
+bool CLogindUPowerSyscall::CanPowerdown()
+{
+ return m_canPowerdown;
+}
+
+bool CLogindUPowerSyscall::CanSuspend()
+{
+ return m_canSuspend;
+}
+
+bool CLogindUPowerSyscall::CanHibernate()
+{
+ return m_canHibernate;
+}
+
+bool CLogindUPowerSyscall::CanReboot()
+{
+ return m_canReboot;
+}
+
+bool CLogindUPowerSyscall::HasLogind()
+{
+ // recommended method by systemd devs. The seats directory
+ // doesn't exist unless logind created it and therefore is running.
+ // see also https://mail.gnome.org/archives/desktop-devel-list/2013-March/msg00092.html
+ return (access("/run/systemd/seats/", F_OK) >= 0);
+}
+
+bool CLogindUPowerSyscall::LogindSetPowerState(const char *state)
+{
+ CDBusMessage message(LOGIND_DEST, LOGIND_PATH, LOGIND_IFACE, state);
+ // The user_interaction boolean parameters can be used to control
+ // wether PolicyKit should interactively ask the user for authentication
+ // credentials if it needs to.
+ message.AppendArgument(false);
+ return message.SendSystem() != NULL;
+}
+
+bool CLogindUPowerSyscall::LogindCheckCapability(const char *capability)
+{
+ char *arg;
+ CDBusMessage message(LOGIND_DEST, LOGIND_PATH, LOGIND_IFACE, capability);
+ DBusMessage *reply = message.SendSystem();
+ if(reply && dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID))
+ {
+ // Returns one of "yes", "no" or "challenge". If "challenge" is
+ // returned the operation is available, but only after authorization.
+ return (strcmp(arg, "yes") == 0);
+ }
+ return false;
+}
+
+int CLogindUPowerSyscall::BatteryLevel()
+{
+ return m_batteryLevel;
+}
+
+void CLogindUPowerSyscall::UpdateBatteryLevel()
+{
+ char** source = NULL;
+ int length = 0;
+ double batteryLevelSum = 0;
+ int batteryCount = 0;
+
+ CDBusMessage message("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "EnumerateDevices");
+ DBusMessage *reply = message.SendSystem();
+
+ if (!reply)
+ return;
+
+ if (!dbus_message_get_args(reply, NULL, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &source, &length, DBUS_TYPE_INVALID))
+ {
+ CLog::Log(LOGWARNING, "LogindUPowerSyscall: failed to enumerate devices");
+ return;
+ }
+
+ for (int i = 0; i < length; i++)
+ {
+ CVariant properties = CDBusUtil::GetAll("org.freedesktop.UPower", source[i], "org.freedesktop.UPower.Device");
+ bool isRechargeable = properties["IsRechargeable"].asBoolean();
+
+ if (isRechargeable)
+ {
+ batteryCount++;
+ batteryLevelSum += properties["Percentage"].asDouble();
+ }
+ }
+
+ dbus_free_string_array(source);
+
+ if (batteryCount > 0)
+ m_batteryLevel = (int)(batteryLevelSum / (double)batteryCount);
+
+ m_lowBattery = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "OnLowBattery").asBoolean();
+}
+
+bool CLogindUPowerSyscall::PumpPowerEvents(IPowerEventsCallback *callback)
+{
+ bool result = false;
+ bool releaseLock = false;
+
+ if (m_connection)
+ {
+ dbus_connection_read_write(m_connection, 0);
+ DBusMessage *msg = dbus_connection_pop_message(m_connection);
+
+ if (msg)
+ {
+ if (dbus_message_is_signal(msg, "org.freedesktop.login1.Manager", "PrepareForSleep"))
+ {
+ bool arg;
+ // the boolean argument defines whether we are going to sleep (true) or just woke up (false)
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &arg, DBUS_TYPE_INVALID);
+ CLog::Log(LOGDEBUG, "LogindUPowerSyscall: Received PrepareForSleep with arg %i", arg);
+ if (arg)
+ {
+ callback->OnSleep();
+ releaseLock = true;
+ }
+ else
+ {
+ callback->OnWake();
+ InhibitDelayLock();
+ }
+
+ result = true;
+ }
+ else if (dbus_message_is_signal(msg, "org.freedesktop.UPower", "DeviceChanged"))
+ {
+ bool lowBattery = m_lowBattery;
+ UpdateBatteryLevel();
+ if (m_lowBattery && !lowBattery)
+ callback->OnLowBattery();
+
+ result = true;
+ }
+ else
+ CLog::Log(LOGDEBUG, "LogindUPowerSyscall - Received unknown signal %s", dbus_message_get_member(msg));
+
+ dbus_message_unref(msg);
+ }
+ }
+
+ if (releaseLock)
+ ReleaseDelayLock();
+
+ return result;
+}
+
+void CLogindUPowerSyscall::InhibitDelayLock()
+{
+ CDBusMessage message("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit");
+ message.AppendArgument("sleep"); // what to inhibit
+ message.AppendArgument("XBMC"); // who
+ message.AppendArgument(""); // reason
+ message.AppendArgument("delay"); // mode
+
+ DBusMessage *reply = message.SendSystem();
+
+ if (!reply)
+ {
+ CLog::Log(LOGWARNING, "LogindUPowerSyscall - failed to inhibit sleep delay lock");
+ m_delayLockFd = -1;
+ return;
+ }
+
+ if (!dbus_message_get_args(reply, NULL, DBUS_TYPE_UNIX_FD, &m_delayLockFd, DBUS_TYPE_INVALID))
+ {
+ CLog::Log(LOGWARNING, "LogindUPowerSyscall - failed to get inhibit file descriptor");
+ m_delayLockFd = -1;
+ return;
+ }
+
+ CLog::Log(LOGDEBUG, "LogindUPowerSyscall - inhibit lock taken, fd %i", m_delayLockFd);
+}
+
+void CLogindUPowerSyscall::ReleaseDelayLock()
+{
+ if (m_delayLockFd != -1)
+ {
+ close(m_delayLockFd);
+ m_delayLockFd = -1;
+ CLog::Log(LOGDEBUG, "LogindUPowerSyscall - delay lock released");
+ }
+}
+
+#endif
diff -Naur xbmc-12.2-e40d13d/xbmc/powermanagement/linux/LogindUPowerSyscall.h xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/LogindUPowerSyscall.h
--- xbmc-12.2-e40d13d/xbmc/powermanagement/linux/LogindUPowerSyscall.h 1970-01-01 01:00:00.000000000 +0100
+++ xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/LogindUPowerSyscall.h 2013-08-05 10:02:45.905395106 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Denis Yantarev
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAS_DBUS
+
+#include "powermanagement/IPowerSyscall.h"
+#include "DBusUtil.h"
+
+class CLogindUPowerSyscall : public IPowerSyscall
+{
+public:
+ CLogindUPowerSyscall();
+ ~CLogindUPowerSyscall();
+ virtual bool Powerdown();
+ virtual bool Suspend();
+ virtual bool Hibernate();
+ virtual bool Reboot();
+ virtual bool CanPowerdown();
+ virtual bool CanSuspend();
+ virtual bool CanHibernate();
+ virtual bool CanReboot();
+ virtual int BatteryLevel();
+ virtual bool PumpPowerEvents(IPowerEventsCallback *callback);
+ // we don't require UPower because everything except the battery level works fine without it
+ static bool HasLogind();
+private:
+ DBusConnection *m_connection;
+ bool m_canPowerdown;
+ bool m_canSuspend;
+ bool m_canHibernate;
+ bool m_canReboot;
+ bool m_hasUPower;
+ bool m_lowBattery;
+ int m_batteryLevel;
+ int m_delayLockFd; // file descriptor for the logind sleep delay lock
+ void UpdateBatteryLevel();
+ void InhibitDelayLock();
+ void ReleaseDelayLock();
+ static bool LogindSetPowerState(const char *state);
+ static bool LogindCheckCapability(const char *capability);
+};
+
+#endif
diff -Naur xbmc-12.2-e40d13d/xbmc/powermanagement/linux/Makefile xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/Makefile
--- xbmc-12.2-e40d13d/xbmc/powermanagement/linux/Makefile 2013-07-30 13:29:21.000000000 +0200
+++ xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/Makefile 2013-08-05 10:02:45.905395106 +0200
@@ -2,7 +2,7 @@
ConsoleUPowerSyscall.cpp \
HALPowerSyscall.cpp \
UPowerSyscall.cpp \
- SystemdUPowerSyscall.cpp
+ LogindUPowerSyscall.cpp
LIB=powermanagement_linux.a
diff -Naur xbmc-12.2-e40d13d/xbmc/powermanagement/linux/SystemdUPowerSyscall.cpp xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/SystemdUPowerSyscall.cpp
--- xbmc-12.2-e40d13d/xbmc/powermanagement/linux/SystemdUPowerSyscall.cpp 2013-07-30 13:29:21.000000000 +0200
+++ xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/SystemdUPowerSyscall.cpp 1970-01-01 01:00:00.000000000 +0100
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2012 Denis Yantarev
- * Copyright (C) 2005-2009 Team XBMC
- * http://www.xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
-
-#include "system.h"
-#include "SystemdUPowerSyscall.h"
-#include "utils/log.h"
-
-#ifdef HAS_DBUS
-#include "Application.h"
-
-// logind DBus interface specification:
-// http://www.freedesktop.org/wiki/Software/systemd/logind
-
-#define LOGIND_DEST "org.freedesktop.login1"
-#define LOGIND_PATH "/org/freedesktop/login1"
-#define LOGIND_IFACE "org.freedesktop.login1.Manager"
-
-CSystemdUPowerSyscall::CSystemdUPowerSyscall()
-{
- UpdateCapabilities();
-}
-
-bool CSystemdUPowerSyscall::Powerdown()
-{
- return SystemdSetPowerState("PowerOff");
-}
-
-bool CSystemdUPowerSyscall::Reboot()
-{
- return SystemdSetPowerState("Reboot");
-}
-
-bool CSystemdUPowerSyscall::Suspend()
-{
- return SystemdSetPowerState("Suspend");
-}
-
-bool CSystemdUPowerSyscall::Hibernate()
-{
- return SystemdSetPowerState("Hibernate");
-}
-
-void CSystemdUPowerSyscall::UpdateCapabilities()
-{
- m_CanPowerdown = SystemdCheckCapability("CanPowerOff");
- m_CanReboot = SystemdCheckCapability("CanReboot");
- m_CanHibernate = SystemdCheckCapability("CanHibernate");
- m_CanSuspend = SystemdCheckCapability("CanSuspend");
-}
-
-bool CSystemdUPowerSyscall::HasSystemdAndUPower()
-{
- DBusConnection *con;
- DBusError error;
- bool hasSystemd = false;
-
- dbus_error_init(&error);
- con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
-
- if(dbus_error_is_set(&error))
- {
- CLog::Log(LOGDEBUG, "SystemdUPowerSyscall: %s: %s", error.name, error.message);
- dbus_error_free(&error);
- return false;
- }
-
- CDBusMessage message(LOGIND_DEST, LOGIND_PATH, LOGIND_IFACE, "CanPowerOff");
- message.Send(con, &error);
-
- if(!dbus_error_is_set(&error))
- hasSystemd = true;
- else
- CLog::Log(LOGDEBUG, "Systemd error: %s: %s", error.name, error.message);
-
- dbus_error_free(&error);
-
- return HasUPower() && hasSystemd;
-}
-
-bool CSystemdUPowerSyscall::SystemdSetPowerState(const char *state)
-{
- bool arg = false;
- CDBusMessage message(LOGIND_DEST, LOGIND_PATH, LOGIND_IFACE, state);
- // The user_interaction boolean parameters can be used to control
- // wether PolicyKit should interactively ask the user for authentication
- // credentials if it needs to.
- message.AppendArgument(arg);
- return message.SendSystem() != NULL;
-}
-
-bool CSystemdUPowerSyscall::SystemdCheckCapability(const char *capability)
-{
- bool result = false;
- char *arg;
- CDBusMessage message(LOGIND_DEST, LOGIND_PATH, LOGIND_IFACE, capability);
- DBusMessage *reply = message.SendSystem();
- if(reply && dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID))
- {
- // Returns one of "yes", "no" or "challenge". If "challenge" is
- // returned the operation is available, but only after authorization.
- result = (strcmp(arg, "yes") == 0);
- }
- return result;
-}
-
-#endif
diff -Naur xbmc-12.2-e40d13d/xbmc/powermanagement/linux/SystemdUPowerSyscall.h xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/SystemdUPowerSyscall.h
--- xbmc-12.2-e40d13d/xbmc/powermanagement/linux/SystemdUPowerSyscall.h 2013-07-30 13:29:21.000000000 +0200
+++ xbmc-12.2-e40d13d.patch/xbmc/powermanagement/linux/SystemdUPowerSyscall.h 1970-01-01 01:00:00.000000000 +0100
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012 Denis Yantarev
- * Copyright (C) 2005-2009 Team XBMC
- * http://www.xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
-
-#ifdef HAS_DBUS
-
-#include "UPowerSyscall.h"
-
-class CSystemdUPowerSyscall : public CUPowerSyscall
-{
-public:
- CSystemdUPowerSyscall();
- virtual bool Powerdown();
- virtual bool Suspend();
- virtual bool Hibernate();
- virtual bool Reboot();
- static bool HasSystemdAndUPower();
-protected:
- void UpdateCapabilities();
-private:
- static bool SystemdSetPowerState(const char *state);
- static bool SystemdCheckCapability(const char *capability);
-};
-
-#endif
diff -Naur xbmc-12.2-e40d13d/xbmc/powermanagement/PowerManager.cpp xbmc-12.2-e40d13d.patch/xbmc/powermanagement/PowerManager.cpp
--- xbmc-12.2-e40d13d/xbmc/powermanagement/PowerManager.cpp 2013-07-30 13:29:21.000000000 +0200
+++ xbmc-12.2-e40d13d.patch/xbmc/powermanagement/PowerManager.cpp 2013-08-05 10:02:45.904395105 +0200
@@ -46,7 +46,7 @@
#if defined(HAS_DBUS)
#include "linux/ConsoleUPowerSyscall.h"
#include "linux/ConsoleDeviceKitPowerSyscall.h"
-#include "linux/SystemdUPowerSyscall.h"
+#include "linux/LogindUPowerSyscall.h"
#include "linux/UPowerSyscall.h"
#if defined(HAS_HAL)
#include "linux/HALPowerSyscall.h"
@@ -83,8 +83,8 @@
m_instance = new CConsoleUPowerSyscall();
else if (CConsoleDeviceKitPowerSyscall::HasDeviceConsoleKit())
m_instance = new CConsoleDeviceKitPowerSyscall();
- else if (CSystemdUPowerSyscall::HasSystemdAndUPower())
- m_instance = new CSystemdUPowerSyscall();
+ else if (CLogindUPowerSyscall::HasLogind())
+ m_instance = new CLogindUPowerSyscall();
else if (CUPowerSyscall::HasUPower())
m_instance = new CUPowerSyscall();
#if defined(HAS_HAL)