diff options
Diffstat (limited to 'src/gpm-phone.c')
-rw-r--r-- | src/gpm-phone.c | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/src/gpm-phone.c b/src/gpm-phone.c new file mode 100644 index 0000000..e5455f7 --- /dev/null +++ b/src/gpm-phone.c @@ -0,0 +1,508 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2007-2008 Richard Hughes <[email protected]> + * + * 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. + */ + +#include "config.h" + +#include <string.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <dbus/dbus-glib.h> + +#include <mateconf/mateconf-client.h> +#include "gpm-phone.h" +#include "egg-debug.h" +#include "gpm-marshal.h" + +#include "egg-dbus-monitor.h" + +static void gpm_phone_finalize (GObject *object); + +#define GPM_PHONE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_PHONE, GpmPhonePrivate)) + +struct GpmPhonePrivate +{ + DBusGProxy *proxy; + DBusGConnection *connection; + EggDbusMonitor *monitor; + gboolean present; + guint percentage; + gboolean onac; +}; + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + DEVICE_REFRESH, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0 }; +static gpointer gpm_phone_object = NULL; + +G_DEFINE_TYPE (GpmPhone, gpm_phone, G_TYPE_OBJECT) + +/** + * gpm_phone_coldplug: + * Return value: Success value, or zero for failure + **/ +gboolean +gpm_phone_coldplug (GpmPhone *phone) +{ + GError *error = NULL; + gboolean ret; + + g_return_val_if_fail (phone != NULL, FALSE); + g_return_val_if_fail (GPM_IS_PHONE (phone), FALSE); + + if (phone->priv->proxy == NULL) { + egg_warning ("not connected"); + return FALSE; + } + + ret = dbus_g_proxy_call (phone->priv->proxy, "Coldplug", &error, + G_TYPE_INVALID, G_TYPE_INVALID); + if (error != NULL) { + egg_warning ("DEBUG: ERROR: %s", error->message); + g_error_free (error); + } + + return ret; +} + +/** + * gpm_phone_coldplug: + * Return value: if present + **/ +gboolean +gpm_phone_get_present (GpmPhone *phone, guint idx) +{ + g_return_val_if_fail (phone != NULL, FALSE); + g_return_val_if_fail (GPM_IS_PHONE (phone), FALSE); + return phone->priv->present; +} + +/** + * gpm_phone_coldplug: + * Return value: if present + **/ +guint +gpm_phone_get_percentage (GpmPhone *phone, guint idx) +{ + g_return_val_if_fail (phone != NULL, 0); + g_return_val_if_fail (GPM_IS_PHONE (phone), 0); + return phone->priv->percentage; +} + +/** + * gpm_phone_coldplug: + * Return value: if present + **/ +gboolean +gpm_phone_get_on_ac (GpmPhone *phone, guint idx) +{ + g_return_val_if_fail (phone != NULL, FALSE); + g_return_val_if_fail (GPM_IS_PHONE (phone), FALSE); + return phone->priv->onac; +} + +/** + * gpm_phone_get_num_batteries: + * Return value: number of phone batteries monitored + **/ +guint +gpm_phone_get_num_batteries (GpmPhone *phone) +{ + g_return_val_if_fail (phone != NULL, 0); + g_return_val_if_fail (GPM_IS_PHONE (phone), 0); + if (phone->priv->present) { + return 1; + } + return 0; +} + +/** Invoked when we get the BatteryStateChanged + */ +static void +gpm_phone_battery_state_changed (DBusGProxy *proxy, guint idx, guint percentage, gboolean on_ac, GpmPhone *phone) +{ + g_return_if_fail (GPM_IS_PHONE (phone)); + + egg_debug ("got BatteryStateChanged %i = %i (%i)", idx, percentage, on_ac); + phone->priv->percentage = percentage; + phone->priv->onac = on_ac; + phone->priv->present = TRUE; + egg_debug ("emitting device-refresh : (%i)", idx); + g_signal_emit (phone, signals [DEVICE_REFRESH], 0, idx); +} + +/** Invoked when we get NumberBatteriesChanged + */ +static void +gpm_phone_num_batteries_changed (DBusGProxy *proxy, guint number, GpmPhone *phone) +{ + g_return_if_fail (GPM_IS_PHONE (phone)); + + egg_debug ("got NumberBatteriesChanged %i", number); + if (number > 1) { + egg_warning ("number not 0 or 1, not valid!"); + return; + } + + /* are we removed? */ + if (number == 0) { + phone->priv->present = FALSE; + phone->priv->percentage = 0; + phone->priv->onac = FALSE; + egg_debug ("emitting device-removed : (%i)", 0); + g_signal_emit (phone, signals [DEVICE_REMOVED], 0, 0); + return; + } + + if (phone->priv->present) { + egg_warning ("duplicate NumberBatteriesChanged with no change"); + return; + } + + /* reset to defaults until we get BatteryStateChanged */ + phone->priv->present = TRUE; + phone->priv->percentage = 0; + phone->priv->onac = FALSE; + egg_debug ("emitting device-added : (%i)", 0); + g_signal_emit (phone, signals [DEVICE_ADDED], 0, 0); +} + +/** + * gpm_phone_class_init: + * @klass: This class instance + **/ +static void +gpm_phone_class_init (GpmPhoneClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = gpm_phone_finalize; + g_type_class_add_private (klass, sizeof (GpmPhonePrivate)); + + signals [DEVICE_ADDED] = + g_signal_new ("device-added", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GpmPhoneClass, device_added), + NULL, NULL, g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + + signals [DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GpmPhoneClass, device_removed), + NULL, NULL, g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + + signals [DEVICE_REFRESH] = + g_signal_new ("device-refresh", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GpmPhoneClass, device_refresh), + NULL, NULL, g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); +} + +/** + * gpm_phone_dbus_connect: + **/ +static gboolean +gpm_phone_dbus_connect (GpmPhone *phone) +{ + GError *error = NULL; + + g_return_val_if_fail (phone != NULL, FALSE); + g_return_val_if_fail (GPM_IS_PHONE (phone), FALSE); + + if (phone->priv->connection == NULL) { + egg_debug ("get connection"); + g_clear_error (&error); + phone->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (error != NULL) { + egg_warning ("Could not connect to DBUS daemon: %s", error->message); + g_error_free (error); + phone->priv->connection = NULL; + return FALSE; + } + } + if (phone->priv->proxy == NULL) { + egg_debug ("get proxy"); + g_clear_error (&error); + phone->priv->proxy = dbus_g_proxy_new_for_name_owner (phone->priv->connection, + MATE_PHONE_MANAGER_DBUS_SERVICE, + MATE_PHONE_MANAGER_DBUS_PATH, + MATE_PHONE_MANAGER_DBUS_INTERFACE, + &error); + if (error != NULL) { + egg_warning ("Cannot connect, maybe the daemon is not running: %s", error->message); + g_error_free (error); + phone->priv->proxy = NULL; + return FALSE; + } + + /* complicated type. ick */ + dbus_g_object_register_marshaller(gpm_marshal_VOID__UINT_UINT_BOOLEAN, + G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, + G_TYPE_BOOLEAN, G_TYPE_INVALID); + + /* get BatteryStateChanged */ + dbus_g_proxy_add_signal (phone->priv->proxy, "BatteryStateChanged", + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (phone->priv->proxy, "BatteryStateChanged", + G_CALLBACK (gpm_phone_battery_state_changed), + phone, NULL); + + /* get NumberBatteriesChanged */ + dbus_g_proxy_add_signal (phone->priv->proxy, "NumberBatteriesChanged", + G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (phone->priv->proxy, "NumberBatteriesChanged", + G_CALLBACK (gpm_phone_num_batteries_changed), + phone, NULL); + + } + return TRUE; +} + +/** + * gpm_phone_dbus_disconnect: + **/ +static gboolean +gpm_phone_dbus_disconnect (GpmPhone *phone) +{ + g_return_val_if_fail (phone != NULL, FALSE); + g_return_val_if_fail (GPM_IS_PHONE (phone), FALSE); + + if (phone->priv->proxy != NULL) { + egg_debug ("removing proxy"); + g_object_unref (phone->priv->proxy); + phone->priv->proxy = NULL; + if (phone->priv->present) { + phone->priv->present = FALSE; + phone->priv->percentage = 0; + egg_debug ("emitting device-removed : (%i)", 0); + g_signal_emit (phone, signals [DEVICE_REMOVED], 0, 0); + } + } + return TRUE; +} + +/** + * monitor_connection_cb: + * @proxy: The dbus raw proxy + * @status: The status of the service, where TRUE is connected + * @screensaver: This class instance + **/ +static void +monitor_connection_cb (EggDbusMonitor *monitor, + gboolean status, + GpmPhone *phone) +{ + if (status) + gpm_phone_dbus_connect (phone); + else + gpm_phone_dbus_disconnect (phone); +} + +/** + * gpm_phone_init: + * @phone: This class instance + **/ +static void +gpm_phone_init (GpmPhone *phone) +{ + DBusGConnection *connection; + phone->priv = GPM_PHONE_GET_PRIVATE (phone); + + phone->priv->connection = NULL; + phone->priv->proxy = NULL; + phone->priv->present = FALSE; + phone->priv->percentage = 0; + phone->priv->onac = FALSE; + + phone->priv->monitor = egg_dbus_monitor_new (); + g_signal_connect (phone->priv->monitor, "connection-changed", + G_CALLBACK (monitor_connection_cb), phone); + connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + egg_dbus_monitor_assign (phone->priv->monitor, connection, MATE_PHONE_MANAGER_DBUS_SERVICE); + gpm_phone_dbus_connect (phone); +} + +/** + * gpm_phone_finalize: + * @object: This class instance + **/ +static void +gpm_phone_finalize (GObject *object) +{ + GpmPhone *phone; + g_return_if_fail (object != NULL); + g_return_if_fail (GPM_IS_PHONE (object)); + + phone = GPM_PHONE (object); + phone->priv = GPM_PHONE_GET_PRIVATE (phone); + + gpm_phone_dbus_disconnect (phone); + if (phone->priv->monitor != NULL) + g_object_unref (phone->priv->monitor); + + G_OBJECT_CLASS (gpm_phone_parent_class)->finalize (object); +} + +/** + * gpm_phone_new: + * Return value: new GpmPhone instance. + **/ +GpmPhone * +gpm_phone_new (void) +{ + if (gpm_phone_object != NULL) { + g_object_ref (gpm_phone_object); + } else { + gpm_phone_object = g_object_new (GPM_TYPE_PHONE, NULL); + g_object_add_weak_pointer (gpm_phone_object, &gpm_phone_object); + } + return GPM_PHONE (gpm_phone_object); +} + +/*************************************************************************** + *** MAKE CHECK TESTS *** + ***************************************************************************/ +#ifdef EGG_TEST +#include "egg-test.h" + +static gboolean test_got_refresh = FALSE; + +static void +egg_test_mainloop_wait (guint ms) +{ + GMainLoop *loop; + loop = g_main_loop_new (NULL, FALSE); + g_timeout_add (ms, (GSourceFunc) g_main_loop_quit, loop); + g_main_loop_run (loop); +} + +static void +phone_device_refresh_cb (GpmPhone *phone, guint idx, gpointer *data) +{ + g_debug ("idx refresh = %i", idx); + if (idx == 0 && GPOINTER_TO_UINT (data) == 44) + test_got_refresh = TRUE; +} + +void +gpm_phone_test (gpointer data) +{ + GpmPhone *phone; + guint value; + gboolean ret; + EggTest *test = (EggTest *) data; + + if (egg_test_start (test, "GpmPhone") == FALSE) + return; + + /************************************************************/ + egg_test_title (test, "make sure we get a non null phone"); + phone = gpm_phone_new (); + if (phone != NULL) + egg_test_success (test, "got GpmPhone"); + else + egg_test_failed (test, "could not get GpmPhone"); + + /* connect signals */ + g_signal_connect (phone, "device-refresh", + G_CALLBACK (phone_device_refresh_cb), GUINT_TO_POINTER(44)); + + /************************************************************/ + egg_test_title (test, "make sure we got a connection"); + if (phone->priv->proxy != NULL) { + egg_test_success (test, "got connection"); + } else { + /* skip this part of the test */ + egg_test_success (test, "could not get a connection!"); + goto out; + } + + /************************************************************/ + egg_test_title (test, "coldplug the data"); + ret = gpm_phone_coldplug (phone); + if (ret) { + egg_test_success (test, "coldplug okay"); + } else { + egg_test_failed (test, "could not coldplug"); + } + + egg_test_mainloop_wait (500); + + /************************************************************/ + egg_test_title (test, "got refresh"); + if (test_got_refresh) { + egg_test_success (test, NULL); + } else { + egg_test_failed (test, "did not get refresh"); + } + + /************************************************************/ + egg_test_title (test, "check the connected phones"); + value = gpm_phone_get_num_batteries (phone); + if (value == 1) { + egg_test_success (test, "connected phone"); + } else { + egg_test_failed (test, "not connected with %i (phone not connected?)", value); + } + + /************************************************************/ + egg_test_title (test, "check the present value"); + ret = gpm_phone_get_present (phone, 0); + if (ret) { + egg_test_success (test, "we are here!"); + } else { + egg_test_failed (test, "not here..."); + } + + /************************************************************/ + egg_test_title (test, "check the percentage"); + value = gpm_phone_get_percentage (phone, 0); + if (value != 0) { + egg_test_success (test, "percentage is %i", phone->priv->percentage); + } else { + egg_test_failed (test, "could not get value"); + } + + /************************************************************/ + egg_test_title (test, "check the ac value"); + ret = gpm_phone_get_on_ac (phone, 0); + if (!ret) { + egg_test_success (test, "not charging, correct"); + } else { + egg_test_failed (test, "charging?"); + } +out: + g_object_unref (phone); + + egg_test_end (test); +} + +#endif + |