#include "gst/gst-i18n-plugin.h"
#include "gstgnomevfssrc.h"
+#include <gnome-vfs-module-2.0/libgnomevfs/gnome-vfs-cancellable-ops.h>
#include <stdio.h>
#include <stdlib.h>
static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src);
static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src);
static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src);
+static gboolean gst_gnome_vfs_src_unlock (GstBaseSrc * basesrc);
+static gboolean gst_gnome_vfs_src_unlock_stop (GstBaseSrc * basesrc);
static gboolean gst_gnome_vfs_src_get_size (GstBaseSrc * src, guint64 * size);
static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc,
guint64 offset, guint size, GstBuffer ** buffer);
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop);
+ gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_unlock);
+ gstbasesrc_class->unlock_stop =
+ GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_unlock_stop);
gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size);
gstbasesrc_class->is_seekable =
GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable);
{
gnomevfssrc->uri = NULL;
gnomevfssrc->uri_name = NULL;
+ gnomevfssrc->context = NULL;
gnomevfssrc->handle = NULL;
+ gnomevfssrc->interrupted = FALSE;
gnomevfssrc->curoffset = 0;
gnomevfssrc->seekable = FALSE;
guint8 *data, *ptr;
gsize todo;
GstGnomeVFSSrc *src;
+ gboolean interrupted = FALSE;
src = GST_GNOME_VFS_SRC (basesrc);
ptr = data;
todo = size;
- while (todo > 0) {
+ while (!src->interrupted && todo > 0) {
/* this can return less that we ask for */
- res = gnome_vfs_read (src->handle, ptr, todo, &readbytes);
+ res =
+ gnome_vfs_read_cancellable (src->handle, data, todo, &readbytes,
+ src->context);
+
+ if (G_UNLIKELY (res == GNOME_VFS_ERROR_CANCELLED)) {
+ GST_DEBUG_OBJECT (src, "interrupted");
+
+ /* Just take what we've so far gotten and return */
+ size = size - todo;
+ todo = 0;
+ interrupted = TRUE;
+ break;
+ }
if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK
&& readbytes == 0)))
}
gst_buffer_unmap (buf, data, size);
+ if (interrupted)
+ goto interrupted;
+
GST_BUFFER_OFFSET (buf) = src->curoffset;
src->curoffset += size;
("Failed to read data: %s", gnome_vfs_result_to_string (res)));
return GST_FLOW_ERROR;
}
+interrupted:
+ {
+ gst_buffer_unref (buf);
+ return GST_FLOW_WRONG_STATE;
+ }
eos:
{
gst_buffer_unmap (buf, data, size);
return ret;
}
+/* Interrupt a blocking request. */
+static gboolean
+gst_gnome_vfs_src_unlock (GstBaseSrc * basesrc)
+{
+ GstGnomeVFSSrc *src;
+
+ src = GST_GNOME_VFS_SRC (basesrc);
+ GST_DEBUG_OBJECT (src, "unlock()");
+ src->interrupted = TRUE;
+ if (src->context) {
+ GnomeVFSCancellation *cancel =
+ gnome_vfs_context_get_cancellation (src->context);
+ if (cancel)
+ gnome_vfs_cancellation_cancel (cancel);
+ }
+ return TRUE;
+}
+
+/* Interrupt interrupt. */
+static gboolean
+gst_gnome_vfs_src_unlock_stop (GstBaseSrc * basesrc)
+{
+ GstGnomeVFSSrc *src;
+
+ src = GST_GNOME_VFS_SRC (basesrc);
+ GST_DEBUG_OBJECT (src, "unlock_stop()");
+
+ src->interrupted = FALSE;
+ return TRUE;
+}
+
static gboolean
gst_gnome_vfs_src_get_size (GstBaseSrc * basesrc, guint64 * size)
{
gst_gnome_vfs_src_push_callbacks (src);
+ src->context = gnome_vfs_context_new ();
if (src->uri != NULL) {
GnomeVFSOpenMode mode = GNOME_VFS_OPEN_READ;
src->handle = NULL;
}
src->curoffset = 0;
+ src->interrupted = FALSE;
+ gnome_vfs_context_free (src->context);
+ src->context = NULL;
return TRUE;
}