static void
gst_gio_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstGioSink *sink = GST_GIO_SINK (object);

  switch (prop_id) {
    case ARG_LOCATION:{
      gchar *uri;

      GST_OBJECT_LOCK (GST_OBJECT (sink));
      if (sink->file) {
        uri = g_file_get_uri (sink->file);
        g_value_set_string (value, uri);
        g_free (uri);
      } else {
        g_value_set_string (value, NULL);
      }
      GST_OBJECT_UNLOCK (GST_OBJECT (sink));
      break;
    }
    case ARG_FILE:
      GST_OBJECT_LOCK (GST_OBJECT (sink));
      g_value_set_object (value, sink->file);
      GST_OBJECT_UNLOCK (GST_OBJECT (sink));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static void
gst_gio_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstGioSink *sink = GST_GIO_SINK (object);

  switch (prop_id) {
    case ARG_LOCATION:{
      const gchar *uri = NULL;

      if (GST_STATE (sink) == GST_STATE_PLAYING ||
          GST_STATE (sink) == GST_STATE_PAUSED) {
        GST_WARNING
            ("Setting a new location or GFile not supported in PLAYING or PAUSED state");
        break;
      }

      GST_OBJECT_LOCK (GST_OBJECT (sink));
      if (sink->file)
        g_object_unref (sink->file);

      uri = g_value_get_string (value);

      if (uri) {
        sink->file = g_file_new_for_uri (uri);

        if (!sink->file) {
          GST_ERROR ("Could not create GFile for URI '%s'", uri);
        }
      } else {
        sink->file = NULL;
      }
      GST_OBJECT_UNLOCK (GST_OBJECT (sink));
      break;
    }
    case ARG_FILE:
      if (GST_STATE (sink) == GST_STATE_PLAYING ||
          GST_STATE (sink) == GST_STATE_PAUSED) {
        GST_WARNING
            ("Setting a new location or GFile not supported in PLAYING or PAUSED state");
        break;
      }

      GST_OBJECT_LOCK (GST_OBJECT (sink));
      if (sink->file)
        g_object_unref (sink->file);

      sink->file = g_value_dup_object (value);

      GST_OBJECT_UNLOCK (GST_OBJECT (sink));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static gboolean
gst_gio_sink_start (GstBaseSink * base_sink)
{
  GstGioSink *sink = GST_GIO_SINK (base_sink);
  GOutputStream *stream;
  GCancellable *cancel = GST_GIO_BASE_SINK (sink)->cancel;
  gboolean success;
  GError *err = NULL;
  gchar *uri;

  if (sink->file == NULL) {
    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
        ("No location or GFile given"));
    return FALSE;
  }

  uri = g_file_get_uri (sink->file);
  if (!uri)
    uri = g_strdup ("(null)");

  stream =
      G_OUTPUT_STREAM (g_file_create (sink->file, G_FILE_CREATE_NONE, cancel,
          &err));

  success = (stream != NULL);

  if (!success && !gst_gio_error (sink, "g_file_create", &err, NULL)) {

    /*if (GST_GIO_ERROR_MATCHES (err, EXISTS)) */
    /* FIXME: Retry with replace if overwrite == TRUE! */

    if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND))
      GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL),
          ("Could not open location %s for writing: %s", uri, err->message));
    else
      GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_READ, (NULL),
          ("Could not open location %s for writing: %s", uri, err->message));

    g_free (uri);
    g_clear_error (&err);
  }

  if (!success)
    return FALSE;

  GST_DEBUG_OBJECT (sink, "opened location %s", uri);

  g_free (uri);

  gst_gio_base_sink_set_stream (GST_GIO_BASE_SINK (sink), stream);

  return GST_BASE_SINK_CLASS (parent_class)->start (base_sink);
}
static void
gst_gio_sink_finalize (GObject * object)
{
  GstGioSink *sink = GST_GIO_SINK (object);

  if (sink->file) {
    g_object_unref (sink->file);
    sink->file = NULL;
  }

  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
static GOutputStream *
gst_gio_sink_get_stream (GstGioBaseSink * bsink)
{
  GstGioSink *sink = GST_GIO_SINK (bsink);
  GOutputStream *stream;
  GCancellable *cancel = GST_GIO_BASE_SINK (sink)->cancel;
  GError *err = NULL;
  gchar *uri;

  if (sink->file == NULL) {
    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
        ("No location or GFile given"));
    return NULL;
  }

  uri = g_file_get_uri (sink->file);
  if (!uri)
    uri = g_strdup ("(null)");

  stream =
      G_OUTPUT_STREAM (g_file_create (sink->file, G_FILE_CREATE_NONE, cancel,
          &err));

  if (!stream) {
    if (!gst_gio_error (sink, "g_file_create", &err, NULL)) {
      /*if (GST_GIO_ERROR_MATCHES (err, EXISTS)) */
      /* FIXME: Retry with replace if overwrite == TRUE! */

      if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND)) {
        GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL),
            ("Could not open location %s for writing: %s", uri, err->message));
      } else if (GST_GIO_ERROR_MATCHES (err, EXISTS)) {
        gst_element_post_message (GST_ELEMENT_CAST (sink),
            gst_message_new_element (GST_OBJECT_CAST (sink),
                gst_structure_new ("file-exists", "file", G_TYPE_FILE,
                    sink->file, "uri", G_TYPE_STRING, uri, NULL)));

        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Location %s already exists: %s", uri, err->message));
      } else if (GST_GIO_ERROR_MATCHES (err, NOT_MOUNTED)) {
        gst_element_post_message (GST_ELEMENT_CAST (sink),
            gst_message_new_element (GST_OBJECT_CAST (sink),
                gst_structure_new ("not-mounted", "file", G_TYPE_FILE,
                    sink->file, "uri", G_TYPE_STRING, uri, NULL)));

        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Location %s not mounted: %s", uri, err->message));
      } else {
        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Could not open location %s for writing: %s", uri, err->message));
      }

      g_clear_error (&err);
    }
    g_free (uri);
    return NULL;
  }

  GST_DEBUG_OBJECT (sink, "opened location %s", uri);

  g_free (uri);

  return stream;
}