|
|
769c0b |
From 23c448b0e38a2e0fc04fa07f4fda030a0dc27d44 Mon Sep 17 00:00:00 2001
|
|
|
769c0b |
From: Philip Langdale <philipl@overt.org>
|
|
|
769c0b |
Date: Sat, 23 Feb 2013 18:24:05 -0800
|
|
|
769c0b |
Subject: [PATCH 1/5] MTP: Refactor read path in preparation for supporting
|
|
|
769c0b |
normal files.
|
|
|
769c0b |
|
|
|
769c0b |
The existing logic for reading only works for preview icons, but
|
|
|
769c0b |
I'm about to add support for reading normal files using special
|
|
|
769c0b |
MTP calls. For that, we need the read calls to work for both cases.
|
|
|
769c0b |
|
|
|
769c0b |
To achieve that, we need to make reading more stateful.
|
|
|
769c0b |
---
|
|
|
769c0b |
daemon/gvfsbackendmtp.c | 140 +++++++++++++++++++++++++++++++++++++----------
|
|
|
769c0b |
1 file changed, 110 insertions(+), 30 deletions(-)
|
|
|
769c0b |
|
|
|
769c0b |
diff --git a/daemon/gvfsbackendmtp.c b/daemon/gvfsbackendmtp.c
|
|
|
769c0b |
index 8daa2c2..71fb732 100644
|
|
|
769c0b |
--- a/daemon/gvfsbackendmtp.c
|
|
|
769c0b |
+++ b/daemon/gvfsbackendmtp.c
|
|
|
769c0b |
@@ -106,6 +106,26 @@ DEBUG_ENUMERATE (const gchar *message, ...)
|
|
|
769c0b |
|
|
|
769c0b |
|
|
|
769c0b |
/************************************************
|
|
|
769c0b |
+ * Private Types
|
|
|
769c0b |
+ ************************************************/
|
|
|
769c0b |
+
|
|
|
769c0b |
+typedef enum {
|
|
|
769c0b |
+ HANDLE_FILE,
|
|
|
769c0b |
+ HANDLE_PREVIEW,
|
|
|
769c0b |
+} HandleType;
|
|
|
769c0b |
+
|
|
|
769c0b |
+typedef struct {
|
|
|
769c0b |
+ HandleType handle_type;
|
|
|
769c0b |
+ uint32_t id;
|
|
|
769c0b |
+ goffset offset;
|
|
|
769c0b |
+ gsize size;
|
|
|
769c0b |
+
|
|
|
769c0b |
+ /* For previews only */
|
|
|
769c0b |
+ GByteArray *bytes;
|
|
|
769c0b |
+} RWHandle;
|
|
|
769c0b |
+
|
|
|
769c0b |
+
|
|
|
769c0b |
+/************************************************
|
|
|
769c0b |
* Initialization
|
|
|
769c0b |
************************************************/
|
|
|
769c0b |
|
|
|
769c0b |
@@ -1447,30 +1467,26 @@ do_open_icon_for_read (GVfsBackend *backend,
|
|
|
769c0b |
guint id = strtol (icon_id, NULL, 10);
|
|
|
769c0b |
|
|
|
769c0b |
if (id > 0) {
|
|
|
769c0b |
+ GByteArray *bytes;
|
|
|
769c0b |
unsigned char *data;
|
|
|
769c0b |
unsigned int size;
|
|
|
769c0b |
int ret = LIBMTP_Get_Thumbnail (G_VFS_BACKEND_MTP (backend)->device, id,
|
|
|
769c0b |
&data, &size);
|
|
|
769c0b |
if (ret == 0) {
|
|
|
769c0b |
DEBUG ("File %u has thumbnail: %u", id, size);
|
|
|
769c0b |
- GByteArray *bytes = g_byte_array_sized_new (size);
|
|
|
769c0b |
+ bytes = g_byte_array_sized_new (size);
|
|
|
769c0b |
g_byte_array_append (bytes, data, size);
|
|
|
769c0b |
free (data);
|
|
|
769c0b |
- g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), FALSE);
|
|
|
769c0b |
- g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), bytes);
|
|
|
769c0b |
- g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
|
769c0b |
} else {
|
|
|
769c0b |
LIBMTP_filesampledata_t *sample_data = LIBMTP_new_filesampledata_t ();
|
|
|
769c0b |
ret = LIBMTP_Get_Representative_Sample (G_VFS_BACKEND_MTP (backend)->device,
|
|
|
769c0b |
id, sample_data);
|
|
|
769c0b |
if (ret == 0) {
|
|
|
769c0b |
DEBUG ("File %u has sampledata: %u", id, size);
|
|
|
769c0b |
- GByteArray *bytes = g_byte_array_sized_new (sample_data->size);
|
|
|
769c0b |
+ bytes = g_byte_array_sized_new (sample_data->size);
|
|
|
769c0b |
g_byte_array_append (bytes, (const guint8 *)sample_data->data, sample_data->size);
|
|
|
769c0b |
+ size = sample_data->size;
|
|
|
769c0b |
LIBMTP_destroy_filesampledata_t (sample_data);
|
|
|
769c0b |
- g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), FALSE);
|
|
|
769c0b |
- g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), bytes);
|
|
|
769c0b |
- g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
|
769c0b |
} else {
|
|
|
769c0b |
DEBUG ("File %u has no thumbnail:", id);
|
|
|
769c0b |
g_vfs_job_failed (G_VFS_JOB (job),
|
|
|
769c0b |
@@ -1478,58 +1494,121 @@ do_open_icon_for_read (GVfsBackend *backend,
|
|
|
769c0b |
G_IO_ERROR_NOT_FOUND,
|
|
|
769c0b |
_("No thumbnail for entity '%s'"),
|
|
|
769c0b |
icon_id);
|
|
|
769c0b |
+ goto exit;
|
|
|
769c0b |
}
|
|
|
769c0b |
}
|
|
|
769c0b |
+
|
|
|
769c0b |
+ RWHandle *handle = g_new0(RWHandle, 1);
|
|
|
769c0b |
+ handle->handle_type = HANDLE_PREVIEW;
|
|
|
769c0b |
+ handle->id = id;
|
|
|
769c0b |
+ handle->offset = 0;
|
|
|
769c0b |
+ handle->size = size;
|
|
|
769c0b |
+ handle->bytes = bytes;
|
|
|
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 |
} else {
|
|
|
769c0b |
g_vfs_job_failed (G_VFS_JOB (job),
|
|
|
769c0b |
G_IO_ERROR,
|
|
|
769c0b |
G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
769c0b |
_("Malformed icon identifier '%s'"),
|
|
|
769c0b |
icon_id);
|
|
|
769c0b |
+ goto exit;
|
|
|
769c0b |
}
|
|
|
769c0b |
+
|
|
|
769c0b |
+ exit:
|
|
|
769c0b |
g_mutex_unlock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
|
|
|
769c0b |
DEBUG ("(I) do_open_icon_for_read done.");
|
|
|
769c0b |
}
|
|
|
769c0b |
+#endif /* HAVE_LIBMTP_GET_THUMBNAIL */
|
|
|
769c0b |
|
|
|
769c0b |
|
|
|
769c0b |
-static gboolean
|
|
|
769c0b |
-try_read (GVfsBackend *backend,
|
|
|
769c0b |
- GVfsJobRead *job,
|
|
|
769c0b |
- GVfsBackendHandle handle,
|
|
|
769c0b |
- char *buffer,
|
|
|
769c0b |
- gsize bytes_requested)
|
|
|
769c0b |
+static void
|
|
|
769c0b |
+do_seek_on_read (GVfsBackend *backend,
|
|
|
769c0b |
+ GVfsJobSeekRead *job,
|
|
|
769c0b |
+ GVfsBackendHandle opaque_handle,
|
|
|
769c0b |
+ goffset offset,
|
|
|
769c0b |
+ GSeekType type)
|
|
|
769c0b |
+{
|
|
|
769c0b |
+ RWHandle *handle = opaque_handle;
|
|
|
769c0b |
+ uint32_t id = handle->id;
|
|
|
769c0b |
+ goffset old_offset = handle->offset;
|
|
|
769c0b |
+ gsize size = handle->size;
|
|
|
769c0b |
+
|
|
|
769c0b |
+ DEBUG ("(I) do_seek_on_read (%u %lu %ld %u)", id, old_offset, offset, type);
|
|
|
769c0b |
+ g_mutex_lock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
+
|
|
|
769c0b |
+ if (type == G_SEEK_END) {
|
|
|
769c0b |
+ offset = size + offset;
|
|
|
769c0b |
+ } else if (type == G_SEEK_CUR) {
|
|
|
769c0b |
+ offset += old_offset;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
+ if (offset > size || offset < 0) {
|
|
|
769c0b |
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
|
|
|
769c0b |
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
769c0b |
+ _("Can't seek outside file"));
|
|
|
769c0b |
+ goto exit;
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+
|
|
|
769c0b |
+ handle->offset = offset;
|
|
|
769c0b |
+ g_vfs_job_seek_read_set_offset (job, offset);
|
|
|
769c0b |
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
|
769c0b |
+
|
|
|
769c0b |
+ exit:
|
|
|
769c0b |
+ g_mutex_unlock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
+ DEBUG ("(I) do_seek_on_read done. (%lu)", offset);
|
|
|
769c0b |
+}
|
|
|
769c0b |
+
|
|
|
769c0b |
+
|
|
|
769c0b |
+static void
|
|
|
769c0b |
+do_read (GVfsBackend *backend,
|
|
|
769c0b |
+ GVfsJobRead *job,
|
|
|
769c0b |
+ GVfsBackendHandle opaque_handle,
|
|
|
769c0b |
+ char *buffer,
|
|
|
769c0b |
+ gsize bytes_requested)
|
|
|
769c0b |
{
|
|
|
769c0b |
- GByteArray *bytes = handle;
|
|
|
769c0b |
+ RWHandle *handle = opaque_handle;
|
|
|
769c0b |
+ uint32_t id = handle->id;
|
|
|
769c0b |
+ goffset offset = handle->offset;
|
|
|
769c0b |
+ gsize size = handle->size;
|
|
|
769c0b |
|
|
|
769c0b |
- DEBUG ("(I) try_read (%u %lu)", bytes->len, bytes_requested);
|
|
|
769c0b |
+ DEBUG ("(I) do_read (%u %lu %lu)", id, offset, bytes_requested);
|
|
|
769c0b |
+ g_mutex_lock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
|
|
|
769c0b |
- gsize bytes_to_copy = MIN (bytes->len, bytes_requested);
|
|
|
769c0b |
- if (bytes_to_copy == 0) {
|
|
|
769c0b |
- goto out;
|
|
|
769c0b |
+ uint32_t actual;
|
|
|
769c0b |
+ if (handle->handle_type == HANDLE_FILE) {
|
|
|
769c0b |
+ g_assert_not_reached();
|
|
|
769c0b |
+ } else {
|
|
|
769c0b |
+ GByteArray *bytes = handle->bytes;
|
|
|
769c0b |
+ actual = MIN (bytes->len - offset, bytes_requested);
|
|
|
769c0b |
+ memcpy (buffer, bytes->data + offset, actual);
|
|
|
769c0b |
}
|
|
|
769c0b |
- memcpy (buffer, bytes->data, bytes_to_copy);
|
|
|
769c0b |
- g_byte_array_remove_range (bytes, 0, bytes_to_copy);
|
|
|
769c0b |
|
|
|
769c0b |
- out:
|
|
|
769c0b |
- g_vfs_job_read_set_size (job, bytes_to_copy);
|
|
|
769c0b |
+ handle->offset = offset + actual;
|
|
|
769c0b |
+ g_vfs_job_read_set_size (job, actual);
|
|
|
769c0b |
g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
|
769c0b |
|
|
|
769c0b |
- DEBUG ("(I) try_read done.");
|
|
|
769c0b |
- return TRUE;
|
|
|
769c0b |
+ exit:
|
|
|
769c0b |
+ g_mutex_unlock (&G_VFS_BACKEND_MTP (backend)->mutex);
|
|
|
769c0b |
+ DEBUG ("(I) do_read done.");
|
|
|
769c0b |
}
|
|
|
769c0b |
|
|
|
769c0b |
static void
|
|
|
769c0b |
do_close_read (GVfsBackend *backend,
|
|
|
769c0b |
GVfsJobCloseRead *job,
|
|
|
769c0b |
- GVfsBackendHandle handle)
|
|
|
769c0b |
+ GVfsBackendHandle opaque_handle)
|
|
|
769c0b |
{
|
|
|
769c0b |
DEBUG ("(I) do_close_read");
|
|
|
769c0b |
- g_byte_array_unref (handle);
|
|
|
769c0b |
+ RWHandle *handle = opaque_handle;
|
|
|
769c0b |
+ if (handle->bytes) {
|
|
|
769c0b |
+ g_byte_array_unref (handle->bytes);
|
|
|
769c0b |
+ }
|
|
|
769c0b |
+ g_free(handle);
|
|
|
769c0b |
g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
|
769c0b |
DEBUG ("(I) do_close_read done.");
|
|
|
769c0b |
}
|
|
|
769c0b |
-#endif /* HAVE_LIBMTP_GET_THUMBNAIL */
|
|
|
769c0b |
|
|
|
769c0b |
|
|
|
769c0b |
/************************************************
|
|
|
769c0b |
@@ -1560,7 +1639,8 @@ g_vfs_backend_mtp_class_init (GVfsBackendMtpClass *klass)
|
|
|
769c0b |
backend_class->create_file_monitor = do_create_file_monitor;
|
|
|
769c0b |
#if HAVE_LIBMTP_1_1_5
|
|
|
769c0b |
backend_class->open_icon_for_read = do_open_icon_for_read;
|
|
|
769c0b |
- backend_class->try_read = try_read;
|
|
|
769c0b |
- backend_class->close_read = do_close_read;
|
|
|
769c0b |
#endif
|
|
|
769c0b |
+ backend_class->seek_on_read = do_seek_on_read;
|
|
|
769c0b |
+ backend_class->read = do_read;
|
|
|
769c0b |
+ backend_class->close_read = do_close_read;
|
|
|
769c0b |
}
|
|
|
769c0b |
--
|
|
|
769c0b |
1.7.10.4
|
|
|
769c0b |
|