|
|
769c0b |
From 1dcd334d633a79bf2a81f8bcb8e463864a858fa1 Mon Sep 17 00:00:00 2001
|
|
|
769c0b |
From: Philip Langdale <philipl@overt.org>
|
|
|
769c0b |
Date: Mon, 11 Feb 2013 07:55:11 -0800
|
|
|
769c0b |
Subject: [PATCH 2/5] WIP: Use android extensions to support in place read of
|
|
|
769c0b |
files.
|
|
|
769c0b |
|
|
|
769c0b |
Allows for opening files directly on the device and reading from them.
|
|
|
769c0b |
---
|
|
|
769c0b |
configure.ac | 5 +++
|
|
|
769c0b |
daemon/gvfsbackendmtp.c | 84 +++++++++++++++++++++++++++++++++++++++++++++--
|
|
|
769c0b |
daemon/gvfsbackendmtp.h | 2 ++
|
|
|
769c0b |
3 files changed, 89 insertions(+), 2 deletions(-)
|
|
|
769c0b |
|
|
|
769c0b |
diff --git a/configure.ac b/configure.ac
|
|
|
769c0b |
index 0f5ab9a..4b88316 100644
|
|
|
769c0b |
--- a/configure.ac
|
|
|
769c0b |
+++ b/configure.ac
|
|
|
769c0b |
@@ -548,6 +548,11 @@ if test "x$enable_libmtp" != "xno" -a "x$msg_gudev" = "xyes"; then
|
|
|
769c0b |
AC_DEFINE(HAVE_LIBMTP_1_1_5, 1, [Define to 1 if libmtp 1.1.5 is available]),
|
|
|
769c0b |
[]
|
|
|
769c0b |
)
|
|
|
769c0b |
+
|
|
|
769c0b |
+ PKG_CHECK_MODULES(LIBMTP_1_1_6, libmtp >= 1.1.6,
|
|
|
769c0b |
+ AC_DEFINE(HAVE_LIBMTP_1_1_6, 1, [Define to 1 if libmtp 1.1.6 is available]),
|
|
|
769c0b |
+ []
|
|
|
769c0b |
+ )
|
|
|
769c0b |
fi
|
|
|
769c0b |
fi
|
|
|
769c0b |
|
|
|
769c0b |
diff --git a/daemon/gvfsbackendmtp.c b/daemon/gvfsbackendmtp.c
|
|
|
769c0b |
index 71fb732..9b58f2b 100644
|
|
|
769c0b |
--- a/daemon/gvfsbackendmtp.c
|
|
|
769c0b |
+++ b/daemon/gvfsbackendmtp.c
|
|
|
769c0b |
@@ -631,6 +631,15 @@ get_device (GVfsBackend *backend, const char *id, GVfsJob *job) {
|
|
|
769c0b |
}
|
|
|
769c0b |
}
|
|
|
769c0b |
|
|
|
769c0b |
+ /* Check supported methods/extensions. */
|
|
|
769c0b |
+ LIBMTP_device_extension_t *extension;
|
|
|
769c0b |
+ for (extension = device->extensions; extension != NULL; extension = extension->next) {
|
|
|
769c0b |
+ if (g_strcmp0 ("android.com", extension->name) == 0) {
|
|
|
769c0b |
+ G_VFS_BACKEND_MTP (backend)->android_extension = TRUE;
|
|
|
769c0b |
+ break;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
exit:
|
|
|
769c0b |
DEBUG ("(II) get_device done.");
|
|
|
769c0b |
return device;
|
|
|
769c0b |
@@ -1455,6 +1464,64 @@ do_set_display_name (GVfsBackend *backend,
|
|
|
769c0b |
}
|
|
|
769c0b |
|
|
|
769c0b |
|
|
|
769c0b |
+#if HAVE_LIBMTP_1_1_6
|
|
|
769c0b |
+static void
|
|
|
769c0b |
+do_open_for_read (GVfsBackend *backend,
|
|
|
769c0b |
+ GVfsJobOpenForRead *job,
|
|
|
769c0b |
+ const char *filename)
|
|
|
769c0b |
+{
|
|
|
769c0b |
+ if (!G_VFS_BACKEND_MTP (backend)->android_extension) {
|
|
|
769c0b |
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
|
|
|
769c0b |
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
|
|
769c0b |
+ _("Operation not supported."));
|
|
|
769c0b |
+ return;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
+ DEBUG ("(I) do_open_for_read (%s)", filename);
|
|
|
769c0b |
+ g_mutex_lock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
+
|
|
|
769c0b |
+ gchar **elements = g_strsplit_set (filename, "/", -1);
|
|
|
769c0b |
+ unsigned int ne = g_strv_length (elements);
|
|
|
769c0b |
+
|
|
|
769c0b |
+ if (ne < 3) {
|
|
|
769c0b |
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
|
|
|
769c0b |
+ G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
769c0b |
+ _("Cannot open this entity"));
|
|
|
769c0b |
+ goto exit;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
+ unsigned int id = strtol (elements[ne-1], NULL, 10);
|
|
|
769c0b |
+
|
|
|
769c0b |
+ LIBMTP_mtpdevice_t *device;
|
|
|
769c0b |
+ device = G_VFS_BACKEND_MTP (backend)->device;
|
|
|
769c0b |
+
|
|
|
769c0b |
+ LIBMTP_file_t *file = LIBMTP_Get_Filemetadata (device, id);
|
|
|
769c0b |
+ if (file == NULL) {
|
|
|
769c0b |
+ fail_job (G_VFS_JOB (job), device);
|
|
|
769c0b |
+ goto exit;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
+ RWHandle *handle = g_new0(RWHandle, 1);
|
|
|
769c0b |
+ handle->handle_type = HANDLE_FILE;
|
|
|
769c0b |
+ handle->id = id;
|
|
|
769c0b |
+ handle->offset = 0;
|
|
|
769c0b |
+ handle->size = file->filesize;
|
|
|
769c0b |
+
|
|
|
769c0b |
+ LIBMTP_destroy_file_t (file);
|
|
|
769c0b |
+
|
|
|
769c0b |
+ g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), TRUE);
|
|
|
769c0b |
+ g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), handle);
|
|
|
769c0b |
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
|
769c0b |
+
|
|
|
769c0b |
+ exit:
|
|
|
769c0b |
+ g_strfreev (elements);
|
|
|
769c0b |
+ g_mutex_unlock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
+
|
|
|
769c0b |
+ DEBUG ("(I) do_open_for_read done.");
|
|
|
769c0b |
+}
|
|
|
769c0b |
+#endif /* HAVE_LIBMTP_1_1_6 */
|
|
|
769c0b |
+
|
|
|
769c0b |
+
|
|
|
769c0b |
#if HAVE_LIBMTP_1_1_5
|
|
|
769c0b |
static void
|
|
|
769c0b |
do_open_icon_for_read (GVfsBackend *backend,
|
|
|
769c0b |
@@ -1521,7 +1588,7 @@ do_open_icon_for_read (GVfsBackend *backend,
|
|
|
769c0b |
|
|
|
769c0b |
DEBUG ("(I) do_open_icon_for_read done.");
|
|
|
769c0b |
}
|
|
|
769c0b |
-#endif /* HAVE_LIBMTP_GET_THUMBNAIL */
|
|
|
769c0b |
+#endif /* HAVE_LIBMTP_1_1_5 */
|
|
|
769c0b |
|
|
|
769c0b |
|
|
|
769c0b |
static void
|
|
|
769c0b |
@@ -1579,7 +1646,17 @@ do_read (GVfsBackend *backend,
|
|
|
769c0b |
|
|
|
769c0b |
uint32_t actual;
|
|
|
769c0b |
if (handle->handle_type == HANDLE_FILE) {
|
|
|
769c0b |
- g_assert_not_reached();
|
|
|
769c0b |
+ unsigned char *temp;
|
|
|
769c0b |
+ int ret = LIBMTP_GetPartialObject (G_VFS_BACKEND_MTP (backend)->device, id, offset,
|
|
|
769c0b |
+ bytes_requested, &temp, &actual);
|
|
|
769c0b |
+ if (ret != 0) {
|
|
|
769c0b |
+ fail_job (G_VFS_JOB (job), G_VFS_BACKEND_MTP (backend)->device);
|
|
|
769c0b |
+ DEBUG ("(I) job failed.");
|
|
|
769c0b |
+ goto exit;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
+ memcpy (buffer, temp, actual);
|
|
|
769c0b |
+ free (temp);
|
|
|
769c0b |
} else {
|
|
|
769c0b |
GByteArray *bytes = handle->bytes;
|
|
|
769c0b |
actual = MIN (bytes->len - offset, bytes_requested);
|
|
|
769c0b |
@@ -1637,6 +1714,9 @@ g_vfs_backend_mtp_class_init (GVfsBackendMtpClass *klass)
|
|
|
769c0b |
backend_class->set_display_name = do_set_display_name;
|
|
|
769c0b |
backend_class->create_dir_monitor = do_create_dir_monitor;
|
|
|
769c0b |
backend_class->create_file_monitor = do_create_file_monitor;
|
|
|
769c0b |
+#if HAVE_LIBMTP_1_1_6
|
|
|
769c0b |
+ backend_class->open_for_read = do_open_for_read;
|
|
|
769c0b |
+#endif
|
|
|
769c0b |
#if HAVE_LIBMTP_1_1_5
|
|
|
769c0b |
backend_class->open_icon_for_read = do_open_icon_for_read;
|
|
|
769c0b |
#endif
|
|
|
769c0b |
diff --git a/daemon/gvfsbackendmtp.h b/daemon/gvfsbackendmtp.h
|
|
|
769c0b |
index 4137b65..0fe1dec 100644
|
|
|
769c0b |
--- a/daemon/gvfsbackendmtp.h
|
|
|
769c0b |
+++ b/daemon/gvfsbackendmtp.h
|
|
|
769c0b |
@@ -57,6 +57,8 @@ struct _GVfsBackendMtp
|
|
|
769c0b |
GHashTable *monitors;
|
|
|
769c0b |
guint hb_id;
|
|
|
769c0b |
gint unmount_started;
|
|
|
769c0b |
+
|
|
|
769c0b |
+ gboolean android_extension;
|
|
|
769c0b |
};
|
|
|
769c0b |
|
|
|
769c0b |
struct _GVfsBackendMtpClass
|
|
|
769c0b |
--
|
|
|
769c0b |
1.7.10.4
|
|
|
769c0b |
|