upower/libupower-glib/up-device.c

1427 lines
41 KiB
C
Raw Normal View History

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* 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 of the License, 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
* SECTION:up-device
* @short_description: Client object for accessing information about UPower devices
*
* A helper GObject to use for accessing UPower devices, and to be notified
* when it is changed.
*
* See also: #UpClient
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <string.h>
#include "up-device.h"
#include "up-stats-item.h"
#include "up-history-item.h"
static void up_device_class_init (UpDeviceClass *klass);
static void up_device_init (UpDevice *device);
static void up_device_finalize (GObject *object);
#define UP_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_DEVICE, UpDevicePrivate))
/**
* UpDevicePrivate:
*
* Private #PkDevice data
**/
struct _UpDevicePrivate
{
gchar *object_path;
DBusGConnection *bus;
DBusGProxy *proxy_device;
DBusGProxy *proxy_props;
/* properties */
guint64 update_time;
gchar *vendor;
gchar *model;
gchar *serial;
gchar *native_path;
gboolean power_supply;
gboolean online;
gboolean is_present;
gboolean is_rechargeable;
gboolean has_history;
gboolean has_statistics;
UpDeviceKind kind;
UpDeviceState state;
UpDeviceTechnology technology;
gdouble capacity; /* percent */
gdouble energy; /* Watt Hours */
gdouble energy_empty; /* Watt Hours */
gdouble energy_full; /* Watt Hours */
gdouble energy_full_design; /* Watt Hours */
gdouble energy_rate; /* Watts */
gdouble voltage; /* Volts */
gdouble luminosity; /* Lux */
gint64 time_to_empty; /* seconds */
gint64 time_to_full; /* seconds */
gdouble percentage; /* percent */
gdouble temperature; /* degrees C */
gboolean recall_notice;
gchar *recall_vendor;
gchar *recall_url;
};
enum {
PROP_0,
PROP_UPDATE_TIME,
PROP_VENDOR,
PROP_MODEL,
PROP_SERIAL,
PROP_NATIVE_PATH,
PROP_POWER_SUPPLY,
PROP_ONLINE,
PROP_IS_PRESENT,
PROP_IS_RECHARGEABLE,
PROP_HAS_HISTORY,
PROP_HAS_STATISTICS,
PROP_KIND,
PROP_STATE,
PROP_TECHNOLOGY,
PROP_CAPACITY,
PROP_ENERGY,
PROP_ENERGY_EMPTY,
PROP_ENERGY_FULL,
PROP_ENERGY_FULL_DESIGN,
PROP_ENERGY_RATE,
PROP_VOLTAGE,
PROP_LUMINOSITY,
PROP_TIME_TO_EMPTY,
PROP_TIME_TO_FULL,
PROP_PERCENTAGE,
PROP_TEMPERATURE,
PROP_RECALL_NOTICE,
PROP_RECALL_VENDOR,
PROP_RECALL_URL,
PROP_LAST
};
enum {
SIGNAL_CHANGED,
SIGNAL_LAST
};
static guint signals [SIGNAL_LAST] = { 0 };
G_DEFINE_TYPE (UpDevice, up_device, G_TYPE_OBJECT)
/*
* up_device_get_device_properties:
*/
static GHashTable *
up_device_get_device_properties (UpDevice *device, GError **error)
{
gboolean ret;
GError *error_local = NULL;
GHashTable *hash_table = NULL;
ret = dbus_g_proxy_call (device->priv->proxy_props, "GetAll", &error_local,
G_TYPE_STRING, "org.freedesktop.UPower.Device",
G_TYPE_INVALID,
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
&hash_table,
G_TYPE_INVALID);
if (!ret) {
g_set_error (error, 1, 0, "Couldn't call GetAll() to get properties for %s: %s", device->priv->object_path, error_local->message);
g_error_free (error_local);
goto out;
}
out:
return hash_table;
}
/*
* up_device_collect_props_cb:
*/
static void
up_device_collect_props_cb (const char *key, const GValue *value, UpDevice *device)
{
if (g_strcmp0 (key, "NativePath") == 0) {
g_free (device->priv->native_path);
device->priv->native_path = g_strdup (g_value_get_string (value));
} else if (g_strcmp0 (key, "Vendor") == 0) {
g_free (device->priv->vendor);
device->priv->vendor = g_strdup (g_value_get_string (value));
} else if (g_strcmp0 (key, "Model") == 0) {
g_free (device->priv->model);
device->priv->model = g_strdup (g_value_get_string (value));
} else if (g_strcmp0 (key, "Serial") == 0) {
g_free (device->priv->serial);
device->priv->serial = g_strdup (g_value_get_string (value));
} else if (g_strcmp0 (key, "UpdateTime") == 0) {
device->priv->update_time = g_value_get_uint64 (value);
} else if (g_strcmp0 (key, "Type") == 0) {
device->priv->kind = g_value_get_uint (value);
} else if (g_strcmp0 (key, "Online") == 0) {
device->priv->online = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "HasHistory") == 0) {
device->priv->has_history = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "HasStatistics") == 0) {
device->priv->has_statistics = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "Energy") == 0) {
device->priv->energy = g_value_get_double (value);
} else if (g_strcmp0 (key, "EnergyEmpty") == 0) {
device->priv->energy_empty = g_value_get_double (value);
} else if (g_strcmp0 (key, "EnergyFull") == 0) {
device->priv->energy_full = g_value_get_double (value);
} else if (g_strcmp0 (key, "EnergyFullDesign") == 0) {
device->priv->energy_full_design = g_value_get_double (value);
} else if (g_strcmp0 (key, "EnergyRate") == 0) {
device->priv->energy_rate = g_value_get_double (value);
} else if (g_strcmp0 (key, "Voltage") == 0) {
device->priv->voltage = g_value_get_double (value);
} else if (g_strcmp0 (key, "Luminosity") == 0) {
device->priv->luminosity = g_value_get_double (value);
} else if (g_strcmp0 (key, "TimeToFull") == 0) {
device->priv->time_to_full = g_value_get_int64 (value);
} else if (g_strcmp0 (key, "TimeToEmpty") == 0) {
device->priv->time_to_empty = g_value_get_int64 (value);
} else if (g_strcmp0 (key, "Percentage") == 0) {
device->priv->percentage = g_value_get_double (value);
} else if (g_strcmp0 (key, "Temperature") == 0) {
device->priv->temperature = g_value_get_double (value);
} else if (g_strcmp0 (key, "Technology") == 0) {
device->priv->technology = g_value_get_uint (value);
} else if (g_strcmp0 (key, "IsPresent") == 0) {
device->priv->is_present = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "IsRechargeable") == 0) {
device->priv->is_rechargeable = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "PowerSupply") == 0) {
device->priv->power_supply = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "Capacity") == 0) {
device->priv->capacity = g_value_get_double (value);
} else if (g_strcmp0 (key, "State") == 0) {
device->priv->state = g_value_get_uint (value);
} else if (g_strcmp0 (key, "RecallNotice") == 0) {
device->priv->recall_notice = g_value_get_boolean (value);
} else if (g_strcmp0 (key, "RecallVendor") == 0) {
g_free (device->priv->recall_vendor);
device->priv->recall_vendor = g_strdup (g_value_get_string (value));
} else if (g_strcmp0 (key, "RecallUrl") == 0) {
g_free (device->priv->recall_url);
device->priv->recall_url = g_strdup (g_value_get_string (value));
} else {
g_warning ("unhandled property '%s'", key);
}
}
/*
* up_device_refresh_internal:
*/
static gboolean
up_device_refresh_internal (UpDevice *device, GError **error)
{
GHashTable *hash;
GError *error_local = NULL;
/* get all the properties */
hash = up_device_get_device_properties (device, &error_local);
if (hash == NULL) {
g_set_error (error, 1, 0, "Cannot get device properties for %s: %s", device->priv->object_path, error_local->message);
g_error_free (error_local);
return FALSE;
}
g_hash_table_foreach (hash, (GHFunc) up_device_collect_props_cb, device);
g_hash_table_unref (hash);
return TRUE;
}
/*
* up_device_changed_cb:
*/
static void
up_device_changed_cb (DBusGProxy *proxy, UpDevice *device)
{
g_return_if_fail (UP_IS_DEVICE (device));
up_device_refresh_internal (device, NULL);
g_signal_emit (device, signals [SIGNAL_CHANGED], 0);
}
/**
* up_device_set_object_path_sync:
* @device: a #UpDevice instance.
* @object_path: The UPower object path.
* @cancellable: a #GCancellable or %NULL
* @error: a #GError, or %NULL.
*
* Sets the object path of the object and fills up initial properties.
*
* Return value: #TRUE for success, else #FALSE and @error is used
*
* Since: 0.9.0
**/
gboolean
up_device_set_object_path_sync (UpDevice *device, const gchar *object_path, GCancellable *cancellable, GError **error)
{
GError *error_local = NULL;
gboolean ret = FALSE;
DBusGProxy *proxy_device;
DBusGProxy *proxy_props;
g_return_val_if_fail (UP_IS_DEVICE (device), FALSE);
if (device->priv->object_path != NULL)
return FALSE;
if (object_path == NULL)
return FALSE;
/* invalid */
if (object_path == NULL || object_path[0] != '/') {
g_set_error (error, 1, 0, "Object path %s invalid", object_path);
goto out;
}
/* connect to the bus */
device->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error_local);
if (device->priv->bus == NULL) {
g_set_error (error, 1, 0, "Couldn't connect to system bus: %s", error_local->message);
g_error_free (error_local);
goto out;
}
/* connect to the correct path for properties */
proxy_props = dbus_g_proxy_new_for_name (device->priv->bus, "org.freedesktop.UPower",
object_path, "org.freedesktop.DBus.Properties");
if (proxy_props == NULL) {
g_set_error_literal (error, 1, 0, "Couldn't connect to proxy");
goto out;
}
/* connect to the correct path for all the other methods */
proxy_device = dbus_g_proxy_new_for_name (device->priv->bus, "org.freedesktop.UPower",
object_path, "org.freedesktop.UPower.Device");
if (proxy_device == NULL) {
g_set_error_literal (error, 1, 0, "Couldn't connect to proxy");
goto out;
}
/* listen to Changed */
dbus_g_proxy_add_signal (proxy_device, "Changed", G_TYPE_INVALID);
dbus_g_proxy_connect_signal (proxy_device, "Changed",
G_CALLBACK (up_device_changed_cb), device, NULL);
/* yay */
device->priv->proxy_device = proxy_device;
device->priv->proxy_props = proxy_props;
device->priv->object_path = g_strdup (object_path);
/* coldplug */
ret = up_device_refresh_internal (device, &error_local);
if (!ret) {
g_set_error (error, 1, 0, "cannot refresh: %s", error_local->message);
g_error_free (error_local);
}
out:
return ret;
}
/**
* up_device_get_object_path:
* @device: a #UpDevice instance.
*
* Gets the object path for the device.
*
* Return value: the object path, or %NULL
*
* Since: 0.9.0
**/
const gchar *
up_device_get_object_path (UpDevice *device)
{
g_return_val_if_fail (UP_IS_DEVICE (device), NULL);
return device->priv->object_path;
}
/*
* up_device_to_text_history:
*/
static void
up_device_to_text_history (UpDevice *device, GString *string, const gchar *type)
{
guint i;
GPtrArray *array;
UpHistoryItem *item;
/* get a fair chunk of data */
array = up_device_get_history_sync (device, type, 120, 10, NULL, NULL);
if (array == NULL)
return;
/* pretty print */
g_string_append_printf (string, " History (%s):\n", type);
for (i=0; i<array->len; i++) {
item = (UpHistoryItem *) g_ptr_array_index (array, i);
g_string_append_printf (string, " %i\t%.3f\t%s\n",
up_history_item_get_time (item),
up_history_item_get_value (item),
up_device_state_to_string (up_history_item_get_state (item)));
}
g_ptr_array_unref (array);
}
/*
* up_device_bool_to_string:
*/
static const gchar *
up_device_bool_to_string (gboolean ret)
{
return ret ? "yes" : "no";
}
/*
* up_device_to_text_time_to_string:
*/
static gchar *
up_device_to_text_time_to_string (gint seconds)
{
gfloat value = seconds;
if (value < 0)
return g_strdup ("unknown");
if (value < 60)
return g_strdup_printf ("%.0f seconds", value);
value /= 60.0;
if (value < 60)
return g_strdup_printf ("%.1f minutes", value);
value /= 60.0;
if (value < 60)
return g_strdup_printf ("%.1f hours", value);
value /= 24.0;
return g_strdup_printf ("%.1f days", value);
}
/**
* up_device_to_text:
* @device: a #UpDevice instance.
*
* Converts the device to a string description.
*
* Return value: text representation of #UpDevice
*
* Since: 0.9.0
**/
gchar *
up_device_to_text (UpDevice *device)
{
struct tm *time_tm;
time_t t;
gchar time_buf[256];
gchar *time_str;
GString *string;
g_return_val_if_fail (UP_IS_DEVICE (device), NULL);
/* get a human readable time */
t = (time_t) device->priv->update_time;
time_tm = localtime (&t);
strftime (time_buf, sizeof time_buf, "%c", time_tm);
string = g_string_new ("");
g_string_append_printf (string, " native-path: %s\n", device->priv->native_path);
if (device->priv->vendor != NULL && device->priv->vendor[0] != '\0')
g_string_append_printf (string, " vendor: %s\n", device->priv->vendor);
if (device->priv->model != NULL && device->priv->model[0] != '\0')
g_string_append_printf (string, " model: %s\n", device->priv->model);
if (device->priv->serial != NULL && device->priv->serial[0] != '\0')
g_string_append_printf (string, " serial: %s\n", device->priv->serial);
g_string_append_printf (string, " power supply: %s\n", up_device_bool_to_string (device->priv->power_supply));
g_string_append_printf (string, " updated: %s (%d seconds ago)\n", time_buf, (int) (time (NULL) - device->priv->update_time));
g_string_append_printf (string, " has history: %s\n", up_device_bool_to_string (device->priv->has_history));
g_string_append_printf (string, " has statistics: %s\n", up_device_bool_to_string (device->priv->has_statistics));
g_string_append_printf (string, " %s\n", up_device_kind_to_string (device->priv->kind));
if (device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_MOUSE ||
device->priv->kind == UP_DEVICE_KIND_KEYBOARD ||
device->priv->kind == UP_DEVICE_KIND_UPS)
g_string_append_printf (string, " present: %s\n", up_device_bool_to_string (device->priv->is_present));
if (device->priv->kind == UP_DEVICE_KIND_PHONE ||
device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_MOUSE ||
device->priv->kind == UP_DEVICE_KIND_KEYBOARD)
g_string_append_printf (string, " rechargeable: %s\n", up_device_bool_to_string (device->priv->is_rechargeable));
if (device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_MOUSE ||
device->priv->kind == UP_DEVICE_KIND_KEYBOARD ||
device->priv->kind == UP_DEVICE_KIND_UPS)
g_string_append_printf (string, " state: %s\n", up_device_state_to_string (device->priv->state));
if (device->priv->kind == UP_DEVICE_KIND_BATTERY) {
g_string_append_printf (string, " energy: %g Wh\n", device->priv->energy);
g_string_append_printf (string, " energy-empty: %g Wh\n", device->priv->energy_empty);
g_string_append_printf (string, " energy-full: %g Wh\n", device->priv->energy_full);
g_string_append_printf (string, " energy-full-design: %g Wh\n", device->priv->energy_full_design);
}
if (device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_MONITOR)
g_string_append_printf (string, " energy-rate: %g W\n", device->priv->energy_rate);
if (device->priv->kind == UP_DEVICE_KIND_UPS ||
device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_MONITOR) {
if (device->priv->voltage > 0)
g_string_append_printf (string, " voltage: %g V\n", device->priv->voltage);
}
if (device->priv->kind == UP_DEVICE_KIND_KEYBOARD) {
if (device->priv->luminosity > 0)
g_string_append_printf (string, " luminosity: %g lx\n", device->priv->luminosity);
}
if (device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_UPS) {
if (device->priv->time_to_full > 0) {
time_str = up_device_to_text_time_to_string (device->priv->time_to_full);
g_string_append_printf (string, " time to full: %s\n", time_str);
g_free (time_str);
}
if (device->priv->time_to_empty > 0) {
time_str = up_device_to_text_time_to_string (device->priv->time_to_empty);
g_string_append_printf (string, " time to empty: %s\n", time_str);
g_free (time_str);
}
}
if (device->priv->kind == UP_DEVICE_KIND_BATTERY ||
device->priv->kind == UP_DEVICE_KIND_MOUSE ||
device->priv->kind == UP_DEVICE_KIND_KEYBOARD ||
device->priv->kind == UP_DEVICE_KIND_PHONE ||
device->priv->kind == UP_DEVICE_KIND_TABLET ||
device->priv->kind == UP_DEVICE_KIND_COMPUTER ||
device->priv->kind == UP_DEVICE_KIND_MEDIA_PLAYER ||
device->priv->kind == UP_DEVICE_KIND_UPS)
g_string_append_printf (string, " percentage: %g%%\n", device->priv->percentage);
if (device->priv->kind == UP_DEVICE_KIND_BATTERY) {
if (device->priv->temperature > 0)
g_string_append_printf (string, " temperature: %g degrees C\n", device->priv->temperature);
if (device->priv->capacity > 0)
g_string_append_printf (string, " capacity: %g%%\n", device->priv->capacity);
}
if (device->priv->kind == UP_DEVICE_KIND_BATTERY) {
if (device->priv->technology != UP_DEVICE_TECHNOLOGY_UNKNOWN)
g_string_append_printf (string, " technology: %s\n", up_device_technology_to_string (device->priv->technology));
}
if (device->priv->kind == UP_DEVICE_KIND_LINE_POWER)
g_string_append_printf (string, " online: %s\n", up_device_bool_to_string (device->priv->online));
if (device->priv->kind == UP_DEVICE_KIND_BATTERY) {
if (device->priv->recall_notice) {
g_string_append_printf (string, " recall vendor: %s\n", device->priv->recall_vendor);
g_string_append_printf (string, " recall url: %s\n", device->priv->recall_url);
}
}
/* if we can, get history */
if (device->priv->has_history) {
up_device_to_text_history (device, string, "charge");
up_device_to_text_history (device, string, "rate");
}
return g_string_free (string, FALSE);
}
/**
* up_device_refresh_sync:
* @device: a #UpDevice instance.
* @cancellable: a #GCancellable or %NULL
* @error: a #GError, or %NULL.
*
* Refreshes properties on the device.
* This function is normally not required.
*
* Return value: #TRUE for success, else #FALSE and @error is used
*
* Since: 0.9.0
**/
gboolean
up_device_refresh_sync (UpDevice *device, GCancellable *cancellable, GError **error)
{
GError *error_local = NULL;
gboolean ret;
g_return_val_if_fail (UP_IS_DEVICE (device), FALSE);
g_return_val_if_fail (device->priv->proxy_device != NULL, FALSE);
/* just refresh the device */
ret = dbus_g_proxy_call (device->priv->proxy_device, "Refresh", &error_local,
G_TYPE_INVALID, G_TYPE_INVALID);
if (!ret) {
g_set_error (error, 1, 0, "Refresh() on %s failed: %s", device->priv->object_path, error_local->message);
g_error_free (error_local);
goto out;
}
out:
return ret;
}
/* FIXME: GValueArray is deprecated in GLib 2.33+, but we need to convert to
* GDBus to get rid of it */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
/**
* up_device_get_history_sync:
* @device: a #UpDevice instance.
* @type: The type of history, known values are "rate" and "charge".
* @timespec: the amount of time to look back into time.
* @resolution: the resolution of data.
* @cancellable: a #GCancellable or %NULL
* @error: a #GError, or %NULL.
*
* Gets the device history.
*
* Return value: (element-type UpHistoryItem) (transfer full): an array of #UpHistoryItem's, with the most
* recent one being first; %NULL if @error is set or @device is
* invalid
*
* Since: 0.9.0
**/
GPtrArray *
up_device_get_history_sync (UpDevice *device, const gchar *type, guint timespec, guint resolution, GCancellable *cancellable, GError **error)
{
GError *error_local = NULL;
GType g_type_gvalue_array;
GPtrArray *gvalue_ptr_array = NULL;
GValueArray *gva;
GValue *gv;
guint i;
UpHistoryItem *item;
GPtrArray *array = NULL;
gboolean ret;
g_return_val_if_fail (UP_IS_DEVICE (device), NULL);
g_return_val_if_fail (device->priv->proxy_device != NULL, NULL);
g_type_gvalue_array = dbus_g_type_get_collection ("GPtrArray",
dbus_g_type_get_struct("GValueArray",
G_TYPE_UINT,
G_TYPE_DOUBLE,
G_TYPE_UINT,
G_TYPE_INVALID));
/* get compound data */
ret = dbus_g_proxy_call (device->priv->proxy_device, "GetHistory", &error_local,
G_TYPE_STRING, type,
G_TYPE_UINT, timespec,
G_TYPE_UINT, resolution,
G_TYPE_INVALID,
g_type_gvalue_array, &gvalue_ptr_array,
G_TYPE_INVALID);
if (!ret) {
g_set_error (error, 1, 0, "GetHistory(%s,%i) on %s failed: %s", type, timespec,
device->priv->object_path, error_local->message);
g_error_free (error_local);
goto out;
}
/* no data */
if (gvalue_ptr_array->len == 0) {
g_set_error_literal (error, 1, 0, "no data");
goto out;
}
/* convert */
array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
for (i=0; i<gvalue_ptr_array->len; i++) {
gva = (GValueArray *) g_ptr_array_index (gvalue_ptr_array, i);
item = up_history_item_new ();
/* 0 */
gv = g_value_array_get_nth (gva, 0);
up_history_item_set_time (item, g_value_get_uint (gv));
g_value_unset (gv);
/* 1 */
gv = g_value_array_get_nth (gva, 1);
up_history_item_set_value (item, g_value_get_double (gv));
g_value_unset (gv);
/* 2 */
gv = g_value_array_get_nth (gva, 2);
up_history_item_set_state (item, g_value_get_uint (gv));
g_value_unset (gv);
g_ptr_array_add (array, item);
g_value_array_free (gva);
}
out:
if (gvalue_ptr_array != NULL)
g_ptr_array_free (gvalue_ptr_array, TRUE);
return array;
}
/**
* up_device_get_statistics_sync:
* @device: a #UpDevice instance.
* @type: the type of statistics.
* @cancellable: a #GCancellable or %NULL
* @error: a #GError, or %NULL.
*
* Gets the device current statistics.
*
* Return value: (element-type UpStatsItem) (transfer full): an array of #UpStatsItem's, else #NULL and @error is used
*
* Since: 0.9.0
**/
GPtrArray *
up_device_get_statistics_sync (UpDevice *device, const gchar *type, GCancellable *cancellable, GError **error)
{
GError *error_local = NULL;
GType g_type_gvalue_array;
GPtrArray *gvalue_ptr_array = NULL;
GValueArray *gva;
GValue *gv;
guint i;
UpStatsItem *item;
GPtrArray *array = NULL;
gboolean ret;
g_return_val_if_fail (UP_IS_DEVICE (device), NULL);
g_return_val_if_fail (device->priv->proxy_device != NULL, NULL);
g_type_gvalue_array = dbus_g_type_get_collection ("GPtrArray",
dbus_g_type_get_struct("GValueArray",
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_INVALID));
/* get compound data */
ret = dbus_g_proxy_call (device->priv->proxy_device, "GetStatistics", &error_local,
G_TYPE_STRING, type,
G_TYPE_INVALID,
g_type_gvalue_array, &gvalue_ptr_array,
G_TYPE_INVALID);
if (!ret) {
g_set_error (error, 1, 0, "GetStatistics(%s) on %s failed: %s", type,
device->priv->object_path, error_local->message);
g_error_free (error_local);
goto out;
}
/* no data */
if (gvalue_ptr_array->len == 0) {
g_set_error_literal (error, 1, 0, "no data");
goto out;
}
/* convert */
array = g_ptr_array_new ();
for (i=0; i<gvalue_ptr_array->len; i++) {
gva = (GValueArray *) g_ptr_array_index (gvalue_ptr_array, i);
item = up_stats_item_new ();
/* 0 */
gv = g_value_array_get_nth (gva, 0);
up_stats_item_set_value (item, g_value_get_double (gv));
g_value_unset (gv);
/* 1 */
gv = g_value_array_get_nth (gva, 1);
up_stats_item_set_accuracy (item, g_value_get_double (gv));
g_value_unset (gv);
/* 2 */
g_ptr_array_add (array, item);
g_value_array_free (gva);
}
out:
if (gvalue_ptr_array != NULL)
g_ptr_array_free (gvalue_ptr_array, TRUE);
return array;
}
#pragma GCC diagnostic error "-Wdeprecated-declarations"
/*
* up_device_set_property:
*/
static void
up_device_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
UpDevice *device = UP_DEVICE (object);
switch (prop_id) {
case PROP_NATIVE_PATH:
g_free (device->priv->native_path);
device->priv->native_path = g_strdup (g_value_get_string (value));
break;
case PROP_VENDOR:
g_free (device->priv->vendor);
device->priv->vendor = g_strdup (g_value_get_string (value));
break;
case PROP_MODEL:
g_free (device->priv->model);
device->priv->model = g_strdup (g_value_get_string (value));
break;
case PROP_SERIAL:
g_free (device->priv->serial);
device->priv->serial = g_strdup (g_value_get_string (value));
break;
case PROP_UPDATE_TIME:
device->priv->update_time = g_value_get_uint64 (value);
break;
case PROP_KIND:
device->priv->kind = g_value_get_uint (value);
break;
case PROP_POWER_SUPPLY:
device->priv->power_supply = g_value_get_boolean (value);
break;
case PROP_ONLINE:
device->priv->online = g_value_get_boolean (value);
break;
case PROP_IS_PRESENT:
device->priv->is_present = g_value_get_boolean (value);
break;
case PROP_IS_RECHARGEABLE:
device->priv->is_rechargeable = g_value_get_boolean (value);
break;
case PROP_HAS_HISTORY:
device->priv->has_history = g_value_get_boolean (value);
break;
case PROP_HAS_STATISTICS:
device->priv->has_statistics = g_value_get_boolean (value);
break;
case PROP_STATE:
device->priv->state = g_value_get_uint (value);
break;
case PROP_CAPACITY:
device->priv->capacity = g_value_get_double (value);
break;
case PROP_ENERGY:
device->priv->energy = g_value_get_double (value);
break;
case PROP_ENERGY_EMPTY:
device->priv->energy_empty = g_value_get_double (value);
break;
case PROP_ENERGY_FULL:
device->priv->energy_full = g_value_get_double (value);
break;
case PROP_ENERGY_FULL_DESIGN:
device->priv->energy_full_design = g_value_get_double (value);
break;
case PROP_ENERGY_RATE:
device->priv->energy_rate = g_value_get_double (value);
break;
case PROP_VOLTAGE:
device->priv->voltage = g_value_get_double (value);
break;
case PROP_LUMINOSITY:
device->priv->luminosity = g_value_get_double (value);
break;
case PROP_TIME_TO_EMPTY:
device->priv->time_to_empty = g_value_get_int64 (value);
break;
case PROP_TIME_TO_FULL:
device->priv->time_to_full = g_value_get_int64 (value);
break;
case PROP_PERCENTAGE:
device->priv->percentage = g_value_get_double (value);
break;
case PROP_TEMPERATURE:
device->priv->temperature = g_value_get_double (value);
break;
case PROP_TECHNOLOGY:
device->priv->technology = g_value_get_uint (value);
break;
case PROP_RECALL_NOTICE:
device->priv->recall_notice = g_value_get_boolean (value);
break;
case PROP_RECALL_VENDOR:
g_free (device->priv->recall_vendor);
device->priv->recall_vendor = g_strdup (g_value_get_string (value));
break;
case PROP_RECALL_URL:
g_free (device->priv->recall_url);
device->priv->recall_url = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*
* up_device_get_property:
*/
static void
up_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
UpDevice *device = UP_DEVICE (object);
switch (prop_id) {
case PROP_UPDATE_TIME:
g_value_set_uint64 (value, device->priv->update_time);
break;
case PROP_VENDOR:
g_value_set_string (value, device->priv->vendor);
break;
case PROP_MODEL:
g_value_set_string (value, device->priv->model);
break;
case PROP_SERIAL:
g_value_set_string (value, device->priv->serial);
break;
case PROP_NATIVE_PATH:
g_value_set_string (value, device->priv->native_path);
break;
case PROP_POWER_SUPPLY:
g_value_set_boolean (value, device->priv->power_supply);
break;
case PROP_ONLINE:
g_value_set_boolean (value, device->priv->online);
break;
case PROP_IS_PRESENT:
g_value_set_boolean (value, device->priv->is_present);
break;
case PROP_IS_RECHARGEABLE:
g_value_set_boolean (value, device->priv->is_rechargeable);
break;
case PROP_HAS_HISTORY:
g_value_set_boolean (value, device->priv->has_history);
break;
case PROP_HAS_STATISTICS:
g_value_set_boolean (value, device->priv->has_statistics);
break;
case PROP_KIND:
g_value_set_uint (value, device->priv->kind);
break;
case PROP_STATE:
g_value_set_uint (value, device->priv->state);
break;
case PROP_TECHNOLOGY:
g_value_set_uint (value, device->priv->technology);
break;
case PROP_CAPACITY:
g_value_set_double (value, device->priv->capacity);
break;
case PROP_ENERGY:
g_value_set_double (value, device->priv->energy);
break;
case PROP_ENERGY_EMPTY:
g_value_set_double (value, device->priv->energy_empty);
break;
case PROP_ENERGY_FULL:
g_value_set_double (value, device->priv->energy_full);
break;
case PROP_ENERGY_FULL_DESIGN:
g_value_set_double (value, device->priv->energy_full_design);
break;
case PROP_ENERGY_RATE:
g_value_set_double (value, device->priv->energy_rate);
break;
case PROP_VOLTAGE:
g_value_set_double (value, device->priv->voltage);
break;
case PROP_LUMINOSITY:
g_value_set_double (value, device->priv->luminosity);
break;
case PROP_TIME_TO_EMPTY:
g_value_set_int64 (value, device->priv->time_to_empty);
break;
case PROP_TIME_TO_FULL:
g_value_set_int64 (value, device->priv->time_to_full);
break;
case PROP_PERCENTAGE:
g_value_set_double (value, device->priv->percentage);
break;
case PROP_TEMPERATURE:
g_value_set_double (value, device->priv->temperature);
break;
case PROP_RECALL_NOTICE:
g_value_set_boolean (value, device->priv->recall_notice);
break;
case PROP_RECALL_VENDOR:
g_value_set_string (value, device->priv->recall_vendor);
break;
case PROP_RECALL_URL:
g_value_set_string (value, device->priv->recall_url);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*
* up_device_class_init:
*/
static void
up_device_class_init (UpDeviceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = up_device_finalize;
object_class->set_property = up_device_set_property;
object_class->get_property = up_device_get_property;
/**
* UpDevice::changed:
* @device: the #UpDevice instance that emitted the signal
*
* The ::changed signal is emitted when the device data has changed.
*
* Since: 0.9.0
**/
signals [SIGNAL_CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (UpDeviceClass, changed),
NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* UpDevice:update-time:
*
* The last time the device was updated.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_UPDATE_TIME,
g_param_spec_uint64 ("update-time",
NULL, NULL,
0, G_MAXUINT64, 0,
G_PARAM_READWRITE));
/**
* UpDevice:vendor:
*
* The vendor of the device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_VENDOR,
g_param_spec_string ("vendor",
NULL, NULL,
NULL,
G_PARAM_READWRITE));
/**
* UpDevice:model:
*
* The model of the device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_MODEL,
g_param_spec_string ("model",
NULL, NULL,
NULL,
G_PARAM_READWRITE));
/**
* UpDevice:serial:
*
* The serial number of the device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_SERIAL,
g_param_spec_string ("serial",
NULL, NULL,
NULL,
G_PARAM_READWRITE));
/**
* UpDevice:native-path:
*
* The native path of the device, useful for direct device access.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_NATIVE_PATH,
g_param_spec_string ("native-path",
NULL, NULL,
NULL,
G_PARAM_READWRITE));
/**
* UpDevice:power-supply:
*
* If the device is powering the system.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_POWER_SUPPLY,
g_param_spec_boolean ("power-supply",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:online:
*
* If the device is online, i.e. connected.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_ONLINE,
g_param_spec_boolean ("online",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:is-present:
*
* If the device is present, as some devices like laptop batteries
* can be removed, leaving an empty bay that is still technically a
* device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_IS_PRESENT,
g_param_spec_boolean ("is-present",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:is-rechargeable:
*
* If the device has a rechargable battery.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_IS_RECHARGEABLE,
g_param_spec_boolean ("is-rechargeable",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:has-history:
*
* If the device has history data that might be useful.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_HAS_HISTORY,
g_param_spec_boolean ("has-history",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:has-statistics:
*
* If the device has statistics data that might be useful.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_HAS_STATISTICS,
g_param_spec_boolean ("has-statistics",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:kind:
*
* The device kind, e.g. %UP_DEVICE_KIND_KEYBOARD.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_KIND,
g_param_spec_uint ("kind",
NULL, NULL,
UP_DEVICE_KIND_UNKNOWN,
UP_DEVICE_KIND_LAST,
UP_DEVICE_KIND_UNKNOWN,
G_PARAM_READWRITE));
/**
* UpDevice:state:
*
* The state the device is in at this time, e.g. %UP_DEVICE_STATE_EMPTY.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_STATE,
g_param_spec_uint ("state",
NULL, NULL,
UP_DEVICE_STATE_UNKNOWN,
UP_DEVICE_STATE_LAST,
UP_DEVICE_STATE_UNKNOWN,
G_PARAM_READWRITE));
/**
* UpDevice:technology:
*
* The battery technology e.g. %UP_DEVICE_TECHNOLOGY_LITHIUM_ION.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_TECHNOLOGY,
g_param_spec_uint ("technology",
NULL, NULL,
UP_DEVICE_TECHNOLOGY_UNKNOWN,
UP_DEVICE_TECHNOLOGY_LAST,
UP_DEVICE_TECHNOLOGY_UNKNOWN,
G_PARAM_READWRITE));
/**
* UpDevice:capacity:
*
* The percentage capacity of the device where 100% means the device has
* the same charge potential as when it was manufactured.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_CAPACITY,
g_param_spec_double ("capacity", NULL, NULL,
0.0, 100.f, 100.0,
G_PARAM_READWRITE));
/**
* UpDevice:energy:
*
* The energy left in the device. Measured in mWh.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_ENERGY,
g_param_spec_double ("energy", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:energy-empty:
*
* The energy the device will have when it is empty. This is usually zero.
* Measured in mWh.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_ENERGY_EMPTY,
g_param_spec_double ("energy-empty", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:energy-full:
*
* The amount of energy when the device is fully charged. Measured in mWh.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_ENERGY_FULL,
g_param_spec_double ("energy-full", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:energy-full-design:
*
* The amount of energy when the device was brand new. Measured in mWh.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_ENERGY_FULL_DESIGN,
g_param_spec_double ("energy-full-design", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:energy-rate:
*
* The rate of discharge or charge. Measured in mW.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_ENERGY_RATE,
g_param_spec_double ("energy-rate", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:voltage:
*
* The current voltage of the device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_VOLTAGE,
g_param_spec_double ("voltage", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:luminosity:
*
* The current luminosity of the device.
*
* Since: 0.9.19
**/
g_object_class_install_property (object_class,
PROP_LUMINOSITY,
g_param_spec_double ("luminosity", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:time-to-empty:
*
* The amount of time until the device is empty.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_TIME_TO_EMPTY,
g_param_spec_int64 ("time-to-empty", NULL, NULL,
0, G_MAXINT64, 0,
G_PARAM_READWRITE));
/**
* UpDevice:time-to-full:
*
* The amount of time until the device is fully charged.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_TIME_TO_FULL,
g_param_spec_int64 ("time-to-full", NULL, NULL,
0, G_MAXINT64, 0,
G_PARAM_READWRITE));
/**
* UpDevice:percentage:
*
* The percentage charge of the device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_PERCENTAGE,
g_param_spec_double ("percentage", NULL, NULL,
0.0, 100.f, 100.0,
G_PARAM_READWRITE));
/**
* UpDevice:temperature:
*
* The temperature of the device in degrees Celsius.
*
* Since: 0.9.22
**/
g_object_class_install_property (object_class,
PROP_TEMPERATURE,
g_param_spec_double ("temperature", NULL, NULL,
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
/**
* UpDevice:recall-notice:
*
* If the device may be recalled due to defect. NOTE: This property does
* not mean the battery is broken, and just that the user should
* _check_ with the vendor.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_RECALL_NOTICE,
g_param_spec_boolean ("recall-notice",
NULL, NULL,
FALSE,
G_PARAM_READWRITE));
/**
* UpDevice:recall-vendor:
*
* The vendor that is recalling the device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_RECALL_VENDOR,
g_param_spec_string ("recall-vendor",
NULL, NULL,
NULL,
G_PARAM_READWRITE));
/**
* UpDevice:recall-url:
*
* The vendors internet link for the recalled device.
*
* Since: 0.9.0
**/
g_object_class_install_property (object_class,
PROP_RECALL_URL,
g_param_spec_string ("recall-url",
NULL, NULL,
NULL,
G_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (UpDevicePrivate));
}
/*
* up_device_init:
*/
static void
up_device_init (UpDevice *device)
{
device->priv = UP_DEVICE_GET_PRIVATE (device);
device->priv->object_path = NULL;
device->priv->proxy_device = NULL;
device->priv->proxy_props = NULL;
}
/*
* up_device_finalize:
*/
static void
up_device_finalize (GObject *object)
{
UpDevice *device;
g_return_if_fail (UP_IS_DEVICE (object));
device = UP_DEVICE (object);
g_free (device->priv->object_path);
g_free (device->priv->vendor);
g_free (device->priv->model);
g_free (device->priv->serial);
g_free (device->priv->native_path);
g_free (device->priv->recall_vendor);
g_free (device->priv->recall_url);
if (device->priv->proxy_device != NULL)
g_object_unref (device->priv->proxy_device);
if (device->priv->proxy_props != NULL)
g_object_unref (device->priv->proxy_props);
G_OBJECT_CLASS (up_device_parent_class)->finalize (object);
}
/**
* up_device_new:
*
* Creates a new #UpDevice object.
*
* Return value: a new UpDevice object.
*
* Since: 0.9.0
**/
UpDevice *
up_device_new (void)
{
UpDevice *device;
device = g_object_new (UP_TYPE_DEVICE, NULL);
return UP_DEVICE (device);
}