2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 * 2001 Bastien Nocera <hadess@hadess.net>
5 * 2002 Kristian Rietveld <kris@gtk.org>
6 * 2002,2003 Colin Walters <walters@gnu.org>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
27 * SECTION:element-gnomevfssrc
28 * @short_description: Read from any GnomeVFS-supported location
29 * @see_also: #GstFileSrc, #GstGnomeVFSSink
33 * This plugin reads data from a local or remote location specified
34 * by an URI. This location can be specified using any protocol supported by
35 * the GnomeVFS library. Common protocols are 'file', 'http', 'ftp', or 'smb'.
38 * In case the element-gnomevfssrc::iradio-mode property is set and the
39 * location is a http resource, gnomevfssrc will send special icecast http
40 * headers to the server to request additional icecast metainformation. If
41 * the server is not an icecast server, it will display the same behaviour
42 * as if the element-gnomevfssrc::iradio-mode property was not set. However,
43 * if the server is in fact an icecast server, gnomevfssrc will output
44 * data with a media type of application/x-icy, in which case you will
45 * need to use the #ICYDemux element as follow-up element to extract
46 * the icecast meta data and to determine the underlying media type.
51 * gst-launch -v gnomevfssrc location=file:///home/joe/foo.xyz ! fakesink
53 * The above pipeline will simply read a local file and do nothing with the
54 * data read. Instead of gnomevfssrc, we could just as well have used the
55 * filesrc element here.
58 * Another example pipeline:
60 * gst-launch -v gnomevfssrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz
62 * The above pipeline will copy a file from a remote host to the local file
63 * system using the Samba protocol.
66 * Yet another example pipeline:
68 * gst-launch -v gnomevfssrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink
70 * The above pipeline will read and decode and play an mp3 file from a
71 * web server using the http protocol.
79 /*#undef BROKEN_SIG */
85 #include "gst/gst-i18n-plugin.h"
87 #include "gstgnomevfssrc.h"
90 #include <sys/types.h>
91 #include <sys/socket.h>
93 #include <netinet/in.h>
94 #include <arpa/inet.h>
104 /* gnome-vfs.h doesn't include the following header, which we need: */
105 #include <libgnomevfs/gnome-vfs-standard-callbacks.h>
107 GST_DEBUG_CATEGORY_STATIC (gnomevfssrc_debug);
108 #define GST_CAT_DEFAULT gnomevfssrc_debug
110 static const GstElementDetails gst_gnome_vfs_src_details =
111 GST_ELEMENT_DETAILS ("GnomeVFS Source",
113 "Read from any GnomeVFS-supported file",
114 "Bastien Nocera <hadess@hadess.net>\n"
115 "Ronald S. Bultje <rbultje@ronald.bitfreak.net>");
117 static GStaticMutex count_lock = G_STATIC_MUTEX_INIT;
118 static gint ref_count = 0;
119 static gboolean vfs_owner = FALSE;
121 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
124 GST_STATIC_CAPS_ANY);
138 static void gst_gnome_vfs_src_base_init (gpointer g_class);
139 static void gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass);
140 static void gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc);
141 static void gst_gnome_vfs_src_finalize (GObject * object);
142 static void gst_gnome_vfs_src_uri_handler_init (gpointer g_iface,
143 gpointer iface_data);
145 static void gst_gnome_vfs_src_set_property (GObject * object, guint prop_id,
146 const GValue * value, GParamSpec * pspec);
147 static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id,
148 GValue * value, GParamSpec * pspec);
150 static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src);
151 static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src);
152 static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src);
153 static gboolean gst_gnome_vfs_src_check_get_range (GstBaseSrc * src);
154 static gboolean gst_gnome_vfs_src_get_size (GstBaseSrc * src, guint64 * size);
155 static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc,
156 guint64 offset, guint size, GstBuffer ** buffer);
158 static GstElementClass *parent_class = NULL;
161 gst_gnome_vfs_src_get_type (void)
163 static GType gnomevfssrc_type = 0;
165 if (!gnomevfssrc_type) {
166 static const GTypeInfo gnomevfssrc_info = {
167 sizeof (GstGnomeVFSSrcClass),
168 gst_gnome_vfs_src_base_init,
170 (GClassInitFunc) gst_gnome_vfs_src_class_init,
173 sizeof (GstGnomeVFSSrc),
175 (GInstanceInitFunc) gst_gnome_vfs_src_init,
177 static const GInterfaceInfo urihandler_info = {
178 gst_gnome_vfs_src_uri_handler_init,
184 g_type_register_static (GST_TYPE_BASE_SRC,
185 "GstGnomeVFSSrc", &gnomevfssrc_info, 0);
186 g_type_add_interface_static (gnomevfssrc_type, GST_TYPE_URI_HANDLER,
189 return gnomevfssrc_type;
193 gst_gnome_vfs_src_base_init (gpointer g_class)
195 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
197 gst_element_class_add_pad_template (element_class,
198 gst_static_pad_template_get (&srctemplate));
199 gst_element_class_set_details (element_class, &gst_gnome_vfs_src_details);
201 GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0,
206 gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass)
208 GObjectClass *gobject_class;
209 GstElementClass *gstelement_class;
210 GstBaseSrcClass *gstbasesrc_class;
212 gobject_class = G_OBJECT_CLASS (klass);
213 gstelement_class = GST_ELEMENT_CLASS (klass);
214 gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
216 parent_class = g_type_class_peek_parent (klass);
218 gobject_class->finalize = gst_gnome_vfs_src_finalize;
219 gobject_class->set_property = gst_gnome_vfs_src_set_property;
220 gobject_class->get_property = gst_gnome_vfs_src_get_property;
223 gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass),
224 "location", ARG_LOCATION, G_PARAM_READWRITE, NULL);
225 g_object_class_install_property (gobject_class,
227 g_param_spec_boxed ("handle",
228 "GnomeVFSHandle", "Handle for GnomeVFS",
229 GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE));
232 g_object_class_install_property (gobject_class,
234 g_param_spec_boolean ("iradio-mode",
236 "Enable internet radio mode (extraction of shoutcast/icecast metadata)",
237 FALSE, G_PARAM_READWRITE));
238 g_object_class_install_property (gobject_class,
240 g_param_spec_string ("iradio-name",
241 "iradio-name", "Name of the stream", NULL, G_PARAM_READABLE));
242 g_object_class_install_property (gobject_class,
244 g_param_spec_string ("iradio-genre",
245 "iradio-genre", "Genre of the stream", NULL, G_PARAM_READABLE));
246 g_object_class_install_property (gobject_class,
248 g_param_spec_string ("iradio-url",
250 "Homepage URL for radio stream", NULL, G_PARAM_READABLE));
251 g_object_class_install_property (gobject_class,
253 g_param_spec_string ("iradio-title",
255 "Name of currently playing song", NULL, G_PARAM_READABLE));
257 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start);
258 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop);
259 gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size);
260 gstbasesrc_class->is_seekable =
261 GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable);
262 gstbasesrc_class->check_get_range =
263 GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_check_get_range);
264 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_create);
268 gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc)
270 gnomevfssrc->uri = NULL;
271 gnomevfssrc->uri_name = NULL;
272 gnomevfssrc->handle = NULL;
273 gnomevfssrc->curoffset = 0;
274 gnomevfssrc->seekable = FALSE;
276 gnomevfssrc->icy_caps = NULL;
277 gnomevfssrc->iradio_mode = FALSE;
278 gnomevfssrc->http_callbacks_pushed = FALSE;
279 gnomevfssrc->iradio_name = NULL;
280 gnomevfssrc->iradio_genre = NULL;
281 gnomevfssrc->iradio_url = NULL;
282 gnomevfssrc->iradio_title = NULL;
284 g_static_mutex_lock (&count_lock);
285 if (ref_count == 0) {
286 /* gnome vfs engine init */
287 if (gnome_vfs_initialized () == FALSE) {
293 g_static_mutex_unlock (&count_lock);
297 gst_gnome_vfs_src_finalize (GObject * object)
299 GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (object);
301 g_static_mutex_lock (&count_lock);
303 if (ref_count == 0 && vfs_owner) {
304 if (gnome_vfs_initialized () == TRUE) {
305 gnome_vfs_shutdown ();
308 g_static_mutex_unlock (&count_lock);
311 gnome_vfs_uri_unref (src->uri);
315 g_free (src->uri_name);
316 src->uri_name = NULL;
318 g_free (src->iradio_name);
319 src->iradio_name = NULL;
321 g_free (src->iradio_genre);
322 src->iradio_genre = NULL;
324 g_free (src->iradio_url);
325 src->iradio_url = NULL;
327 g_free (src->iradio_title);
328 src->iradio_title = NULL;
331 gst_caps_unref (src->icy_caps);
332 src->icy_caps = NULL;
335 G_OBJECT_CLASS (parent_class)->finalize (object);
339 * URI interface support.
343 gst_gnome_vfs_src_uri_get_type (void)
349 gst_gnome_vfs_src_uri_get_protocols (void)
351 static gchar **protocols = NULL;
354 protocols = gst_gnomevfs_get_supported_uris ();
360 gst_gnome_vfs_src_uri_get_uri (GstURIHandler * handler)
362 GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler);
364 return src->uri_name;
368 gst_gnome_vfs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
370 GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler);
372 if (GST_STATE (src) == GST_STATE_PLAYING ||
373 GST_STATE (src) == GST_STATE_PAUSED)
376 g_object_set (G_OBJECT (src), "location", uri, NULL);
382 gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
384 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
386 iface->get_type = gst_gnome_vfs_src_uri_get_type;
387 iface->get_protocols = gst_gnome_vfs_src_uri_get_protocols;
388 iface->get_uri = gst_gnome_vfs_src_uri_get_uri;
389 iface->set_uri = gst_gnome_vfs_src_uri_set_uri;
393 gst_gnome_vfs_src_set_property (GObject * object, guint prop_id,
394 const GValue * value, GParamSpec * pspec)
398 src = GST_GNOME_VFS_SRC (object);
402 const gchar *new_location;
404 /* the element must be stopped or paused in order to do this */
405 if (GST_STATE (src) == GST_STATE_PLAYING ||
406 GST_STATE (src) == GST_STATE_PAUSED)
410 gnome_vfs_uri_unref (src->uri);
414 g_free (src->uri_name);
415 src->uri_name = NULL;
418 new_location = g_value_get_string (value);
420 src->uri_name = gst_gnome_vfs_location_to_uri_string (new_location);
421 src->uri = gnome_vfs_uri_new (src->uri_name);
426 if (GST_STATE (src) == GST_STATE_NULL ||
427 GST_STATE (src) == GST_STATE_READY) {
429 gnome_vfs_uri_unref (src->uri);
433 g_free (src->uri_name);
434 src->uri_name = NULL;
436 src->handle = g_value_get_boxed (value);
439 case ARG_IRADIO_MODE:
440 src->iradio_mode = g_value_get_boolean (value);
443 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
449 gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, GValue * value,
454 src = GST_GNOME_VFS_SRC (object);
458 g_value_set_string (value, src->uri_name);
461 g_value_set_boxed (value, src->handle);
463 case ARG_IRADIO_MODE:
464 g_value_set_boolean (value, src->iradio_mode);
466 case ARG_IRADIO_NAME:
467 g_value_set_string (value, src->iradio_name);
469 case ARG_IRADIO_GENRE:
470 g_value_set_string (value, src->iradio_genre);
473 g_value_set_string (value, src->iradio_url);
475 case ARG_IRADIO_TITLE:
476 g_value_set_string (value, src->iradio_title);
479 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
485 unicodify (const char *str, int len, ...)
487 char *ret = NULL, *cset;
489 gsize bytes_read, bytes_written;
491 if (g_utf8_validate (str, len, NULL))
492 return g_strndup (str, len >= 0 ? len : strlen (str));
494 va_start (args, len);
495 while ((cset = va_arg (args, char *)) != NULL)
497 if (!strcmp (cset, "locale"))
498 ret = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
500 ret = g_convert (str, len, "UTF-8", cset,
501 &bytes_read, &bytes_written, NULL);
511 gst_gnome_vfs_src_unicodify (const char *str)
513 return unicodify (str, -1, "locale", "ISO-8859-1", NULL);
517 gst_gnome_vfs_src_send_additional_headers_callback (gconstpointer in,
518 gsize in_size, gpointer out, gsize out_size, gpointer callback_data)
520 GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data);
521 GnomeVFSModuleCallbackAdditionalHeadersOut *out_args =
522 (GnomeVFSModuleCallbackAdditionalHeadersOut *) out;
524 if (!src->iradio_mode)
526 GST_DEBUG_OBJECT (src, "sending headers\n");
528 out_args->headers = g_list_append (out_args->headers,
529 g_strdup ("icy-metadata:1\r\n"));
533 gst_gnome_vfs_src_received_headers_callback (gconstpointer in,
534 gsize in_size, gpointer out, gsize out_size, gpointer callback_data)
538 GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data);
539 GnomeVFSModuleCallbackReceivedHeadersIn *in_args =
540 (GnomeVFSModuleCallbackReceivedHeadersIn *) in;
542 /* This is only used for internet radio stuff right now */
543 if (!src->iradio_mode)
546 for (i = in_args->headers; i; i = i->next) {
547 char *data = (char *) i->data;
549 char *value = strchr (data, ':');
560 if (strncmp (data, "icy-metaint:", 12) == 0) { /* ugh */
561 if (sscanf (data + 12, "%d", &icy_metaint) == 1) {
563 src->icy_caps = gst_caps_new_simple ("application/x-icy",
564 "metadata-interval", G_TYPE_INT, icy_metaint, NULL);
569 if (!strncmp (data, "icy-", 4))
574 GST_DEBUG_OBJECT (src, "key: %s", key);
575 if (!strncmp (key, "name", 4)) {
576 g_free (src->iradio_name);
577 src->iradio_name = gst_gnome_vfs_src_unicodify (value);
578 if (src->iradio_name)
579 g_object_notify (G_OBJECT (src), "iradio-name");
580 } else if (!strncmp (key, "genre", 5)) {
581 g_free (src->iradio_genre);
582 src->iradio_genre = gst_gnome_vfs_src_unicodify (value);
583 if (src->iradio_genre)
584 g_object_notify (G_OBJECT (src), "iradio-genre");
585 } else if (!strncmp (key, "url", 3)) {
586 g_free (src->iradio_url);
587 src->iradio_url = gst_gnome_vfs_src_unicodify (value);
589 g_object_notify (G_OBJECT (src), "iradio-url");
595 gst_gnome_vfs_src_push_callbacks (GstGnomeVFSSrc * src)
597 if (src->http_callbacks_pushed)
600 GST_DEBUG_OBJECT (src, "pushing callbacks");
601 gnome_vfs_module_callback_push
602 (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS,
603 gst_gnome_vfs_src_send_additional_headers_callback, src, NULL);
604 gnome_vfs_module_callback_push
605 (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS,
606 gst_gnome_vfs_src_received_headers_callback, src, NULL);
608 src->http_callbacks_pushed = TRUE;
612 gst_gnome_vfs_src_pop_callbacks (GstGnomeVFSSrc * src)
614 if (!src->http_callbacks_pushed)
617 GST_DEBUG_OBJECT (src, "popping callbacks");
618 gnome_vfs_module_callback_pop
619 (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS);
620 gnome_vfs_module_callback_pop
621 (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS);
623 src->http_callbacks_pushed = FALSE;
627 * Read a new buffer from src->reqoffset, takes care of events
628 * and seeking and such.
631 gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
636 GnomeVFSFileSize readbytes;
640 src = GST_GNOME_VFS_SRC (basesrc);
642 GST_DEBUG ("now at %llu, reading %lld, size %u", src->curoffset, offset,
645 /* seek if required */
646 if (G_UNLIKELY (src->curoffset != offset)) {
647 GST_DEBUG ("need to seek");
649 GST_DEBUG ("seeking to %lld", offset);
650 res = gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_START, offset);
651 if (res != GNOME_VFS_OK)
653 src->curoffset = offset;
659 buf = gst_buffer_new_and_alloc (size);
662 gst_buffer_set_caps (buf, src->icy_caps);
664 data = GST_BUFFER_DATA (buf);
665 GST_BUFFER_OFFSET (buf) = src->curoffset;
667 res = gnome_vfs_read (src->handle, data, size, &readbytes);
669 if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK
673 GST_BUFFER_SIZE (buf) = readbytes;
675 if (G_UNLIKELY (res != GNOME_VFS_OK))
678 src->curoffset += readbytes;
680 /* we're done, return the buffer */
687 GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL),
688 ("Failed to seek to requested position %" G_GINT64_FORMAT ": %s",
689 offset, gnome_vfs_result_to_string (res)));
690 return GST_FLOW_ERROR;
694 GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL),
695 ("Requested seek from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT
696 "on non-seekable stream", src->curoffset, offset));
697 return GST_FLOW_ERROR;
701 gst_buffer_unref (buf);
702 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
703 ("Failed to read data: %s", gnome_vfs_result_to_string (res)));
704 return GST_FLOW_ERROR;
708 gst_buffer_unref (buf);
709 GST_DEBUG_OBJECT (src, "Reading data gave EOS");
710 return GST_FLOW_UNEXPECTED;
715 gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc)
719 src = GST_GNOME_VFS_SRC (basesrc);
721 return src->seekable;
725 gst_gnome_vfs_src_check_get_range (GstBaseSrc * basesrc)
728 const gchar *protocol;
730 src = GST_GNOME_VFS_SRC (basesrc);
732 if (src->uri == NULL) {
733 GST_WARNING_OBJECT (src, "no URI set yet");
737 if (gnome_vfs_uri_is_local (src->uri)) {
738 GST_LOG_OBJECT (src, "local URI (%s), assuming random access is possible",
739 GST_STR_NULL (src->uri_name));
743 /* blacklist certain protocols we know won't work getrange-based */
744 protocol = gnome_vfs_uri_get_scheme (src->uri);
745 if (protocol == NULL)
748 if (strcmp (protocol, "http") == 0) {
749 GST_LOG_OBJECT (src, "blacklisted protocol '%s', no random access possible"
750 " (URI=%s)", protocol, GST_STR_NULL (src->uri_name));
754 /* fall through to undecided */
758 /* don't know what to do, let the basesrc class decide for us */
759 GST_LOG_OBJECT (src, "undecided about URI '%s', let base class handle it",
760 GST_STR_NULL (src->uri_name));
762 if (GST_BASE_SRC_CLASS (parent_class)->check_get_range)
763 return GST_BASE_SRC_CLASS (parent_class)->check_get_range (basesrc);
770 gst_gnome_vfs_src_get_size (GstBaseSrc * basesrc, guint64 * size)
774 src = GST_GNOME_VFS_SRC (basesrc);
776 GST_DEBUG_OBJECT (src, "size %" G_GUINT64_FORMAT, src->size);
778 if (src->size == (GnomeVFSFileSize) - 1)
786 /* open the file, do stuff necessary to go to PAUSED state */
788 gst_gnome_vfs_src_start (GstBaseSrc * basesrc)
790 GnomeVFSFileInfoOptions options;
792 GnomeVFSFileInfo *info;
795 src = GST_GNOME_VFS_SRC (basesrc);
797 gst_gnome_vfs_src_push_callbacks (src);
799 if (src->uri != NULL) {
800 GnomeVFSOpenMode mode;
802 /* this can block... */
803 mode = GNOME_VFS_OPEN_READ;
804 res = gnome_vfs_open_uri (&src->handle, src->uri, mode);
805 if (res != GNOME_VFS_OK)
807 src->own_handle = TRUE;
808 } else if (!src->handle) {
811 src->own_handle = FALSE;
814 src->size = (GnomeVFSFileSize) - 1;
815 info = gnome_vfs_file_info_new ();
816 options = GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS;
817 res = gnome_vfs_get_file_info_from_handle (src->handle, info, options);
818 if (res == GNOME_VFS_OK) {
819 if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) {
820 src->size = info->size;
821 GST_DEBUG_OBJECT (src, "size: %" G_GUINT64_FORMAT " bytes", src->size);
822 } else if (src->own_handle && gnome_vfs_uri_is_local (src->uri)) {
823 GST_DEBUG_OBJECT (src, "file size not known, trying fallback");
824 res = gnome_vfs_get_file_info_uri (src->uri, info, options);
825 if (res == GNOME_VFS_OK &&
826 (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) {
827 src->size = info->size;
828 GST_DEBUG_OBJECT (src, "size: %" G_GUINT64_FORMAT " bytes", src->size);
831 if (src->size == (GnomeVFSFileSize) - 1)
832 GST_DEBUG_OBJECT (src, "file size not known");
834 GST_WARNING_OBJECT (src, "getting info failed: %s",
835 gnome_vfs_result_to_string (res));
837 gnome_vfs_file_info_unref (info);
839 if (gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_CURRENT, 0)
841 src->seekable = TRUE;
843 src->seekable = FALSE;
851 gchar *filename = gnome_vfs_uri_to_string (src->uri,
852 GNOME_VFS_URI_HIDE_PASSWORD);
854 gst_gnome_vfs_src_pop_callbacks (src);
856 if (res == GNOME_VFS_ERROR_NOT_FOUND ||
857 res == GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE) {
858 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
859 ("Could not open vfs file \"%s\" for reading: %s",
860 filename, gnome_vfs_result_to_string (res)));
862 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
863 ("Could not open vfs file \"%s\" for reading: %s",
864 filename, gnome_vfs_result_to_string (res)));
871 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given"));
877 gst_gnome_vfs_src_stop (GstBaseSrc * basesrc)
881 src = GST_GNOME_VFS_SRC (basesrc);
883 gst_gnome_vfs_src_pop_callbacks (src);
885 if (src->own_handle) {
886 gnome_vfs_close (src->handle);
889 src->size = (GnomeVFSFileSize) - 1;
893 gst_caps_unref (src->icy_caps);
894 src->icy_caps = NULL;