Blame SOURCES/gvfs-1.16.1-MTP-Refactor-read-path-in-preparation-for-supporting.patch

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