diff options
author | Zaheer Abbas Merali <zaheerabbas@merali.org> | 2004-07-22 17:57:04 +0000 |
---|---|---|
committer | Zaheer Abbas Merali <zaheerabbas@merali.org> | 2004-07-22 17:57:04 +0000 |
commit | 26faa6d555b49e2908f6425a3357be29034cc48f (patch) | |
tree | 25abfdbd2edc5d9f8b3f3bac1843351f3dc6deff | |
parent | 2feee52bc1a48cab82df53e05086147db2d52b87 (diff) | |
download | gst-plugins-bad-26faa6d555b49e2908f6425a3357be29034cc48f.tar.gz gst-plugins-bad-26faa6d555b49e2908f6425a3357be29034cc48f.tar.bz2 gst-plugins-bad-26faa6d555b49e2908f6425a3357be29034cc48f.zip |
multifilesink plugin for creating new files every time a new media discontinuity event occurs
Original commit message from CVS:
2004-07-22 Zaheer Abbas Merali <zaheerabbas at merali dot org>
* configure.ac:
* gst/Makefile.am:
* gst/multifilesink/Makefile.am:
* gst/multifilesink/gstmultifilesink.c:
(gst_multifilesink_get_formats),
(gst_multifilesink_get_query_types), (_do_init),
(gst_multifilesink_base_init), (gst_multifilesink_class_init),
(gst_multifilesink_init), (gst_multifilesink_dispose),
(gst_multifilesink_set_location), (gst_multifilesink_set_property),
(gst_multifilesink_get_property), (gst_multifilesink_open_file),
(gst_multifilesink_close_file), (gst_multifilesink_next_file),
(gst_multifilesink_pad_query), (gst_multifilesink_handle_event),
(gst_multifilesink_chain), (gst_multifilesink_change_state),
(gst_multifilesink_uri_get_type),
(gst_multifilesink_uri_get_protocols),
(gst_multifilesink_uri_get_uri), (gst_multifilesink_uri_set_uri),
(gst_multifilesink_uri_handler_init), (plugin_init):
* gst/multifilesink/gstmultifilesink.h:
* testsuite/Makefile.am:
* testsuite/multifilesink/Makefile.am:
* testsuite/multifilesink/fakesrc_test.c: (gst_newmedia_base_init),
(gst_newmedia_class_init), (gst_newmedia_init),
(gst_newmedia_chain), (gst_newmedia_trigger), (test_format),
(newfile_signal), (test_signal), (main):
multifilesink plugin for creating new files every time a new media
discontinuity event occurs
-rw-r--r-- | ChangeLog | 29 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | gst/multifilesink/Makefile.am | 10 | ||||
-rw-r--r-- | gst/multifilesink/gstmultifilesink.c | 637 | ||||
-rw-r--r-- | gst/multifilesink/gstmultifilesink.h | 78 |
5 files changed, 757 insertions, 0 deletions
@@ -1,3 +1,32 @@ +2004-07-22 Zaheer Abbas Merali <zaheerabbas at merali dot org> + + * configure.ac: + * gst/Makefile.am: + * gst/multifilesink/Makefile.am: + * gst/multifilesink/gstmultifilesink.c: + (gst_multifilesink_get_formats), + (gst_multifilesink_get_query_types), (_do_init), + (gst_multifilesink_base_init), (gst_multifilesink_class_init), + (gst_multifilesink_init), (gst_multifilesink_dispose), + (gst_multifilesink_set_location), (gst_multifilesink_set_property), + (gst_multifilesink_get_property), (gst_multifilesink_open_file), + (gst_multifilesink_close_file), (gst_multifilesink_next_file), + (gst_multifilesink_pad_query), (gst_multifilesink_handle_event), + (gst_multifilesink_chain), (gst_multifilesink_change_state), + (gst_multifilesink_uri_get_type), + (gst_multifilesink_uri_get_protocols), + (gst_multifilesink_uri_get_uri), (gst_multifilesink_uri_set_uri), + (gst_multifilesink_uri_handler_init), (plugin_init): + * gst/multifilesink/gstmultifilesink.h: + * testsuite/Makefile.am: + * testsuite/multifilesink/Makefile.am: + * testsuite/multifilesink/fakesrc_test.c: (gst_newmedia_base_init), + (gst_newmedia_class_init), (gst_newmedia_init), + (gst_newmedia_chain), (gst_newmedia_trigger), (test_format), + (newfile_signal), (test_signal), (main): + multifilesink plugin for creating new files every time a new media + discontinuity event occurs + 2004-07-22 Wim Taymans <wim@fluendo.com> * gst/alpha/Makefile.am: diff --git a/configure.ac b/configure.ac index 75c21060..b4b3539b 100644 --- a/configure.ac +++ b/configure.ac @@ -370,6 +370,7 @@ GST_PLUGINS_ALL="\ mpegaudioparse \ mpegstream \ monoscope \ + multifilesink \ multipart \ overlay \ passthrough \ @@ -1835,6 +1836,7 @@ gst/mpegstream/Makefile gst/modplug/Makefile gst/modplug/libmodplug/Makefile gst/monoscope/Makefile +gst/multifilesink/Makefile gst/multipart/Makefile gst/overlay/Makefile gst/passthrough/Makefile @@ -1974,6 +1976,7 @@ examples/switch/Makefile examples/Makefile testsuite/spider/Makefile testsuite/alsa/Makefile +testsuite/multifilesink/Makefile testsuite/Makefile tools/Makefile gconf/Makefile diff --git a/gst/multifilesink/Makefile.am b/gst/multifilesink/Makefile.am new file mode 100644 index 00000000..c59668d6 --- /dev/null +++ b/gst/multifilesink/Makefile.am @@ -0,0 +1,10 @@ + +plugin_LTLIBRARIES = libgstmultifilesink.la + +libgstmultifilesink_la_SOURCES = gstmultifilesink.c +libgstmultifilesink_la_CFLAGS = $(GST_CFLAGS) +libgstmultifilesink_la_LIBADD = $(GST_LIBS) +libgstmultifilesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = gstmultifilesink.h + diff --git a/gst/multifilesink/gstmultifilesink.c b/gst/multifilesink/gstmultifilesink.c new file mode 100644 index 00000000..70c4612e --- /dev/null +++ b/gst/multifilesink/gstmultifilesink.c @@ -0,0 +1,637 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * + * gstmultifilesink.c: + * + * 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. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst/gst-i18n-plugin.h" + +#include <gst/gst.h> +#include <errno.h> +#include "gstmultifilesink.h" +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + + +GST_DEBUG_CATEGORY_STATIC (gst_multifilesink_debug); +#define GST_CAT_DEFAULT gst_multifilesink_debug + +GstElementDetails gst_multifilesink_details = +GST_ELEMENT_DETAILS ("Multiple File Sink", + "Sink/File", + "Write stream to multiple files sequentially", + "Zaheer Abbas Merali <zaheerabbas at merali dot org>"); + + +/* FileSink signals and args */ +enum +{ + /* FILL ME */ + SIGNAL_HANDOFF, + SIGNAL_NEWFILE, + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_LOCATION +}; + +static const GstFormat * +gst_multifilesink_get_formats (GstPad * pad) +{ + static const GstFormat formats[] = { + GST_FORMAT_BYTES, + 0, + }; + + return formats; +} + +static const GstQueryType * +gst_multifilesink_get_query_types (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_TOTAL, + GST_QUERY_POSITION, + 0 + }; + + return types; +} + +static void gst_multifilesink_dispose (GObject * object); + +static void gst_multifilesink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_multifilesink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_multifilesink_open_file (GstMultiFileSink * sink); +static void gst_multifilesink_close_file (GstMultiFileSink * sink); + +static gboolean gst_multifilesink_handle_event (GstPad * pad, GstEvent * event); +static gboolean gst_multifilesink_pad_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value); +static void gst_multifilesink_chain (GstPad * pad, GstData * _data); + +static void gst_multifilesink_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +static GstElementStateReturn gst_multifilesink_change_state (GstElement * + element); + +static guint gst_multifilesink_signals[LAST_SIGNAL] = { 0 }; + +static void +_do_init (GType filesink_type) +{ + static const GInterfaceInfo urihandler_info = { + gst_multifilesink_uri_handler_init, + NULL, + NULL + }; + + g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER, + &urihandler_info); + GST_DEBUG_CATEGORY_INIT (gst_multifilesink_debug, "multifilesink", 0, + "multifilesink element"); +} + +GST_BOILERPLATE_FULL (GstMultiFileSink, gst_multifilesink, GstElement, + GST_TYPE_ELEMENT, _do_init); + + +static void +gst_multifilesink_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gstelement_class->change_state = gst_multifilesink_change_state; + gst_element_class_set_details (gstelement_class, &gst_multifilesink_details); +} +static void +gst_multifilesink_class_init (GstMultiFileSinkClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION, + g_param_spec_string ("location", "File Location", + "Location of the file to write", NULL, G_PARAM_READWRITE)); + + gst_multifilesink_signals[SIGNAL_HANDOFF] = + g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMultiFileSinkClass, handoff), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + gst_multifilesink_signals[SIGNAL_NEWFILE] = + g_signal_new ("newfile", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMultiFileSinkClass, newfile), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + gobject_class->set_property = gst_multifilesink_set_property; + gobject_class->get_property = gst_multifilesink_get_property; + gobject_class->dispose = gst_multifilesink_dispose; +} +static void +gst_multifilesink_init (GstMultiFileSink * filesink) +{ + GstPad *pad; + + pad = gst_pad_new ("sink", GST_PAD_SINK); + gst_element_add_pad (GST_ELEMENT (filesink), pad); + gst_pad_set_chain_function (pad, gst_multifilesink_chain); + + GST_FLAG_SET (GST_ELEMENT (filesink), GST_ELEMENT_EVENT_AWARE); + + gst_pad_set_query_function (pad, gst_multifilesink_pad_query); + gst_pad_set_query_type_function (pad, gst_multifilesink_get_query_types); + gst_pad_set_formats_function (pad, gst_multifilesink_get_formats); + + filesink->filename = NULL; + filesink->file = NULL; + filesink->curfilename = NULL; + filesink->curfileindex = 0; + filesink->numfiles = 0; +} +static void +gst_multifilesink_dispose (GObject * object) +{ + GstMultiFileSink *sink = GST_MULTIFILESINK (object); + + G_OBJECT_CLASS (parent_class)->dispose (object); + + g_free (sink->uri); + sink->uri = NULL; + g_free (sink->filename); + sink->filename = NULL; + if (sink->curfilename) + g_free (sink->curfilename); + sink->curfilename = NULL; +} + +static gboolean +gst_multifilesink_set_location (GstMultiFileSink * sink, const gchar * location) +{ + GST_DEBUG ("location set is: %s", location); + /* the element must be stopped or paused in order to do this or in newfile + signal */ + if (GST_STATE (sink) > GST_STATE_PAUSED && + !GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_NEWFILE)) + return FALSE; + if (GST_STATE (sink) == GST_STATE_PAUSED && + (GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_OPEN) || + !GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_NEWFILE))) + + return FALSE; + + g_free (sink->filename); + g_free (sink->uri); + if (location != NULL) { + sink->filename = g_strdup (location); + sink->curfileindex = 0; + sink->curfilename = g_strdup_printf (location, sink->curfileindex); + sink->uri = gst_uri_construct ("file", sink->curfilename); + } else { + sink->filename = NULL; + sink->uri = NULL; + } + + if (GST_STATE (sink) == GST_STATE_PAUSED && + !GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_NEWFILE)) + gst_multifilesink_open_file (sink); + + return TRUE; +} +static void +gst_multifilesink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMultiFileSink *sink; + + /* it's not null if we got it, but it might not be ours */ + sink = GST_MULTIFILESINK (object); + + switch (prop_id) { + case ARG_LOCATION: + if (!gst_multifilesink_set_location (sink, g_value_get_string (value))) + GST_DEBUG ("location not set properly"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_multifilesink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstMultiFileSink *sink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_MULTIFILESINK (object)); + + sink = GST_MULTIFILESINK (object); + + switch (prop_id) { + case ARG_LOCATION: + g_value_set_string (value, sink->curfilename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_multifilesink_open_file (GstMultiFileSink * sink) +{ + g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_OPEN), FALSE); + + /* open the file */ + if (sink->curfilename == NULL || sink->curfilename[0] == '\0') { + GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, + (_("No file name specified for writing.")), (NULL)); + return FALSE; + } + + sink->file = fopen (sink->curfilename, "wb"); + if (sink->file == NULL) { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, + (_("Could not open file \"%s\" for writing."), sink->curfilename), + GST_ERROR_SYSTEM); + return FALSE; + } + + GST_FLAG_SET (sink, GST_MULTIFILESINK_OPEN); + + sink->data_written = 0; + sink->curfileindex++; + + return TRUE; +} + +static void +gst_multifilesink_close_file (GstMultiFileSink * sink) +{ + g_return_if_fail (GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_OPEN)); + + if (fclose (sink->file) != 0) { + GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE, + (_("Error closing file \"%s\"."), sink->curfilename), GST_ERROR_SYSTEM); + } else { + GST_FLAG_UNSET (sink, GST_MULTIFILESINK_OPEN); + } +} + +static gboolean +gst_multifilesink_next_file (GstMultiFileSink * sink) +{ + GST_DEBUG ("next file"); + g_return_val_if_fail (GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_OPEN), FALSE); + + if (fclose (sink->file) != 0) { + GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE, + (_("Error closing file \"%s\"."), sink->curfilename), GST_ERROR_SYSTEM); + } else { + GST_FLAG_UNSET (sink, GST_MULTIFILESINK_OPEN); + } + + g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_MULTIFILESINK_OPEN), FALSE); + if (sink->curfilename) + g_free (sink->curfilename); + if (sink->uri) + g_free (sink->uri); + sink->curfilename = g_strdup_printf (sink->filename, sink->curfileindex); + sink->uri = gst_uri_construct ("file", sink->curfilename); + GST_DEBUG ("Next file is: %s", sink->curfilename); + /* open the file */ + if (sink->curfilename == NULL || sink->curfilename[0] == '\0') { + GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, + (_("No file name specified for writing.")), (NULL)); + return FALSE; + } + + sink->file = fopen (sink->curfilename, "wb"); + if (sink->file == NULL) { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, + (_("Could not open file \"%s\" for writing."), sink->curfilename), + GST_ERROR_SYSTEM); + return FALSE; + } + + GST_FLAG_SET (sink, GST_MULTIFILESINK_OPEN); + + sink->data_written = 0; + sink->curfileindex++; + + return TRUE; +} + +static gboolean +gst_multifilesink_pad_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value) +{ + GstMultiFileSink *sink = GST_MULTIFILESINK (GST_PAD_PARENT (pad)); + + switch (type) { + case GST_QUERY_TOTAL: + switch (*format) { + case GST_FORMAT_BYTES: + if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_MULTIFILESINK_OPEN)) { + *value = sink->data_written; /* FIXME - doesn't the kernel provide + such a function? */ + break; + } + default: + return FALSE; + } + break; + case GST_QUERY_POSITION: + switch (*format) { + case GST_FORMAT_BYTES: + if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_MULTIFILESINK_OPEN)) { + *value = ftell (sink->file); + break; + } + default: + return FALSE; + } + break; + default: + return FALSE; + } + + return TRUE; +} + +/* handle events (search) */ +static gboolean +gst_multifilesink_handle_event (GstPad * pad, GstEvent * event) +{ + GstEventType type; + GstMultiFileSink *filesink; + + filesink = GST_MULTIFILESINK (gst_pad_get_parent (pad)); + + + if (!(GST_FLAG_IS_SET (filesink, GST_MULTIFILESINK_OPEN))) { + gst_event_unref (event); + return FALSE; + } + + + type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; + + switch (type) { + case GST_EVENT_SEEK: + if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) { + gst_event_unref (event); + return FALSE; + } + + if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) { + if (fflush (filesink->file)) { + gst_event_unref (event); + GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filesink->filename), + GST_ERROR_SYSTEM); + } + } + + switch (GST_EVENT_SEEK_METHOD (event)) { + case GST_SEEK_METHOD_SET: + fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_SET); + break; + case GST_SEEK_METHOD_CUR: + fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_CUR); + break; + case GST_SEEK_METHOD_END: + fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END); + break; + default: + g_warning ("unknown seek method!"); + break; + } + gst_event_unref (event); + break; + case GST_EVENT_DISCONTINUOUS: + { + gint64 offset; + + if (GST_EVENT_DISCONT_NEW_MEDIA (event)) { + /* do not create a new file on the first new media discont */ + if (filesink->numfiles > 0) { + GST_FLAG_SET (filesink, GST_MULTIFILESINK_NEWFILE); + g_signal_emit (G_OBJECT (filesink), + gst_multifilesink_signals[SIGNAL_NEWFILE], 0); + GST_FLAG_UNSET (filesink, GST_MULTIFILESINK_NEWFILE); + if (!gst_multifilesink_next_file (filesink)) + GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, + (_("Error switching files to \"%s\"."), + filesink->curfilename), GST_ERROR_SYSTEM); + } + filesink->numfiles++; + gst_event_unref (event); + break; + } else { + + if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset)) + fseek (filesink->file, offset, SEEK_SET); + + gst_event_unref (event); + break; + } + } + case GST_EVENT_FLUSH: + if (fflush (filesink->file)) { + gst_event_unref (event); + GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filesink->curfilename), + GST_ERROR_SYSTEM); + } + break; + case GST_EVENT_EOS: + gst_event_unref (event); + gst_multifilesink_close_file (filesink); + gst_element_set_eos (GST_ELEMENT (filesink)); + break; + default: + gst_pad_event_default (pad, event); + break; + } + + return TRUE; +} + +/** + * gst_filesink_chain: + * @pad: the pad this filesink 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_multifilesink_chain (GstPad * pad, GstData * _data) +{ + GstBuffer *buf = GST_BUFFER (_data); + GstMultiFileSink *filesink; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + filesink = GST_MULTIFILESINK (gst_pad_get_parent (pad)); + + if (GST_IS_EVENT (buf)) { + gst_multifilesink_handle_event (pad, GST_EVENT (buf)); + return; + } + + if (GST_FLAG_IS_SET (filesink, GST_MULTIFILESINK_OPEN)) { + guint bytes_written = 0, back_pending = 0; + + if (ftell (filesink->file) < filesink->data_written) + back_pending = filesink->data_written - ftell (filesink->file); + while (bytes_written < GST_BUFFER_SIZE (buf)) { + size_t wrote = fwrite (GST_BUFFER_DATA (buf) + bytes_written, 1, + GST_BUFFER_SIZE (buf) - bytes_written, + filesink->file); + + if (wrote <= 0) { + GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filesink->filename), + ("Only %d of %d bytes written: %s", + bytes_written, GST_BUFFER_SIZE (buf), strerror (errno))); + break; + } + bytes_written += wrote; + } + + filesink->data_written += bytes_written - back_pending; + } + + gst_buffer_unref (buf); + + g_signal_emit (G_OBJECT (filesink), + gst_multifilesink_signals[SIGNAL_HANDOFF], 0, filesink); +} + +static GstElementStateReturn +gst_multifilesink_change_state (GstElement * element) +{ + g_return_val_if_fail (GST_IS_MULTIFILESINK (element), GST_STATE_FAILURE); + + switch (GST_STATE_TRANSITION (element)) { + case GST_STATE_PAUSED_TO_READY: + if (GST_FLAG_IS_SET (element, GST_MULTIFILESINK_OPEN)) + gst_multifilesink_close_file (GST_MULTIFILESINK (element)); + break; + + case GST_STATE_READY_TO_PAUSED: + if (!GST_FLAG_IS_SET (element, GST_MULTIFILESINK_OPEN)) { + if (!gst_multifilesink_open_file (GST_MULTIFILESINK (element))) + return GST_STATE_FAILURE; + } + break; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static guint +gst_multifilesink_uri_get_type (void) +{ + return GST_URI_SINK; +} +static gchar ** +gst_multifilesink_uri_get_protocols (void) +{ + static gchar *protocols[] = { "file", NULL }; + + return protocols; +} +static const gchar * +gst_multifilesink_uri_get_uri (GstURIHandler * handler) +{ + GstMultiFileSink *sink = GST_MULTIFILESINK (handler); + + return sink->uri; +} + +static gboolean +gst_multifilesink_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + gchar *protocol, *location; + gboolean ret; + GstMultiFileSink *sink = GST_MULTIFILESINK (handler); + + protocol = gst_uri_get_protocol (uri); + if (strcmp (protocol, "file") != 0) { + g_free (protocol); + return FALSE; + } + g_free (protocol); + location = gst_uri_get_location (uri); + ret = gst_multifilesink_set_location (sink, location); + g_free (location); + + return ret; +} + +static void +gst_multifilesink_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_multifilesink_uri_get_type; + iface->get_protocols = gst_multifilesink_uri_get_protocols; + iface->get_uri = gst_multifilesink_uri_get_uri; + iface->set_uri = gst_multifilesink_uri_set_uri; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "multifilesink", GST_RANK_NONE, + GST_TYPE_MULTIFILESINK); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "gstmultifilesink", + "multiple file sink (sequentially) after new media events", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN) diff --git a/gst/multifilesink/gstmultifilesink.h b/gst/multifilesink/gstmultifilesink.h new file mode 100644 index 00000000..4f0d60a1 --- /dev/null +++ b/gst/multifilesink/gstmultifilesink.h @@ -0,0 +1,78 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * + * gstmultifilesink.h: + * + * 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_MULTIFILESINK_H__ +#define __GST_MULTIFILESINK_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS + + +#define GST_TYPE_MULTIFILESINK \ + (gst_multifilesink_get_type()) +#define GST_MULTIFILESINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTIFILESINK,GstMultiFileSink)) +#define GST_FILESINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTIFILESINK,GstMultiFileSinkClass)) +#define GST_IS_MULTIFILESINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTIFILESINK)) +#define GST_IS_MULTIFILESINK_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULTIFILESINK)) + +typedef struct _GstMultiFileSink GstMultiFileSink; +typedef struct _GstMultiFileSinkClass GstMultiFileSinkClass; + +typedef enum { + GST_MULTIFILESINK_OPEN = GST_ELEMENT_FLAG_LAST, + GST_MULTIFILESINK_NEWFILE = GST_ELEMENT_FLAG_LAST +2, + + GST_MULTIFILESINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 4 +} GstMultiFileSinkFlags; + +struct _GstMultiFileSink { + GstElement element; + + gchar *filename; + gchar *uri; + gint curfileindex; + gchar* curfilename; + gint numfiles; + FILE *file; + + guint64 data_written; +}; + +struct _GstMultiFileSinkClass { + GstElementClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element, GstPad *pad); + void (*newfile) (GstElement *element); +}; + +GType gst_multifilesink_get_type(void); + +G_END_DECLS + +#endif /* __GST_MULTIFILESINK_H__ */ |