[rhythmbox] mtp: drop support for libmtp < 0.3.0, add GUdev based detection
- From: Jonathan Matthew <jmatthew src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [rhythmbox] mtp: drop support for libmtp < 0.3.0, add GUdev based detection
- Date: Wed, 5 Aug 2009 11:49:56 +0000 (UTC)
commit 91e93ba16a92c1d50c2c44e23aef460b445bbf05
Author: Jonathan Matthew <jonathan d14n org>
Date: Wed Aug 5 21:45:43 2009 +1000
mtp: drop support for libmtp < 0.3.0, add GUdev based detection
The HAL device detection code is still there, and will be until GUdev is
widely available.
This uses the new device management functions in libmtp 0.3.0, which
means multiple devices should work (bug #563544). Since the device
detection is triggered by the removable media manager now, the 'scan
removable media' menu item now finds available MTP devices (bug #561953).
configure.ac | 32 ++++----
plugins/mtpdevice/Makefile.am | 2 +
plugins/mtpdevice/rb-mtp-plugin.c | 138 ++++++++++++++++++++++++++++++++++---
plugins/mtpdevice/rb-mtp-source.c | 64 +++++------------
plugins/mtpdevice/rb-mtp-source.h | 7 ++-
5 files changed, 173 insertions(+), 70 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f205536..153d344 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,7 @@ VALA_REQS=0.1.0
AVAHI_REQS=0.6
LIBSOUP_REQS=2.26.0
GUDEV_REQS=143
+LIBMTP_REQS=0.3.0
AC_MSG_CHECKING([for GNU extension fwrite_unlocked])
AC_LINK_IFELSE(
@@ -168,27 +169,26 @@ AC_ARG_WITH(mtp,
[Enable MTP support]),,
with_mtp=auto)
if test "x$with_mtp" != "xno"; then
-
- PKG_CHECK_MODULES(MTP, libmtp, have_libmtp=yes, have_libmtp=no)
- if test "x$have_libmtp" = "xno" -a "x$with_mtp" = "xyes"; then
- AC_MSG_ERROR([MTP explicitly requested but libmtp couldn't be found])
+ can_use_mtp=no
+ if test x"$use_gudev" = "xyes" -o x"$enable_hal" = "xyes"; then
+ can_use_mtp=yes
fi
- if test "x$have_libmtp" = "xyes"; then
- if test "x$with_hal" = xyes && test "x$enable_hal" = xno; then
- AC_MSG_ERROR([MTP explicitly requested but HAL not found or too old])
+
+ PKG_CHECK_MODULES(MTP, libmtp >= $LIBMTP_REQS, have_libmtp=yes, have_libmtp=no)
+ if test x"$with_mtp" = "xyes"; then
+ if test x"$have_libmtp" = "xno"; then
+ AC_MSG_ERROR([MTP explicitly requested but libmtp is not available])
+ fi
+ if test x"$can_use_mtp" = "xno"; then
+ AC_MSG_ERROR([MTP explicitly requested but GUdev and HAL are not available])
fi
- if test "x$enable_hal" = xyes; then
- use_mtp=yes
- dnl Check for libmtp 0.3.0+
- PKG_CHECK_EXISTS(libmtp >= 0.3.0, found_libmtp_030_pkg=yes, found_libmtp_030_pkg=no)
- if test x"$found_libmtp_030_pkg" = "xyes" ; then
- AC_DEFINE([HAVE_LIBMTP_030], 1, [indicates whether libmtp 0.3.0 is installed])
- fi
- fi
+ fi
+ if test "x$have_libmtp" = "xyes" -a "x$can_use_mtp" = "xyes"; then
+ use_mtp=yes
AC_SUBST(MTP_CFLAGS)
AC_SUBST(MTP_LIBS)
fi
-fi
+fi
AM_CONDITIONAL(USE_MTP, test x"$use_mtp" = xyes)
diff --git a/plugins/mtpdevice/Makefile.am b/plugins/mtpdevice/Makefile.am
index 599a8a6..71175aa 100644
--- a/plugins/mtpdevice/Makefile.am
+++ b/plugins/mtpdevice/Makefile.am
@@ -13,6 +13,7 @@ libmtpdevice_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libmtpdevice_la_LIBTOOLFLAGS = --tag=disable-static
libmtpdevice_la_LIBADD = \
$(top_builddir)/shell/librhythmbox-core.la \
+ $(GUDEV_LIBS) \
$(HAL_LIBS) \
$(MTP_LIBS)
@@ -35,6 +36,7 @@ INCLUDES = \
-DSHARE_DIR=\"$(pkgdatadir)\" \
-DDATADIR=\""$(datadir)"\" \
$(RHYTHMBOX_CFLAGS) \
+ $(GUDEV_CFLAGS) \
$(HAL_CFLAGS) \
$(MTP_CFLAGS) \
-D_XOPEN_SOURCE -D_BSD_SOURCE
diff --git a/plugins/mtpdevice/rb-mtp-plugin.c b/plugins/mtpdevice/rb-mtp-plugin.c
index 8aa40f4..c1d7053 100644
--- a/plugins/mtpdevice/rb-mtp-plugin.c
+++ b/plugins/mtpdevice/rb-mtp-plugin.c
@@ -37,10 +37,16 @@
#include <glib.h>
#include <glib-object.h>
#include <libmtp.h>
+
+#if defined(HAVE_GUDEV)
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+#else
#include <hal/libhal.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#endif
#include "rb-source.h"
#include "rb-sourcelist.h"
@@ -51,6 +57,7 @@
#include "rb-util.h"
#include "rb-shell.h"
#include "rb-stock-icons.h"
+#include "rb-removable-media-manager.h"
#define RB_TYPE_MTP_PLUGIN (rb_mtp_plugin_get_type ())
@@ -69,10 +76,14 @@ typedef struct
GtkActionGroup *action_group;
guint ui_merge_id;
+ guint create_device_source_id;
+
GList *mtp_sources;
+#if !defined(HAVE_GUDEV)
LibHalContext *hal_context;
DBusConnection *dbus_connection;
+#endif
} RBMtpPlugin;
typedef struct
@@ -89,11 +100,14 @@ static void rb_mtp_plugin_finalize (GObject *object);
static void impl_activate (RBPlugin *plugin, RBShell *shell);
static void impl_deactivate (RBPlugin *plugin, RBShell *shell);
+#if defined(HAVE_GUDEV)
+static RBSource* create_source_device_cb (RBRemovableMediaManager *rmm, GObject *device, RBMtpPlugin *plugin);
+#else
static void rb_mtp_plugin_device_added (LibHalContext *context, const char *udi);
static void rb_mtp_plugin_device_removed (LibHalContext *context, const char *udi);
static gboolean rb_mtp_plugin_setup_dbus_hal_connection (RBMtpPlugin *plugin);
-
static RBSource* create_source_cb (RBMtpPlugin *plugin, LIBMTP_mtpdevice_t *device, const char *udi);
+#endif
static void rb_mtp_plugin_eject (GtkAction *action, RBMtpPlugin *plugin);
static void rb_mtp_plugin_rename (GtkAction *action, RBMtpPlugin *plugin);
@@ -149,16 +163,22 @@ impl_activate (RBPlugin *bplugin, RBShell *shell)
{
RBMtpPlugin *plugin = RB_MTP_PLUGIN (bplugin);
GtkUIManager *uimanager = NULL;
+ RBRemovableMediaManager *rmm;
char *file = NULL;
+#if defined(HAVE_GUDEV)
+ gboolean rmm_scanned = FALSE;
+#else
int num, i, ret;
char **devices;
LIBMTP_device_entry_t *entries;
int numentries;
+#endif
plugin->shell = shell;
g_object_get (G_OBJECT (shell),
"ui-manager", &uimanager,
+ "removable-media-manager", &rmm,
NULL);
/* ui */
@@ -174,9 +194,22 @@ impl_activate (RBPlugin *bplugin, RBShell *shell)
g_object_unref (G_OBJECT (uimanager));
/* device detection */
-
+#if defined(HAVE_GUDEV)
+ plugin->create_device_source_id =
+ g_signal_connect_object (rmm,
+ "create-source-device",
+ G_CALLBACK (create_source_device_cb),
+ plugin,
+ 0);
+
+ /* only scan if we're being loaded after the initial scan has been done */
+ g_object_get (rmm, "scanned", &rmm_scanned, NULL);
+ if (rmm_scanned)
+ rb_removable_media_manager_scan (rmm);
+#else
if (rb_mtp_plugin_setup_dbus_hal_connection (plugin) == FALSE) {
rb_debug ("not scanning for MTP devices because we couldn't get a HAL context");
+ g_object_unref (rmm);
return;
}
@@ -213,6 +246,10 @@ impl_activate (RBPlugin *bplugin, RBShell *shell)
libhal_free_string_array (devices);
rb_profile_end ("scanning for MTP devices");
+
+#endif
+
+ g_object_unref (rmm);
}
static void
@@ -220,9 +257,11 @@ impl_deactivate (RBPlugin *bplugin, RBShell *shell)
{
RBMtpPlugin *plugin = RB_MTP_PLUGIN (bplugin);
GtkUIManager *uimanager = NULL;
+ RBRemovableMediaManager *rmm = NULL;
g_object_get (G_OBJECT (shell),
"ui-manager", &uimanager,
+ "removable-media-manager", &rmm,
NULL);
gtk_ui_manager_remove_ui (uimanager, plugin->ui_merge_id);
@@ -232,6 +271,10 @@ impl_deactivate (RBPlugin *bplugin, RBShell *shell)
g_list_free (plugin->mtp_sources);
plugin->mtp_sources = NULL;
+#if defined(HAVE_GUDEV)
+ g_signal_handler_disconnect (rmm, plugin->create_device_source_id);
+ plugin->create_device_source_id = 0;
+#else
if (plugin->hal_context != NULL) {
DBusError error;
dbus_error_init (&error);
@@ -246,16 +289,89 @@ impl_deactivate (RBPlugin *bplugin, RBShell *shell)
dbus_connection_unref (plugin->dbus_connection);
plugin->dbus_connection = NULL;
}
+#endif
- g_object_unref (G_OBJECT (uimanager));
+ g_object_unref (uimanager);
+ g_object_unref (rmm);
}
static void
-rb_mtp_plugin_source_deleted (RBMtpSource *source, RBMtpPlugin *plugin)
+source_deleted_cb (RBMtpSource *source, RBMtpPlugin *plugin)
{
plugin->mtp_sources = g_list_remove (plugin->mtp_sources, source);
}
+#if defined(HAVE_GUDEV)
+static RBSource *
+create_source_device_cb (RBRemovableMediaManager *rmm, GObject *device, RBMtpPlugin *plugin)
+{
+ GUdevDeviceNumber device_number;
+ int i;
+ int num_raw_devices;
+ const char *devnum_str;
+ int devnum;
+ LIBMTP_raw_device_t *raw_devices;
+
+ /* check subsystem == usb? */
+ if (g_strcmp0 (g_udev_device_get_subsystem (G_UDEV_DEVICE (device)), "usb") != 0) {
+ rb_debug ("this is not a USB device");
+ return NULL;
+ }
+
+ device_number = g_udev_device_get_device_number (G_UDEV_DEVICE (device));
+ if (device_number == 0) {
+ rb_debug ("can't get udev device number for this device");
+ return NULL;
+ }
+ /* fun thing: usb device numbers are zero padded, which causes strtol to
+ * interpret them as octal if you don't specify a base.
+ */
+ devnum_str = g_udev_device_get_property (G_UDEV_DEVICE (device), "DEVNUM");
+ if (devnum_str == NULL) {
+ rb_debug ("device doesn't have a USB device number");
+ return NULL;
+ }
+ devnum = strtol (devnum_str, NULL, 10);
+
+ rb_debug ("trying to match device %x (usb device %d) against detected mtp devices",
+ device_number, devnum);
+
+ /* see what devices libmtp can find */
+ if (LIBMTP_Detect_Raw_Devices (&raw_devices, &num_raw_devices) == 0) {
+ for (i = 0; i < num_raw_devices; i++) {
+ LIBMTP_mtpdevice_t *device;
+ RBSource *source;
+
+ rb_debug ("detected mtp device: device number %d", raw_devices[i].devnum);
+
+ /* check bus number/device location somehow */
+ if (devnum != raw_devices[i].devnum) {
+ rb_debug ("device number mismatches: %d vs %d", devnum, raw_devices[i].devnum);
+ continue;
+ }
+
+ device = LIBMTP_Open_Raw_Device (&raw_devices[i]);
+ if (device == NULL) {
+ rb_debug ("unable to open device. weird.");
+ break;
+ }
+
+ rb_debug ("device matched, creating a source");
+ source = rb_mtp_source_new (plugin->shell, device);
+ plugin->mtp_sources = g_list_prepend (plugin->mtp_sources, source);
+ g_signal_connect_object (G_OBJECT (source),
+ "deleted", G_CALLBACK (source_deleted_cb),
+ plugin, 0);
+ return source;
+ }
+ }
+
+ rb_debug ("device didn't match anything");
+ return NULL;
+}
+
+#else
+
static RBSource *
create_source_cb (RBMtpPlugin *plugin, LIBMTP_mtpdevice_t *device, const char *udi)
{
@@ -267,15 +383,17 @@ create_source_cb (RBMtpPlugin *plugin, LIBMTP_mtpdevice_t *device, const char *u
plugin->mtp_sources = g_list_prepend (plugin->mtp_sources, source);
g_signal_connect_object (G_OBJECT (source),
- "deleted", G_CALLBACK (rb_mtp_plugin_source_deleted),
+ "deleted", G_CALLBACK (source_deleted_cb),
plugin, 0);
return source;
}
+#endif
+
+
static void
-rb_mtp_plugin_eject (GtkAction *action,
- RBMtpPlugin *plugin)
+rb_mtp_plugin_eject (GtkAction *action, RBMtpPlugin *plugin)
{
RBSourceList *sourcelist = NULL;
RBSource *source = NULL;
@@ -299,8 +417,7 @@ rb_mtp_plugin_eject (GtkAction *action,
}
static void
-rb_mtp_plugin_rename (GtkAction *action,
- RBMtpPlugin *plugin)
+rb_mtp_plugin_rename (GtkAction *action, RBMtpPlugin *plugin)
{
RBSourceList *sourcelist = NULL;
RBSource *source = NULL;
@@ -323,6 +440,8 @@ rb_mtp_plugin_rename (GtkAction *action,
g_object_unref (source);
}
+#if !defined(HAVE_GUDEV)
+
static void
rb_mtp_plugin_device_added (LibHalContext *context, const char *udi)
{
@@ -428,3 +547,4 @@ rb_mtp_plugin_setup_dbus_hal_connection (RBMtpPlugin *plugin)
return TRUE;
}
+#endif
diff --git a/plugins/mtpdevice/rb-mtp-source.c b/plugins/mtpdevice/rb-mtp-source.c
index 2508d38..20513de 100644
--- a/plugins/mtpdevice/rb-mtp-source.c
+++ b/plugins/mtpdevice/rb-mtp-source.c
@@ -54,40 +54,6 @@
#define CONF_STATE_PANED_POSITION CONF_PREFIX "/state/mtp/paned_position"
#define CONF_STATE_SHOW_BROWSER CONF_PREFIX "/state/mtp/show_browser"
-#ifndef HAVE_LIBMTP_030
-/*
- * Helpful macros to determine filetype properties
- */
-#define LIBMTP_FILETYPE_IS_AUDIO(a)\
-(a == LIBMTP_FILETYPE_WAV ||\
- a == LIBMTP_FILETYPE_MP3 ||\
- a == LIBMTP_FILETYPE_MP2 ||\
- a == LIBMTP_FILETYPE_WMA ||\
- a == LIBMTP_FILETYPE_OGG ||\
- a == LIBMTP_FILETYPE_FLAC ||\
- a == LIBMTP_FILETYPE_AAC ||\
- a == LIBMTP_FILETYPE_M4A ||\
- a == LIBMTP_FILETYPE_UNDEF_AUDIO)
-
-#define LIBMTP_FILETYPE_IS_VIDEO(a)\
-(a == LIBMTP_FILETYPE_WMV ||\
- a == LIBMTP_FILETYPE_AVI ||\
- a == LIBMTP_FILETYPE_MPEG ||\
- a == LIBMTP_FILETYPE_UNDEF_VIDEO)
-
-#define LIBMTP_FILETYPE_IS_AUDIOVIDEO(a)\
-(a == LIBMTP_FILETYPE_MP4 ||\
- a == LIBMTP_FILETYPE_ASF ||\
- a == LIBMTP_FILETYPE_QT)
-
-#define LIBMTP_FILETYPE_IS_TRACK(a)\
-(LIBMTP_FILETYPE_IS_AUDIO(a) ||\
- LIBMTP_FILETYPE_IS_VIDEO(a) ||\
- LIBMTP_FILETYPE_IS_AUDIOVIDEO(a))
-
-#endif
-
-
static GObject *rb_mtp_source_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties);
@@ -146,7 +112,9 @@ typedef struct
GHashTable *entry_map;
GHashTable *album_map;
GHashTable *artwork_request_map;
+#if !defined(HAVE_GUDEV)
char *udi;
+#endif
uint16_t supported_types[LIBMTP_FILETYPE_UNKNOWN+1];
GList *mediatypes;
gboolean album_art_supported;
@@ -227,6 +195,7 @@ rb_mtp_source_class_init (RBMtpSourceClass *klass)
"libmtp-device",
"libmtp device",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+#if !defined(HAVE_GUDEV)
g_object_class_install_property (object_class,
PROP_UDI,
g_param_spec_string ("udi",
@@ -234,6 +203,7 @@ rb_mtp_source_class_init (RBMtpSourceClass *klass)
"udi",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+#endif
g_type_class_add_private (klass, sizeof (RBMtpSourcePrivate));
}
@@ -422,9 +392,11 @@ rb_mtp_source_set_property (GObject *object,
case PROP_LIBMTP_DEVICE:
priv->device = g_value_get_pointer (value);
break;
+#if !defined(HAVE_GUDEV)
case PROP_UDI:
priv->udi = g_value_dup_string (value);
break;
+#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -443,9 +415,11 @@ rb_mtp_source_get_property (GObject *object,
case PROP_LIBMTP_DEVICE:
g_value_set_pointer (value, priv->device);
break;
+#if !defined(HAVE_GUDEV)
case PROP_UDI:
g_value_set_string (value, priv->udi);
break;
+#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -486,7 +460,9 @@ rb_mtp_source_finalize (GObject *object)
g_hash_table_destroy (priv->album_map);
g_hash_table_destroy (priv->artwork_request_map);
+#if !defined(HAVE_GUDEV)
g_free (priv->udi);
+#endif
LIBMTP_Release_Device (priv->device);
@@ -505,10 +481,16 @@ impl_get_paned_key (RBBrowserSource *source)
return g_strdup (CONF_STATE_PANED_POSITION);
}
-RBBrowserSource *
+#if defined(HAVE_GUDEV)
+RBSource *
+rb_mtp_source_new (RBShell *shell,
+ LIBMTP_mtpdevice_t *device)
+#else
+RBSource *
rb_mtp_source_new (RBShell *shell,
LIBMTP_mtpdevice_t *device,
const char *udi)
+#endif
{
RBMtpSource *source = NULL;
RhythmDBEntryType entry_type;
@@ -532,12 +514,14 @@ rb_mtp_source_new (RBShell *shell,
"volume", NULL,
"source-group", RB_SOURCE_GROUP_DEVICES,
"libmtp-device", device,
+#if !defined(HAVE_GUDEV)
"udi", udi,
+#endif
NULL));
rb_shell_register_entry_type_for_source (shell, RB_SOURCE (source), entry_type);
- return RB_BROWSER_SOURCE (source);
+ return RB_SOURCE (source);
}
static void
@@ -691,11 +675,7 @@ load_mtp_db_idle_cb (RBMtpSource* source)
device_forgets_albums = FALSE;
}
-#ifdef HAVE_LIBMTP_030
tracks = LIBMTP_Get_Tracklisting_With_Callback (priv->device, NULL, NULL);
-#else
- tracks = LIBMTP_Get_Tracklisting (priv->device);
-#endif
report_libmtp_errors (priv->device, FALSE);
if (tracks != NULL) {
LIBMTP_track_t *track;
@@ -1003,11 +983,7 @@ transfer_track (RBMtpSource *source,
LIBMTP_Get_Filetype_Description (trackmeta->filetype),
mimetype);
-#ifdef HAVE_LIBMTP_030
ret = LIBMTP_Send_Track_From_File (device, filename, trackmeta, NULL, NULL);
-#else
- ret = LIBMTP_Send_Track_From_File (device, filename, trackmeta, NULL, NULL, 0);
-#endif
rb_debug ("LIBMTP_Send_Track_From_File (%s) returned %d", filename, ret);
if (ret != 0) {
report_libmtp_errors (device, TRUE);
diff --git a/plugins/mtpdevice/rb-mtp-source.h b/plugins/mtpdevice/rb-mtp-source.h
index 5cc90b5..7c08ab3 100644
--- a/plugins/mtpdevice/rb-mtp-source.h
+++ b/plugins/mtpdevice/rb-mtp-source.h
@@ -54,7 +54,12 @@ typedef struct
RBRemovableMediaSourceClass parent;
} RBMtpSourceClass;
-RBBrowserSource * rb_mtp_source_new (RBShell *shell, LIBMTP_mtpdevice_t *device, const char *udi);
+#if defined(HAVE_GUDEV)
+RBSource * rb_mtp_source_new (RBShell *shell, LIBMTP_mtpdevice_t *device);
+#else
+RBSource * rb_mtp_source_new (RBShell *shell, LIBMTP_mtpdevice_t *device, const char *udi);
+#endif
+
GType rb_mtp_source_get_type (void);
GType rb_mtp_source_register_type (GTypeModule *module);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]