diff --git a/ChangeLog b/ChangeLog index 2739cc8988..acaff3816c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +2005-12-27 Tim-Philipp Müller + + * ext/gnomevfs/Makefile.am: + * ext/gnomevfs/gstgnomevfs.c: (gst_gnome_vfs_uri_get_type), + (gst_gnome_vfs_handle_copy), (gst_gnome_vfs_handle_free), + (gst_gnome_vfs_handle_get_type), (plugin_init): + * ext/gnomevfs/gstgnomevfs.h: + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_do_init), + (gst_gnome_vfs_sink_base_init), (gst_gnome_vfs_sink_class_init), + (gst_gnome_vfs_sink_finalize), (gst_gnome_vfs_sink_init), + (gst_gnome_vfs_sink_set_property), + (gst_gnome_vfs_sink_get_property), (gst_gnome_vfs_sink_open_file), + (gst_gnome_vfs_sink_close_file), (gst_gnome_vfs_sink_start), + (gst_gnome_vfs_sink_stop), (gst_gnome_vfs_sink_handle_event), + (gst_gnome_vfs_sink_query), (gst_gnome_vfs_sink_render), + (gst_gnome_vfs_sink_uri_get_type), + (gst_gnome_vfs_sink_uri_get_protocols), + (gst_gnome_vfs_sink_uri_get_uri), (gst_gnome_vfs_sink_uri_set_uri), + (gst_gnome_vfs_sink_uri_handler_init): + * ext/gnomevfs/gstgnomevfssink.h: + Port gnomevfssink; add gtk-doc blurb. + + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_get_type), + (gst_gnome_vfs_src_base_init), (gst_gnome_vfs_src_class_init), + (gst_gnome_vfs_src_init), (gst_gnome_vfs_src_finalize), + (gst_gnome_vfs_src_uri_get_type), + (gst_gnome_vfs_src_uri_get_protocols), + (gst_gnome_vfs_src_uri_get_uri), (gst_gnome_vfs_src_uri_set_uri), + (gst_gnome_vfs_src_uri_handler_init), + (gst_gnome_vfs_src_set_property), (gst_gnome_vfs_src_get_property), + (gst_gnome_vfs_src_unicodify), (audiocast_thread_run), + (gst_gnome_vfs_src_send_additional_headers_callback), + (gst_gnome_vfs_src_received_headers_callback), + (gst_gnome_vfs_src_push_callbacks), + (gst_gnome_vfs_src_pop_callbacks), + (gst_gnome_vfs_src_get_icy_metadata), (gst_gnome_vfs_src_create), + (gst_gnome_vfs_src_is_seekable), (gst_gnome_vfs_src_get_size), + (gst_gnome_vfs_src_start), (gst_gnome_vfs_src_stop): + * ext/gnomevfs/gstgnomevfssrc.h: + s/gst_gnomevfssrc/gst_gnome_vfs_src/; move header stuff to header + file; add gtk-doc blurb with example pipelines. + === release 0.10.1 === 2005-12-23 Thomas Vander Stichele diff --git a/ext/gnomevfs/Makefile.am b/ext/gnomevfs/Makefile.am index 9c8b800b1d..4466b971d9 100644 --- a/ext/gnomevfs/Makefile.am +++ b/ext/gnomevfs/Makefile.am @@ -2,16 +2,16 @@ plugin_LTLIBRARIES = libgstgnomevfs.la libgstgnomevfs_la_SOURCES = \ gstgnomevfs.c \ + gstgnomevfssink.c \ gstgnomevfssrc.c \ gstgnomevfsuri.c -EXTRA_DIST = \ - gstgnomevfssink.c - libgstgnomevfs_la_CFLAGS = $(GST_CFLAGS) $(GNOME_VFS_CFLAGS) libgstgnomevfs_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstgnomevfs_la_LIBADD = $(GNOME_VFS_LIBS) $(GST_BASE_LIBS) noinst_HEADERS = \ gstgnomevfs.h \ + gstgnomevfssink.h \ + gstgnomevfssrc.h \ gstgnomevfsuri.h diff --git a/ext/gnomevfs/gstgnomevfs.c b/ext/gnomevfs/gstgnomevfs.c index 43ef565b87..1e6fb64039 100644 --- a/ext/gnomevfs/gstgnomevfs.c +++ b/ext/gnomevfs/gstgnomevfs.c @@ -26,27 +26,67 @@ #include "gst/gst-i18n-plugin.h" #include "gstgnomevfs.h" +#include "gstgnomevfssrc.h" +#include "gstgnomevfssink.h" + #include #include -GST_DEBUG_CATEGORY_EXTERN (gnomevfssrc_debug); +GType +gst_gnome_vfs_uri_get_type (void) +{ + static GType type; /* 0 */ + + if (type == 0) { + type = g_boxed_type_register_static ("GnomeVFSURI", + (GBoxedCopyFunc) gnome_vfs_uri_ref, + (GBoxedFreeFunc) gnome_vfs_uri_unref); + } + + return type; +} + +static gpointer +gst_gnome_vfs_handle_copy (gpointer handle) +{ + return handle; +} + +static void +gst_gnome_vfs_handle_free (gpointer handle) +{ + return; +} + +GType +gst_gnome_vfs_handle_get_type (void) +{ + static GType type; /* 0 */ + + if (type == 0) { + /* hackish, but makes it show up nicely in gst-inspect */ + type = g_boxed_type_register_static ("GnomeVFSHandle", + (GBoxedCopyFunc) gst_gnome_vfs_handle_copy, + (GBoxedFreeFunc) gst_gnome_vfs_handle_free); + } + + return type; +} + static gboolean plugin_init (GstPlugin * plugin) { - gnome_vfs_init (); - - GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0, - "Gnome-VFS Source"); - + /* gnome vfs engine init */ + if (!gnome_vfs_initialized ()) + gnome_vfs_init (); if (!gst_element_register (plugin, "gnomevfssrc", GST_RANK_SECONDARY, - gst_gnomevfssrc_get_type ())) + gst_gnome_vfs_src_get_type ())) return FALSE; -/* + if (!gst_element_register (plugin, "gnomevfssink", GST_RANK_SECONDARY, - gst_gnomevfssink_get_type ())) + gst_gnome_vfs_sink_get_type ())) return FALSE; -*/ #ifdef ENABLE_NLS setlocale (LC_ALL, ""); diff --git a/ext/gnomevfs/gstgnomevfs.h b/ext/gnomevfs/gstgnomevfs.h index 350a911bee..8069a6f36d 100644 --- a/ext/gnomevfs/gstgnomevfs.h +++ b/ext/gnomevfs/gstgnomevfs.h @@ -24,11 +24,12 @@ #include G_BEGIN_DECLS - -GType gst_gnomevfssink_get_type (void); -GType gst_gnomevfssrc_get_type (void); +#define GST_TYPE_GNOME_VFS_URI (gst_gnome_vfs_uri_get_type ()) +#define GST_TYPE_GNOME_VFS_HANDLE (gst_gnome_vfs_handle_get_type ()) +GType gst_gnome_vfs_uri_get_type (void); +GType gst_gnome_vfs_handle_get_type (void); G_END_DECLS diff --git a/ext/gnomevfs/gstgnomevfssink.c b/ext/gnomevfs/gstgnomevfssink.c index fb1a3e1e89..9114d65062 100644 --- a/ext/gnomevfs/gstgnomevfssink.c +++ b/ext/gnomevfs/gstgnomevfssink.c @@ -3,6 +3,7 @@ * 2000 Wim Taymans * 2001 Bastien Nocera * 2003 Colin Walters + * 2005 Tim-Philipp Müller * * gstgnomevfssink.c: * @@ -22,71 +23,52 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-gnomevfssink + * @short_description: Write a stream to a GnomeVFS URI + * @see_also: #GstFileSink, #GstGnomeVFSSrc + * + * + * + * This plugin writes incoming data to a local or remote location specified + * by an URI. This location can be specified using any protocol supported by + * the GnomeVFS library. Common protocols are 'file', 'ftp', or 'smb'. + * + * + * Example pipeline: + * + * gst-launch -v filesrc location=input.xyz ! gnomevfssink location=file:///home/joe/out.xyz + * + * The above pipeline will simply copy a local file. Instead of gnomevfssink, + * we could just as well have used the filesink element here. + * + * + * Another example pipeline: + * + * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! gnomevfssink location=smb://othercomputer/foo.flac + * + * The above pipeline will re-encode an mp3 file into FLAC format and store + * it on a remote host using the Samba protocol. + * + * + * + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "gst/gst-i18n-plugin.h" +#include "gstgnomevfssink.h" -#include "gstgnomevfs.h" -#include "gstgnomevfsuri.h" +#include "gst/gst-i18n-plugin.h" #include #include #include #include - -#define GST_TYPE_GNOMEVFSSINK \ - (gst_gnomevfssink_get_type()) -#define GST_GNOMEVFSSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOMEVFSSINK,GstGnomeVFSSink)) -#define GST_GNOMEVFSSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOMEVFSSINK,GstGnomeVFSSinkClass)) -#define GST_IS_GNOMEVFSSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOMEVFSSINK)) -#define GST_IS_GNOMEVFSSINK_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOMEVFSSINK)) - -typedef struct _GstGnomeVFSSink GstGnomeVFSSink; -typedef struct _GstGnomeVFSSinkClass GstGnomeVFSSinkClass; - -typedef enum -{ - GST_GNOMEVFSSINK_OPEN = GST_ELEMENT_FLAG_LAST, - - GST_GNOMEVFSSINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2 -} -GstGnomeVFSSinkFlags; - -struct _GstGnomeVFSSink -{ - GstElement element; - - /* uri */ - GnomeVFSURI *uri; - gchar *uri_name; - - /* handle */ - GnomeVFSHandle *handle; - - /* whether we opened the handle ourselves */ - gboolean own_handle; -}; - -struct _GstGnomeVFSSinkClass -{ - GstElementClass parent_class; - - /* signals */ - gboolean (*erase_ask) (GstElement * element, GnomeVFSURI * uri); -}; - -/* GnomeVFSSink signals and args */ enum { - /* FILL ME */ SIGNAL_ERASE_ASK, LAST_SIGNAL }; @@ -99,73 +81,68 @@ enum ARG_HANDLE }; -static void gst_gnomevfssink_base_init (gpointer g_class); -static void gst_gnomevfssink_class_init (GstGnomeVFSSinkClass * klass); -static void gst_gnomevfssink_init (GstGnomeVFSSink * gnomevfssink); -static void gst_gnomevfssink_finalize (GObject * obj); +static void gst_gnome_vfs_sink_finalize (GObject * obj); -static void gst_gnomevfssink_uri_handler_init (gpointer g_iface, +static void gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface, gpointer iface_data); -static void gst_gnomevfssink_set_property (GObject * object, guint prop_id, +static void gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_gnomevfssink_get_property (GObject * object, guint prop_id, +static void gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static gboolean gst_gnomevfssink_open_file (GstGnomeVFSSink * sink); -static void gst_gnomevfssink_close_file (GstGnomeVFSSink * sink); +static gboolean gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink); +static void gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink); +static gboolean gst_gnome_vfs_sink_start (GstBaseSink * basesink); +static gboolean gst_gnome_vfs_sink_stop (GstBaseSink * basesink); +static GstFlowReturn gst_gnome_vfs_sink_render (GstBaseSink * basesink, + GstBuffer * buffer); +static gboolean gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink, + GstEvent * event); +static gboolean gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query); -static void gst_gnomevfssink_chain (GstPad * pad, GstData * _data); +static guint gst_gnome_vfs_sink_signals[LAST_SIGNAL]; /* all 0 */ -static GstStateChangeReturn gst_gnomevfssink_change_state (GstElement * - element); +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); -static GstElementClass *parent_class = NULL; -static guint gst_gnomevfssink_signals[LAST_SIGNAL] = { 0 }; - -GType -gst_gnomevfssink_get_type (void) -{ - static GType gnomevfssink_type = 0; - - if (!gnomevfssink_type) { - static const GTypeInfo gnomevfssink_info = { - sizeof (GstGnomeVFSSinkClass), - gst_gnomevfssink_base_init, - NULL, - (GClassInitFunc) gst_gnomevfssink_class_init, - NULL, - NULL, - sizeof (GstGnomeVFSSink), - 0, - (GInstanceInitFunc) gst_gnomevfssink_init, - }; - static const GInterfaceInfo urihandler_info = { - gst_gnomevfssink_uri_handler_init, - NULL, - NULL - }; - - gnomevfssink_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstGnomeVFSSink", - &gnomevfssink_info, 0); - g_type_add_interface_static (gnomevfssink_type, GST_TYPE_URI_HANDLER, - &urihandler_info); - } - return gnomevfssink_type; -} +GST_DEBUG_CATEGORY_STATIC (gst_gnome_vfs_sink_debug); +#define GST_CAT_DEFAULT gst_gnome_vfs_sink_debug static void -gst_gnomevfssink_base_init (gpointer g_class) +gst_gnome_vfs_sink_do_init (GType type) +{ + static const GInterfaceInfo urihandler_info = { + gst_gnome_vfs_sink_uri_handler_init, + NULL, + NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info); + + GST_DEBUG_CATEGORY_INIT (gst_gnome_vfs_sink_debug, "gnomevfssink", 0, + "Gnome VFS sink element"); +} + +GST_BOILERPLATE_FULL (GstGnomeVFSSink, gst_gnome_vfs_sink, GstBaseSink, + GST_TYPE_BASE_SINK, gst_gnome_vfs_sink_do_init); + +static void +gst_gnome_vfs_sink_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - static GstElementDetails gst_gnomevfssink_details = + static GstElementDetails gst_gnome_vfs_sink_details = GST_ELEMENT_DETAILS ("GnomeVFS Sink", "Sink/File", - "Write stream to a GnomeVFS URI", + "Write a stream to a GnomeVFS URI", "Bastien Nocera "); - gst_element_class_set_details (element_class, &gst_gnomevfssink_details); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details (element_class, &gst_gnome_vfs_sink_details); } static gboolean @@ -183,48 +160,45 @@ _gst_boolean_allow_overwrite_accumulator (GSignalInvocationHint * ihint, } static void -gst_gnomevfssink_class_init (GstGnomeVFSSinkClass * klass) +gst_gnome_vfs_sink_class_init (GstGnomeVFSSinkClass * klass) { + GstBaseSinkClass *basesink_class; GObjectClass *gobject_class; - GstElementClass *gstelement_class; gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + basesink_class = (GstBaseSinkClass *) klass; + gobject_class->set_property = gst_gnome_vfs_sink_set_property; + gobject_class->get_property = gst_gnome_vfs_sink_get_property; + gobject_class->finalize = gst_gnome_vfs_sink_finalize; gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass), "location", ARG_LOCATION, G_PARAM_READWRITE, NULL); g_object_class_install_property (gobject_class, ARG_URI, - g_param_spec_pointer ("uri", "GnomeVFSURI", "URI for GnomeVFS", - G_PARAM_READWRITE)); + g_param_spec_boxed ("uri", "GnomeVFSURI", "URI for GnomeVFS", + GST_TYPE_GNOME_VFS_URI, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, ARG_HANDLE, - g_param_spec_pointer ("handle", - "GnomeVFSHandle", "Handle for GnomeVFS", G_PARAM_READWRITE)); + g_param_spec_boxed ("handle", + "GnomeVFSHandle", "Handle for GnomeVFS", + GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE)); - gst_gnomevfssink_signals[SIGNAL_ERASE_ASK] = + gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK] = g_signal_new ("allow-overwrite", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_CLEANUP, G_STRUCT_OFFSET (GstGnomeVFSSinkClass, erase_ask), _gst_boolean_allow_overwrite_accumulator, NULL, - gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, G_TYPE_POINTER); + gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_GNOME_VFS_URI); - - gobject_class->set_property = gst_gnomevfssink_set_property; - gobject_class->get_property = gst_gnomevfssink_get_property; - gobject_class->finalize = gst_gnomevfssink_finalize; - - gstelement_class->change_state = gst_gnomevfssink_change_state; - - /* gnome vfs engine init */ - if (gnome_vfs_initialized () == FALSE) - gnome_vfs_init (); + basesink_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_stop); + basesink_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_start); + basesink_class->event = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_handle_event); + basesink_class->render = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_render); + basesink_class->get_times = NULL; } static void -gst_gnomevfssink_finalize (GObject * obj) +gst_gnome_vfs_sink_finalize (GObject * obj) { - GstGnomeVFSSink *sink = GST_GNOMEVFSSINK (obj); + GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (obj); if (sink->uri) { gnome_vfs_uri_unref (sink->uri); @@ -240,168 +214,122 @@ gst_gnomevfssink_finalize (GObject * obj) } static void -gst_gnomevfssink_init (GstGnomeVFSSink * gnomevfssink) +gst_gnome_vfs_sink_init (GstGnomeVFSSink * sink, GstGnomeVFSSinkClass * klass) { - GstPad *pad; + gst_pad_set_query_function (GST_BASE_SINK_PAD (sink), + GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_query)); - GST_OBJECT_FLAG_SET (gnomevfssink, GST_ELEMENT_EVENT_AWARE); + sink->uri = NULL; + sink->uri_name = NULL; + sink->handle = NULL; + sink->own_handle = FALSE; + sink->data_written = 0; - pad = gst_pad_new ("sink", GST_PAD_SINK); - gst_element_add_pad (GST_ELEMENT (gnomevfssink), pad); - gst_pad_set_chain_function (pad, gst_gnomevfssink_chain); - - gnomevfssink->uri = NULL; - gnomevfssink->uri_name = NULL; - gnomevfssink->handle = NULL; - gnomevfssink->own_handle = FALSE; -} - -static guint -gst_gnomevfssink_uri_get_type (void) -{ - return GST_URI_SINK; -} - -static gchar ** -gst_gnomevfssink_uri_get_protocols (void) -{ - static gchar **protocols = NULL; - - if (!protocols) - protocols = gst_gnomevfs_get_supported_uris (); - - return protocols; -} - -static const gchar * -gst_gnomevfssink_uri_get_uri (GstURIHandler * handler) -{ - GstGnomeVFSSink *sink = GST_GNOMEVFSSINK (handler); - - return sink->uri_name; -} - -static gboolean -gst_gnomevfssink_uri_set_uri (GstURIHandler * handler, const gchar * uri) -{ - GstGnomeVFSSink *sink = GST_GNOMEVFSSINK (handler); - - if (GST_STATE (sink) == GST_STATE_PLAYING || - GST_STATE (sink) == GST_STATE_PAUSED) - return FALSE; - - g_object_set (G_OBJECT (sink), "location", uri, NULL); - - return TRUE; + GST_BASE_SINK (sink)->sync = FALSE; } static void -gst_gnomevfssink_uri_handler_init (gpointer g_iface, gpointer iface_data) -{ - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; - - iface->get_type = gst_gnomevfssink_uri_get_type; - iface->get_protocols = gst_gnomevfssink_uri_get_protocols; - iface->get_uri = gst_gnomevfssink_uri_get_uri; - iface->set_uri = gst_gnomevfssink_uri_set_uri; -} - -static void -gst_gnomevfssink_set_property (GObject * object, guint prop_id, +gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstGnomeVFSSink *sink; + GstState cur_state; - sink = GST_GNOMEVFSSINK (object); + sink = GST_GNOME_VFS_SINK (object); + + gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0); + + if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) { + GST_WARNING_OBJECT (sink, "cannot set property when PAUSED or PLAYING"); + return; + } + + GST_OBJECT_LOCK (sink); switch (prop_id) { - case ARG_LOCATION: - if (GST_STATE (sink) == GST_STATE_NULL || - GST_STATE (sink) == GST_STATE_READY) { - if (sink->uri) { - gnome_vfs_uri_unref (sink->uri); - sink->uri = NULL; - } - if (sink->uri_name) { - g_free (sink->uri_name); - sink->uri_name = NULL; - } - if (g_value_get_string (value)) { - sink->uri_name = g_strdup (g_value_get_string (value)); - sink->uri = gnome_vfs_uri_new (sink->uri_name); - } + case ARG_LOCATION:{ + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; + } + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + if (g_value_get_string (value)) { + sink->uri_name = g_value_dup_string (value); + sink->uri = gnome_vfs_uri_new (sink->uri_name); } break; - case ARG_URI: - if (GST_STATE (sink) == GST_STATE_NULL || - GST_STATE (sink) == GST_STATE_READY) { - if (sink->uri) { - gnome_vfs_uri_unref (sink->uri); - sink->uri = NULL; - } - if (sink->uri_name) { - g_free (sink->uri_name); - sink->uri_name = NULL; - } - if (g_value_get_pointer (value)) { - sink->uri = gnome_vfs_uri_ref (g_value_get_pointer (value)); - sink->uri_name = gnome_vfs_uri_to_string (sink->uri, 0); - } + } + case ARG_URI:{ + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; + } + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + if (g_value_get_boxed (value)) { + sink->uri = (GnomeVFSURI *) g_value_dup_boxed (value); + sink->uri_name = gnome_vfs_uri_to_string (sink->uri, 0); } break; - case ARG_HANDLE: - if (GST_STATE (sink) == GST_STATE_NULL || - GST_STATE (sink) == GST_STATE_READY) { - if (sink->uri) { - gnome_vfs_uri_unref (sink->uri); - sink->uri = NULL; - } - if (sink->uri_name) { - g_free (sink->uri_name); - sink->uri_name = NULL; - } - sink->handle = g_value_get_pointer (value); + } + case ARG_HANDLE:{ + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; } + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + sink->handle = g_value_get_boxed (value); break; + } default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_OBJECT_UNLOCK (sink); } static void -gst_gnomevfssink_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) +gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) { GstGnomeVFSSink *sink; - g_return_if_fail (GST_IS_GNOMEVFSSINK (object)); + sink = GST_GNOME_VFS_SINK (object); - sink = GST_GNOMEVFSSINK (object); + GST_OBJECT_LOCK (sink); switch (prop_id) { case ARG_LOCATION: g_value_set_string (value, sink->uri_name); break; case ARG_URI: - g_value_set_pointer (value, sink->uri); + g_value_set_boxed (value, sink->uri); break; case ARG_HANDLE: - g_value_set_pointer (value, sink->handle); + g_value_set_boxed (value, sink->handle); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_OBJECT_UNLOCK (sink); } static gboolean -gst_gnomevfssink_open_file (GstGnomeVFSSink * sink) +gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink) { GnomeVFSResult result; - g_return_val_if_fail (!GST_OBJECT_FLAG_IS_SET (sink, GST_GNOMEVFSSINK_OPEN), - FALSE); - if (sink->uri) { /* open the file */ result = gnome_vfs_create_uri (&(sink->handle), sink->uri, @@ -413,7 +341,7 @@ gst_gnomevfssink_open_file (GstGnomeVFSSink * sink) gboolean erase_anyway = FALSE; g_signal_emit (G_OBJECT (sink), - gst_gnomevfssink_signals[SIGNAL_ERASE_ASK], 0, sink->uri, + gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK], 0, sink->uri, &erase_anyway); if (erase_anyway) { result = gnome_vfs_create_uri (&(sink->handle), sink->uri, @@ -422,7 +350,9 @@ gst_gnomevfssink_open_file (GstGnomeVFSSink * sink) | GNOME_VFS_PERM_GROUP_READ); } } - GST_DEBUG ("open: %s", gnome_vfs_result_to_string (result)); + + GST_DEBUG_OBJECT (sink, "open: %s", gnome_vfs_result_to_string (result)); + if (result != GNOME_VFS_OK) { gchar *filename = gnome_vfs_uri_to_string (sink->uri, GNOME_VFS_URI_HIDE_PASSWORD); @@ -442,18 +372,16 @@ gst_gnomevfssink_open_file (GstGnomeVFSSink * sink) sink->own_handle = FALSE; } - GST_OBJECT_FLAG_SET (sink, GST_GNOMEVFSSINK_OPEN); + sink->data_written = 0; return TRUE; } static void -gst_gnomevfssink_close_file (GstGnomeVFSSink * sink) +gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink) { GnomeVFSResult result; - g_return_if_fail (GST_OBJECT_FLAG_IS_SET (sink, GST_GNOMEVFSSINK_OPEN)); - if (sink->own_handle) { /* close the file */ result = gnome_vfs_close (sink->handle); @@ -470,176 +398,212 @@ gst_gnomevfssink_close_file (GstGnomeVFSSink * sink) sink->own_handle = FALSE; sink->handle = NULL; } - - GST_OBJECT_FLAG_UNSET (sink, GST_GNOMEVFSSINK_OPEN); } -/** - * gst_gnomevfssink_handle_event: - * @sink: reference to GstGnomeVFSSink - * @event: the event to dispatch - * - * Handles the event appropriately (seek, end-of-file, ...) - * - * Return value: whether to continue processing or not. - */ +static gboolean +gst_gnome_vfs_sink_start (GstBaseSink * basesink) +{ + gboolean ret; + + ret = gst_gnome_vfs_sink_open_file (GST_GNOME_VFS_SINK (basesink)); + + return ret; +} static gboolean -gst_gnomevfssink_handle_event (GstGnomeVFSSink * sink, GstEvent * event) +gst_gnome_vfs_sink_stop (GstBaseSink * basesink) { - GstEventType type; - gboolean res = FALSE; + GST_DEBUG_OBJECT (basesink, "closing ..."); + gst_gnome_vfs_sink_close_file (GST_GNOME_VFS_SINK (basesink)); + return TRUE; +} - type = GST_EVENT_TYPE (event); +static gboolean +gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink, GstEvent * event) +{ + GstGnomeVFSSink *sink; - switch (type) { - case GST_EVENT_EOS: - gst_gnomevfssink_close_file (sink); - gst_element_set_eos (GST_ELEMENT (sink)); - break; + sink = GST_GNOME_VFS_SINK (basesink); - case GST_EVENT_DISCONTINUOUS:{ + GST_DEBUG_OBJECT (sink, "processing %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT:{ GnomeVFSResult res; + GstFormat format; gint64 offset; - if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset)) { - if ((res = gnome_vfs_seek (sink->handle, GNOME_VFS_SEEK_START, - offset)) != GNOME_VFS_OK) { - GST_ERROR_OBJECT (sink, "Failed to seek to offset %" - G_GINT64_FORMAT ": %s", offset, gnome_vfs_result_to_string (res)); - } - } + gst_event_parse_new_segment (event, NULL, NULL, &format, &offset, + NULL, NULL); - res = TRUE; - break; - } - - case GST_EVENT_SEEK:{ - GnomeVFSResult res; - GnomeVFSSeekPosition method; - gint64 offset; - - if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) { - GST_ERROR_OBJECT (sink, "Can only seek in bytes"); + if (format != GST_FORMAT_BYTES) { + GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format", + gst_format_get_name (format)); break; } - switch (GST_EVENT_SEEK_METHOD (event)) { - case GST_SEEK_METHOD_SET: - method = GNOME_VFS_SEEK_START; - break; - case GST_SEEK_METHOD_CUR: - method = GNOME_VFS_SEEK_CURRENT; - break; - case GST_SEEK_METHOD_END: - method = GNOME_VFS_SEEK_END; - break; - default: - GST_ERROR_OBJECT (sink, "Unknown seek method %d", - GST_EVENT_SEEK_METHOD (event)); - goto end; - break; - } - offset = GST_EVENT_SEEK_OFFSET (event); + GST_LOG_OBJECT (sink, "seeking to offset %" G_GINT64_FORMAT, offset); + res = gnome_vfs_seek (sink->handle, GNOME_VFS_SEEK_START, offset); - if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) { - /* how does Gnome-VFS flush? */ - } - - if ((res = gnome_vfs_seek (sink->handle, method, offset)) != GNOME_VFS_OK) { + if (res != GNOME_VFS_OK) { GST_ERROR_OBJECT (sink, "Failed to seek to offset %" - G_GINT64_FORMAT " with method %d: %s", offset, method, - gnome_vfs_result_to_string (res)); + G_GINT64_FORMAT ": %s", offset, gnome_vfs_result_to_string (res)); } - res = TRUE; break; } - case GST_EVENT_FLUSH: - /* how does Gnome-VFS flush? */ + case GST_EVENT_FLUSH_START: + case GST_EVENT_EOS:{ + /* how does Gnome-VFS flush? Do we need to flush? */ break; - + } default: - GST_WARNING ("Unhandled event type %d", type); - gst_pad_event_default (gst_element_get_pad (GST_ELEMENT (sink), "sink"), - event); - event = NULL; break; } -end: - if (event) - gst_event_unref (event); - - return res; + return TRUE; } -/** - * gst_gnomevfssink_chain: - * @pad: the pad this gnomevfssink is connected to - * @buf: the buffer that has to be absorbed - * - * take the buffer from the pad and write to file if it's open - */ -static void -gst_gnomevfssink_chain (GstPad * pad, GstData * _data) +static gboolean +gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query) { - GstBuffer *buf; + GstGnomeVFSSink *sink; + GstFormat format; + + sink = GST_GNOME_VFS_SINK (GST_PAD_PARENT (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + gst_query_parse_position (query, &format, NULL); + switch (format) { + case GST_FORMAT_DEFAULT: + case GST_FORMAT_BYTES: + gst_query_set_position (query, GST_FORMAT_BYTES, sink->data_written); + return TRUE; + default: + return FALSE; + } + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + return TRUE; + + default: + return gst_pad_query_default (pad, query); + } +} + +static GstFlowReturn +gst_gnome_vfs_sink_render (GstBaseSink * basesink, GstBuffer * buf) +{ + GnomeVFSFileSize written, cur_pos; GstGnomeVFSSink *sink; GnomeVFSResult result; - GnomeVFSFileSize bytes_written; + GstFlowReturn ret; + guint64 back_pending = 0; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); + sink = GST_GNOME_VFS_SINK (basesink); - sink = GST_GNOMEVFSSINK (gst_pad_get_parent (pad)); - - if (GST_OBJECT_FLAG_IS_SET (sink, GST_GNOMEVFSSINK_OPEN)) { - if (GST_IS_EVENT (_data)) { - gst_gnomevfssink_handle_event (sink, GST_EVENT (_data)); - return; - } - - buf = GST_BUFFER (_data); - g_return_if_fail (buf != NULL); - result = - gnome_vfs_write (sink->handle, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf), &bytes_written); - GST_DEBUG ("write: %s, written_bytes: %" G_GUINT64_FORMAT, - gnome_vfs_result_to_string (result), bytes_written); - if (bytes_written < GST_BUFFER_SIZE (buf)) { - printf ("gnomevfssink : Warning : %d bytes should be written, only %" - G_GUINT64_FORMAT " bytes written\n", GST_BUFFER_SIZE (buf), - bytes_written); - } + if (gnome_vfs_tell (sink->handle, &cur_pos) == GNOME_VFS_OK) { + if (cur_pos < sink->data_written) + back_pending = sink->data_written - cur_pos; } - gst_data_unref (_data); -} -static GstStateChangeReturn -gst_gnomevfssink_change_state (GstElement * element, GstStateChange transition) -{ - g_return_val_if_fail (GST_IS_GNOMEVFSSINK (element), - GST_STATE_CHANGE_FAILURE); + result = gnome_vfs_write (sink->handle, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf), &written); - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - if (!GST_OBJECT_FLAG_IS_SET (element, GST_GNOMEVFSSINK_OPEN)) { - if (!gst_gnomevfssink_open_file (GST_GNOMEVFSSINK (element))) - return GST_STATE_CHANGE_FAILURE; + switch (result) { + case GNOME_VFS_OK:{ + GST_DEBUG_OBJECT (sink, "wrote %" G_GINT64_FORMAT " bytes at %" + G_GINT64_FORMAT, (gint64) written, (gint64) cur_pos); + + if (written < GST_BUFFER_SIZE (buf)) { + /* FIXME: what to do here? (tpm) */ + g_warning ("%s: %d bytes should be written, only %" + G_GUINT64_FORMAT " bytes written", G_STRLOC, + GST_BUFFER_SIZE (buf), written); } + + sink->data_written += GST_BUFFER_SIZE (buf) - back_pending; + ret = GST_FLOW_OK; break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (GST_OBJECT_FLAG_IS_SET (element, GST_GNOMEVFSSINK_OPEN)) - gst_gnomevfssink_close_file (GST_GNOMEVFSSINK (element)); - break; - default: + } + case GNOME_VFS_ERROR_NO_SPACE:{ + /* TODO: emit signal/send msg on out-of-diskspace and + * handle this gracefully (see open bug) (tpm) */ + } + /* fall-through */ + default:{ + gchar *filename = gnome_vfs_uri_to_string (sink->uri, + GNOME_VFS_URI_HIDE_PASSWORD); + + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filename), + ("%s, bufsize=%u, written=%u", gnome_vfs_result_to_string (result), + GST_BUFFER_SIZE (buf), (guint) written)); + + g_free (filename); + ret = GST_FLOW_ERROR; break; + } } - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - return GST_STATE_CHANGE_SUCCESS; + return GST_FLOW_OK; +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static guint +gst_gnome_vfs_sink_uri_get_type (void) +{ + return GST_URI_SINK; +} + +static gchar ** +gst_gnome_vfs_sink_uri_get_protocols (void) +{ + static gchar **protocols = NULL; + + if (!protocols) + protocols = gst_gnomevfs_get_supported_uris (); + + return protocols; +} + +static const gchar * +gst_gnome_vfs_sink_uri_get_uri (GstURIHandler * handler) +{ + GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler); + + return sink->uri_name; +} + +static gboolean +gst_gnome_vfs_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler); + GstState cur_state; + + gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0); + + if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) { + GST_WARNING_OBJECT (sink, "cannot set uri when PAUSED or PLAYING"); + return FALSE; + } + + g_object_set (sink, "location", uri, NULL); + + return TRUE; +} + +static void +gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_gnome_vfs_sink_uri_get_type; + iface->get_protocols = gst_gnome_vfs_sink_uri_get_protocols; + iface->get_uri = gst_gnome_vfs_sink_uri_get_uri; + iface->set_uri = gst_gnome_vfs_sink_uri_set_uri; } diff --git a/ext/gnomevfs/gstgnomevfssink.h b/ext/gnomevfs/gstgnomevfssink.h new file mode 100644 index 0000000000..b8ec51802b --- /dev/null +++ b/ext/gnomevfs/gstgnomevfssink.h @@ -0,0 +1,79 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2003 Colin Walters + * 2005 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GNOME_VFS_SINK_H__ +#define __GST_GNOME_VFS_SINK_H__ + +#include "gstgnomevfs.h" +#include "gstgnomevfsuri.h" +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GNOME_VFS_SINK \ + (gst_gnome_vfs_sink_get_type()) +#define GST_GNOME_VFS_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSink)) +#define GST_GNOME_VFS_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSinkClass)) +#define GST_IS_GNOME_VFS_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SINK)) +#define GST_IS_GNOME_VFS_SINK_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SINK)) + +typedef struct _GstGnomeVFSSink GstGnomeVFSSink; +typedef struct _GstGnomeVFSSinkClass GstGnomeVFSSinkClass; + +struct _GstGnomeVFSSink +{ + GstBaseSink basesink; + + /*< private >*/ + + /* uri */ + GnomeVFSURI *uri; + gchar *uri_name; + + /* handle */ + GnomeVFSHandle *handle; + + /* whether we opened the handle ourselves */ + gboolean own_handle; + + guint64 data_written; +}; + +struct _GstGnomeVFSSinkClass +{ + GstBaseSink basesink_class; + + /* signals */ + gboolean (*erase_ask) (GstElement * element, GnomeVFSURI * uri); +}; + +GType gst_gnome_vfs_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_GNOME_VFS_SINK_H__ */ + diff --git a/ext/gnomevfs/gstgnomevfssrc.c b/ext/gnomevfs/gstgnomevfssrc.c index 92914a16b1..20daa44fdf 100644 --- a/ext/gnomevfs/gstgnomevfssrc.c +++ b/ext/gnomevfs/gstgnomevfssrc.c @@ -23,6 +23,47 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-gnomevfssrc + * @short_description: Read from any GnomeVFS-supported location + * @see_also: #GstFileSrc, #GstGnomeVFSSink + * + * + * + * This plugin reads data from a local or remote location specified + * by an URI. This location can be specified using any protocol supported by + * the GnomeVFS library. Common protocols are 'file', 'http', 'ftp', or 'smb'. + * + * + * Example pipeline: + * + * gst-launch -v gnomevfssrc location=file:///home/joe/foo.xyz ! fakesink + * + * The above pipeline will simply read a local file and do nothing with the + * data read. Instead of gnomevfssrc, we could just as well have used the + * filesrc element here. + * + * + * Another example pipeline: + * + * gst-launch -v gnomevfssrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz + * + * The above pipeline will copy a file from a remote host to the local file + * system using the Samba protocol. + * + * + * Yet another example pipeline: + * + * gst-launch -v gnomevfssrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioscale ! alsasink + * + * The above pipeline will read and decode and play an mp3 file from a + * web server using the http protocol. + * + * + * + */ + + #define BROKEN_SIG 1 /*#undef BROKEN_SIG */ @@ -32,8 +73,7 @@ #include "gst/gst-i18n-plugin.h" -#include "gstgnomevfs.h" -#include "gstgnomevfsuri.h" +#include "gstgnomevfssrc.h" #include #include @@ -50,68 +90,17 @@ #include #include -#include -#include /* gnome-vfs.h doesn't include the following header, which we need: */ #include -GST_DEBUG_CATEGORY (gnomevfssrc_debug); +GST_DEBUG_CATEGORY_STATIC (gnomevfssrc_debug); #define GST_CAT_DEFAULT gnomevfssrc_debug -#define GST_TYPE_GNOMEVFSSRC \ - (gst_gnomevfssrc_get_type()) -#define GST_GNOMEVFSSRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOMEVFSSRC,GstGnomeVFSSrc)) -#define GST_GNOMEVFSSRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOMEVFSSRC,GstGnomeVFSSrcClass)) -#define GST_IS_GNOMEVFSSRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOMEVFSSRC)) -#define GST_IS_GNOMEVFSSRC_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOMEVFSSRC)) static GStaticMutex count_lock = G_STATIC_MUTEX_INIT; static gint ref_count = 0; static gboolean vfs_owner = FALSE; -typedef struct _GstGnomeVFSSrc -{ - GstBaseSrc element; - - /* uri, file, ... */ - GnomeVFSURI *uri; - gchar *uri_name; - GnomeVFSHandle *handle; - gboolean own_handle; - GnomeVFSFileSize size; /* -1 = unknown */ - GnomeVFSFileOffset curoffset; /* current offset in file */ - gboolean seekable; - - /* icecast/audiocast metadata extraction handling */ - gboolean iradio_mode; - gboolean http_callbacks_pushed; - - gint icy_metaint; - GnomeVFSFileSize icy_count; - - gchar *iradio_name; - gchar *iradio_genre; - gchar *iradio_url; - gchar *iradio_title; - - GThread *audiocast_thread; - GList *audiocast_notify_queue; - GMutex *audiocast_queue_mutex; - GMutex *audiocast_udpdata_mutex; - gint audiocast_thread_die_infd; - gint audiocast_thread_die_outfd; - gint audiocast_port; - gint audiocast_fd; -} GstGnomeVFSSrc; - -typedef struct _GstGnomeVFSSrcClass -{ - GstBaseSrcClass parent_class; -} GstGnomeVFSSrcClass; static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -130,23 +119,23 @@ enum ARG_IRADIO_TITLE }; -static void gst_gnomevfssrc_base_init (gpointer g_class); -static void gst_gnomevfssrc_class_init (GstGnomeVFSSrcClass * klass); -static void gst_gnomevfssrc_init (GstGnomeVFSSrc * gnomevfssrc); -static void gst_gnomevfssrc_finalize (GObject * object); -static void gst_gnomevfssrc_uri_handler_init (gpointer g_iface, +static void gst_gnome_vfs_src_base_init (gpointer g_class); +static void gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass); +static void gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc); +static void gst_gnome_vfs_src_finalize (GObject * object); +static void gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, gpointer iface_data); -static void gst_gnomevfssrc_set_property (GObject * object, guint prop_id, +static void gst_gnome_vfs_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_gnomevfssrc_get_property (GObject * object, guint prop_id, +static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static gboolean gst_gnomevfssrc_stop (GstBaseSrc * src); -static gboolean gst_gnomevfssrc_start (GstBaseSrc * src); -static gboolean gst_gnomevfssrc_is_seekable (GstBaseSrc * src); -static gboolean gst_gnomevfssrc_get_size (GstBaseSrc * src, guint64 * size); -static GstFlowReturn gst_gnomevfssrc_create (GstBaseSrc * basesrc, +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_get_size (GstBaseSrc * src, guint64 * size); +static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size, GstBuffer ** buffer); static int audiocast_init (GstGnomeVFSSrc * src); @@ -158,24 +147,24 @@ static void audiocast_thread_kill (GstGnomeVFSSrc * src); static GstElementClass *parent_class = NULL; GType -gst_gnomevfssrc_get_type (void) +gst_gnome_vfs_src_get_type (void) { static GType gnomevfssrc_type = 0; if (!gnomevfssrc_type) { static const GTypeInfo gnomevfssrc_info = { sizeof (GstGnomeVFSSrcClass), - gst_gnomevfssrc_base_init, + gst_gnome_vfs_src_base_init, NULL, - (GClassInitFunc) gst_gnomevfssrc_class_init, + (GClassInitFunc) gst_gnome_vfs_src_class_init, NULL, NULL, sizeof (GstGnomeVFSSrc), 0, - (GInstanceInitFunc) gst_gnomevfssrc_init, + (GInstanceInitFunc) gst_gnome_vfs_src_init, }; static const GInterfaceInfo urihandler_info = { - gst_gnomevfssrc_uri_handler_init, + gst_gnome_vfs_src_uri_handler_init, NULL, NULL }; @@ -190,10 +179,10 @@ gst_gnomevfssrc_get_type (void) } static void -gst_gnomevfssrc_base_init (gpointer g_class) +gst_gnome_vfs_src_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - static GstElementDetails gst_gnomevfssrc_details = + static GstElementDetails gst_gnome_vfs_src_details = GST_ELEMENT_DETAILS ("GnomeVFS Source", "Source/File", "Read from any GnomeVFS-supported file", @@ -202,11 +191,14 @@ gst_gnomevfssrc_base_init (gpointer g_class) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&srctemplate)); - gst_element_class_set_details (element_class, &gst_gnomevfssrc_details); + gst_element_class_set_details (element_class, &gst_gnome_vfs_src_details); + + GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0, + "Gnome-VFS Source"); } static void -gst_gnomevfssrc_class_init (GstGnomeVFSSrcClass * klass) +gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -216,19 +208,20 @@ gst_gnomevfssrc_class_init (GstGnomeVFSSrcClass * klass) gstelement_class = GST_ELEMENT_CLASS (klass); gstbasesrc_class = GST_BASE_SRC_CLASS (klass); - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = gst_gnomevfssrc_finalize; - gobject_class->set_property = gst_gnomevfssrc_set_property; - gobject_class->get_property = gst_gnomevfssrc_get_property; + gobject_class->finalize = gst_gnome_vfs_src_finalize; + gobject_class->set_property = gst_gnome_vfs_src_set_property; + gobject_class->get_property = gst_gnome_vfs_src_get_property; /* properties */ gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass), "location", ARG_LOCATION, G_PARAM_READWRITE, NULL); g_object_class_install_property (gobject_class, ARG_HANDLE, - g_param_spec_pointer ("handle", - "GnomeVFSHandle", "Handle for GnomeVFS", G_PARAM_READWRITE)); + g_param_spec_boxed ("handle", + "GnomeVFSHandle", "Handle for GnomeVFS", + GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE)); /* icecast stuff */ g_object_class_install_property (gobject_class, @@ -256,16 +249,16 @@ gst_gnomevfssrc_class_init (GstGnomeVFSSrcClass * klass) "iradio-title", "Name of currently playing song", NULL, G_PARAM_READABLE)); - gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnomevfssrc_start); - gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnomevfssrc_stop); - gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnomevfssrc_get_size); + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size); gstbasesrc_class->is_seekable = - GST_DEBUG_FUNCPTR (gst_gnomevfssrc_is_seekable); - gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnomevfssrc_create); + GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_create); } static void -gst_gnomevfssrc_init (GstGnomeVFSSrc * gnomevfssrc) +gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc) { gnomevfssrc->uri = NULL; gnomevfssrc->uri_name = NULL; @@ -300,9 +293,9 @@ gst_gnomevfssrc_init (GstGnomeVFSSrc * gnomevfssrc) } static void -gst_gnomevfssrc_finalize (GObject * object) +gst_gnome_vfs_src_finalize (GObject * object) { - GstGnomeVFSSrc *src = GST_GNOMEVFSSRC (object); + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (object); g_static_mutex_lock (&count_lock); ref_count--; @@ -334,13 +327,13 @@ gst_gnomevfssrc_finalize (GObject * object) */ static guint -gst_gnomevfssrc_uri_get_type (void) +gst_gnome_vfs_src_uri_get_type (void) { return GST_URI_SRC; } static gchar ** -gst_gnomevfssrc_uri_get_protocols (void) +gst_gnome_vfs_src_uri_get_protocols (void) { static gchar **protocols = NULL; @@ -351,17 +344,17 @@ gst_gnomevfssrc_uri_get_protocols (void) } static const gchar * -gst_gnomevfssrc_uri_get_uri (GstURIHandler * handler) +gst_gnome_vfs_src_uri_get_uri (GstURIHandler * handler) { - GstGnomeVFSSrc *src = GST_GNOMEVFSSRC (handler); + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler); return src->uri_name; } static gboolean -gst_gnomevfssrc_uri_set_uri (GstURIHandler * handler, const gchar * uri) +gst_gnome_vfs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) { - GstGnomeVFSSrc *src = GST_GNOMEVFSSRC (handler); + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler); if (GST_STATE (src) == GST_STATE_PLAYING || GST_STATE (src) == GST_STATE_PAUSED) @@ -373,24 +366,24 @@ gst_gnomevfssrc_uri_set_uri (GstURIHandler * handler, const gchar * uri) } static void -gst_gnomevfssrc_uri_handler_init (gpointer g_iface, gpointer iface_data) +gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, gpointer iface_data) { GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; - iface->get_type = gst_gnomevfssrc_uri_get_type; - iface->get_protocols = gst_gnomevfssrc_uri_get_protocols; - iface->get_uri = gst_gnomevfssrc_uri_get_uri; - iface->set_uri = gst_gnomevfssrc_uri_set_uri; + iface->get_type = gst_gnome_vfs_src_uri_get_type; + iface->get_protocols = gst_gnome_vfs_src_uri_get_protocols; + iface->get_uri = gst_gnome_vfs_src_uri_get_uri; + iface->set_uri = gst_gnome_vfs_src_uri_set_uri; } static void -gst_gnomevfssrc_set_property (GObject * object, guint prop_id, +gst_gnome_vfs_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstGnomeVFSSrc *src; gchar cwd[PATH_MAX]; - src = GST_GNOMEVFSSRC (object); + src = GST_GNOME_VFS_SRC (object); switch (prop_id) { case ARG_LOCATION: @@ -438,7 +431,7 @@ gst_gnomevfssrc_set_property (GObject * object, guint prop_id, g_free (src->uri_name); src->uri_name = NULL; } - src->handle = g_value_get_pointer (value); + src->handle = g_value_get_boxed (value); } break; case ARG_IRADIO_MODE: @@ -451,19 +444,19 @@ gst_gnomevfssrc_set_property (GObject * object, guint prop_id, } static void -gst_gnomevfssrc_get_property (GObject * object, guint prop_id, GValue * value, +gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstGnomeVFSSrc *src; - src = GST_GNOMEVFSSRC (object); + src = GST_GNOME_VFS_SRC (object); switch (prop_id) { case ARG_LOCATION: g_value_set_string (value, src->uri_name); break; case ARG_HANDLE: - g_value_set_pointer (value, src->handle); + g_value_set_boxed (value, src->handle); break; case ARG_IRADIO_MODE: g_value_set_boolean (value, src->iradio_mode); @@ -515,7 +508,7 @@ unicodify (const char *str, int len, ...) } static char * -gst_gnomevfssrc_unicodify (const char *str) +gst_gnome_vfs_src_unicodify (const char *str) { return unicodify (str, -1, "locale", "ISO-8859-1", NULL); } @@ -674,7 +667,7 @@ audiocast_thread_run (GstGnomeVFSSrc * src) if (!strlen (valptr)) continue; - value = gst_gnomevfssrc_unicodify (valptr); + value = gst_gnome_vfs_src_unicodify (valptr); if (!value) { g_print ("Unable to convert \"%s\" to UTF-8!\n", valptr); continue; @@ -745,10 +738,10 @@ audiocast_thread_kill (GstGnomeVFSSrc * src) } static void -gst_gnomevfssrc_send_additional_headers_callback (gconstpointer in, +gst_gnome_vfs_src_send_additional_headers_callback (gconstpointer in, gsize in_size, gpointer out, gsize out_size, gpointer callback_data) { - GstGnomeVFSSrc *src = GST_GNOMEVFSSRC (callback_data); + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data); GnomeVFSModuleCallbackAdditionalHeadersOut *out_args = (GnomeVFSModuleCallbackAdditionalHeadersOut *) out; @@ -763,12 +756,12 @@ gst_gnomevfssrc_send_additional_headers_callback (gconstpointer in, } static void -gst_gnomevfssrc_received_headers_callback (gconstpointer in, +gst_gnome_vfs_src_received_headers_callback (gconstpointer in, gsize in_size, gpointer out, gsize out_size, gpointer callback_data) { GList *i; gint icy_metaint; - GstGnomeVFSSrc *src = GST_GNOMEVFSSRC (callback_data); + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data); GnomeVFSModuleCallbackReceivedHeadersIn *in_args = (GnomeVFSModuleCallbackReceivedHeadersIn *) in; @@ -810,17 +803,17 @@ gst_gnomevfssrc_received_headers_callback (gconstpointer in, GST_DEBUG_OBJECT (src, "key: %s", key); if (!strncmp (key, "name", 4)) { g_free (src->iradio_name); - src->iradio_name = gst_gnomevfssrc_unicodify (value); + src->iradio_name = gst_gnome_vfs_src_unicodify (value); if (src->iradio_name) g_object_notify (G_OBJECT (src), "iradio-name"); } else if (!strncmp (key, "genre", 5)) { g_free (src->iradio_genre); - src->iradio_genre = gst_gnomevfssrc_unicodify (value); + src->iradio_genre = gst_gnome_vfs_src_unicodify (value); if (src->iradio_genre) g_object_notify (G_OBJECT (src), "iradio-genre"); } else if (!strncmp (key, "url", 3)) { g_free (src->iradio_url); - src->iradio_url = gst_gnomevfssrc_unicodify (value); + src->iradio_url = gst_gnome_vfs_src_unicodify (value); if (src->iradio_url) g_object_notify (G_OBJECT (src), "iradio-url"); } @@ -828,7 +821,7 @@ gst_gnomevfssrc_received_headers_callback (gconstpointer in, } static void -gst_gnomevfssrc_push_callbacks (GstGnomeVFSSrc * src) +gst_gnome_vfs_src_push_callbacks (GstGnomeVFSSrc * src) { if (src->http_callbacks_pushed) return; @@ -836,16 +829,16 @@ gst_gnomevfssrc_push_callbacks (GstGnomeVFSSrc * src) GST_DEBUG_OBJECT (src, "pushing callbacks"); gnome_vfs_module_callback_push (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS, - gst_gnomevfssrc_send_additional_headers_callback, src, NULL); + gst_gnome_vfs_src_send_additional_headers_callback, src, NULL); gnome_vfs_module_callback_push (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS, - gst_gnomevfssrc_received_headers_callback, src, NULL); + gst_gnome_vfs_src_received_headers_callback, src, NULL); src->http_callbacks_pushed = TRUE; } static void -gst_gnomevfssrc_pop_callbacks (GstGnomeVFSSrc * src) +gst_gnome_vfs_src_pop_callbacks (GstGnomeVFSSrc * src) { if (!src->http_callbacks_pushed) return; @@ -858,7 +851,7 @@ gst_gnomevfssrc_pop_callbacks (GstGnomeVFSSrc * src) } static void -gst_gnomevfssrc_get_icy_metadata (GstGnomeVFSSrc * src) +gst_gnome_vfs_src_get_icy_metadata (GstGnomeVFSSrc * src) { GnomeVFSFileSize length = 0; GnomeVFSResult res; @@ -903,7 +896,7 @@ gst_gnomevfssrc_get_icy_metadata (GstGnomeVFSSrc * src) for (i = 0; tags[i]; i++) { if (!g_ascii_strncasecmp (tags[i], "StreamTitle=", 12)) { g_free (src->iradio_title); - src->iradio_title = gst_gnomevfssrc_unicodify (tags[i] + 13); + src->iradio_title = gst_gnome_vfs_src_unicodify (tags[i] + 13); if (src->iradio_title) { GST_DEBUG_OBJECT (src, "sending notification on icecast title"); g_object_notify (G_OBJECT (src), "iradio-title"); @@ -914,7 +907,7 @@ gst_gnomevfssrc_get_icy_metadata (GstGnomeVFSSrc * src) } if (!g_ascii_strncasecmp (tags[i], "StreamUrl=", 10)) { g_free (src->iradio_url); - src->iradio_url = gst_gnomevfssrc_unicodify (tags[i] + 11); + src->iradio_url = gst_gnome_vfs_src_unicodify (tags[i] + 11); if (src->iradio_url) { GST_DEBUG_OBJECT (src, "sending notification on icecast url"); g_object_notify (G_OBJECT (src), "iradio-url"); @@ -934,7 +927,7 @@ gst_gnomevfssrc_get_icy_metadata (GstGnomeVFSSrc * src) * and seeking and such. */ static GstFlowReturn -gst_gnomevfssrc_create (GstBaseSrc * basesrc, guint64 offset, guint size, +gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size, GstBuffer ** buffer) { GnomeVFSResult res; @@ -943,7 +936,7 @@ gst_gnomevfssrc_create (GstBaseSrc * basesrc, guint64 offset, guint size, guint8 *data; GstGnomeVFSSrc *src; - src = GST_GNOMEVFSSRC (basesrc); + src = GST_GNOME_VFS_SRC (basesrc); GST_DEBUG ("now at %llu, reading %lld, size %u", src->curoffset, offset, size); @@ -988,7 +981,7 @@ gst_gnomevfssrc_create (GstBaseSrc * basesrc, guint64 offset, guint size, src->curoffset += readbytes; if (src->icy_count == src->icy_metaint) { - gst_gnomevfssrc_get_icy_metadata (src); + gst_gnome_vfs_src_get_icy_metadata (src); src->icy_count = 0; } } else { @@ -1045,21 +1038,21 @@ eos: } static gboolean -gst_gnomevfssrc_is_seekable (GstBaseSrc * basesrc) +gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc) { GstGnomeVFSSrc *src; - src = GST_GNOMEVFSSRC (basesrc); + src = GST_GNOME_VFS_SRC (basesrc); return src->seekable; } static gboolean -gst_gnomevfssrc_get_size (GstBaseSrc * basesrc, guint64 * size) +gst_gnome_vfs_src_get_size (GstBaseSrc * basesrc, guint64 * size) { GstGnomeVFSSrc *src; - src = GST_GNOMEVFSSRC (basesrc); + src = GST_GNOME_VFS_SRC (basesrc); GST_DEBUG_OBJECT (src, "size %" G_GUINT64_FORMAT, src->size); @@ -1073,18 +1066,18 @@ gst_gnomevfssrc_get_size (GstBaseSrc * basesrc, guint64 * size) /* open the file, do stuff necessary to go to READY state */ static gboolean -gst_gnomevfssrc_start (GstBaseSrc * basesrc) +gst_gnome_vfs_src_start (GstBaseSrc * basesrc) { GnomeVFSResult res; GnomeVFSFileInfo *info; GstGnomeVFSSrc *src; - src = GST_GNOMEVFSSRC (basesrc); + src = GST_GNOME_VFS_SRC (basesrc); if (!audiocast_init (src)) return FALSE; - gst_gnomevfssrc_push_callbacks (src); + gst_gnome_vfs_src_push_callbacks (src); if (src->uri != NULL) { if ((res = gnome_vfs_open_uri (&src->handle, src->uri, @@ -1092,7 +1085,7 @@ gst_gnomevfssrc_start (GstBaseSrc * basesrc) gchar *filename = gnome_vfs_uri_to_string (src->uri, GNOME_VFS_URI_HIDE_PASSWORD); - gst_gnomevfssrc_pop_callbacks (src); + gst_gnome_vfs_src_pop_callbacks (src); audiocast_thread_kill (src); if (res == GNOME_VFS_ERROR_NOT_FOUND) { @@ -1143,13 +1136,13 @@ gst_gnomevfssrc_start (GstBaseSrc * basesrc) } static gboolean -gst_gnomevfssrc_stop (GstBaseSrc * basesrc) +gst_gnome_vfs_src_stop (GstBaseSrc * basesrc) { GstGnomeVFSSrc *src; - src = GST_GNOMEVFSSRC (basesrc); + src = GST_GNOME_VFS_SRC (basesrc); - gst_gnomevfssrc_pop_callbacks (src); + gst_gnome_vfs_src_pop_callbacks (src); audiocast_thread_kill (src); if (src->own_handle) { diff --git a/ext/gnomevfs/gstgnomevfssrc.h b/ext/gnomevfs/gstgnomevfssrc.h new file mode 100644 index 0000000000..2a8853b35c --- /dev/null +++ b/ext/gnomevfs/gstgnomevfssrc.h @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2002 Kristian Rietveld + * 2002,2003 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GNOME_VFS_SRC_H__ +#define __GST_GNOME_VFS_SRC_H__ + +#include + +#include "gstgnomevfs.h" +#include "gstgnomevfsuri.h" +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GNOME_VFS_SRC \ + (gst_gnome_vfs_src_get_type()) +#define GST_GNOME_VFS_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrc)) +#define GST_GNOME_VFS_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrcClass)) +#define GST_IS_GNOME_VFS_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SRC)) +#define GST_IS_GNOME_VFS_SRC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SRC)) + +typedef struct _GstGnomeVFSSrc GstGnomeVFSSrc; +typedef struct _GstGnomeVFSSrcClass GstGnomeVFSSrcClass; + +struct _GstGnomeVFSSrc +{ + GstBaseSrc basesrc; + + /* uri, file, ... */ + GnomeVFSURI *uri; + gchar *uri_name; + GnomeVFSHandle *handle; + gboolean own_handle; + GnomeVFSFileSize size; /* -1 = unknown */ + GnomeVFSFileOffset curoffset; /* current offset in file */ + gboolean seekable; + + /* icecast/audiocast metadata extraction handling */ + gboolean iradio_mode; + gboolean http_callbacks_pushed; + + gint icy_metaint; + GnomeVFSFileSize icy_count; + + gchar *iradio_name; + gchar *iradio_genre; + gchar *iradio_url; + gchar *iradio_title; + + GThread *audiocast_thread; + GList *audiocast_notify_queue; + GMutex *audiocast_queue_mutex; + GMutex *audiocast_udpdata_mutex; + gint audiocast_thread_die_infd; + gint audiocast_thread_die_outfd; + gint audiocast_port; + gint audiocast_fd; +}; + +struct _GstGnomeVFSSrcClass +{ + GstBaseSrcClass basesrc_class; +}; + +GType gst_gnome_vfs_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_GNOME_VFS_SRC_H__ */ +