[gnome-photos/wip/rishi/collection: 24/51] source-manager: Track GMounts representing USB storage & PTP devices
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/wip/rishi/collection: 24/51] source-manager: Track GMounts representing USB storage & PTP devices
- Date: Tue, 6 Feb 2018 16:07:41 +0000 (UTC)
commit 41703dbee2cd285cbc7116271ada23e0d5327aee
Author: Petr Štětka <stetka peta gmail com>
Date: Wed Sep 6 09:29:08 2017 +0200
source-manager: Track GMounts representing USB storage & PTP devices
The GMounts are synchronously enumerated at start-up. However, since
hot-plugging a USB device generates a flurry of events from
GVolumeMonitor while the GDaemonMount gets created and then shadowed
by a new GProxyShadowMount, SourceManager waits for a small period of
time to let things settle down before updating itself.
Only USB mass storage and PTP devices, represented by the "file" and
"gphoto2" URI schemes are tracked at the moment.
https://gitlab.gnome.org/GNOME/gnome-photos/issues/29
src/photos-source-manager.c | 226 +++++++++++++++++++++++++++++++++-----------
1 file changed, 171 insertions(+), 55 deletions(-)
---
diff --git a/src/photos-source-manager.c b/src/photos-source-manager.c
index 8aaac9e6..2a6cca9d 100644
--- a/src/photos-source-manager.c
+++ b/src/photos-source-manager.c
@@ -40,7 +40,9 @@ struct _PhotosSourceManager
PhotosBaseManager parent_instance;
GCancellable *cancellable;
GHashTable *sources_notified;
+ GVolumeMonitor *volume_monitor;
GoaClient *client;
+ guint refresh_mounts_timeout_id;
};
enum
@@ -56,6 +58,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (PhotosSourceManager, photos_source_manager, PHOTOS_TYPE_BASE_MANAGER);
+enum
+{
+ REFRESH_MOUNTS_TIMEOUT = 1 /* s */
+};
+
+
static gchar *
photos_source_manager_get_filter (PhotosBaseManager *mngr, gint flags)
{
@@ -107,47 +115,142 @@ photos_source_manager_remove_object_by_id (PhotosBaseManager *mngr, const gchar
}
+static gboolean
+photos_source_manager_online_source_needs_notification (PhotosSource *source)
+{
+ GoaAccount *account;
+ GoaObject *object;
+ gboolean attention_needed;
+
+ object = photos_source_get_goa_object (source);
+ g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
+
+ account = goa_object_peek_account (object);
+ g_return_val_if_fail (GOA_IS_ACCOUNT (account), FALSE);
+
+ attention_needed = goa_account_get_attention_needed (account);
+ return attention_needed;
+}
+
+
+static void
+photos_source_manager_notify_sources (PhotosSourceManager *self)
+{
+ guint i;
+ guint n_items;
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
+ for (i = 0; i < n_items; i++)
+ {
+ GMount *mount;
+ GoaObject *object;
+ g_autoptr (PhotosSource) source = NULL;
+ gboolean needs_notification;
+ gboolean source_notified;
+ const gchar *id;
+
+ source = PHOTOS_SOURCE (g_list_model_get_object (G_LIST_MODEL (self), i));
+ mount = photos_source_get_mount (source);
+ object = photos_source_get_goa_object (source);
+
+ if (object != NULL)
+ needs_notification = photos_source_manager_online_source_needs_notification (source);
+ else if (mount != NULL)
+ needs_notification = TRUE;
+ else
+ needs_notification = FALSE;
+
+ id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
+ source_notified = g_hash_table_contains (self->sources_notified, id);
+
+ if (!needs_notification && source_notified)
+ {
+ gboolean removed;
+
+ g_signal_emit (self, signals[NOTIFICATION_HIDE], 0, source);
+ removed = g_hash_table_remove (self->sources_notified, id);
+ g_assert_true (removed);
+ }
+ else if (needs_notification && !source_notified)
+ {
+ gboolean inserted;
+
+ g_signal_emit (self, signals[NOTIFICATION_SHOW], 0, source);
+ inserted = g_hash_table_insert (self->sources_notified, g_strdup (id), g_object_ref (source));
+ g_assert_true (inserted);
+ }
+ }
+}
+
+
static void
-photos_source_manager_refresh_accounts (PhotosSourceManager *self)
+photos_source_manager_refresh_sources (PhotosSourceManager *self)
{
GApplication *app;
g_autoptr (GHashTable) new_sources = NULL;
- GList *accounts = NULL;
GList *l;
+ GList *mounts = NULL;
PhotosSource *active_source;
const gchar *active_id;
- guint i;
- guint n_items;
app = g_application_get_default ();
if (photos_application_get_empty_results (PHOTOS_APPLICATION (app)))
goto out;
- accounts = goa_client_get_accounts (self->client);
new_sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
- for (l = accounts; l != NULL; l = l->next)
+ mounts = g_volume_monitor_get_mounts (self->volume_monitor);
+
+ for (l = mounts; l != NULL; l = l->next)
{
- GoaAccount *account;
- GoaObject *object = GOA_OBJECT (l->data);
+ g_autoptr (GFile) root = NULL;
+ GMount *mount = G_MOUNT (l->data);
g_autoptr (PhotosSource) source = NULL;
const gchar *id;
- account = goa_object_peek_account (object);
- if (account == NULL)
- continue;
-
- if (goa_account_get_photos_disabled (account))
+ if (g_mount_is_shadowed (mount))
continue;
- if (goa_object_peek_photos (object) == NULL)
+ root = g_mount_get_root (mount);
+ if (!g_file_has_uri_scheme (root, "file") && !g_file_has_uri_scheme (root, "gphoto2"))
continue;
- source = photos_source_new_from_goa_object (GOA_OBJECT (l->data));
+ source = photos_source_new_from_mount (mount);
id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
g_hash_table_insert (new_sources, g_strdup (id), g_object_ref (source));
}
+ if (self->client != NULL)
+ {
+ GList *accounts = NULL;
+
+ accounts = goa_client_get_accounts (self->client);
+
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ GoaAccount *account;
+ GoaObject *object = GOA_OBJECT (l->data);
+ g_autoptr (PhotosSource) source = NULL;
+ const gchar *id;
+
+ account = goa_object_peek_account (object);
+ if (account == NULL)
+ continue;
+
+ if (goa_account_get_photos_disabled (account))
+ continue;
+
+ if (goa_object_peek_photos (object) == NULL)
+ continue;
+
+ source = photos_source_new_from_goa_object (GOA_OBJECT (l->data));
+ id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
+ g_hash_table_insert (new_sources, g_strdup (id), g_object_ref (source));
+ }
+
+ g_list_free_full (accounts, g_object_unref);
+ }
+
active_source = PHOTOS_SOURCE (photos_base_manager_get_active_object (PHOTOS_BASE_MANAGER (self)));
active_id = photos_filterable_get_id (PHOTOS_FILTERABLE (active_source));
if (!photos_filterable_get_builtin (PHOTOS_FILTERABLE (active_source))
@@ -157,50 +260,42 @@ photos_source_manager_refresh_accounts (PhotosSourceManager *self)
}
photos_base_manager_process_new_objects (PHOTOS_BASE_MANAGER (self), new_sources);
+ photos_source_manager_notify_sources (self);
- n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
- for (i = 0; i < n_items; i++)
- {
- GoaAccount *account;
- GoaObject *object;
- g_autoptr (PhotosSource) source = NULL;
- gboolean attention_needed;
- gboolean source_notified;
- const gchar *id;
-
- source = PHOTOS_SOURCE (g_list_model_get_object (G_LIST_MODEL (self), i));
- object = photos_source_get_goa_object (source);
- if (object == NULL)
- continue;
+ out:
+ return;
+}
- account = goa_object_peek_account (object);
- if (account == NULL)
- continue;
- attention_needed = goa_account_get_attention_needed (account);
- id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
- source_notified = g_hash_table_contains (self->sources_notified, id);
+static gboolean
+photos_source_manager_refresh_mounts_timeout (gpointer user_data)
+{
+ PhotosSourceManager *self = PHOTOS_SOURCE_MANAGER (user_data);
- if (!attention_needed && source_notified)
- {
- gboolean removed;
+ self->refresh_mounts_timeout_id = 0;
+ photos_source_manager_refresh_sources (self);
+ return G_SOURCE_REMOVE;
+}
- g_signal_emit (self, signals[NOTIFICATION_HIDE], 0, source);
- removed = g_hash_table_remove (self->sources_notified, id);
- g_assert_true (removed);
- }
- else if (attention_needed && !source_notified)
- {
- gboolean inserted;
- g_signal_emit (self, signals[NOTIFICATION_SHOW], 0, source);
- inserted = g_hash_table_insert (self->sources_notified, g_strdup (id), g_object_ref (source));
- g_assert_true (inserted);
- }
+static void
+photos_source_manager_remove_refresh_mounts_timeout (PhotosSourceManager *self)
+{
+ if (self->refresh_mounts_timeout_id != 0)
+ {
+ g_source_remove (self->refresh_mounts_timeout_id);
+ self->refresh_mounts_timeout_id = 0;
}
+}
- out:
- g_list_free_full (accounts, g_object_unref);
+
+static void
+photos_source_manager_queue_refresh_mounts (PhotosSourceManager *self)
+{
+ photos_source_manager_remove_refresh_mounts_timeout (self);
+ self->refresh_mounts_timeout_id = g_timeout_add_seconds (REFRESH_MOUNTS_TIMEOUT,
+ photos_source_manager_refresh_mounts_timeout,
+ self);
}
@@ -230,19 +325,19 @@ photos_source_manager_goa_client (GObject *source_object, GAsyncResult *res, gpo
self->client = g_object_ref (client);
g_signal_connect_swapped (self->client,
"account-added",
- G_CALLBACK (photos_source_manager_refresh_accounts),
+ G_CALLBACK (photos_source_manager_refresh_sources),
self);
g_signal_connect_swapped (self->client,
"account-changed",
- G_CALLBACK (photos_source_manager_refresh_accounts),
+ G_CALLBACK (photos_source_manager_refresh_sources),
self);
g_signal_connect_swapped (self->client,
"account-removed",
- G_CALLBACK (photos_source_manager_refresh_accounts),
+ G_CALLBACK (photos_source_manager_refresh_sources),
self);
}
- photos_source_manager_refresh_accounts (self);
+ photos_source_manager_refresh_sources (self);
out:
return;
@@ -254,11 +349,14 @@ photos_source_manager_dispose (GObject *object)
{
PhotosSourceManager *self = PHOTOS_SOURCE_MANAGER (object);
+ photos_source_manager_remove_refresh_mounts_timeout (self);
+
if (self->cancellable != NULL)
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->client);
+ g_clear_object (&self->volume_monitor);
g_clear_pointer (&self->sources_notified, (GDestroyNotify) g_hash_table_unref);
G_OBJECT_CLASS (photos_source_manager_parent_class)->dispose (object);
@@ -279,6 +377,24 @@ photos_source_manager_init (PhotosSourceManager *self)
self->cancellable = g_cancellable_new ();
self->sources_notified = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+ self->volume_monitor = g_volume_monitor_get ();
+ g_signal_connect_object (self->volume_monitor,
+ "mount-added",
+ G_CALLBACK (photos_source_manager_queue_refresh_mounts),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->volume_monitor,
+ "mount-changed",
+ G_CALLBACK (photos_source_manager_queue_refresh_mounts),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->volume_monitor,
+ "mount-removed",
+ G_CALLBACK (photos_source_manager_queue_refresh_mounts),
+ self,
+ G_CONNECT_SWAPPED);
+
goa_client_new (self->cancellable, photos_source_manager_goa_client, self);
photos_base_manager_set_active_object_by_id (PHOTOS_BASE_MANAGER (self), PHOTOS_SOURCE_STOCK_ALL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]