Index: docs/plugins/gstreamer-plugins.args
===================================================================
RCS file: /cvs/gstreamer/gstreamer/docs/plugins/gstreamer-plugins.args,v
retrieving revision 1.14
diff -u -p -r1.14 gstreamer-plugins.args
--- docs/plugins/gstreamer-plugins.args	28 Jan 2008 23:27:12 -0000	1.14
+++ docs/plugins/gstreamer-plugins.args	6 Feb 2008 11:17:25 -0000
@@ -599,6 +599,16 @@
 </ARG>
 
 <ARG>
+<NAME>GstFileSink::max-size</NAME>
+<TYPE>gint64</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Max. number of bytes to write</NICK>
+<BLURB>If >= 0, emit out-of-space signal when max-size bytes are written</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
 <NAME>GstTee::has-chain</NAME>
 <TYPE>gboolean</TYPE>
 <RANGE></RANGE>
Index: docs/plugins/gstreamer-plugins.signals
===================================================================
RCS file: /cvs/gstreamer/gstreamer/docs/plugins/gstreamer-plugins.signals,v
retrieving revision 1.5
diff -u -p -r1.5 gstreamer-plugins.signals
--- docs/plugins/gstreamer-plugins.signals	5 Jun 2007 12:47:23 -0000	1.5
+++ docs/plugins/gstreamer-plugins.signals	6 Feb 2008 11:17:25 -0000
@@ -100,3 +100,9 @@ GstMultiQueue *gstmultiqueue
 GstMultiQueue *gstmultiqueue
 </SIGNAL>
 
+<SIGNAL>
+<NAME>GstFileSink::out-of-space</NAME>
+<RETURNS>gboolean</RETURNS>
+<FLAGS>l</FLAGS>
+</SIGNAL>
+
Index: plugins/elements/gstfilesink.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/plugins/elements/gstfilesink.c,v
retrieving revision 1.93
diff -u -p -r1.93 gstfilesink.c
--- plugins/elements/gstfilesink.c	5 Feb 2008 14:15:13 -0000	1.93
+++ plugins/elements/gstfilesink.c	6 Feb 2008 11:17:25 -0000
@@ -82,10 +82,17 @@ GST_DEBUG_CATEGORY_STATIC (gst_file_sink
 
 enum
 {
+  OUT_OF_SPACE,
+  LAST_SIGNAL
+};
+
+enum
+{
   PROP_0,
   PROP_LOCATION,
   PROP_BUFFER_MODE,
   PROP_BUFFER_SIZE,
+  PROP_MAX_SIZE,
   PROP_LAST
 };
 
@@ -115,6 +122,8 @@ static gboolean gst_file_sink_query (Gst
 static void gst_file_sink_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
 
+static guint gst_file_sink_signals[LAST_SIGNAL] = { 0 };
+
 
 static void
 _do_init (GType filesink_type)
@@ -134,6 +143,27 @@ _do_init (GType filesink_type)
 GST_BOILERPLATE_FULL (GstFileSink, gst_file_sink, GstBaseSink,
     GST_TYPE_BASE_SINK, _do_init);
 
+static gboolean
+gst_file_sink_out_of_space (GstFileSink * filesink)
+{
+  GST_ELEMENT_ERROR (filesink, RESOURCE, NO_SPACE_LEFT,
+      (NULL), ("Out of disk space writing to file \"%s\"",
+      filesink->filename));
+  return FALSE;
+}
+
+/* If one of the out-of-space signal handlers returns TRUE, stop
+ * calling handlers and retry the operation. */
+static gboolean
+gst_file_sink_out_of_space_accu (GSignalInvocationHint * ihint,
+    GValue * return_accu, const GValue * handler_return, gpointer data)
+{
+  gboolean current_value = g_value_get_boolean (handler_return);
+  g_value_set_boolean (return_accu, current_value);
+
+  return !current_value;
+}
+
 static void
 gst_file_sink_base_init (gpointer g_class)
 {
@@ -170,6 +200,24 @@ gst_file_sink_class_init (GstFileSinkCla
       g_param_spec_uint ("buffer-size", "Buffering size",
           "Size of buffer in number of bytes for line or full buffer-mode", 0,
           G_MAXUINT, DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_MAX_SIZE,
+      g_param_spec_int64 ("max-size", "Max. number of bytes to write",
+          "If >= 0, emit out-of-space signal when max-size bytes are written",
+          -1, G_MAXINT64, -1, G_PARAM_READWRITE));
+  /**
+   * GstFileSink::out-of-space:
+   *
+   * This signal gets emitted when writing to the file failed because
+   * there is no more space on the filesystem, or if the file offset of
+   * max-size bytes is transgressed.
+   * The signal handler should return TRUE if the write should be retried,
+   * or FALSE if the operation should report failure.
+   */
+  gst_file_sink_signals[OUT_OF_SPACE] = g_signal_new ("out_of_space",
+      G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstFileSinkClass, out_of_space),
+      gst_file_sink_out_of_space_accu, NULL, gst_marshal_BOOLEAN__VOID,
+      G_TYPE_BOOLEAN, 0);
 
   gstbasesink_class->get_times = NULL;
   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_file_sink_start);
@@ -177,6 +225,8 @@ gst_file_sink_class_init (GstFileSinkCla
   gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_file_sink_render);
   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_file_sink_event);
 
+  klass->out_of_space = GST_DEBUG_FUNCPTR (gst_file_sink_out_of_space);
+
   if (sizeof (off_t) < 8) {
     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
         sizeof (off_t));
@@ -197,6 +247,7 @@ gst_file_sink_init (GstFileSink * filesi
   filesink->buffer_mode = DEFAULT_BUFFER_MODE;
   filesink->buffer_size = DEFAULT_BUFFER_SIZE;
   filesink->buffer = NULL;
+  filesink->max_size = -1;
 
   gst_base_sink_set_sync (GST_BASE_SINK (filesink), FALSE);
 }
@@ -259,6 +310,9 @@ gst_file_sink_set_property (GObject * ob
     case PROP_BUFFER_SIZE:
       sink->buffer_size = g_value_get_uint (value);
       break;
+    case PROP_MAX_SIZE:
+      sink->max_size = g_value_get_int64 (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -281,6 +335,9 @@ gst_file_sink_get_property (GObject * ob
     case PROP_BUFFER_SIZE:
       g_value_set_uint (value, sink->buffer_size);
       break;
+    case PROP_MAX_SIZE:
+      g_value_set_int64 (value, sink->max_size);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -555,33 +612,38 @@ gst_file_sink_render (GstBaseSink * sink
 
   filesink = GST_FILE_SINK (sink);
 
-  GST_DEBUG_OBJECT (filesink, "writing %u bytes at %" G_GUINT64_FORMAT,
+  GST_DEBUG_OBJECT (filesink, "writing %u bytes at %" G_GSIZE_FORMAT,
       size, filesink->current_pos);
 
   if (size > 0 && GST_BUFFER_DATA (buffer) != NULL) {
-    if (fwrite (GST_BUFFER_DATA (buffer), size, 1, filesink->file) != 1)
-      goto handle_error;
-
-    filesink->current_pos += size;
+    gboolean retry;
+    do {
+      if (filesink->max_size < 0 ||
+	  filesink->current_pos + size <= filesink->max_size) {
+        if (fwrite (GST_BUFFER_DATA (buffer), size, 1, filesink->file) == 1) {
+          /* Success. */
+          filesink->current_pos += size;
+          break;
+        }
+        else if (errno != ENOSPC)
+          /* Failure other than out of disk space. */
+          goto handle_error;
+      }
+      /* Out of space. */
+      retry = FALSE;
+      g_signal_emit (filesink, gst_file_sink_signals[OUT_OF_SPACE], 0, &retry);
+      GST_DEBUG_OBJECT (filesink, "retry writing %u bytes at %"
+          G_GSIZE_FORMAT, size, filesink->current_pos);
+    } while (retry);
   }
 
   return GST_FLOW_OK;
 
 handle_error:
-  {
-    switch (errno) {
-      case ENOSPC:{
-        GST_ELEMENT_ERROR (filesink, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL));
-        break;
-      }
-      default:{
-        GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
-            (_("Error while writing to file \"%s\"."), filesink->filename),
-            ("%s", g_strerror (errno)));
-      }
-    }
-    return GST_FLOW_ERROR;
-  }
+  GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
+      (_("Error while writing to file \"%s\"."), filesink->filename),
+      ("%s", g_strerror (errno)));
+  return GST_FLOW_ERROR;
 }
 
 static gboolean
Index: plugins/elements/gstfilesink.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/plugins/elements/gstfilesink.h,v
retrieving revision 1.17
diff -u -p -r1.17 gstfilesink.h
--- plugins/elements/gstfilesink.h	24 Dec 2007 19:11:29 -0000	1.17
+++ plugins/elements/gstfilesink.h	6 Feb 2008 11:17:25 -0000
@@ -58,6 +58,7 @@ struct _GstFileSink {
 
   gboolean seekable;
   guint64 current_pos;
+  gint64 max_size;
 
   gint    buffer_mode;
   guint   buffer_size;
@@ -66,6 +67,9 @@ struct _GstFileSink {
 
 struct _GstFileSinkClass {
   GstBaseSinkClass parent_class;
+
+  /* signals */
+  gboolean (*out_of_space) (GstFileSink *filesink);
 };
 
 GType gst_file_sink_get_type(void);
