Commit f93d8cbc authored by Bastien Nocera's avatar Bastien Nocera Committed by Daniel Drake

Clean up device when the client disconnects

Track clients connected to each device using EggDbusMonitor.
When there are no more clients connected to the device, release it.

When no devices are used anymore, set up a timeout to exit within
30 seconds.
parent b0f20606
......@@ -6,7 +6,7 @@ EXTRA_DIST = fprintd.xml
libexec_PROGRAMS = fprintd
fprintd_SOURCES = main.c manager.c device.c file_storage.c
fprintd_SOURCES = main.c manager.c device.c file_storage.c egg-dbus-monitor.c egg-dbus-monitor.h
fprintd_LDADD = $(FPRINT_LIBS) $(DAEMON_LIBS)
fprintd_CFLAGS = $(WARN_CFLAGS) $(FPRINT_CFLAGS) $(DAEMON_CFLAGS) -DLOCALEDIR=\""$(datadir)/locale"\" -DPLUGINDIR=\""$(libdir)/fprintd/modules"\"
......
......@@ -31,6 +31,7 @@
#include "fprintd.h"
#include "storage.h"
#include "egg-dbus-monitor.h"
extern DBusGConnection *fprintd_dbus_conn;
......@@ -92,6 +93,9 @@ struct FprintDevicePrivate {
/* type of storage */
int storage_type;
/* Hashtable of connected clients */
GHashTable *clients;
/* whether we're running an identify, or a verify */
FprintDeviceAction current_action;
};
......@@ -102,7 +106,7 @@ typedef struct FprintDevicePrivate FprintDevicePrivate;
enum fprint_device_properties {
FPRINT_DEVICE_CONSTRUCT_DDEV = 1,
FPRINT_DEVICE_ACTION,
FPRINT_DEVICE_IN_USE,
};
enum fprint_device_signals {
......@@ -118,6 +122,10 @@ static guint signals[NUM_SIGNALS] = { 0, };
static void fprint_device_finalize(GObject *object)
{
FprintDevice *self = (FprintDevice *) object;
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self);
g_hash_table_destroy (priv->clients);
/* FIXME close and stuff */
}
......@@ -144,8 +152,8 @@ static void fprint_device_get_property(GObject *object, guint property_id,
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self);
switch (property_id) {
case FPRINT_DEVICE_ACTION:
g_value_set_int(value, priv->current_action);
case FPRINT_DEVICE_IN_USE:
g_value_set_boolean(value, g_hash_table_size (priv->clients) != 0);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
......@@ -153,17 +161,6 @@ static void fprint_device_get_property(GObject *object, guint property_id,
}
}
static void fprint_device_set_action(FprintDevice *device, FprintDeviceAction action)
{
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(device);
if (priv->current_action == action)
return;
priv->current_action = action;
g_object_notify (G_OBJECT(device), "action");
}
static void fprint_device_class_init(FprintDeviceClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
......@@ -183,11 +180,11 @@ static void fprint_device_class_init(FprintDeviceClass *klass)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property(gobject_class,
FPRINT_DEVICE_CONSTRUCT_DDEV, pspec);
pspec = g_param_spec_int("action", "Current device action",
"The current device action", ACTION_NONE, ACTION_ENROLL,
ACTION_NONE, G_PARAM_READABLE);
pspec = g_param_spec_boolean("in-use", "In use",
"Whether the device is currently in use", FALSE,
G_PARAM_READABLE);
g_object_class_install_property(gobject_class,
FPRINT_DEVICE_ACTION, pspec);
FPRINT_DEVICE_IN_USE, pspec);
signals[SIGNAL_VERIFY_STATUS] = g_signal_new("verify-status",
G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
......@@ -247,6 +244,10 @@ static void fprint_device_init(FprintDevice *device)
polkit_context_unref (priv->pol_ctx);
priv->pol_ctx = NULL;
}
priv->clients = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
g_object_unref);
}
G_DEFINE_TYPE(FprintDevice, fprint_device, G_TYPE_OBJECT);
......@@ -414,6 +415,82 @@ _fprint_device_check_for_username (FprintDevice *rdev,
return g_strdup (username);
}
static void action_stop_cb(struct fp_dev *dev, void *user_data)
{
gboolean *done = (gboolean *) user_data;
*done = TRUE;
}
static void
_fprint_device_client_disconnected (EggDbusMonitor *monitor, gboolean connected, FprintDevice *rdev)
{
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
if (connected == FALSE) {
const char *sender;
sender = egg_dbus_monitor_get_service (monitor);
/* Was that the client that claimed the device? */
if (priv->sender != NULL) {
gboolean done = FALSE;
switch (priv->current_action) {
case ACTION_NONE:
break;
case ACTION_IDENTIFY:
fp_async_identify_stop(priv->dev, action_stop_cb, &done);
while (done == FALSE)
g_main_context_iteration (NULL, TRUE);
break;
case ACTION_VERIFY:
fp_async_verify_stop(priv->dev, action_stop_cb, &done);
while (done == FALSE)
g_main_context_iteration (NULL, TRUE);
break;
case ACTION_ENROLL:
fp_async_enroll_stop(priv->dev, action_stop_cb, &done);
while (done == FALSE)
g_main_context_iteration (NULL, TRUE);
break;
}
priv->current_action = ACTION_NONE;
done = FALSE;
/* Close the claimed device as well */
fp_async_dev_close (priv->dev, action_stop_cb, &done);
while (done == FALSE)
g_main_context_iteration (NULL, TRUE);
g_free (priv->sender);
priv->sender = NULL;
g_free (priv->username);
priv->username = NULL;
}
g_hash_table_remove (priv->clients, sender);
}
if (g_hash_table_size (priv->clients) == 0) {
g_object_notify (G_OBJECT (rdev), "in-use");
}
}
static void
_fprint_device_add_client (FprintDevice *rdev, const char *sender)
{
EggDbusMonitor *monitor;
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
monitor = g_hash_table_lookup (priv->clients, sender);
if (monitor == NULL) {
monitor = egg_dbus_monitor_new ();
egg_dbus_monitor_assign (monitor, fprintd_dbus_conn, sender);
//FIXME handle replaced
g_signal_connect (G_OBJECT (monitor), "connection-changed",
G_CALLBACK (_fprint_device_client_disconnected), rdev);
g_hash_table_insert (priv->clients, g_strdup (sender), monitor);
g_object_notify (G_OBJECT (rdev), "in-use");
}
}
static void dev_open_cb(struct fp_dev *dev, int status, void *user_data)
{
FprintDevice *rdev = user_data;
......@@ -481,6 +558,8 @@ static void fprint_device_claim(FprintDevice *rdev,
return;
}
_fprint_device_add_client (rdev, sender);
priv->username = user;
priv->sender = sender;
......@@ -493,6 +572,12 @@ static void fprint_device_claim(FprintDevice *rdev,
if (r < 0) {
g_slice_free(struct session_data, priv->session);
priv->session = NULL;
g_free (priv->username);
priv->username = NULL;
g_free (priv->sender);
priv->sender = NULL;
g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
"Could not attempt device open, error %d", r);
dbus_g_method_return_error(context, error);
......@@ -543,10 +628,6 @@ static void fprint_device_release(FprintDevice *rdev,
session->context_release_device = context;
fp_async_dev_close(priv->dev, dev_close_cb, rdev);
g_free (priv->sender);
priv->sender = NULL;
g_free (priv->username);
priv->username = NULL;
}
static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img,
......@@ -642,17 +723,19 @@ static void fprint_device_verify_start(FprintDevice *rdev,
if (fp_dev_supports_identification(priv->dev) && finger_num == -1) {
if (gallery == NULL) {
//FIXME exit
g_message ("NO GALLERY");
g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
"No fingerprints on that device");
dbus_g_method_return_error(context, error);
g_error_free (error);
return;
}
fprint_device_set_action (rdev, ACTION_IDENTIFY);
priv->current_action = ACTION_IDENTIFY;
g_message ("start identification device %d", priv->id);
//FIXME we're supposed to free the gallery here?
r = fp_async_identify_start (priv->dev, gallery, identify_cb, rdev);
} else {
fprint_device_set_action (rdev, ACTION_VERIFY);
priv->current_action = ACTION_VERIFY;
g_message("start verification device %d finger %d", priv->id, finger_num);
......@@ -739,7 +822,7 @@ static void fprint_device_verify_stop(FprintDevice *rdev,
g_error_free (error);
}
fprint_device_set_action (rdev, ACTION_NONE);
priv->current_action = ACTION_NONE;
}
static void enroll_stage_cb(struct fp_dev *dev, int result,
......@@ -804,7 +887,7 @@ static void fprint_device_enroll_start(FprintDevice *rdev,
return;
}
fprint_device_set_action (rdev, ACTION_ENROLL);
priv->current_action = ACTION_ENROLL;
dbus_g_method_return(context);
}
......@@ -847,7 +930,7 @@ static void fprint_device_enroll_stop(FprintDevice *rdev,
g_error_free (error);
}
fprint_device_set_action (rdev, ACTION_NONE);
priv->current_action = ACTION_NONE;
}
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev,
......@@ -859,7 +942,7 @@ static void fprint_device_list_enrolled_fingers(FprintDevice *rdev,
GSList *prints;
GSList *item;
GArray *ret;
char *user;
char *user, *sender;
user = _fprint_device_check_for_username (rdev,
context,
......@@ -878,6 +961,10 @@ static void fprint_device_list_enrolled_fingers(FprintDevice *rdev,
return;
}
sender = dbus_g_method_get_sender (context);
_fprint_device_add_client (rdev, sender);
g_free (sender);
prints = store.discover_prints(priv->ddev, user);
g_free (user);
if (!prints) {
......@@ -904,7 +991,7 @@ static void fprint_device_delete_enrolled_fingers(FprintDevice *rdev,
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
GError *error = NULL;
guint i;
char *user;
char *user, *sender;
user = _fprint_device_check_for_username (rdev,
context,
......@@ -923,6 +1010,10 @@ static void fprint_device_delete_enrolled_fingers(FprintDevice *rdev,
return;
}
sender = dbus_g_method_get_sender (context);
_fprint_device_add_client (rdev, sender);
g_free (sender);
for (i = LEFT_THUMB; i <= RIGHT_LITTLE; i++) {
store.print_data_delete(priv->ddev, i, user);
}
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2006-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <dbus/dbus.h>
#include "egg-dbus-monitor.h"
static void egg_dbus_monitor_class_init (EggDbusMonitorClass *klass);
static void egg_dbus_monitor_init (EggDbusMonitor *dbus_monitor);
static void egg_dbus_monitor_finalize (GObject *object);
#define EGG_DBUS_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_DBUS_MONITOR, EggDbusMonitorPrivate))
struct EggDbusMonitorPrivate
{
gchar *service;
DBusGProxy *proxy;
DBusGConnection *connection;
const gchar *unique_name;
};
enum {
EGG_DBUS_MONITOR_CONNECTION_CHANGED,
EGG_DBUS_MONITOR_CONNECTION_REPLACED,
EGG_DBUS_MONITOR_LAST_SIGNAL
};
static guint signals [EGG_DBUS_MONITOR_LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (EggDbusMonitor, egg_dbus_monitor, G_TYPE_OBJECT)
/**
* egg_dbus_monitor_name_owner_changed_cb:
**/
static void
egg_dbus_monitor_name_owner_changed_cb (DBusGProxy *proxy, const gchar *name,
const gchar *prev, const gchar *new,
EggDbusMonitor *monitor)
{
guint new_len;
guint prev_len;
g_return_if_fail (EGG_IS_DBUS_MONITOR (monitor));
if (monitor->priv->proxy == NULL)
return;
/* not us */
if (strcmp (name, monitor->priv->service) != 0)
return;
/* ITS4: ignore, not used for allocation */
new_len = strlen (new);
/* ITS4: ignore, not used for allocation */
prev_len = strlen (prev);
/* something --> nothing */
if (prev_len != 0 && new_len == 0) {
g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED], 0, FALSE);
return;
}
/* nothing --> something */
if (prev_len == 0 && new_len != 0) {
g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED], 0, TRUE);
return;
}
/* something --> something (we've replaced the old process) */
if (prev_len != 0 && new_len != 0) {
/* only send this to the prev client */
if (strcmp (monitor->priv->unique_name, prev) == 0)
g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_REPLACED], 0);
return;
}
}
/**
* egg_dbus_monitor_assign:
* @monitor: This class instance
* @connection: The bus connection
* @service: The EGG_DBUS_MONITOR service name
* Return value: success
*
* Emits connection-changed(TRUE) if connection is alive - this means you
* have to connect up the callback before this function is called.
**/
gboolean
egg_dbus_monitor_assign (EggDbusMonitor *monitor, DBusGConnection *connection, const gchar *service)
{
GError *error = NULL;
gboolean connected;
DBusConnection *conn;
g_return_val_if_fail (EGG_IS_DBUS_MONITOR (monitor), FALSE);
g_return_val_if_fail (service != NULL, FALSE);
g_return_val_if_fail (connection != NULL, FALSE);
if (monitor->priv->proxy != NULL) {
g_warning ("already assigned!");
return FALSE;
}
monitor->priv->service = g_strdup (service);
monitor->priv->connection = connection;
monitor->priv->proxy = dbus_g_proxy_new_for_name_owner (monitor->priv->connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
&error);
if (error != NULL) {
g_warning ("Cannot connect to DBUS: %s", error->message);
g_error_free (error);
return FALSE;
}
dbus_g_proxy_add_signal (monitor->priv->proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (monitor->priv->proxy, "NameOwnerChanged",
G_CALLBACK (egg_dbus_monitor_name_owner_changed_cb),
monitor, NULL);
/* coldplug */
connected = egg_dbus_monitor_is_connected (monitor);
if (connected)
g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED], 0, TRUE);
/* save this for the replaced check */
conn = dbus_g_connection_get_connection (monitor->priv->connection);
monitor->priv->unique_name = dbus_bus_get_unique_name (conn);
return TRUE;
}
/**
* egg_dbus_monitor_is_connected:
* @monitor: This class instance
* Return value: if we are connected to a valid watch
**/
gboolean
egg_dbus_monitor_is_connected (EggDbusMonitor *monitor)
{
DBusError error;
DBusConnection *conn;
gboolean ret;
g_return_val_if_fail (EGG_IS_DBUS_MONITOR (monitor), FALSE);
/* get raw connection */
conn = dbus_g_connection_get_connection (monitor->priv->connection);
dbus_error_init (&error);
ret = dbus_bus_name_has_owner (conn, monitor->priv->service, &error);
if (dbus_error_is_set (&error)) {
g_debug ("error: %s", error.message);
dbus_error_free (&error);
}
return ret;
}
/**
* egg_dbus_monitor_get_service:
* @monitor: This class instance
* Return value: the service name being monitored
**/
const gchar *
egg_dbus_monitor_get_service (EggDbusMonitor *monitor)
{
g_return_val_if_fail (EGG_IS_DBUS_MONITOR (monitor), FALSE);
return monitor->priv->service;
}
/**
* egg_dbus_monitor_class_init:
* @klass: The EggDbusMonitorClass
**/
static void
egg_dbus_monitor_class_init (EggDbusMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = egg_dbus_monitor_finalize;
g_type_class_add_private (klass, sizeof (EggDbusMonitorPrivate));
signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED] =
g_signal_new ("connection-changed",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggDbusMonitorClass, connection_changed),
NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
signals [EGG_DBUS_MONITOR_CONNECTION_REPLACED] =
g_signal_new ("connection-replaced",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggDbusMonitorClass, connection_replaced),
NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
/**
* egg_dbus_monitor_init:
* @monitor: This class instance
**/
static void
egg_dbus_monitor_init (EggDbusMonitor *monitor)
{
monitor->priv = EGG_DBUS_MONITOR_GET_PRIVATE (monitor);
monitor->priv->service = NULL;
monitor->priv->connection = NULL;
monitor->priv->proxy = NULL;
}
/**
* egg_dbus_monitor_finalize:
* @object: The object to finalize
**/
static void
egg_dbus_monitor_finalize (GObject *object)
{
EggDbusMonitor *monitor;
g_return_if_fail (EGG_IS_DBUS_MONITOR (object));
monitor = EGG_DBUS_MONITOR (object);
g_return_if_fail (monitor->priv != NULL);
if (monitor->priv->proxy != NULL)
g_object_unref (monitor->priv->proxy);
G_OBJECT_CLASS (egg_dbus_monitor_parent_class)->finalize (object);
}
/**
* egg_dbus_monitor_new:
*
* Return value: a new EggDbusMonitor object.
**/
EggDbusMonitor *
egg_dbus_monitor_new (void)
{
EggDbusMonitor *monitor;
monitor = g_object_new (EGG_TYPE_DBUS_MONITOR, NULL);
return EGG_DBUS_MONITOR (monitor);
}
/* -*- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __EGG_DBUS_MONITOR_H
#define __EGG_DBUS_MONITOR_H
#include <glib-object.h>
#include <dbus/dbus-glib.h>
G_BEGIN_DECLS
#define EGG_TYPE_DBUS_MONITOR (egg_dbus_monitor_get_type ())
#define EGG_DBUS_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_DBUS_MONITOR, EggDbusMonitor))
#define EGG_DBUS_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EGG_TYPE_DBUS_MONITOR, EggDbusMonitorClass))
#define EGG_IS_DBUS_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_DBUS_MONITOR))
#define EGG_IS_DBUS_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_DBUS_MONITOR))
#define EGG_DBUS_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_DBUS_MONITOR, EggDbusMonitorClass))
#define EGG_DBUS_MONITOR_ERROR (egg_dbus_monitor_error_quark ())
#define EGG_DBUS_MONITOR_TYPE_ERROR (egg_dbus_monitor_error_get_type ())
typedef struct EggDbusMonitorPrivate EggDbusMonitorPrivate;
typedef struct
{
GObject parent;
EggDbusMonitorPrivate *priv;
} EggDbusMonitor;
typedef struct
{
GObjectClass parent_class;
void (* connection_changed) (EggDbusMonitor *watch,
gboolean connected);
void (* connection_replaced) (EggDbusMonitor *watch);
} EggDbusMonitorClass;
GType egg_dbus_monitor_get_type (void) G_GNUC_CONST;
EggDbusMonitor *egg_dbus_monitor_new (void);
gboolean egg_dbus_monitor_assign (EggDbusMonitor *monitor,
DBusGConnection *connection,
const gchar *service);
const gchar *egg_dbus_monitor_get_service (EggDbusMonitor *monitor);
gboolean egg_dbus_monitor_is_connected (EggDbusMonitor *monitor);
G_END_DECLS
#endif /* __EGG_DBUS_MONITOR_H */
......@@ -41,7 +41,6 @@ typedef struct
GError *last_error;
GSList *dev_registry;
guint timeout_id;
volatile int num_device_used;
} FprintManagerPrivate;
#define FPRINT_MANAGER_GET_PRIVATE(o) \
......@@ -81,27 +80,32 @@ fprint_manager_timeout_cb (FprintManager *manager)
g_message ("No devices in use, exit");
//FIXME kill all the devices
exit(0);
return FALSE;
}
static void
fprint_manager_action_notified (FprintDevice *rdev, GParamSpec *spec, FprintManager *manager)
fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintManager *manager)
{
FprintManagerPrivate *priv = FPRINT_MANAGER_GET_PRIVATE (manager);
int action;
guint num_devices_used = 0;
GSList *l;
gboolean in_use;
g_object_get (G_OBJECT(rdev), "action", &action, NULL);
if (priv->timeout_id > 0) {
g_source_remove (priv->timeout_id);
priv->timeout_id = 0;
}
if (action == 0) {
if (g_atomic_int_dec_and_test (&priv->num_device_used)) {
if (!no_timeout)
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
}
} else {
g_atomic_int_add (&priv->num_device_used, 1);
for (l = priv->dev_registry; l != NULL; l = l->next) {
FprintDevice *dev = l->data;
g_object_get (G_OBJECT(dev), "in-use", &in_use, NULL);
if (in_use != FALSE)
num_devices_used++;
}
if (num_devices_used == 0 && !no_timeout)
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
}
static void
......@@ -112,8 +116,6 @@ fprint_manager_init (FprintManager *manager)
struct fp_dscv_dev *ddev;
int i = 0;
priv->num_device_used = 0;
if (!discovered_devs) {
priv->last_error = g_error_new (FPRINT_ERROR, FPRINT_ERROR_INTERNAL,
_("An internal error occurred in libfprint"));
......@@ -127,8 +129,8 @@ fprint_manager_init (FprintManager *manager)
FprintDevice *rdev = fprint_device_new(ddev);
gchar *path;
g_signal_connect (G_OBJECT(rdev), "notify::action",
G_CALLBACK (fprint_manager_action_notified), manager);
g_signal_connect (G_OBJECT(rdev), "notify::in-use",
G_CALLBACK (fprint_manager_in_use_notified), manager);
priv->dev_registry = g_slist_prepend(priv->dev_registry, rdev);
path = get_device_path(rdev);
......
......@@ -148,6 +148,7 @@ static DBusGProxy *open_device(const char *username)
if (!net_reactivated_Fprint_Device_claim(dev, username, &error))
g_error("failed to claim device: %s", error->message);
return dev;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment