Index: src/tracker-indexer/tracker-indexer.c =================================================================== --- src/tracker-indexer/tracker-indexer.c (revision 3160) +++ src/tracker-indexer/tracker-indexer.c (working copy) @@ -56,7 +56,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -132,7 +133,8 @@ TrackerConfig *config; TrackerLanguage *language; - TrackerHal *hal; + TrackerPower *hal_power; + TrackerStorage *hal_storage; GTimer *timer; @@ -454,7 +456,7 @@ */ throttle = tracker_config_get_throttle (indexer->private->config); - if (tracker_hal_get_battery_in_use (indexer->private->hal)) { + if (tracker_power_get_battery_in_use (indexer->private->hal_power)) { g_message ("We are running on battery"); if (throttle == THROTTLE_DEFAULT) { @@ -619,11 +621,12 @@ } #ifdef HAVE_HAL - g_signal_handlers_disconnect_by_func (priv->hal, + g_signal_handlers_disconnect_by_func (priv->hal_power, notify_battery_in_use_cb, TRACKER_INDEXER (object)); - g_object_unref (priv->hal); + g_object_unref (priv->hal_power); + g_object_unref (priv->hal_storage); #endif /* HAVE_HAL */ g_object_unref (priv->language); @@ -1013,9 +1016,10 @@ priv->config = tracker_config_new (); #ifdef HAVE_HAL - priv->hal = tracker_hal_new (); + priv->hal_power = tracker_power_new (); + priv->hal_storage = tracker_storage_new (); - g_signal_connect (priv->hal, "notify::battery-in-use", + g_signal_connect (priv->hal_power, "notify::battery-in-use", G_CALLBACK (notify_battery_in_use_cb), indexer); @@ -1679,10 +1683,10 @@ basename, NULL); - if (tracker_hal_path_is_on_removable_device (indexer->private->hal, - service_path, - &mount_point, - NULL)) { + if (tracker_storage_path_is_on_removable_device (indexer->private->hal_storage, + service_path, + &mount_point, + NULL)) { tracker_removable_device_add_metadata (indexer, mount_point, @@ -1759,12 +1763,12 @@ path = g_file_get_path (file); source_path = g_file_get_path (source_file); - if (tracker_hal_path_is_on_removable_device (indexer->private->hal, - source_path, - &mount_point, - NULL) ) { + if (tracker_storage_path_is_on_removable_device (indexer->private->hal_storage, + source_path, + &mount_point, + NULL) ) { - if (tracker_hal_path_is_on_removable_device (indexer->private->hal, + if (tracker_storage_path_is_on_removable_device (indexer->private->hal_storage, path, NULL, NULL) ) { @@ -2103,10 +2107,10 @@ g_hash_table_destroy (children); } - if (tracker_hal_path_is_on_removable_device (indexer->private->hal, - path, - &mount_point, - NULL)) { + if (tracker_storage_path_is_on_removable_device (indexer->private->hal_storage, + path, + &mount_point, + NULL)) { tracker_removable_device_add_removal (indexer, mount_point, path, Index: src/trackerd/tracker-processor.c =================================================================== --- src/trackerd/tracker-processor.c (revision 3160) +++ src/trackerd/tracker-processor.c (working copy) @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -58,7 +58,7 @@ struct TrackerProcessorPrivate { TrackerConfig *config; - TrackerHal *hal; + TrackerStorage *hal; TrackerMonitor *monitor; DBusGProxy *indexer_proxy; @@ -165,11 +165,11 @@ gpointer user_data); #ifdef HAVE_HAL -static void mount_point_added_cb (TrackerHal *hal, +static void mount_point_added_cb (TrackerStorage *hal, const gchar *volume_uuid, const gchar *mount_point, gpointer user_data); -static void mount_point_removed_cb (TrackerHal *hal, +static void mount_point_removed_cb (TrackerStorage *hal, const gchar *volume_uuid, const gchar *mount_point, gpointer user_data); @@ -360,8 +360,8 @@ GList *l2; #ifdef HAVE_HAL - l1 = tracker_hal_get_mounted_directory_roots (processor->private->hal); - l2 = tracker_hal_get_removable_device_roots (processor->private->hal); + l1 = tracker_storage_get_mounted_directory_roots (processor->private->hal); + l2 = tracker_storage_get_removable_device_roots (processor->private->hal); #else /* HAVE_HAL */ l1 = NULL; l2 = NULL; @@ -1519,10 +1519,10 @@ #ifdef HAVE_HAL static void -mount_point_added_cb (TrackerHal *hal, - const gchar *udi, - const gchar *mount_point, - gpointer user_data) +mount_point_added_cb (TrackerStorage *hal, + const gchar *udi, + const gchar *mount_point, + gpointer user_data) { TrackerProcessor *processor; TrackerProcessorPrivate *priv; @@ -1567,10 +1567,10 @@ } static void -mount_point_removed_cb (TrackerHal *hal, - const gchar *udi, - const gchar *mount_point, - gpointer user_data) +mount_point_removed_cb (TrackerStorage *hal, + const gchar *udi, + const gchar *mount_point, + gpointer user_data) { TrackerProcessor *processor; TrackerProcessorPrivate *priv; @@ -1614,8 +1614,8 @@ #endif /* HAVE_HAL */ TrackerProcessor * -tracker_processor_new (TrackerConfig *config, - TrackerHal *hal) +tracker_processor_new (TrackerConfig *config, + TrackerStorage *hal) { TrackerProcessor *processor; TrackerProcessorPrivate *priv; @@ -1626,7 +1626,7 @@ g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); #ifdef HAVE_HAL - g_return_val_if_fail (TRACKER_IS_HAL (hal), NULL); + g_return_val_if_fail (TRACKER_IS_STORAGE (hal), NULL); #endif /* HAVE_HAL */ tracker_status_set_and_signal (TRACKER_STATUS_INITIALIZING); @@ -1641,7 +1641,7 @@ /* Set up hal */ priv->hal = g_object_ref (hal); - priv->removable_devices = tracker_hal_get_removable_device_roots (priv->hal); + priv->removable_devices = tracker_storage_get_removable_device_roots (priv->hal); priv->removable_devices_current = priv->removable_devices; priv->removable_devices_completed = NULL; Index: src/trackerd/tracker-processor.h =================================================================== --- src/trackerd/tracker-processor.h (revision 3160) +++ src/trackerd/tracker-processor.h (working copy) @@ -25,7 +25,7 @@ #include #include -#include +#include G_BEGIN_DECLS @@ -54,7 +54,7 @@ GType tracker_processor_get_type (void) G_GNUC_CONST; TrackerProcessor *tracker_processor_new (TrackerConfig *config, - TrackerHal *hal); + TrackerStorage *hal); void tracker_processor_start (TrackerProcessor *processor); void tracker_processor_stop (TrackerProcessor *processor); Index: src/trackerd/tracker-main.c =================================================================== --- src/trackerd/tracker-main.c (revision 3160) +++ src/trackerd/tracker-main.c (working copy) @@ -42,7 +42,8 @@ #include #include -#include +#include +#include #include #include #include @@ -224,8 +225,8 @@ } static TrackerRunningLevel -check_runtime_level (TrackerConfig *config, - TrackerHal *hal) +check_runtime_level (TrackerConfig *config, + TrackerPower *hal) { TrackerRunningLevel runlevel; gchar *lock_file; @@ -274,8 +275,8 @@ runlevel = TRACKER_RUNNING_MAIN_INSTANCE; #ifdef HAVE_HAL - if (!tracker_hal_get_battery_exists (hal) || - !tracker_hal_get_battery_in_use (hal)) { + if (!tracker_power_get_battery_exists (hal) || + !tracker_power_get_battery_in_use (hal)) { return TRACKER_RUNNING_MAIN_INSTANCE; } @@ -328,10 +329,10 @@ } static void -mount_point_added_cb (TrackerHal *hal, - const gchar *udi, - const gchar *mount_point, - gpointer user_data) +mount_point_added_cb (TrackerStorage *hal, + const gchar *udi, + const gchar *mount_point, + gpointer user_data) { TrackerMainPrivate *private; @@ -376,10 +377,10 @@ } static void -mount_point_removed_cb (TrackerHal *hal, - const gchar *udi, - const gchar *mount_point, - gpointer user_data) +mount_point_removed_cb (TrackerStorage *hal, + const gchar *udi, + const gchar *mount_point, + gpointer user_data) { TrackerMainPrivate *private; @@ -767,7 +768,7 @@ GError *error, gpointer user_data) { - TrackerHal *hal; + TrackerStorage *hal; GList *roots, *l; if (error) { @@ -780,7 +781,7 @@ g_message ("Indexer is being notified about ALL UDIs"); hal = user_data; - roots = tracker_hal_get_removable_device_udis (hal); + roots = tracker_storage_get_removable_device_udis (hal); for (l = roots; l; l = l->next) { gchar *udi; @@ -788,8 +789,8 @@ gboolean is_mounted; udi = l->data; - mount_point = tracker_hal_udi_get_mount_point (hal, udi); - is_mounted = tracker_hal_udi_get_is_mounted (hal, udi); + mount_point = tracker_storage_udi_get_mount_point (hal, udi); + is_mounted = tracker_storage_udi_get_is_mounted (hal, udi); g_message (" %s", udi); @@ -805,7 +806,7 @@ } static void -set_up_mount_points (TrackerHal *hal) +set_up_mount_points (TrackerStorage *hal) { g_message ("Indexer is being notified to disable all volumes"); org_freedesktop_Tracker_Indexer_volume_disable_all_async (tracker_dbus_indexer_get_proxy (), @@ -841,7 +842,8 @@ TrackerMainPrivate *private; TrackerConfig *config; TrackerLanguage *language; - TrackerHal *hal; + TrackerPower *hal_power; + TrackerStorage *hal_storage; TrackerDBIndex *file_index; TrackerDBIndex *email_index; TrackerRunningLevel runtime_level; @@ -969,17 +971,18 @@ tracker_nfs_lock_init (tracker_config_get_nfs_locking (config)); #ifdef HAVE_HAL - hal = tracker_hal_new (); + hal_power = tracker_power_new (); + hal_storage = tracker_storage_new (); - g_signal_connect (hal, "mount-point-added", + g_signal_connect (hal_storage, "mount-point-added", G_CALLBACK (mount_point_added_cb), NULL); - g_signal_connect (hal, "mount-point-removed", + g_signal_connect (hal_storage, "mount-point-removed", G_CALLBACK (mount_point_removed_cb), NULL); #endif /* HAVE_HAL */ - tracker_status_init (config, hal); + tracker_status_init (config, hal_power); tracker_module_config_init (); @@ -1012,7 +1015,7 @@ /* * Check instances running */ - runtime_level = check_runtime_level (config, hal); + runtime_level = check_runtime_level (config, hal_power); switch (runtime_level) { case TRACKER_RUNNING_NON_ALLOWED: @@ -1051,10 +1054,10 @@ * we have to have already initialised the databases if we * are going to do that. */ - set_up_mount_points (hal); + set_up_mount_points (hal_storage); #endif /* HAVE_HAL */ - private->processor = tracker_processor_new (config, hal); + private->processor = tracker_processor_new (config, hal_storage); /* Make Tracker available for introspection */ if (!tracker_dbus_register_objects (config, @@ -1143,14 +1146,15 @@ tracker_log_shutdown (); #ifdef HAVE_HAL - g_signal_handlers_disconnect_by_func (hal, + g_signal_handlers_disconnect_by_func (hal_storage, mount_point_added_cb, NULL); - g_signal_handlers_disconnect_by_func (hal, + g_signal_handlers_disconnect_by_func (hal_storage, mount_point_removed_cb, NULL); - g_object_unref (hal); + g_object_unref (hal_power); + g_object_unref (hal_storage); #endif /* HAVE_HAL */ g_object_unref (language); Index: src/trackerd/tracker-status.c =================================================================== --- src/trackerd/tracker-status.c (revision 3160) +++ src/trackerd/tracker-status.c (working copy) @@ -42,7 +42,7 @@ guint disk_space_check_id; TrackerConfig *config; - TrackerHal *hal; + TrackerPower *hal; DBusGProxy *indexer_proxy; @@ -355,7 +355,7 @@ */ throttle = tracker_config_get_throttle (private->config); - if (tracker_hal_get_battery_in_use (private->hal)) { + if (tracker_power_get_battery_in_use (private->hal)) { if (debugging) { g_message ("We are running on battery"); } @@ -418,8 +418,8 @@ private = g_static_private_get (&private_key); g_return_if_fail (private != NULL); - percentage = tracker_hal_get_battery_percentage (private->hal); - battery_in_use = tracker_hal_get_battery_in_use (private->hal); + percentage = tracker_power_get_battery_percentage (private->hal); + battery_in_use = tracker_power_get_battery_in_use (private->hal); g_message ("Battery percentage is now %.0f%%", percentage * 100); @@ -443,7 +443,7 @@ gboolean tracker_status_init (TrackerConfig *config, - TrackerHal *hal) + TrackerPower *hal) { GType type; DBusGProxy *proxy; Index: src/trackerd/tracker-status.h =================================================================== --- src/trackerd/tracker-status.h (revision 3160) +++ src/trackerd/tracker-status.h (working copy) @@ -25,7 +25,7 @@ #include #include -#include +#include G_BEGIN_DECLS @@ -44,7 +44,7 @@ gboolean tracker_status_init (TrackerConfig *config, - TrackerHal *hal); + TrackerPower *hal); void tracker_status_shutdown (void); GType tracker_status_get_type (void) G_GNUC_CONST; Index: src/libtracker-common/tracker-albumart.c =================================================================== --- src/libtracker-common/tracker-albumart.c (revision 3160) +++ src/libtracker-common/tracker-albumart.c (working copy) @@ -255,7 +255,7 @@ tracker_albumart_copy_to_local (const gchar *filename, const gchar *local_uri) { #ifdef HAVE_HAL - TrackerHal *hal; + TrackerStorage *hal; #endif GList *removable_roots, *l; gboolean on_removable_device = FALSE; @@ -272,8 +272,8 @@ /* Determining if we are on a removable device */ #ifdef HAVE_HAL - hal = tracker_hal_new (); - removable_roots = tracker_hal_get_removable_device_roots (hal); + hal = tracker_storage_new (); + removable_roots = tracker_storage_get_removable_device_roots (hal); g_object_unref (hal); #else removable_roots = g_list_append (removable_roots, "/media"); Index: src/libtracker-common/tracker-common.h =================================================================== --- src/libtracker-common/tracker-common.h (revision 3160) +++ src/libtracker-common/tracker-common.h (working copy) @@ -35,7 +35,8 @@ #include "tracker-config.h" #include "tracker-field.h" #include "tracker-file-utils.h" -#include "tracker-hal.h" +#include "tracker-power.h" +#include "tracker-storage.h" #include "tracker-language.h" #include "tracker-module-config.h" #include "tracker-ontology.h" Index: src/libtracker-common/tracker-hal.c =================================================================== --- src/libtracker-common/tracker-hal.c (revision 3160) +++ src/libtracker-common/tracker-hal.c (working copy) @@ -1,1299 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org) - * Copyright (C) 2008, Nokia (urho konttori nokia com) - * - * This library 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 library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#ifdef HAVE_HAL - -#include - -#include -#include - -#include - -#include "tracker-log.h" -#include "tracker-hal.h" -#include "tracker-utils.h" -#include "tracker-marshal.h" - -#define CAPABILITY_AC_ADAPTER "ac_adapter" -#define CAPABILITY_BATTERY "battery" -#define CAPABILITY_VOLUME "volume" - -#define PROP_AC_ADAPTER_ON "ac_adapter.present" -#define PROP_BATT_PERCENTAGE "battery.charge_level.percentage" -#define PROP_IS_MOUNTED "volume.is_mounted" - -#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_HAL, TrackerHalPriv)) - -typedef struct { - LibHalContext *context; - - GHashTable *all_devices; - GHashTable *mounted_devices; - GHashTable *removable_devices; - GHashTable *batteries; - - gchar *ac_adapter_udi; - gboolean battery_in_use; - gdouble battery_percentage; -} TrackerHalPriv; - -typedef struct { - LibHalContext *context; - GList *roots; -} GetRoots; - -static void tracker_hal_finalize (GObject *object); -static void hal_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static gboolean hal_setup_devices (TrackerHal *hal); -static gboolean hal_setup_ac_adapters (TrackerHal *hal); -static gboolean hal_setup_batteries (TrackerHal *hal); - -static void hal_battery_modify (TrackerHal *hal, - const gchar *udi); -static void hal_battery_remove (TrackerHal *hal, - const gchar *udi); - -static gboolean hal_device_add (TrackerHal *hal, - LibHalVolume *volume); -static void hal_device_added_cb (LibHalContext *context, - const gchar *udi); -static void hal_device_removed_cb (LibHalContext *context, - const gchar *udi); -static void hal_device_property_modified_cb (LibHalContext *context, - const char *udi, - const char *key, - dbus_bool_t is_removed, - dbus_bool_t is_added); - -enum { - PROP_0, - PROP_BATTERY_IN_USE, - PROP_BATTERY_EXISTS, - PROP_BATTERY_PERCENTAGE -}; - -enum { - MOUNT_POINT_ADDED, - MOUNT_POINT_REMOVED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (TrackerHal, tracker_hal, G_TYPE_OBJECT); - -static void -tracker_hal_class_init (TrackerHalClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_hal_finalize; - object_class->get_property = hal_get_property; - - signals[MOUNT_POINT_ADDED] = - g_signal_new ("mount-point-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - tracker_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_STRING); - - signals[MOUNT_POINT_REMOVED] = - g_signal_new ("mount-point-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - tracker_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_STRING); - - g_object_class_install_property (object_class, - PROP_BATTERY_IN_USE, - g_param_spec_boolean ("battery-in-use", - "Battery in use", - "Whether the battery is being used", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_BATTERY_EXISTS, - g_param_spec_boolean ("battery-exists", - "Battery exists", - "There is a battery on this machine", - FALSE, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, - PROP_BATTERY_PERCENTAGE, - g_param_spec_double ("battery-percentage", - "Battery percentage", - "Battery percentage", - 0.0, 1.0, 0.0, - G_PARAM_READABLE)); - - g_type_class_add_private (object_class, sizeof (TrackerHalPriv)); -} - -static void -tracker_hal_init (TrackerHal *hal) -{ - TrackerHalPriv *priv; - DBusError error; - DBusConnection *connection; - - g_message ("Initializing HAL..."); - - priv = GET_PRIV (hal); - - priv->all_devices = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - - priv->mounted_devices = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - - priv->removable_devices = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - priv->batteries = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - NULL); - - dbus_error_init (&error); - - connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if (dbus_error_is_set (&error)) { - g_critical ("Could not get the system DBus connection, %s", - error.message); - dbus_error_free (&error); - return; - } - - dbus_connection_set_exit_on_disconnect (connection, FALSE); - dbus_connection_setup_with_g_main (connection, NULL); - - priv->context = libhal_ctx_new (); - - if (!priv->context) { - g_critical ("Could not create HAL context"); - return; - } - - libhal_ctx_set_user_data (priv->context, hal); - libhal_ctx_set_dbus_connection (priv->context, connection); - - if (!libhal_ctx_init (priv->context, &error)) { - if (dbus_error_is_set (&error)) { - g_critical ("Could not initialize the HAL context, %s", - error.message); - dbus_error_free (&error); - } else { - g_critical ("Could not initialize the HAL context, " - "no error, is hald running?"); - } - - libhal_ctx_free (priv->context); - priv->context = NULL; - return; - } - - - /* Volume and property notification callbacks */ - g_message ("HAL monitors set for devices added/removed/mounted/umounted..."); - libhal_ctx_set_device_added (priv->context, hal_device_added_cb); - libhal_ctx_set_device_removed (priv->context, hal_device_removed_cb); - libhal_ctx_set_device_property_modified (priv->context, hal_device_property_modified_cb); - - /* Get all devices which are mountable and set them up */ - if (!hal_setup_devices (hal)) { - return; - } - - /* Get all AC adapters info and set them up */ - if (!hal_setup_ac_adapters (hal)) { - return; - } - - /* Get all battery devices and set them up */ - if (!hal_setup_batteries (hal)) { - return; - } -} - -static void -tracker_hal_finalize (GObject *object) -{ - TrackerHalPriv *priv; - - priv = GET_PRIV (object); - - if (priv->removable_devices) { - g_hash_table_unref (priv->removable_devices); - } - - if (priv->mounted_devices) { - g_hash_table_unref (priv->mounted_devices); - } - - if (priv->all_devices) { - g_hash_table_unref (priv->all_devices); - } - - if (priv->batteries) { - g_hash_table_unref (priv->batteries); - } - - g_free (priv->ac_adapter_udi); - - if (priv->context) { - libhal_ctx_set_user_data (priv->context, NULL); - libhal_ctx_free (priv->context); - } - - (G_OBJECT_CLASS (tracker_hal_parent_class)->finalize) (object); -} - -static void -hal_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerHalPriv *priv; - - priv = GET_PRIV (object); - - switch (param_id) { - case PROP_BATTERY_IN_USE: - g_value_set_boolean (value, priv->battery_in_use); - break; - case PROP_BATTERY_EXISTS: - g_value_set_boolean (value, priv->ac_adapter_udi != NULL); - break; - case PROP_BATTERY_PERCENTAGE: - g_value_set_double (value, priv->battery_percentage); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static gboolean -hal_setup_devices (TrackerHal *hal) -{ - TrackerHalPriv *priv; - DBusError error; - gchar **devices, **p; - gint num; - - priv = GET_PRIV (hal); - - dbus_error_init (&error); - - devices = libhal_find_device_by_capability (priv->context, - CAPABILITY_VOLUME, - &num, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get devices with 'volume' capability, %s", - error.message); - dbus_error_free (&error); - return FALSE; - } - - if (!devices || !devices[0]) { - g_message ("HAL devices not found with 'volume' capability"); - return TRUE; - } - - for (p = devices; *p; p++) { - LibHalVolume *volume; - - volume = libhal_volume_from_udi (priv->context, *p); - if (!volume) { - continue; - } - - g_debug ("HAL device:'%s' found:", - libhal_volume_get_device_file (volume)); - g_debug (" UDI : %s", - libhal_volume_get_udi (volume)); - g_debug (" Mount point: %s", - libhal_volume_get_mount_point (volume)); - g_debug (" UUID : %s", - libhal_volume_get_uuid (volume)); - g_debug (" Mounted : %s", - libhal_volume_is_mounted (volume) ? "yes" : "no"); - g_debug (" File system: %s", - libhal_volume_get_fstype (volume)); - g_debug (" Label : %s", - libhal_volume_get_label (volume)); - - hal_device_add (hal, volume); - libhal_volume_free (volume); - } - - libhal_free_string_array (devices); - - return TRUE; -} - -static gboolean -hal_setup_ac_adapters (TrackerHal *hal) -{ - TrackerHalPriv *priv; - DBusError error; - gchar **devices, **p; - gint num; - - priv = GET_PRIV (hal); - - dbus_error_init (&error); - - devices = libhal_find_device_by_capability (priv->context, - CAPABILITY_AC_ADAPTER, - &num, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get AC adapter capable devices, %s", - error.message); - dbus_error_free (&error); - return FALSE; - } - - g_message ("HAL found %d AC adapter capable devices", num); - - if (!devices || !devices[0]) { - libhal_free_string_array (devices); - - priv->battery_in_use = FALSE; - g_object_notify (G_OBJECT (hal), "battery-in-use"); - - priv->ac_adapter_udi = NULL; - g_object_notify (G_OBJECT (hal), "battery-exists"); - - return TRUE; - } - - for (p = devices; *p; p++) { - if (!priv->ac_adapter_udi) { - /* For now just use the first one we find */ - priv->ac_adapter_udi = g_strdup (*p); - g_object_notify (G_OBJECT (hal), "battery-exists"); - - g_message (" Device '%s' (default)", *p); - } else { - g_message (" Device '%s'", *p); - } - } - - libhal_free_string_array (devices); - - /* Make sure we watch changes to the battery use */ - libhal_device_add_property_watch (priv->context, - priv->ac_adapter_udi, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not add device:'%s' to property watch, %s", - priv->ac_adapter_udi, error.message); - dbus_error_free (&error); - return FALSE; - } - - /* Get current state, are we using the battery now? */ - priv->battery_in_use = !libhal_device_get_property_bool (priv->context, - priv->ac_adapter_udi, - PROP_AC_ADAPTER_ON, - NULL); - - g_message ("HAL reports system is currently powered by %s", - priv->battery_in_use ? "battery" : "AC adapter"); - - g_object_notify (G_OBJECT (hal), "battery-in-use"); - - return TRUE; -} - -static gboolean -hal_setup_batteries (TrackerHal *hal) -{ - TrackerHalPriv *priv; - DBusError error; - gchar **devices, **p; - gint num; - - priv = GET_PRIV (hal); - - dbus_error_init (&error); - - devices = libhal_find_device_by_capability (priv->context, - CAPABILITY_BATTERY, - &num, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get Battery HAL info, %s", - error.message); - dbus_error_free (&error); - return FALSE; - } - - g_message ("HAL found %d batteries", num); - - if (!devices || !devices[0]) { - libhal_free_string_array (devices); - return TRUE; - } - - for (p = devices; *p; p++) { - g_message (" Device '%s'", *p); - - hal_battery_modify (hal, *p); - libhal_device_add_property_watch (priv->context, *p, &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not add device:'%s' to property watch, %s", - *p, error.message); - dbus_error_free (&error); - } - } - - libhal_free_string_array (devices); - - return TRUE; -} - -static void -hal_mount_point_add (TrackerHal *hal, - const gchar *udi, - const gchar *mount_point, - gboolean removable_device) -{ - TrackerHalPriv *priv; - - priv = GET_PRIV (hal); - - g_message ("HAL device:'%s' with mount point:'%s', removable:%s now being tracked", - (const gchar*) g_hash_table_lookup (priv->all_devices, udi), - mount_point, - removable_device ? "yes" : "no"); - - g_hash_table_insert (priv->mounted_devices, - g_strdup (udi), - g_strdup (mount_point)); - - if (removable_device) { - g_hash_table_insert (priv->removable_devices, - g_strdup (udi), - g_strdup (mount_point)); - } - - g_signal_emit (hal, signals[MOUNT_POINT_ADDED], 0, udi, mount_point, NULL); -} - -static void -hal_mount_point_remove (TrackerHal *hal, - const gchar *udi) -{ - TrackerHalPriv *priv; - const gchar *mount_point; - - priv = GET_PRIV (hal); - - mount_point = g_hash_table_lookup (priv->mounted_devices, udi); - - if (!mount_point) { - return; - } - - g_message ("HAL device:'%s' with mount point:'%s' (uuid:'%s'), removable:%s NO LONGER being tracked", - (const gchar*) g_hash_table_lookup (priv->all_devices, udi), - mount_point, - udi, - g_hash_table_remove (priv->removable_devices, udi) ? "yes" : "no"); - - g_signal_emit (hal, signals[MOUNT_POINT_REMOVED], 0, udi, mount_point, NULL); - - g_hash_table_remove (priv->mounted_devices, udi); - g_hash_table_remove (priv->removable_devices, udi); -} - -static const gchar * -hal_drive_type_to_string (LibHalDriveType type) -{ - switch (type) { - case LIBHAL_DRIVE_TYPE_REMOVABLE_DISK: - return "LIBHAL_DRIVE_TYPE_REMOVABLE_DISK"; - case LIBHAL_DRIVE_TYPE_DISK: - return "LIBHAL_DRIVE_TYPE_DISK"; - case LIBHAL_DRIVE_TYPE_CDROM: - return "LIBHAL_DRIVE_TYPE_CDROM"; - case LIBHAL_DRIVE_TYPE_FLOPPY: - return "LIBHAL_DRIVE_TYPE_FLOPPY"; - case LIBHAL_DRIVE_TYPE_TAPE: - return "LIBHAL_DRIVE_TYPE_TAPE"; - case LIBHAL_DRIVE_TYPE_COMPACT_FLASH: - return "LIBHAL_DRIVE_TYPE_COMPACT_FLASH"; - case LIBHAL_DRIVE_TYPE_MEMORY_STICK: - return "LIBHAL_DRIVE_TYPE_MEMORY_STICK"; - case LIBHAL_DRIVE_TYPE_SMART_MEDIA: - return "LIBHAL_DRIVE_TYPE_SMART_MEDIA"; - case LIBHAL_DRIVE_TYPE_SD_MMC: - return "LIBHAL_DRIVE_TYPE_SD_MMC"; - case LIBHAL_DRIVE_TYPE_CAMERA: - return "LIBHAL_DRIVE_TYPE_CAMERA"; - case LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER: - return "LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER"; - case LIBHAL_DRIVE_TYPE_ZIP: - return "LIBHAL_DRIVE_TYPE_ZIP"; - case LIBHAL_DRIVE_TYPE_JAZ: - return "LIBHAL_DRIVE_TYPE_JAZ"; - case LIBHAL_DRIVE_TYPE_FLASHKEY: - return "LIBHAL_DRIVE_TYPE_FLASHKEY"; - case LIBHAL_DRIVE_TYPE_MO: - return "LIBHAL_DRIVE_TYPE_MO"; - default: - return ""; - } -} - -static gboolean -hal_device_is_removable (TrackerHal *hal, - const gchar *device_file) -{ - TrackerHalPriv *priv; - LibHalDrive *drive; - gboolean removable; - - if (!device_file) { - return FALSE; - } - - priv = GET_PRIV (hal); - - drive = libhal_drive_from_device_file (priv->context, device_file); - if (!drive) { - return FALSE; - } - - removable = libhal_drive_uses_removable_media (drive); - libhal_drive_free (drive); - - return removable; -} - -static gboolean -hal_device_should_be_tracked (TrackerHal *hal, - const gchar *device_file) -{ - TrackerHalPriv *priv; - LibHalDrive *drive; - LibHalDriveType drive_type; - gboolean eligible; - - if (!device_file) { - return FALSE; - } - - priv = GET_PRIV (hal); - - drive = libhal_drive_from_device_file (priv->context, device_file); - if (!drive) { - return FALSE; - } - - /* From the list, the first one below seems to be the ONLY one - * to ignore: - * - * LIBHAL_DRIVE_TYPE_REMOVABLE_DISK = 0x00, - * LIBHAL_DRIVE_TYPE_DISK = 0x01, - * LIBHAL_DRIVE_TYPE_CDROM = 0x02, - * LIBHAL_DRIVE_TYPE_FLOPPY = 0x03, - * LIBHAL_DRIVE_TYPE_TAPE = 0x04, - * LIBHAL_DRIVE_TYPE_COMPACT_FLASH = 0x05, - * LIBHAL_DRIVE_TYPE_MEMORY_STICK = 0x06, - * LIBHAL_DRIVE_TYPE_SMART_MEDIA = 0x07, - * LIBHAL_DRIVE_TYPE_SD_MMC = 0x08, - * LIBHAL_DRIVE_TYPE_CAMERA = 0x09, - * LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER = 0x0a, - * LIBHAL_DRIVE_TYPE_ZIP = 0x0b, - * LIBHAL_DRIVE_TYPE_JAZ = 0x0c, - * LIBHAL_DRIVE_TYPE_FLASHKEY = 0x0d, - * LIBHAL_DRIVE_TYPE_MO = 0x0e - * - */ - - drive_type = libhal_drive_get_type (drive); - - /* So here we don't track CDROM devices or the hard disks in - * the machine, we simply track devices which are added or - * removed in real time which we are interested in and which - * are viable for tracking. CDROMs are too slow. - */ - eligible = TRUE; - eligible &= drive_type != LIBHAL_DRIVE_TYPE_DISK; - eligible &= drive_type != LIBHAL_DRIVE_TYPE_CDROM; - - libhal_drive_free (drive); - - if (!eligible) { - g_message ("HAL device:'%s' is not eligible for tracking, type is '%s'", - device_file, - hal_drive_type_to_string (drive_type)); - } else { - g_message ("HAL device:'%s' is eligible for tracking, type is '%s'", - device_file, - hal_drive_type_to_string (drive_type)); - } - - return eligible; -} - -static void -hal_battery_notify (TrackerHal *hal) -{ - TrackerHalPriv *priv; - GList *values, *v; - gint percentage, n_values; - - priv = GET_PRIV (hal); - percentage = n_values = 0; - - values = g_hash_table_get_values (priv->batteries); - - for (v = values; v; v = v->next) { - percentage += GPOINTER_TO_INT (v->data); - n_values++; - } - - if (n_values > 0) { - priv->battery_percentage = (gdouble) percentage / n_values; - priv->battery_percentage /= 100; - } else { - priv->battery_percentage = 0; - } - - g_list_free (values); - - g_object_notify (G_OBJECT (hal), "battery-percentage"); -} - -static void -hal_battery_modify (TrackerHal *hal, - const gchar *udi) -{ - TrackerHalPriv *priv; - gint percentage; - - priv = GET_PRIV (hal); - percentage = libhal_device_get_property_int (priv->context, udi, - PROP_BATT_PERCENTAGE, - NULL); - - g_hash_table_insert (priv->batteries, - g_strdup (udi), - GINT_TO_POINTER (percentage)); - - hal_battery_notify (hal); -} - -static void -hal_battery_remove (TrackerHal *hal, - const gchar *udi) -{ - TrackerHalPriv *priv; - - priv = GET_PRIV (hal); - - g_hash_table_remove (priv->batteries, udi); - hal_battery_notify (hal); -} - -static gboolean -hal_device_add (TrackerHal *hal, - LibHalVolume *volume) -{ - TrackerHalPriv *priv; - DBusError error; - const gchar *udi; - const gchar *mount_point; - const gchar *device_file; - - priv = GET_PRIV (hal); - - dbus_error_init (&error); - - udi = libhal_volume_get_udi (volume); - mount_point = libhal_volume_get_mount_point (volume); - device_file = libhal_volume_get_device_file (volume); - - if (g_hash_table_lookup (priv->all_devices, udi)) { - return TRUE; - } - - /* If there is no mount point, then there is nothing to track */ - if (!hal_device_should_be_tracked (hal, device_file)) { - return TRUE; - } - - /* Make sure we watch changes to the mount/umount state */ - libhal_device_add_property_watch (priv->context, udi, &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not add device:'%s' property watch for udi:'%s', %s", - device_file, - udi, - error.message); - dbus_error_free (&error); - return FALSE; - } - - g_hash_table_insert (priv->all_devices, - g_strdup (udi), - g_strdup (device_file)); - - if (mount_point) { - hal_mount_point_add (hal, - udi, - mount_point, - hal_device_is_removable (hal, device_file)); - } - - return TRUE; -} - -static void -hal_device_added_cb (LibHalContext *context, - const gchar *udi) -{ - TrackerHal *hal; - LibHalVolume *volume; - - hal = libhal_ctx_get_user_data (context); - - if (libhal_device_query_capability (context, udi, CAPABILITY_BATTERY, NULL)) { - hal_battery_modify (hal, udi); - } else if (libhal_device_query_capability (context, udi, CAPABILITY_VOLUME, NULL)) { - volume = libhal_volume_from_udi (context, udi); - - if (!volume) { - /* Not a device with a volume */ - return; - } - - g_message ("HAL device:'%s' added:", - libhal_volume_get_device_file (volume)); - g_message (" UDI : %s", - udi); - g_message (" Mount point: %s", - libhal_volume_get_mount_point (volume)); - g_message (" UUID : %s", - libhal_volume_get_uuid (volume)); - g_message (" Mounted : %s", - libhal_volume_is_mounted (volume) ? "yes" : "no"); - g_message (" File system: %s", - libhal_volume_get_fstype (volume)); - g_message (" Label : %s", - libhal_volume_get_label (volume)); - - hal_device_add (hal, volume); - libhal_volume_free (volume); - } -} - -static void -hal_device_removed_cb (LibHalContext *context, - const gchar *udi) -{ - TrackerHal *hal; - TrackerHalPriv *priv; - const gchar *device_file; - const gchar *mount_point; - - hal = (TrackerHal*) libhal_ctx_get_user_data (context); - priv = GET_PRIV (hal); - - if (g_hash_table_lookup (priv->batteries, udi)) { - hal_battery_remove (hal, udi); - } else if (g_hash_table_lookup (priv->all_devices, udi)) { - device_file = g_hash_table_lookup (priv->all_devices, udi); - - if (!device_file) { - /* Don't report about unknown devices */ - return; - } - - mount_point = g_hash_table_lookup (priv->mounted_devices, udi); - - g_message ("HAL device:'%s' removed:", - device_file); - g_message (" UDI : %s", - udi); - g_message (" Mount point: %s", - mount_point); - - g_hash_table_remove (priv->all_devices, udi); - - hal_mount_point_remove (hal, udi); - } -} - -static void -hal_device_property_modified_cb (LibHalContext *context, - const char *udi, - const char *key, - dbus_bool_t is_removed, - dbus_bool_t is_added) -{ - TrackerHal *hal; - TrackerHalPriv *priv; - DBusError error; - - hal = (TrackerHal*) libhal_ctx_get_user_data (context); - priv = GET_PRIV (hal); - - dbus_error_init (&error); - - if (priv->ac_adapter_udi && strcmp (priv->ac_adapter_udi, udi) == 0) { - /* Property change is on the AC adapter */ - priv->battery_in_use = !libhal_device_get_property_bool (priv->context, - priv->ac_adapter_udi, - PROP_AC_ADAPTER_ON, - &error); - g_message ("HAL reports system is now powered by %s", - priv->battery_in_use ? "battery" : "AC adapter"); - - g_object_notify (G_OBJECT (hal), "battery-in-use"); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get device property:'%s' for udi:'%s', %s", - udi, PROP_AC_ADAPTER_ON, error.message); - dbus_error_free (&error); - return; - } - } else if (g_hash_table_lookup (priv->batteries, udi)) { - /* Property change is on any battery */ - if (strcmp (key, PROP_BATT_PERCENTAGE) == 0) { - hal_battery_modify (hal, udi); - } - } else if (g_hash_table_lookup (priv->all_devices, udi)) { - const gchar *device_file; - gboolean is_mounted; - - device_file = g_hash_table_lookup (priv->all_devices, udi); - - g_message ("HAL device:'%s' property change for udi:'%s' and key:'%s'", - device_file, - udi, - key); - - if (strcmp (key, PROP_IS_MOUNTED) != 0) { - return; - } - - is_mounted = libhal_device_get_property_bool (context, - udi, - key, - &error); - - if (dbus_error_is_set (&error)) { - g_message ("Could not get device property:'%s' for udi:'%s', %s", - udi, key, error.message); - dbus_error_free (&error); - - g_message ("HAL device:'%s' with udi:'%s' is now unmounted (due to error)", - device_file, - udi); - hal_mount_point_remove (hal, udi); - return; - } - - if (is_mounted) { - LibHalVolume *volume; - const gchar *mount_point; - const gchar *device_file; - - volume = libhal_volume_from_udi (context, udi); - mount_point = libhal_volume_get_mount_point (volume); - device_file = libhal_volume_get_device_file (volume); - - g_message ("HAL device:'%s' with udi:'%s' is now mounted", - device_file, - udi); - - hal_mount_point_add (hal, - udi, - mount_point, - hal_device_is_removable (hal, device_file)); - - libhal_volume_free (volume); - } else { - g_message ("HAL device:'%s' with udi:'%s' is now unmounted", - device_file, - udi); - - hal_mount_point_remove (hal, udi); - } - } -} - -/** - * tracker_hal_new: - * - * Creates a new instance of #TrackerHal. - * - * Returns: The newly created #TrackerHal. - **/ -TrackerHal * -tracker_hal_new () -{ - return g_object_new (TRACKER_TYPE_HAL, NULL); -} - -/** - * tracker_hal_get_battery_in_use: - * @hal: A #TrackerHal. - * - * Returns whether the computer battery (if any) is currently in use. - * - * Returns: #TRUE if the computer is running on battery power. - **/ -gboolean -tracker_hal_get_battery_in_use (TrackerHal *hal) -{ - TrackerHalPriv *priv; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), TRUE); - - priv = GET_PRIV (hal); - - return priv->battery_in_use; -} - -/** - * tracker_hal_get_battery_exists: - * @hal: A #TrackerHal - * - * Returns whether the computer has batteries. - * - * Returns: #TRUE if the computer has batteries available. - **/ -gboolean -tracker_hal_get_battery_exists (TrackerHal *hal) -{ - TrackerHalPriv *priv; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), TRUE); - - priv = GET_PRIV (hal); - - return priv->ac_adapter_udi != NULL; -} - -/** - * tracker_hal_get_battery_percentage: - * @hal: A #TrackerHal - * - * Returns the battery percentage left on the - * computer, or #0.0 if no batteries are present. - * - * Returns: The battery percentage left. - **/ -gdouble -tracker_hal_get_battery_percentage (TrackerHal *hal) -{ - TrackerHalPriv *priv; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), 0.0); - - priv = GET_PRIV (hal); - - return priv->battery_percentage; -} - -static void -hal_get_mount_point_by_udi_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - LibHalVolume *volume; - GetRoots *gr; - const gchar *udi; - const gchar *mount_point; - gboolean is_mounted; - - gr = (GetRoots*) user_data; - udi = key; - - volume = libhal_volume_from_udi (gr->context, udi); - if (!volume) { - g_message ("HAL device with udi:'%s' has no volume, " - "should we delete?", - udi); - return; - } - - mount_point = libhal_volume_get_mount_point (volume); - is_mounted = libhal_volume_is_mounted (volume); - - if (is_mounted && mount_point) { - gr->roots = g_list_prepend (gr->roots, g_strdup (mount_point)); - } - - libhal_volume_free (volume); -} - -/** - * tracker_hal_get_mounted_directory_roots: - * @hal: A #TrackerHal - * - * Returns a #Glist of strings containing the root directories for mounted devices. - * Each element must be freed using g_free() and the list itself using g_list_free(). - * - * Returns: The list of root directories. - **/ -GList * -tracker_hal_get_mounted_directory_roots (TrackerHal *hal) -{ - TrackerHalPriv *priv; - GetRoots gr; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), NULL); - - priv = GET_PRIV (hal); - - gr.context = priv->context; - gr.roots = NULL; - - g_hash_table_foreach (priv->mounted_devices, - hal_get_mount_point_by_udi_foreach, - &gr); - - return gr.roots; -} - -/** - * tracker_hal_get_removable_device_roots: - * @hal: A #TrackerHal - * - * Returns a #GList of strings containing the root directories for removable devices. - * Each element must be freed using g_free() and the list itself through g_list_free(). - * - * Returns: The list of root directories. - **/ -GList * -tracker_hal_get_removable_device_roots (TrackerHal *hal) -{ - TrackerHalPriv *priv; - GetRoots gr; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), NULL); - - priv = GET_PRIV (hal); - - gr.context = priv->context; - gr.roots = NULL; - - g_hash_table_foreach (priv->removable_devices, - hal_get_mount_point_by_udi_foreach, - &gr); - - return gr.roots; -} - -/** - * tracker_hal_path_is_on_removable_device: - * @hal: A #TrackerHal - * @path: a path - * @mount_mount: if @path is on a removable device, the mount point will - * be filled in here. You must free the returned result - * @available: if @path is on a removable device, this will be set to - * TRUE in case the file is available right now - * - * Returns Whether or not @path is on a known removable device - * - * Returns: TRUE if @path on a known removable device, FALSE otherwise - **/ -gboolean -tracker_hal_path_is_on_removable_device (TrackerHal *hal, - const gchar *path, - gchar **mount_point, - gboolean *available) -{ - TrackerHalPriv *priv; - GHashTableIter iter; - gboolean found = FALSE; - gpointer key, value; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), FALSE); - - if (!path) - return FALSE; - - priv = GET_PRIV (hal); - - g_hash_table_iter_init (&iter, priv->removable_devices); - - while (g_hash_table_iter_next (&iter, &key, &value)) { - LibHalVolume *volume; - const gchar *udi; - const gchar *mp; - - udi = key; - - volume = libhal_volume_from_udi (priv->context, udi); - - if (!volume) { - g_message ("HAL device with udi:'%s' has no volume, " - "should we delete?", - udi); - continue; - } - - mp = libhal_volume_get_mount_point (volume); - - if (g_strcmp0 (mp, path) != 0) { - if (g_strrstr (path, mp)) { - found = TRUE; - - if (mount_point) - *mount_point = g_strdup (mp); - - if (available) - *available = libhal_volume_is_mounted (volume); - - libhal_volume_free (volume); - break; - } - } - - libhal_volume_free (volume); - } - - return found; -} - - -/** - * tracker_hal_get_removable_device_udis: - * @hal: A #TrackerHal - * - * Returns a #GList of strings containing the UDI for removable devices. - * Each element is owned by the #GHashTable internally, the list - * itself through should be freed using g_list_free(). - * - * Returns: The list of UDIs. - **/ -GList * -tracker_hal_get_removable_device_udis (TrackerHal *hal) -{ - TrackerHalPriv *priv; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), NULL); - - priv = GET_PRIV (hal); - - return g_hash_table_get_keys (priv->removable_devices); -} - -/** - * tracker_hal_udi_get_mount_point: - * @hal: A #TrackerHal - * @udi: A string pointer to the UDI for the device. - * - * Returns: The mount point for @udi, this should not be freed. - **/ -const gchar * -tracker_hal_udi_get_mount_point (TrackerHal *hal, - const gchar *udi) -{ - TrackerHalPriv *priv; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), NULL); - g_return_val_if_fail (udi != NULL, NULL); - - priv = GET_PRIV (hal); - - return g_hash_table_lookup (priv->removable_devices, udi); -} - -/** - * tracker_hal_udi_get_mount_point: - * @hal: A #TrackerHal - * @udi: A #gboolean - * - * Returns: The %TRUE if @udi is mounted or %FALSE if it isn't. - **/ -gboolean -tracker_hal_udi_get_is_mounted (TrackerHal *hal, - const gchar *udi) -{ - TrackerHalPriv *priv; - LibHalVolume *volume; - const gchar *mount_point; - gboolean is_mounted; - - g_return_val_if_fail (TRACKER_IS_HAL (hal), FALSE); - g_return_val_if_fail (udi != NULL, FALSE); - - priv = GET_PRIV (hal); - - volume = libhal_volume_from_udi (priv->context, udi); - if (!volume) { - g_message ("HAL device with udi:'%s' has no volume, " - "should we delete?", - udi); - return FALSE; - } - - mount_point = libhal_volume_get_mount_point (volume); - is_mounted = libhal_volume_is_mounted (volume); - - libhal_volume_free (volume); - - return is_mounted && mount_point; - -} - -#endif /* HAVE_HAL */ Index: src/libtracker-common/tracker-hal.h =================================================================== --- src/libtracker-common/tracker-hal.h (revision 3160) +++ src/libtracker-common/tracker-hal.h (working copy) @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org) - * Copyright (C) 2008, Nokia (urho konttori nokia com) - * - * This library 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 library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_HAL_H__ -#define __LIBTRACKER_HAL_H__ - -#include - -G_BEGIN_DECLS - -#if !defined (__LIBTRACKER_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only must be included directly." -#endif - -#define TRACKER_TYPE_HAL (tracker_hal_get_type ()) -#define TRACKER_HAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_HAL, TrackerHal)) -#define TRACKER_HAL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_HAL, TrackerHalClass)) -#define TRACKER_IS_HAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_HAL)) -#define TRACKER_IS_HAL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_HAL)) -#define TRACKER_HAL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_HAL, TrackerHalClass)) - -typedef struct _TrackerHal TrackerHal; -typedef struct _TrackerHalClass TrackerHalClass; - -struct _TrackerHal { - GObject parent; -}; - -struct _TrackerHalClass { - GObjectClass parent_class; -}; - -#ifdef HAVE_HAL - -GType tracker_hal_get_type (void) G_GNUC_CONST; - -TrackerHal * tracker_hal_new (void); - -gboolean tracker_hal_get_battery_in_use (TrackerHal *hal); -gboolean tracker_hal_get_battery_exists (TrackerHal *hal); -gdouble tracker_hal_get_battery_percentage (TrackerHal *hal); - -GList * tracker_hal_get_mounted_directory_roots (TrackerHal *hal); -GList * tracker_hal_get_removable_device_roots (TrackerHal *hal); -GList * tracker_hal_get_removable_device_udis (TrackerHal *hal); - -const gchar *tracker_hal_udi_get_mount_point (TrackerHal *hal, - const gchar *udi); -gboolean tracker_hal_udi_get_is_mounted (TrackerHal *hal, - const gchar *udi); -gboolean tracker_hal_path_is_on_removable_device (TrackerHal *hal, - const gchar *path, - gchar **mount_point, - gboolean *available); - -#endif /* HAVE_HAL */ - -G_END_DECLS - -#endif /* __LIBTRACKER_HAL_H__ */ Index: src/libtracker-common/Makefile.am =================================================================== --- src/libtracker-common/Makefile.am (revision 3160) +++ src/libtracker-common/Makefile.am (working copy) @@ -27,9 +27,11 @@ if HAVE_HAL hal_sources = \ - tracker-hal.c + tracker-power-hal.c \ + tracker-storage-hal.c hal_headers = \ - tracker-hal.h + tracker-power.h \ + tracker-storage.h endif libtracker_common_la_SOURCES = \ --- /dev/null 2009-03-30 16:45:46.017035090 +0100 +++ src/libtracker-common/tracker-power.h 2009-04-02 10:13:43.000000000 +0100 @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org) + * Copyright (C) 2008, Nokia (urho konttori nokia com) + * + * This library 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 library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __LIBTRACKER_POWER_H__ +#define __LIBTRACKER_POWER_H__ + +#include + +G_BEGIN_DECLS + +#if !defined (__LIBTRACKER_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION) +#error "only must be included directly." +#endif + +#define TRACKER_TYPE_POWER (tracker_power_get_type ()) +#define TRACKER_POWER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_POWER, TrackerPower)) +#define TRACKER_POWER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_POWER, TrackerPowerClass)) +#define TRACKER_IS_POWER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_POWER)) +#define TRACKER_IS_POWER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_POWER)) +#define TRACKER_POWER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_POWER, TrackerPowerClass)) + +typedef struct _TrackerPower TrackerPower; +typedef struct _TrackerPowerClass TrackerPowerClass; + +struct _TrackerPower { + GObject parent; +}; + +struct _TrackerPowerClass { + GObjectClass parent_class; +}; + +#ifdef HAVE_HAL + +GType tracker_power_get_type (void) G_GNUC_CONST; + +TrackerPower * tracker_power_new (void); + +gboolean tracker_power_get_battery_in_use (TrackerPower *power); +gboolean tracker_power_get_battery_exists (TrackerPower *power); +gdouble tracker_power_get_battery_percentage (TrackerPower *power); + +#endif /* HAVE_HAL */ + +G_END_DECLS + +#endif /* __LIBTRACKER_POWER_H__ */ --- /dev/null 2009-03-30 16:45:46.017035090 +0100 +++ src/libtracker-common/tracker-power-hal.c 2009-04-02 10:13:16.000000000 +0100 @@ -0,0 +1,588 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org) + * Copyright (C) 2008, Nokia (urho konttori nokia com) + * + * This library 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 library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#ifdef HAVE_HAL + +#include + +#include +#include + +#include + +#include "tracker-log.h" +#include "tracker-power.h" +#include "tracker-utils.h" +#include "tracker-marshal.h" + +#define CAPABILITY_AC_ADAPTER "ac_adapter" +#define CAPABILITY_BATTERY "battery" +#define PROP_AC_ADAPTER_ON "ac_adapter.present" +#define PROP_BATT_PERCENTAGE "battery.charge_level.percentage" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_POWER, TrackerPowerPriv)) + +typedef struct { + LibHalContext *context; + + GHashTable *all_devices; + GHashTable *batteries; + + gchar *ac_adapter_udi; + gboolean battery_in_use; + gdouble battery_percentage; +} TrackerPowerPriv; + +typedef struct { + LibHalContext *context; + GList *roots; +} GetRoots; + +static void tracker_power_finalize (GObject *object); +static void hal_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static gboolean hal_setup_ac_adapters (TrackerPower *power); +static gboolean hal_setup_batteries (TrackerPower *power); + +static void hal_battery_modify (TrackerPower *power, + const gchar *udi); +static void hal_battery_remove (TrackerPower *power, + const gchar *udi); + +static void hal_device_added_cb (LibHalContext *context, + const gchar *udi); +static void hal_device_removed_cb (LibHalContext *context, + const gchar *udi); +static void hal_device_property_modified_cb (LibHalContext *context, + const char *udi, + const char *key, + dbus_bool_t is_removed, + dbus_bool_t is_added); + +enum { + PROP_0, + PROP_BATTERY_IN_USE, + PROP_BATTERY_EXISTS, + PROP_BATTERY_PERCENTAGE +}; + +G_DEFINE_TYPE (TrackerPower, tracker_power, G_TYPE_OBJECT); + +static void +tracker_power_class_init (TrackerPowerClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = tracker_power_finalize; + object_class->get_property = hal_get_property; + + g_object_class_install_property (object_class, + PROP_BATTERY_IN_USE, + g_param_spec_boolean ("battery-in-use", + "Battery in use", + "Whether the battery is being used", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_BATTERY_EXISTS, + g_param_spec_boolean ("battery-exists", + "Battery exists", + "There is a battery on this machine", + FALSE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_BATTERY_PERCENTAGE, + g_param_spec_double ("battery-percentage", + "Battery percentage", + "Battery percentage", + 0.0, 1.0, 0.0, + G_PARAM_READABLE)); + + g_type_class_add_private (object_class, sizeof (TrackerPowerPriv)); +} + +static void +tracker_power_init (TrackerPower *power) +{ + TrackerPowerPriv *priv; + DBusError error; + DBusConnection *connection; + + g_message ("Initializing HAL..."); + + priv = GET_PRIV (power); + + priv->all_devices = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + + priv->batteries = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + NULL); + + dbus_error_init (&error); + + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (dbus_error_is_set (&error)) { + g_critical ("Could not get the system DBus connection, %s", + error.message); + dbus_error_free (&error); + return; + } + + dbus_connection_set_exit_on_disconnect (connection, FALSE); + dbus_connection_setup_with_g_main (connection, NULL); + + priv->context = libhal_ctx_new (); + + if (!priv->context) { + g_critical ("Could not create HAL context"); + return; + } + + libhal_ctx_set_user_data (priv->context, power); + libhal_ctx_set_dbus_connection (priv->context, connection); + + if (!libhal_ctx_init (priv->context, &error)) { + if (dbus_error_is_set (&error)) { + g_critical ("Could not initialize the HAL context, %s", + error.message); + dbus_error_free (&error); + } else { + g_critical ("Could not initialize the HAL context, " + "no error, is hald running?"); + } + + libhal_ctx_free (priv->context); + priv->context = NULL; + return; + } + + + /* Volume and property notification callbacks */ + g_message ("HAL monitors set for devices added/removed/mounted/umounted..."); + libhal_ctx_set_device_added (priv->context, hal_device_added_cb); + libhal_ctx_set_device_removed (priv->context, hal_device_removed_cb); + libhal_ctx_set_device_property_modified (priv->context, hal_device_property_modified_cb); + + /* Get all AC adapters info and set them up */ + if (!hal_setup_ac_adapters (power)) { + return; + } + + /* Get all battery devices and set them up */ + if (!hal_setup_batteries (power)) { + return; + } +} + +static void +tracker_power_finalize (GObject *object) +{ + TrackerPowerPriv *priv; + + priv = GET_PRIV (object); + + if (priv->all_devices) { + g_hash_table_unref (priv->all_devices); + } + + if (priv->batteries) { + g_hash_table_unref (priv->batteries); + } + + g_free (priv->ac_adapter_udi); + + if (priv->context) { + libhal_ctx_set_user_data (priv->context, NULL); + libhal_ctx_free (priv->context); + } + + (G_OBJECT_CLASS (tracker_power_parent_class)->finalize) (object); +} + +static void +hal_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerPowerPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_BATTERY_IN_USE: + g_value_set_boolean (value, priv->battery_in_use); + break; + case PROP_BATTERY_EXISTS: + g_value_set_boolean (value, priv->ac_adapter_udi != NULL); + break; + case PROP_BATTERY_PERCENTAGE: + g_value_set_double (value, priv->battery_percentage); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static gboolean +hal_setup_ac_adapters (TrackerPower *power) +{ + TrackerPowerPriv *priv; + DBusError error; + gchar **devices, **p; + gint num; + + priv = GET_PRIV (power); + + dbus_error_init (&error); + + devices = libhal_find_device_by_capability (priv->context, + CAPABILITY_AC_ADAPTER, + &num, + &error); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not get AC adapter capable devices, %s", + error.message); + dbus_error_free (&error); + return FALSE; + } + + g_message ("HAL found %d AC adapter capable devices", num); + + if (!devices || !devices[0]) { + libhal_free_string_array (devices); + + priv->battery_in_use = FALSE; + g_object_notify (G_OBJECT (power), "battery-in-use"); + + priv->ac_adapter_udi = NULL; + g_object_notify (G_OBJECT (power), "battery-exists"); + + return TRUE; + } + + for (p = devices; *p; p++) { + if (!priv->ac_adapter_udi) { + /* For now just use the first one we find */ + priv->ac_adapter_udi = g_strdup (*p); + g_object_notify (G_OBJECT (power), "battery-exists"); + + g_message (" Device '%s' (default)", *p); + } else { + g_message (" Device '%s'", *p); + } + } + + libhal_free_string_array (devices); + + /* Make sure we watch changes to the battery use */ + libhal_device_add_property_watch (priv->context, + priv->ac_adapter_udi, + &error); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not add device:'%s' to property watch, %s", + priv->ac_adapter_udi, error.message); + dbus_error_free (&error); + return FALSE; + } + + /* Get current state, are we using the battery now? */ + priv->battery_in_use = !libhal_device_get_property_bool (priv->context, + priv->ac_adapter_udi, + PROP_AC_ADAPTER_ON, + NULL); + + g_message ("HAL reports system is currently powered by %s", + priv->battery_in_use ? "battery" : "AC adapter"); + + g_object_notify (G_OBJECT (power), "battery-in-use"); + + return TRUE; +} + +static gboolean +hal_setup_batteries (TrackerPower *power) +{ + TrackerPowerPriv *priv; + DBusError error; + gchar **devices, **p; + gint num; + + priv = GET_PRIV (power); + + dbus_error_init (&error); + + devices = libhal_find_device_by_capability (priv->context, + CAPABILITY_BATTERY, + &num, + &error); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not get Battery HAL info, %s", + error.message); + dbus_error_free (&error); + return FALSE; + } + + g_message ("HAL found %d batteries", num); + + if (!devices || !devices[0]) { + libhal_free_string_array (devices); + return TRUE; + } + + for (p = devices; *p; p++) { + g_message (" Device '%s'", *p); + + hal_battery_modify (power, *p); + libhal_device_add_property_watch (priv->context, *p, &error); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not add device:'%s' to property watch, %s", + *p, error.message); + dbus_error_free (&error); + } + } + + libhal_free_string_array (devices); + + return TRUE; +} + +static void +hal_battery_notify (TrackerPower *power) +{ + TrackerPowerPriv *priv; + GList *values, *v; + gint percentage, n_values; + + priv = GET_PRIV (power); + percentage = n_values = 0; + + values = g_hash_table_get_values (priv->batteries); + + for (v = values; v; v = v->next) { + percentage += GPOINTER_TO_INT (v->data); + n_values++; + } + + if (n_values > 0) { + priv->battery_percentage = (gdouble) percentage / n_values; + priv->battery_percentage /= 100; + } else { + priv->battery_percentage = 0; + } + + g_list_free (values); + + g_object_notify (G_OBJECT (power), "battery-percentage"); +} + +static void +hal_battery_modify (TrackerPower *power, + const gchar *udi) +{ + TrackerPowerPriv *priv; + gint percentage; + + priv = GET_PRIV (power); + percentage = libhal_device_get_property_int (priv->context, udi, + PROP_BATT_PERCENTAGE, + NULL); + + g_hash_table_insert (priv->batteries, + g_strdup (udi), + GINT_TO_POINTER (percentage)); + + hal_battery_notify (power); +} + +static void +hal_battery_remove (TrackerPower *power, + const gchar *udi) +{ + TrackerPowerPriv *priv; + + priv = GET_PRIV (power); + + g_hash_table_remove (priv->batteries, udi); + hal_battery_notify (power); +} + +static void +hal_device_added_cb (LibHalContext *context, + const gchar *udi) +{ + TrackerPower *power; + + power = libhal_ctx_get_user_data (context); + + if (libhal_device_query_capability (context, udi, CAPABILITY_BATTERY, NULL)) { + hal_battery_modify (power, udi); + } +} + +static void +hal_device_removed_cb (LibHalContext *context, + const gchar *udi) +{ + TrackerPower *power; + TrackerPowerPriv *priv; + + power = (TrackerPower*) libhal_ctx_get_user_data (context); + priv = GET_PRIV (power); + + if (g_hash_table_lookup (priv->batteries, udi)) { + hal_battery_remove (power, udi); + } +} + +static void +hal_device_property_modified_cb (LibHalContext *context, + const char *udi, + const char *key, + dbus_bool_t is_removed, + dbus_bool_t is_added) +{ + TrackerPower *power; + TrackerPowerPriv *priv; + DBusError error; + + power = (TrackerPower*) libhal_ctx_get_user_data (context); + priv = GET_PRIV (power); + + dbus_error_init (&error); + + if (priv->ac_adapter_udi && strcmp (priv->ac_adapter_udi, udi) == 0) { + /* Property change is on the AC adapter */ + priv->battery_in_use = !libhal_device_get_property_bool (priv->context, + priv->ac_adapter_udi, + PROP_AC_ADAPTER_ON, + &error); + g_message ("HAL reports system is now powered by %s", + priv->battery_in_use ? "battery" : "AC adapter"); + + g_object_notify (G_OBJECT (power), "battery-in-use"); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not get device property:'%s' for udi:'%s', %s", + udi, PROP_AC_ADAPTER_ON, error.message); + dbus_error_free (&error); + return; + } + } else if (g_hash_table_lookup (priv->batteries, udi)) { + /* Property change is on any battery */ + if (strcmp (key, PROP_BATT_PERCENTAGE) == 0) { + hal_battery_modify (power, udi); + } + } +} + +/** + * tracker_power_new: + * + * Creates a new instance of #TrackerPower. + * + * Returns: The newly created #TrackerPower. + **/ +TrackerPower * +tracker_power_new () +{ + return g_object_new (TRACKER_TYPE_POWER, NULL); +} + +/** + * tracker_power_get_battery_in_use: + * @power: A #TrackerPower. + * + * Returns whether the computer battery (if any) is currently in use. + * + * Returns: #TRUE if the computer is running on battery power. + **/ +gboolean +tracker_power_get_battery_in_use (TrackerPower *power) +{ + TrackerPowerPriv *priv; + + g_return_val_if_fail (TRACKER_IS_POWER (power), TRUE); + + priv = GET_PRIV (power); + + return priv->battery_in_use; +} + +/** + * tracker_power_get_battery_exists: + * @power: A #TrackerPower + * + * Returns whether the computer has batteries. + * + * Returns: #TRUE if the computer has batteries available. + **/ +gboolean +tracker_power_get_battery_exists (TrackerPower *power) +{ + TrackerPowerPriv *priv; + + g_return_val_if_fail (TRACKER_IS_POWER (power), TRUE); + + priv = GET_PRIV (power); + + return priv->ac_adapter_udi != NULL; +} + +/** + * tracker_power_get_battery_percentage: + * @power: A #TrackerPower + * + * Returns the battery percentage left on the + * computer, or #0.0 if no batteries are present. + * + * Returns: The battery percentage left. + **/ +gdouble +tracker_power_get_battery_percentage (TrackerPower *power) +{ + TrackerPowerPriv *priv; + + g_return_val_if_fail (TRACKER_IS_POWER (power), 0.0); + + priv = GET_PRIV (power); + + return priv->battery_percentage; +} + + +#endif /* HAVE_HAL */ --- /dev/null 2009-03-30 16:45:46.017035090 +0100 +++ src/libtracker-common/tracker-storage.h 2009-04-02 10:13:36.000000000 +0100 @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org) + * Copyright (C) 2008, Nokia (urho konttori nokia com) + * + * This library 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 library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __LIBTRACKER_STORAGE_H__ +#define __LIBTRACKER_STORAGE_H__ + +#include + +G_BEGIN_DECLS + +#if !defined (__LIBTRACKER_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION) +#error "only must be included directly." +#endif + +#define TRACKER_TYPE_STORAGE (tracker_storage_get_type ()) +#define TRACKER_STORAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_STORAGE, TrackerStorage)) +#define TRACKER_STORAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_STORAGE, TrackerStorageClass)) +#define TRACKER_IS_STORAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_STORAGE)) +#define TRACKER_IS_STORAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_STORAGE)) +#define TRACKER_STORAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_STORAGE, TrackerStorageClass)) + +typedef struct _TrackerStorage TrackerStorage; +typedef struct _TrackerStorageClass TrackerStorageClass; + +struct _TrackerStorage { + GObject parent; +}; + +struct _TrackerStorageClass { + GObjectClass parent_class; +}; + +#ifdef HAVE_HAL + +GType tracker_storage_get_type (void) G_GNUC_CONST; + +TrackerStorage * tracker_storage_new (void); + +GList * tracker_storage_get_mounted_directory_roots (TrackerStorage *storage); +GList * tracker_storage_get_removable_device_roots (TrackerStorage *storage); +GList * tracker_storage_get_removable_device_udis (TrackerStorage *storage); + +const gchar *tracker_storage_udi_get_mount_point (TrackerStorage *storage, + const gchar *udi); +gboolean tracker_storage_udi_get_is_mounted (TrackerStorage *storage, + const gchar *udi); +gboolean tracker_storage_path_is_on_removable_device (TrackerStorage *storage, + const gchar *path, + gchar **mount_point, + gboolean *available); + +#endif /* HAVE_HAL */ + +G_END_DECLS + +#endif /* __LIBTRACKER_STORAGE_H__ */ --- /dev/null 2009-03-30 16:45:46.017035090 +0100 +++ src/libtracker-common/tracker-storage-hal.c 2009-04-02 10:13:08.000000000 +0100 @@ -0,0 +1,953 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org) + * Copyright (C) 2008, Nokia (urho konttori nokia com) + * + * This library 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 library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#ifdef HAVE_HAL + +#include + +#include +#include + +#include + +#include "tracker-log.h" +#include "tracker-storage.h" +#include "tracker-utils.h" +#include "tracker-marshal.h" + +#define CAPABILITY_VOLUME "volume" +#define PROP_IS_MOUNTED "volume.is_mounted" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_STORAGE, TrackerStoragePriv)) + +typedef struct { + LibHalContext *context; + + GHashTable *all_devices; + GHashTable *mounted_devices; + GHashTable *removable_devices; +} TrackerStoragePriv; + +typedef struct { + LibHalContext *context; + GList *roots; +} GetRoots; + +static void tracker_storage_finalize (GObject *object); +static void hal_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static gboolean hal_setup_devices (TrackerStorage *storage); + +static gboolean hal_device_add (TrackerStorage *storage, + LibHalVolume *volume); +static void hal_device_added_cb (LibHalContext *context, + const gchar *udi); +static void hal_device_removed_cb (LibHalContext *context, + const gchar *udi); +static void hal_device_property_modified_cb (LibHalContext *context, + const char *udi, + const char *key, + dbus_bool_t is_removed, + dbus_bool_t is_added); + +enum { + PROP_0, +}; + +enum { + MOUNT_POINT_ADDED, + MOUNT_POINT_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (TrackerStorage, tracker_storage, G_TYPE_OBJECT); + +static void +tracker_storage_class_init (TrackerStorageClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = tracker_storage_finalize; + object_class->get_property = hal_get_property; + + signals[MOUNT_POINT_ADDED] = + g_signal_new ("mount-point-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + tracker_marshal_VOID__STRING_STRING, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[MOUNT_POINT_REMOVED] = + g_signal_new ("mount-point-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + tracker_marshal_VOID__STRING_STRING, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_STRING); + + g_type_class_add_private (object_class, sizeof (TrackerStoragePriv)); +} + +static void +tracker_storage_init (TrackerStorage *storage) +{ + TrackerStoragePriv *priv; + DBusError error; + DBusConnection *connection; + + g_message ("Initializing HAL..."); + + priv = GET_PRIV (storage); + + priv->all_devices = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + + priv->mounted_devices = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + + priv->removable_devices = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + + dbus_error_init (&error); + + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (dbus_error_is_set (&error)) { + g_critical ("Could not get the system DBus connection, %s", + error.message); + dbus_error_free (&error); + return; + } + + dbus_connection_set_exit_on_disconnect (connection, FALSE); + dbus_connection_setup_with_g_main (connection, NULL); + + priv->context = libhal_ctx_new (); + + if (!priv->context) { + g_critical ("Could not create HAL context"); + return; + } + + libhal_ctx_set_user_data (priv->context, storage); + libhal_ctx_set_dbus_connection (priv->context, connection); + + if (!libhal_ctx_init (priv->context, &error)) { + if (dbus_error_is_set (&error)) { + g_critical ("Could not initialize the HAL context, %s", + error.message); + dbus_error_free (&error); + } else { + g_critical ("Could not initialize the HAL context, " + "no error, is hald running?"); + } + + libhal_ctx_free (priv->context); + priv->context = NULL; + return; + } + + + /* Volume and property notification callbacks */ + g_message ("HAL monitors set for devices added/removed/mounted/umounted..."); + libhal_ctx_set_device_added (priv->context, hal_device_added_cb); + libhal_ctx_set_device_removed (priv->context, hal_device_removed_cb); + libhal_ctx_set_device_property_modified (priv->context, hal_device_property_modified_cb); + + /* Get all devices which are mountable and set them up */ + if (!hal_setup_devices (storage)) { + return; + } +} + +static void +tracker_storage_finalize (GObject *object) +{ + TrackerStoragePriv *priv; + + priv = GET_PRIV (object); + + if (priv->removable_devices) { + g_hash_table_unref (priv->removable_devices); + } + + if (priv->mounted_devices) { + g_hash_table_unref (priv->mounted_devices); + } + + if (priv->all_devices) { + g_hash_table_unref (priv->all_devices); + } + + if (priv->context) { + libhal_ctx_set_user_data (priv->context, NULL); + libhal_ctx_free (priv->context); + } + + (G_OBJECT_CLASS (tracker_storage_parent_class)->finalize) (object); +} + +static void +hal_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerStoragePriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static gboolean +hal_setup_devices (TrackerStorage *storage) +{ + TrackerStoragePriv *priv; + DBusError error; + gchar **devices, **p; + gint num; + + priv = GET_PRIV (storage); + + dbus_error_init (&error); + + devices = libhal_find_device_by_capability (priv->context, + CAPABILITY_VOLUME, + &num, + &error); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not get devices with 'volume' capability, %s", + error.message); + dbus_error_free (&error); + return FALSE; + } + + if (!devices || !devices[0]) { + g_message ("HAL devices not found with 'volume' capability"); + return TRUE; + } + + for (p = devices; *p; p++) { + LibHalVolume *volume; + + volume = libhal_volume_from_udi (priv->context, *p); + if (!volume) { + continue; + } + + g_debug ("HAL device:'%s' found:", + libhal_volume_get_device_file (volume)); + g_debug (" UDI : %s", + libhal_volume_get_udi (volume)); + g_debug (" Mount point: %s", + libhal_volume_get_mount_point (volume)); + g_debug (" UUID : %s", + libhal_volume_get_uuid (volume)); + g_debug (" Mounted : %s", + libhal_volume_is_mounted (volume) ? "yes" : "no"); + g_debug (" File system: %s", + libhal_volume_get_fstype (volume)); + g_debug (" Label : %s", + libhal_volume_get_label (volume)); + + hal_device_add (storage, volume); + libhal_volume_free (volume); + } + + libhal_free_string_array (devices); + + return TRUE; +} + +static void +hal_mount_point_add (TrackerStorage *storage, + const gchar *udi, + const gchar *mount_point, + gboolean removable_device) +{ + TrackerStoragePriv *priv; + + priv = GET_PRIV (storage); + + g_message ("HAL device:'%s' with mount point:'%s', removable:%s now being tracked", + (const gchar*) g_hash_table_lookup (priv->all_devices, udi), + mount_point, + removable_device ? "yes" : "no"); + + g_hash_table_insert (priv->mounted_devices, + g_strdup (udi), + g_strdup (mount_point)); + + if (removable_device) { + g_hash_table_insert (priv->removable_devices, + g_strdup (udi), + g_strdup (mount_point)); + } + + g_signal_emit (storage, signals[MOUNT_POINT_ADDED], 0, udi, mount_point, NULL); +} + +static void +hal_mount_point_remove (TrackerStorage *storage, + const gchar *udi) +{ + TrackerStoragePriv *priv; + const gchar *mount_point; + + priv = GET_PRIV (storage); + + mount_point = g_hash_table_lookup (priv->mounted_devices, udi); + + if (!mount_point) { + return; + } + + g_message ("HAL device:'%s' with mount point:'%s' (uuid:'%s'), removable:%s NO LONGER being tracked", + (const gchar*) g_hash_table_lookup (priv->all_devices, udi), + mount_point, + udi, + g_hash_table_remove (priv->removable_devices, udi) ? "yes" : "no"); + + g_signal_emit (storage, signals[MOUNT_POINT_REMOVED], 0, udi, mount_point, NULL); + + g_hash_table_remove (priv->mounted_devices, udi); + g_hash_table_remove (priv->removable_devices, udi); +} + +static const gchar * +hal_drive_type_to_string (LibHalDriveType type) +{ + switch (type) { + case LIBHAL_DRIVE_TYPE_REMOVABLE_DISK: + return "LIBHAL_DRIVE_TYPE_REMOVABLE_DISK"; + case LIBHAL_DRIVE_TYPE_DISK: + return "LIBHAL_DRIVE_TYPE_DISK"; + case LIBHAL_DRIVE_TYPE_CDROM: + return "LIBHAL_DRIVE_TYPE_CDROM"; + case LIBHAL_DRIVE_TYPE_FLOPPY: + return "LIBHAL_DRIVE_TYPE_FLOPPY"; + case LIBHAL_DRIVE_TYPE_TAPE: + return "LIBHAL_DRIVE_TYPE_TAPE"; + case LIBHAL_DRIVE_TYPE_COMPACT_FLASH: + return "LIBHAL_DRIVE_TYPE_COMPACT_FLASH"; + case LIBHAL_DRIVE_TYPE_MEMORY_STICK: + return "LIBHAL_DRIVE_TYPE_MEMORY_STICK"; + case LIBHAL_DRIVE_TYPE_SMART_MEDIA: + return "LIBHAL_DRIVE_TYPE_SMART_MEDIA"; + case LIBHAL_DRIVE_TYPE_SD_MMC: + return "LIBHAL_DRIVE_TYPE_SD_MMC"; + case LIBHAL_DRIVE_TYPE_CAMERA: + return "LIBHAL_DRIVE_TYPE_CAMERA"; + case LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER: + return "LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER"; + case LIBHAL_DRIVE_TYPE_ZIP: + return "LIBHAL_DRIVE_TYPE_ZIP"; + case LIBHAL_DRIVE_TYPE_JAZ: + return "LIBHAL_DRIVE_TYPE_JAZ"; + case LIBHAL_DRIVE_TYPE_FLASHKEY: + return "LIBHAL_DRIVE_TYPE_FLASHKEY"; + case LIBHAL_DRIVE_TYPE_MO: + return "LIBHAL_DRIVE_TYPE_MO"; + default: + return ""; + } +} + +static gboolean +hal_device_is_removable (TrackerStorage *storage, + const gchar *device_file) +{ + TrackerStoragePriv *priv; + LibHalDrive *drive; + gboolean removable; + + if (!device_file) { + return FALSE; + } + + priv = GET_PRIV (storage); + + drive = libhal_drive_from_device_file (priv->context, device_file); + if (!drive) { + return FALSE; + } + + removable = libhal_drive_uses_removable_media (drive); + libhal_drive_free (drive); + + return removable; +} + +static gboolean +hal_device_should_be_tracked (TrackerStorage *storage, + const gchar *device_file) +{ + TrackerStoragePriv *priv; + LibHalDrive *drive; + LibHalDriveType drive_type; + gboolean eligible; + + if (!device_file) { + return FALSE; + } + + priv = GET_PRIV (storage); + + drive = libhal_drive_from_device_file (priv->context, device_file); + if (!drive) { + return FALSE; + } + + /* From the list, the first one below seems to be the ONLY one + * to ignore: + * + * LIBHAL_DRIVE_TYPE_REMOVABLE_DISK = 0x00, + * LIBHAL_DRIVE_TYPE_DISK = 0x01, + * LIBHAL_DRIVE_TYPE_CDROM = 0x02, + * LIBHAL_DRIVE_TYPE_FLOPPY = 0x03, + * LIBHAL_DRIVE_TYPE_TAPE = 0x04, + * LIBHAL_DRIVE_TYPE_COMPACT_FLASH = 0x05, + * LIBHAL_DRIVE_TYPE_MEMORY_STICK = 0x06, + * LIBHAL_DRIVE_TYPE_SMART_MEDIA = 0x07, + * LIBHAL_DRIVE_TYPE_SD_MMC = 0x08, + * LIBHAL_DRIVE_TYPE_CAMERA = 0x09, + * LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER = 0x0a, + * LIBHAL_DRIVE_TYPE_ZIP = 0x0b, + * LIBHAL_DRIVE_TYPE_JAZ = 0x0c, + * LIBHAL_DRIVE_TYPE_FLASHKEY = 0x0d, + * LIBHAL_DRIVE_TYPE_MO = 0x0e + * + */ + + drive_type = libhal_drive_get_type (drive); + + /* So here we don't track CDROM devices or the hard disks in + * the machine, we simply track devices which are added or + * removed in real time which we are interested in and which + * are viable for tracking. CDROMs are too slow. + */ + eligible = TRUE; + eligible &= drive_type != LIBHAL_DRIVE_TYPE_DISK; + eligible &= drive_type != LIBHAL_DRIVE_TYPE_CDROM; + + libhal_drive_free (drive); + + if (!eligible) { + g_message ("HAL device:'%s' is not eligible for tracking, type is '%s'", + device_file, + hal_drive_type_to_string (drive_type)); + } else { + g_message ("HAL device:'%s' is eligible for tracking, type is '%s'", + device_file, + hal_drive_type_to_string (drive_type)); + } + + return eligible; +} + +static gboolean +hal_device_add (TrackerStorage *storage, + LibHalVolume *volume) +{ + TrackerStoragePriv *priv; + DBusError error; + const gchar *udi; + const gchar *mount_point; + const gchar *device_file; + + priv = GET_PRIV (storage); + + dbus_error_init (&error); + + udi = libhal_volume_get_udi (volume); + mount_point = libhal_volume_get_mount_point (volume); + device_file = libhal_volume_get_device_file (volume); + + if (g_hash_table_lookup (priv->all_devices, udi)) { + return TRUE; + } + + /* If there is no mount point, then there is nothing to track */ + if (!hal_device_should_be_tracked (storage, device_file)) { + return TRUE; + } + + /* Make sure we watch changes to the mount/umount state */ + libhal_device_add_property_watch (priv->context, udi, &error); + + if (dbus_error_is_set (&error)) { + g_critical ("Could not add device:'%s' property watch for udi:'%s', %s", + device_file, + udi, + error.message); + dbus_error_free (&error); + return FALSE; + } + + g_hash_table_insert (priv->all_devices, + g_strdup (udi), + g_strdup (device_file)); + + if (mount_point) { + hal_mount_point_add (storage, + udi, + mount_point, + hal_device_is_removable (storage, device_file)); + } + + return TRUE; +} + +static void +hal_device_added_cb (LibHalContext *context, + const gchar *udi) +{ + TrackerStorage *storage; + LibHalVolume *volume; + + storage = libhal_ctx_get_user_data (context); + + if (libhal_device_query_capability (context, udi, CAPABILITY_VOLUME, NULL)) { + volume = libhal_volume_from_udi (context, udi); + + if (!volume) { + /* Not a device with a volume */ + return; + } + + g_message ("HAL device:'%s' added:", + libhal_volume_get_device_file (volume)); + g_message (" UDI : %s", + udi); + g_message (" Mount point: %s", + libhal_volume_get_mount_point (volume)); + g_message (" UUID : %s", + libhal_volume_get_uuid (volume)); + g_message (" Mounted : %s", + libhal_volume_is_mounted (volume) ? "yes" : "no"); + g_message (" File system: %s", + libhal_volume_get_fstype (volume)); + g_message (" Label : %s", + libhal_volume_get_label (volume)); + + hal_device_add (storage, volume); + libhal_volume_free (volume); + } +} + +static void +hal_device_removed_cb (LibHalContext *context, + const gchar *udi) +{ + TrackerStorage *storage; + TrackerStoragePriv *priv; + const gchar *device_file; + const gchar *mount_point; + + storage = (TrackerStorage*) libhal_ctx_get_user_data (context); + priv = GET_PRIV (storage); + + if (g_hash_table_lookup (priv->all_devices, udi)) { + device_file = g_hash_table_lookup (priv->all_devices, udi); + + if (!device_file) { + /* Don't report about unknown devices */ + return; + } + + mount_point = g_hash_table_lookup (priv->mounted_devices, udi); + + g_message ("HAL device:'%s' removed:", + device_file); + g_message (" UDI : %s", + udi); + g_message (" Mount point: %s", + mount_point); + + g_hash_table_remove (priv->all_devices, udi); + + hal_mount_point_remove (storage, udi); + } +} + +static void +hal_device_property_modified_cb (LibHalContext *context, + const char *udi, + const char *key, + dbus_bool_t is_removed, + dbus_bool_t is_added) +{ + TrackerStorage *storage; + TrackerStoragePriv *priv; + DBusError error; + + storage = (TrackerStorage*) libhal_ctx_get_user_data (context); + priv = GET_PRIV (storage); + + dbus_error_init (&error); + + if (g_hash_table_lookup (priv->all_devices, udi)) { + const gchar *device_file; + gboolean is_mounted; + + device_file = g_hash_table_lookup (priv->all_devices, udi); + + g_message ("HAL device:'%s' property change for udi:'%s' and key:'%s'", + device_file, + udi, + key); + + if (strcmp (key, PROP_IS_MOUNTED) != 0) { + return; + } + + is_mounted = libhal_device_get_property_bool (context, + udi, + key, + &error); + + if (dbus_error_is_set (&error)) { + g_message ("Could not get device property:'%s' for udi:'%s', %s", + udi, key, error.message); + dbus_error_free (&error); + + g_message ("HAL device:'%s' with udi:'%s' is now unmounted (due to error)", + device_file, + udi); + hal_mount_point_remove (storage, udi); + return; + } + + if (is_mounted) { + LibHalVolume *volume; + const gchar *mount_point; + const gchar *device_file; + + volume = libhal_volume_from_udi (context, udi); + mount_point = libhal_volume_get_mount_point (volume); + device_file = libhal_volume_get_device_file (volume); + + g_message ("HAL device:'%s' with udi:'%s' is now mounted", + device_file, + udi); + + hal_mount_point_add (storage, + udi, + mount_point, + hal_device_is_removable (storage, device_file)); + + libhal_volume_free (volume); + } else { + g_message ("HAL device:'%s' with udi:'%s' is now unmounted", + device_file, + udi); + + hal_mount_point_remove (storage, udi); + } + } +} + +/** + * tracker_storage_new: + * + * Creates a new instance of #TrackerStorage. + * + * Returns: The newly created #TrackerStorage. + **/ +TrackerStorage * +tracker_storage_new () +{ + return g_object_new (TRACKER_TYPE_STORAGE, NULL); +} + +static void +hal_get_mount_point_by_udi_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + LibHalVolume *volume; + GetRoots *gr; + const gchar *udi; + const gchar *mount_point; + gboolean is_mounted; + + gr = (GetRoots*) user_data; + udi = key; + + volume = libhal_volume_from_udi (gr->context, udi); + if (!volume) { + g_message ("HAL device with udi:'%s' has no volume, " + "should we delete?", + udi); + return; + } + + mount_point = libhal_volume_get_mount_point (volume); + is_mounted = libhal_volume_is_mounted (volume); + + if (is_mounted && mount_point) { + gr->roots = g_list_prepend (gr->roots, g_strdup (mount_point)); + } + + libhal_volume_free (volume); +} + +/** + * tracker_storage_get_mounted_directory_roots: + * @storage: A #TrackerStorage + * + * Returns a #Glist of strings containing the root directories for mounted devices. + * Each element must be freed using g_free() and the list itself using g_list_free(). + * + * Returns: The list of root directories. + **/ +GList * +tracker_storage_get_mounted_directory_roots (TrackerStorage *storage) +{ + TrackerStoragePriv *priv; + GetRoots gr; + + g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); + + priv = GET_PRIV (storage); + + gr.context = priv->context; + gr.roots = NULL; + + g_hash_table_foreach (priv->mounted_devices, + hal_get_mount_point_by_udi_foreach, + &gr); + + return gr.roots; +} + +/** + * tracker_storage_get_removable_device_roots: + * @storage: A #TrackerStorage + * + * Returns a #GList of strings containing the root directories for removable devices. + * Each element must be freed using g_free() and the list itself through g_list_free(). + * + * Returns: The list of root directories. + **/ +GList * +tracker_storage_get_removable_device_roots (TrackerStorage *storage) +{ + TrackerStoragePriv *priv; + GetRoots gr; + + g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); + + priv = GET_PRIV (storage); + + gr.context = priv->context; + gr.roots = NULL; + + g_hash_table_foreach (priv->removable_devices, + hal_get_mount_point_by_udi_foreach, + &gr); + + return gr.roots; +} + +/** + * tracker_storage_path_is_on_removable_device: + * @storage: A #TrackerStorage + * @path: a path + * @mount_mount: if @path is on a removable device, the mount point will + * be filled in here. You must free the returned result + * @available: if @path is on a removable device, this will be set to + * TRUE in case the file is available right now + * + * Returns Whether or not @path is on a known removable device + * + * Returns: TRUE if @path on a known removable device, FALSE otherwise + **/ +gboolean +tracker_storage_path_is_on_removable_device (TrackerStorage *storage, + const gchar *path, + gchar **mount_point, + gboolean *available) +{ + TrackerStoragePriv *priv; + GHashTableIter iter; + gboolean found = FALSE; + gpointer key, value; + + g_return_val_if_fail (TRACKER_IS_STORAGE (storage), FALSE); + + if (!path) + return FALSE; + + priv = GET_PRIV (storage); + + g_hash_table_iter_init (&iter, priv->removable_devices); + + while (g_hash_table_iter_next (&iter, &key, &value)) { + LibHalVolume *volume; + const gchar *udi; + const gchar *mp; + + udi = key; + + volume = libhal_volume_from_udi (priv->context, udi); + + if (!volume) { + g_message ("HAL device with udi:'%s' has no volume, " + "should we delete?", + udi); + continue; + } + + mp = libhal_volume_get_mount_point (volume); + + if (g_strcmp0 (mp, path) != 0) { + if (g_strrstr (path, mp)) { + found = TRUE; + + if (mount_point) + *mount_point = g_strdup (mp); + + if (available) + *available = libhal_volume_is_mounted (volume); + + libhal_volume_free (volume); + break; + } + } + + libhal_volume_free (volume); + } + + return found; +} + + +/** + * tracker_storage_get_removable_device_udis: + * @storage: A #TrackerStorage + * + * Returns a #GList of strings containing the UDI for removable devices. + * Each element is owned by the #GHashTable internally, the list + * itself through should be freed using g_list_free(). + * + * Returns: The list of UDIs. + **/ +GList * +tracker_storage_get_removable_device_udis (TrackerStorage *storage) +{ + TrackerStoragePriv *priv; + + g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); + + priv = GET_PRIV (storage); + + return g_hash_table_get_keys (priv->removable_devices); +} + +/** + * tracker_storage_udi_get_mount_point: + * @storage: A #TrackerStorage + * @udi: A string pointer to the UDI for the device. + * + * Returns: The mount point for @udi, this should not be freed. + **/ +const gchar * +tracker_storage_udi_get_mount_point (TrackerStorage *storage, + const gchar *udi) +{ + TrackerStoragePriv *priv; + + g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); + g_return_val_if_fail (udi != NULL, NULL); + + priv = GET_PRIV (storage); + + return g_hash_table_lookup (priv->removable_devices, udi); +} + +/** + * tracker_storage_udi_get_mount_point: + * @storage: A #TrackerStorage + * @udi: A #gboolean + * + * Returns: The %TRUE if @udi is mounted or %FALSE if it isn't. + **/ +gboolean +tracker_storage_udi_get_is_mounted (TrackerStorage *storage, + const gchar *udi) +{ + TrackerStoragePriv *priv; + LibHalVolume *volume; + const gchar *mount_point; + gboolean is_mounted; + + g_return_val_if_fail (TRACKER_IS_STORAGE (storage), FALSE); + g_return_val_if_fail (udi != NULL, FALSE); + + priv = GET_PRIV (storage); + + volume = libhal_volume_from_udi (priv->context, udi); + if (!volume) { + g_message ("HAL device with udi:'%s' has no volume, " + "should we delete?", + udi); + return FALSE; + } + + mount_point = libhal_volume_get_mount_point (volume); + is_mounted = libhal_volume_is_mounted (volume); + + libhal_volume_free (volume); + + return is_mounted && mount_point; + +} + +#endif /* HAVE_HAL */