[rhythmbox] removable-media: add support for device-based sources
- From: Jonathan Matthew <jmatthew src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [rhythmbox] removable-media: add support for device-based sources
- Date: Tue, 4 Aug 2009 21:28:46 +0000 (UTC)
commit 627ad41233dcd650324882897e1ae44607eac162
Author: Jonathan Matthew <jonathan d14n org>
Date: Wed Aug 5 07:18:49 2009 +1000
removable-media: add support for device-based sources
This is for sources representing devices for which no GVolume or GMount
will be created, such as MTP devices. There's a new
create-source-device signal, similar to create-source-volume and
create-source-mount.
shell/Makefile.am | 2 +
shell/rb-removable-media-manager.c | 122 ++++++++++++++++++++++++++++++++++-
shell/rb-removable-media-manager.h | 3 +
3 files changed, 123 insertions(+), 4 deletions(-)
---
diff --git a/shell/Makefile.am b/shell/Makefile.am
index eacf157..9601e4a 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -47,6 +47,7 @@ INCLUDES = \
$(RHYTHMBOX_CFLAGS) \
$(TOTEM_PLPARSER_CFLAGS) \
$(DBUS_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-D_XOPEN_SOURCE -D__EXTENSIONS__ -D_BSD_SOURCE
librhythmbox_core_la_SOURCES = \
@@ -112,6 +113,7 @@ librhythmbox_core_la_LIBADD = \
$(top_builddir)/lib/libmediaplayerid/libmediaplayerid.la \
$(DBUS_LIBS) \
$(TOTEM_PLPARSER_LIBS) \
+ $(GUDEV_LIBS) \
$(RHYTHMBOX_LIBS) \
-lgstpbutils-0.10 \
-lgstcontroller-0.10
diff --git a/shell/rb-removable-media-manager.c b/shell/rb-removable-media-manager.c
index 4d24a96..6cac256 100644
--- a/shell/rb-removable-media-manager.c
+++ b/shell/rb-removable-media-manager.c
@@ -79,7 +79,7 @@ static gboolean rb_removable_media_manager_source_can_eject (RBRemovableMediaMan
static void rb_removable_media_manager_set_uimanager (RBRemovableMediaManager *mgr,
GtkUIManager *uimanager);
-static void rb_removable_media_manager_append_media_source (RBRemovableMediaManager *mgr, RBRemovableMediaSource *source);
+static void rb_removable_media_manager_append_media_source (RBRemovableMediaManager *mgr, RBSource *source);
static void rb_removable_media_manager_add_volume (RBRemovableMediaManager *mgr, GVolume *volume);
static void rb_removable_media_manager_remove_volume (RBRemovableMediaManager *mgr, GVolume *volume);
@@ -90,6 +90,9 @@ static void volume_added_cb (GVolumeMonitor *monitor, GVolume *volume, RBRemovab
static void volume_removed_cb (GVolumeMonitor *monitor, GVolume *volume, RBRemovableMediaManager *manager);
static void mount_added_cb (GVolumeMonitor *monitor, GMount *mount, RBRemovableMediaManager *manager);
static void mount_removed_cb (GVolumeMonitor *monitor, GMount *mount, RBRemovableMediaManager *manager);
+#if defined(HAVE_GUDEV)
+static void uevent_cb (GUdevClient *client, const char *action, GUdevDevice *device, RBRemovableMediaManager *manager);
+#endif
static void do_transfer (RBRemovableMediaManager *manager);
static void rb_removable_media_manager_cmd_copy_tracks (GtkAction *action,
@@ -107,6 +110,7 @@ typedef struct
GList *sources;
GHashTable *volume_mapping;
GHashTable *mount_mapping;
+ GHashTable *device_mapping;
gboolean scanned;
GAsyncQueue *transfer_queue;
@@ -121,6 +125,11 @@ typedef struct
guint mount_removed_id;
guint volume_added_id;
guint volume_removed_id;
+
+#if defined(HAVE_GUDEV)
+ GUdevClient *gudev_client;
+ guint uevent_id;
+#endif
} RBRemovableMediaManagerPrivate;
G_DEFINE_TYPE (RBRemovableMediaManager, rb_removable_media_manager, G_TYPE_OBJECT)
@@ -138,6 +147,7 @@ enum
{
MEDIUM_ADDED,
TRANSFER_PROGRESS,
+ CREATE_SOURCE_DEVICE,
CREATE_SOURCE_VOLUME,
CREATE_SOURCE_MOUNT,
LAST_SIGNAL
@@ -248,6 +258,25 @@ rb_removable_media_manager_class_init (RBRemovableMediaManagerClass *klass)
3, G_TYPE_INT, G_TYPE_INT, G_TYPE_DOUBLE);
/**
+ * RBRemovableMediaManager::create-source-device
+ * @mgr: the #RBRemovableMediaManager
+ * @device: the device (actually a #GUdevDevice)
+ *
+ * Emitted when a new device is detected to allow plugins to create a
+ * corresponding #RBSource. The first signal handler that returns a
+ * source wins. Plugins should only use this signal if there will be
+ * no #GVolume or #GMount created for the device.
+ */
+ rb_removable_media_manager_signals[CREATE_SOURCE_DEVICE] =
+ g_signal_new ("create-source-device",
+ RB_TYPE_REMOVABLE_MEDIA_MANAGER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RBRemovableMediaManagerClass, create_source_device),
+ rb_signal_accumulator_object_handled, NULL,
+ rb_marshal_OBJECT__OBJECT,
+ RB_TYPE_SOURCE,
+ 1, G_TYPE_OBJECT);
+ /**
* RBRemovableMediaManager::create-source-volume
* @mgr: the #RBRemovableMediaManager
* @volume: the #GVolume
@@ -299,6 +328,7 @@ rb_removable_media_manager_init (RBRemovableMediaManager *mgr)
priv->volume_mapping = g_hash_table_new (NULL, NULL);
priv->mount_mapping = g_hash_table_new (NULL, NULL);
+ priv->device_mapping = g_hash_table_new (g_direct_hash, g_direct_equal);
priv->transfer_queue = g_async_queue_new ();
/*
@@ -333,6 +363,27 @@ rb_removable_media_manager_init (RBRemovableMediaManager *mgr)
"mount-removed",
G_CALLBACK (mount_removed_cb),
mgr, 0);
+
+#if defined(HAVE_GUDEV)
+ /*
+ * Monitor udev device events - we're only really interested in events
+ * for USB devices.
+ */
+ {
+ const char * const subsystems[] = { "usb", NULL };
+ priv->gudev_client = g_udev_client_new (subsystems);
+ }
+
+ priv->uevent_id = g_signal_connect_object (priv->gudev_client,
+ "uevent",
+ G_CALLBACK (uevent_cb),
+ mgr, 0);
+#endif
+
+ /* enable debugging of media player device lookups if requested */
+ if (rb_debug_matches ("mpid", "")) {
+ mpid_enable_debug (TRUE);
+ }
}
static void
@@ -363,6 +414,17 @@ rb_removable_media_manager_dispose (GObject *object)
priv->volume_monitor = NULL;
}
+#if defined(HAVE_GUDEV)
+ if (priv->gudev_client != NULL) {
+ g_signal_handler_disconnect (priv->gudev_client,
+ priv->uevent_id);
+ priv->uevent_id = 0;
+
+ g_object_unref (priv->gudev_client);
+ priv->gudev_client = NULL;
+ }
+#endif
+
if (priv->sources) {
g_list_free (priv->sources);
priv->sources = NULL;
@@ -376,6 +438,7 @@ rb_removable_media_manager_finalize (GObject *object)
{
RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (object);
+ g_hash_table_destroy (priv->device_mapping);
g_hash_table_destroy (priv->volume_mapping);
g_hash_table_destroy (priv->mount_mapping);
g_async_queue_unref (priv->transfer_queue);
@@ -494,6 +557,41 @@ mount_removed_cb (GVolumeMonitor *monitor,
}
+static void
+uevent_cb (GUdevClient *client, const char *action, GUdevDevice *device, RBRemovableMediaManager *mgr)
+{
+ RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr);
+ GUdevDeviceNumber devnum;
+ devnum = g_udev_device_get_device_number (device);
+ rb_debug ("%s event for %s (%x)", action, g_udev_device_get_sysfs_path (device), devnum);
+
+ if (g_str_equal (action, "add")) {
+ RBSource *source = NULL;
+
+ /* probably need to filter out devices related to things we've already seen.. */
+ if (g_hash_table_lookup (priv->device_mapping, GINT_TO_POINTER (devnum)) != NULL) {
+ rb_debug ("already have a source for this device");
+ return;
+ }
+
+ g_signal_emit (mgr, rb_removable_media_manager_signals[CREATE_SOURCE_DEVICE], 0, device, &source);
+ if (source != NULL) {
+ rb_debug ("created a source for this device");
+ g_hash_table_insert (priv->device_mapping, GINT_TO_POINTER (devnum), source);
+ rb_removable_media_manager_append_media_source (mgr, source);
+ }
+ } else if (g_str_equal (action, "remove")) {
+ RBSource *source;
+
+ source = g_hash_table_lookup (priv->device_mapping, GINT_TO_POINTER (devnum));
+ if (source) {
+ rb_debug ("removing the source created for this device");
+ rb_source_delete_thyself (source);
+ }
+ }
+}
+#endif
+
static gboolean
remove_by_source (gpointer thing, RBSource *source, RBSource *ref_source)
{
@@ -512,6 +610,9 @@ rb_removable_media_manager_source_deleted_cb (RBSource *source, RBRemovableMedia
g_hash_table_foreach_remove (priv->mount_mapping,
(GHRFunc)remove_by_source,
source);
+ g_hash_table_foreach_remove (priv->device_mapping,
+ (GHRFunc)remove_by_source,
+ source);
priv->sources = g_list_remove (priv->sources, source);
}
@@ -569,7 +670,7 @@ rb_removable_media_manager_add_volume (RBRemovableMediaManager *mgr, GVolume *vo
if (source) {
g_hash_table_insert (priv->volume_mapping, volume, source);
- rb_removable_media_manager_append_media_source (mgr, source);
+ rb_removable_media_manager_append_media_source (mgr, RB_SOURCE (source));
} else {
rb_debug ("Unhandled media");
}
@@ -597,6 +698,9 @@ rb_removable_media_manager_add_mount (RBRemovableMediaManager *mgr, GMount *moun
RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr);
RBRemovableMediaSource *source = NULL;
GVolume *volume;
+ GFile *mount_root;
+ char *mountpoint;
+ MPIDDevice *device_info;
g_assert (mount != NULL);
@@ -638,7 +742,7 @@ rb_removable_media_manager_add_mount (RBRemovableMediaManager *mgr, GMount *moun
if (source) {
g_hash_table_insert (priv->mount_mapping, mount, source);
- rb_removable_media_manager_append_media_source (mgr, source);
+ rb_removable_media_manager_append_media_source (mgr, RB_SOURCE (source));
} else {
rb_debug ("Unhandled media");
}
@@ -662,7 +766,7 @@ rb_removable_media_manager_remove_mount (RBRemovableMediaManager *mgr, GMount *m
}
static void
-rb_removable_media_manager_append_media_source (RBRemovableMediaManager *mgr, RBRemovableMediaSource *source)
+rb_removable_media_manager_append_media_source (RBRemovableMediaManager *mgr, RBSource *source)
{
RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr);
@@ -930,6 +1034,16 @@ rb_removable_media_manager_scan (RBRemovableMediaManager *manager)
g_object_unref (mount);
}
g_list_free (list);
+
+ /* - check devices */
+#if defined(HAVE_GUDEV)
+ list = g_udev_client_query_by_subsystem (priv->gudev_client, "usb");
+ for (it = list; it != NULL; it = g_list_next (it)) {
+ /* pretend the device was just added */
+ uevent_cb (priv->gudev_client, "add", G_UDEV_DEVICE (it->data), manager);
+ }
+ g_list_free (list);
+#endif
}
/* Track transfer */
diff --git a/shell/rb-removable-media-manager.h b/shell/rb-removable-media-manager.h
index 7303056..4586c8d 100644
--- a/shell/rb-removable-media-manager.h
+++ b/shell/rb-removable-media-manager.h
@@ -69,6 +69,9 @@ struct _RBRemovableMediaManagerClass
gint done,
gint total,
double fraction);
+
+ RBSource * (*create_source_device) (RBRemovableMediaManager *mgr,
+ GObject *device); /* actually a GUdevDevice */
RBSource * (*create_source_mount) (RBRemovableMediaManager *mgr,
GMount *mount,
MPIDDevice *device_info);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]