Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

device_store.c

00001 /***************************************************************************
00002  * CVSID: $Id: device_store.c,v 1.19 2004/04/03 07:46:33 david Exp $
00003  *
00004  * device_store.c : HalDeviceStore methods
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  * Copyright (C) 2004 Novell, Inc.
00008  *
00009  * Licensed under the Academic Free License version 2.0
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  **************************************************************************/
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #  include <config.h>
00029 #endif
00030 
00031 #include <stdio.h>
00032 #include <string.h>
00033 
00034 #include "device_store.h"
00035 #include "hald_marshal.h"
00036 #include "logger.h"
00037 
00038 static GObjectClass *parent_class;
00039 
00040 enum {
00041     STORE_CHANGED,
00042     DEVICE_PROPERTY_CHANGED,
00043     DEVICE_CAPABILITY_ADDED,
00044     LAST_SIGNAL
00045 };
00046 
00047 static guint signals[LAST_SIGNAL] = { 0 };
00048 
00049 static void
00050 hal_device_store_finalize (GObject *obj)
00051 {
00052     HalDeviceStore *store = HAL_DEVICE_STORE (obj);
00053 
00054     g_slist_foreach (store->devices, (GFunc) g_object_unref, NULL);
00055 
00056     if (parent_class->finalize)
00057         parent_class->finalize (obj);
00058 }
00059 
00060 static void
00061 hal_device_store_class_init (HalDeviceStoreClass *klass)
00062 {
00063     GObjectClass *obj_class = (GObjectClass *) klass;
00064 
00065     parent_class = g_type_class_peek_parent (klass);
00066 
00067     obj_class->finalize = hal_device_store_finalize;
00068 
00069     signals[STORE_CHANGED] =
00070         g_signal_new ("store_changed",
00071                   G_TYPE_FROM_CLASS (klass),
00072                   G_SIGNAL_RUN_LAST,
00073                   G_STRUCT_OFFSET (HalDeviceStoreClass,
00074                            store_changed),
00075                   NULL, NULL,
00076                   hald_marshal_VOID__OBJECT_BOOL,
00077                   G_TYPE_NONE, 2,
00078                   G_TYPE_OBJECT,
00079                   G_TYPE_BOOLEAN);
00080 
00081     signals[DEVICE_PROPERTY_CHANGED] =
00082         g_signal_new ("device_property_changed",
00083                   G_TYPE_FROM_CLASS (klass),
00084                   G_SIGNAL_RUN_LAST,
00085                   G_STRUCT_OFFSET (HalDeviceStoreClass,
00086                            device_property_changed),
00087                   NULL, NULL,
00088                   hald_marshal_VOID__OBJECT_STRING_BOOL_BOOL,
00089                   G_TYPE_NONE, 4,
00090                   G_TYPE_OBJECT,
00091                   G_TYPE_STRING,
00092                   G_TYPE_BOOLEAN,
00093                   G_TYPE_BOOLEAN);
00094 
00095     signals[DEVICE_CAPABILITY_ADDED] =
00096         g_signal_new ("device_capability_added",
00097                   G_TYPE_FROM_CLASS (klass),
00098                   G_SIGNAL_RUN_LAST,
00099                   G_STRUCT_OFFSET (HalDeviceStoreClass,
00100                            device_capability_added),
00101                   NULL, NULL,
00102                   hald_marshal_VOID__OBJECT_STRING,
00103                   G_TYPE_NONE, 2,
00104                   G_TYPE_OBJECT,
00105                   G_TYPE_STRING);
00106 }
00107 
00108 static void
00109 hal_device_store_init (HalDeviceStore *device)
00110 {
00111 }
00112 
00113 GType
00114 hal_device_store_get_type (void)
00115 {
00116     static GType type = 0;
00117     
00118     if (!type) {
00119         static GTypeInfo type_info = {
00120             sizeof (HalDeviceStoreClass),
00121             NULL, NULL,
00122             (GClassInitFunc) hal_device_store_class_init,
00123             NULL, NULL,
00124             sizeof (HalDeviceStore),
00125             0,
00126             (GInstanceInitFunc) hal_device_store_init
00127         };
00128 
00129         type = g_type_register_static (G_TYPE_OBJECT,
00130                            "HalDeviceStore",
00131                            &type_info,
00132                            0);
00133     }
00134 
00135     return type;
00136 }
00137 
00138 HalDeviceStore *
00139 hal_device_store_new (void)
00140 {
00141     HalDeviceStore *store;
00142 
00143     store = g_object_new (HAL_TYPE_DEVICE_STORE, NULL);
00144 
00145     return store;
00146 }
00147 
00148 static void
00149 emit_device_property_changed (HalDevice *device,
00150                   const char *key,
00151                   gboolean added,
00152                   gboolean removed,
00153                   gpointer data)
00154 {
00155     HalDeviceStore *store = HAL_DEVICE_STORE (data);
00156 
00157     g_signal_emit (store, signals[DEVICE_PROPERTY_CHANGED], 0,
00158                device, key, added, removed);
00159 }
00160 
00161 static void
00162 emit_device_capability_added (HalDevice *device,
00163                   const char *capability,
00164                   gpointer data)
00165 {
00166     HalDeviceStore *store = HAL_DEVICE_STORE (data);
00167 
00168     g_signal_emit (store, signals[DEVICE_CAPABILITY_ADDED], 0,
00169                device, capability);
00170 }
00171 
00172 void
00173 hal_device_store_add (HalDeviceStore *store, HalDevice *device)
00174 {
00175     store->devices = g_slist_prepend (store->devices,
00176                       g_object_ref (device));
00177 
00178     g_signal_connect (device, "property_changed",
00179               G_CALLBACK (emit_device_property_changed), store);
00180     g_signal_connect (device, "capability_added",
00181               G_CALLBACK (emit_device_capability_added), store);
00182 
00183     g_signal_emit (store, signals[STORE_CHANGED], 0, device, TRUE);
00184 }
00185 
00186 gboolean
00187 hal_device_store_remove (HalDeviceStore *store, HalDevice *device)
00188 {
00189     if (!g_slist_find (store->devices, device))
00190         return FALSE;
00191 
00192     store->devices = g_slist_remove (store->devices, device);
00193 
00194     g_signal_handlers_disconnect_by_func (device,
00195                           emit_device_property_changed,
00196                           store);
00197     g_signal_handlers_disconnect_by_func (device,
00198                           emit_device_capability_added,
00199                           store);
00200 
00201     g_signal_emit (store, signals[STORE_CHANGED], 0, device, FALSE);
00202 
00203     g_object_unref (device);
00204 
00205     return TRUE;
00206 }
00207 
00208 HalDevice *
00209 hal_device_store_find (HalDeviceStore *store, const char *udi)
00210 {
00211     GSList *iter;
00212 
00213     for (iter = store->devices; iter != NULL; iter = iter->next) {
00214         HalDevice *d = iter->data;
00215 
00216         if (strcmp (hal_device_get_udi (d), udi) == 0)
00217             return d;
00218     }
00219 
00220     return NULL;
00221 }
00222 
00223 void
00224 hal_device_store_foreach (HalDeviceStore *store,
00225               HalDeviceStoreForeachFn callback,
00226               gpointer user_data)
00227 {
00228     GSList *iter;
00229 
00230     g_return_if_fail (store != NULL);
00231     g_return_if_fail (callback != NULL);
00232 
00233     for (iter = store->devices; iter != NULL; iter = iter->next) {
00234         HalDevice *d = HAL_DEVICE (iter->data);
00235         gboolean cont;
00236 
00237         cont = callback (store, d, user_data);
00238 
00239         if (cont == FALSE)
00240             return;
00241     }
00242 }
00243 
00244 HalDevice *
00245 hal_device_store_match_key_value_string (HalDeviceStore *store,
00246                      const char *key,
00247                      const char *value)
00248 {
00249     GSList *iter;
00250 
00251     g_return_val_if_fail (store != NULL, NULL);
00252     g_return_val_if_fail (key != NULL, NULL);
00253     g_return_val_if_fail (value != NULL, NULL);
00254 
00255     for (iter = store->devices; iter != NULL; iter = iter->next) {
00256         HalDevice *d = HAL_DEVICE (iter->data);
00257         int type;
00258 
00259         if (!hal_device_has_property (d, key))
00260             continue;
00261 
00262         type = hal_device_property_get_type (d, key);
00263         if (type != DBUS_TYPE_STRING)
00264             continue;
00265 
00266         if (strcmp (hal_device_property_get_string (d, key),
00267                 value) == 0)
00268             return d;
00269     }
00270 
00271     return NULL;
00272 }
00273 
00274 GSList *
00275 hal_device_store_match_multiple_key_value_string (HalDeviceStore *store,
00276                           const char *key,
00277                           const char *value)
00278 {
00279     GSList *iter;
00280     GSList *matches = NULL;
00281 
00282     g_return_val_if_fail (store != NULL, NULL);
00283     g_return_val_if_fail (key != NULL, NULL);
00284     g_return_val_if_fail (value != NULL, NULL);
00285 
00286     for (iter = store->devices; iter != NULL; iter = iter->next) {
00287         HalDevice *d = HAL_DEVICE (iter->data);
00288         int type;
00289 
00290         if (!hal_device_has_property (d, key))
00291             continue;
00292 
00293         type = hal_device_property_get_type (d, key);
00294         if (type != DBUS_TYPE_STRING)
00295             continue;
00296 
00297         if (strcmp (hal_device_property_get_string (d, key),
00298                 value) == 0)
00299             matches = g_slist_prepend (matches, d);
00300     }
00301 
00302     return matches;
00303 }
00304 
00305 typedef struct {
00306     HalDeviceStore *store;
00307     char *key;
00308     char *value;
00309     HalDeviceStoreAsyncCallback callback;
00310     gpointer user_data;
00311 
00312     guint prop_signal_id;
00313     guint store_signal_id;
00314     guint timeout_id;
00315 } AsyncMatchInfo;
00316 
00317 static void
00318 destroy_async_match_info (AsyncMatchInfo *info)
00319 {
00320     g_object_unref (info->store);
00321 
00322     g_free (info->key);
00323     g_free (info->value);
00324 
00325     g_signal_handler_disconnect (info->store, info->prop_signal_id);
00326     g_signal_handler_disconnect (info->store, info->store_signal_id);
00327     g_source_remove (info->timeout_id);
00328 
00329     g_free (info);
00330 }
00331 
00332 static void
00333 match_device_async (HalDeviceStore *store, HalDevice *device,
00334             const char *key, gboolean removed, gboolean added,
00335             gpointer user_data)
00336 {
00337     AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
00338 
00339     /* Only want to do it for added or changed properties */
00340     if (removed)
00341         return;
00342 
00343     /* Keys have to match */
00344     if (strcmp (info->key, key) != 0)
00345         return;
00346 
00347     /* Values have to match */
00348     if (strcmp (hal_device_property_get_string (device, key),
00349             info->value) != 0)
00350         return;
00351 
00352     info->callback (store, device, info->user_data);
00353 
00354     destroy_async_match_info (info);
00355 }
00356 
00357 static void
00358 store_changed (HalDeviceStore *store, HalDevice *device,
00359            gboolean added, gpointer user_data)
00360 {
00361     AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
00362 
00363     if (!added)
00364         return;
00365 
00366     if (!hal_device_has_property (device, info->key))
00367         return;
00368 
00369     if (strcmp (hal_device_property_get_string (device, info->key),
00370             info->value) != 0)
00371         return;
00372 
00373     info->callback (store, device, info->user_data);
00374 
00375     destroy_async_match_info (info);
00376 }
00377 
00378 static gboolean
00379 match_device_async_timeout (gpointer user_data)
00380 {
00381     AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;
00382 
00383     info->callback (info->store, NULL, info->user_data);
00384 
00385     destroy_async_match_info (info);
00386 
00387     return FALSE;
00388 }
00389 
00390 void
00391 hal_device_store_match_key_value_string_async (HalDeviceStore *store,
00392                            const char *key,
00393                            const char *value,
00394                            HalDeviceStoreAsyncCallback callback,
00395                            gpointer user_data,
00396                            int timeout)
00397 {
00398     HalDevice *device;
00399     AsyncMatchInfo *info;
00400 
00401     /* First check to see if it's already there */
00402     device = hal_device_store_match_key_value_string (store, key, value);
00403 
00404     if (device != NULL || timeout == 0) {
00405         callback (store, device, user_data);
00406 
00407         return;
00408     }
00409 
00410     info = g_new0 (AsyncMatchInfo, 1);
00411 
00412     info->store = g_object_ref (store);
00413     info->key = g_strdup (key);
00414     info->value = g_strdup (value);
00415     info->callback = callback;
00416     info->user_data = user_data;
00417 
00418     info->prop_signal_id = g_signal_connect (store,
00419                          "device_property_changed",
00420                          G_CALLBACK (match_device_async),
00421                          info);
00422     info->store_signal_id = g_signal_connect (store,
00423                           "store_changed",
00424                           G_CALLBACK (store_changed),
00425                           info);
00426 
00427     info->timeout_id = g_timeout_add (timeout, match_device_async_timeout,
00428                       info);
00429 }

Generated on Sat Apr 24 19:57:44 2004 for HAL by doxygen 1.3.6-20040222