+2008-04-20 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * ext/gio/gstgio.c: (_internal_get_supported_protocols),
+ (gst_gio_get_supported_protocols):
+ Don't generate a new supported protocols list on each call but cache
+ it. It's supposed to be static anyway, this way we only leak it once
+ per process.
+
+ * ext/gio/gstgiosink.c: (gst_gio_sink_base_init),
+ (gst_gio_sink_class_init), (gst_gio_sink_finalize),
+ (gst_gio_sink_set_property), (gst_gio_sink_get_property),
+ (gst_gio_sink_start):
+ * ext/gio/gstgiosink.h:
+ * ext/gio/gstgiosrc.c: (gst_gio_src_base_init),
+ (gst_gio_src_class_init), (gst_gio_src_finalize),
+ (gst_gio_src_set_property), (gst_gio_src_get_property),
+ (gst_gio_src_start):
+ * ext/gio/gstgiosrc.h:
+ API: Add "file" properties where one can set a GFile as source/destination.
+
+ Add locking to the properties and use gst_element_class_set_details_simple()
+ instead of a static GstElementDetails struct.
+
2008-04-19 Sebastian Dröge <slomo@circular-chaos.org>
* gst/typefind/gsttypefindfunctions.c: (musepack_type_find),
return ret;
}
-static gchar **
-gst_gio_get_supported_protocols (void)
+static gpointer
+_internal_get_supported_protocols (gpointer data)
{
const gchar *const *schemes;
gchar **our_schemes;
return our_schemes;
}
+static gchar **
+gst_gio_get_supported_protocols (void)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, _internal_get_supported_protocols, NULL);
+ return (gchar **) once.retval;
+}
+
static GstURIType
gst_gio_uri_handler_get_type_sink (void)
{
enum
{
ARG_0,
- ARG_LOCATION
+ ARG_LOCATION,
+ ARG_FILE
};
GST_BOILERPLATE_FULL (GstGioSink, gst_gio_sink, GstGioBaseSink,
static void
gst_gio_sink_base_init (gpointer gclass)
{
- static GstElementDetails element_details = {
- "GIO sink",
- "Sink/File",
- "Write to any GIO-supported location",
- "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
- "Sebastian Dröge <slomo@circular-chaos.org>"
- };
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
GST_DEBUG_CATEGORY_INIT (gst_gio_sink_debug, "gio_sink", 0, "GIO sink");
- gst_element_class_set_details (element_class, &element_details);
+ gst_element_class_set_details_simple (element_class, "GIO sink",
+ "Sink/File",
+ "Write to any GIO-supported location",
+ "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
+ "Sebastian Dröge <slomo@circular-chaos.org>");
}
static void
g_param_spec_string ("location", "Location", "URI location to write to",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstGioSink:file
+ *
+ * %GFile to write to.
+ *
+ * Since: 0.10.20
+ **/
+ g_object_class_install_property (gobject_class, ARG_FILE,
+ g_param_spec_object ("file", "File", "GFile to write to",
+ G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gio_sink_start);
}
{
GstGioSink *sink = GST_GIO_SINK (object);
- if (sink->location) {
- g_free (sink->location);
- sink->location = NULL;
+ if (sink->file) {
+ g_object_unref (sink->file);
+ sink->file = NULL;
}
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
GstGioSink *sink = GST_GIO_SINK (object);
switch (prop_id) {
- case ARG_LOCATION:
+ 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_STATE (sink) == GST_STATE_PAUSED) {
+ GST_WARNING
+ ("Setting a new location or GFile not supported in PLAYING or PAUSED state");
break;
+ }
- g_free (sink->location);
- sink->location = g_strdup (g_value_get_string (value));
+ 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);
GstGioSink *sink = GST_GIO_SINK (object);
switch (prop_id) {
- case ARG_LOCATION:
- g_value_set_string (value, sink->location);
+ 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);
gst_gio_sink_start (GstBaseSink * base_sink)
{
GstGioSink *sink = GST_GIO_SINK (base_sink);
- GFile *file;
GOutputStream *stream;
GCancellable *cancel = GST_GIO_BASE_SINK (sink)->cancel;
gboolean success;
GError *err = NULL;
+ gchar *uri;
- if (sink->location == NULL) {
+ if (sink->file == NULL) {
GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
- ("No location given"));
+ ("No location or GFile given"));
return FALSE;
}
- file = g_file_new_for_uri (sink->location);
-
- if (file == NULL) {
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
- ("Malformed URI or protocol not supported (%s)", sink->location));
- return FALSE;
- }
+ uri = g_file_get_uri (sink->file);
+ if (!uri)
+ uri = g_strdup ("(null)");
stream =
- G_OUTPUT_STREAM (g_file_create (file, G_FILE_CREATE_NONE, cancel, &err));
+ G_OUTPUT_STREAM (g_file_create (sink->file, G_FILE_CREATE_NONE, cancel,
+ &err));
success = (stream != NULL);
- g_object_unref (file);
-
if (!success && !gst_gio_error (sink, "g_file_create", &err, NULL)) {
/*if (GST_GIO_ERROR_MATCHES (err, EXISTS)) */
if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND))
GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL),
- ("Could not open location %s for writing: %s",
- sink->location, err->message));
+ ("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",
- sink->location, err->message));
+ ("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", sink->location);
+ GST_DEBUG_OBJECT (sink, "opened location %s", uri);
+
+ g_free (uri);
gst_gio_base_sink_set_stream (GST_GIO_BASE_SINK (sink), stream);
GstGioBaseSink sink;
/*< private >*/
- gchar *location;
-
- GMainLoop *loop;
- gboolean mount_successful;
+ GFile *file;
};
struct _GstGioSinkClass
enum
{
ARG_0,
- ARG_LOCATION
+ ARG_LOCATION,
+ ARG_FILE
};
GST_BOILERPLATE_FULL (GstGioSrc, gst_gio_src, GstGioBaseSrc,
static void
gst_gio_src_base_init (gpointer gclass)
{
- static GstElementDetails element_details = {
- "GIO source",
- "Source/File",
- "Read from any GIO-supported location",
- "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
- "Sebastian Dröge <slomo@circular-chaos.org>"
- };
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
GST_DEBUG_CATEGORY_INIT (gst_gio_src_debug, "gio_src", 0, "GIO source");
- gst_element_class_set_details (element_class, &element_details);
+ gst_element_class_set_details_simple (element_class, "GIO source",
+ "Source/File",
+ "Read from any GIO-supported location",
+ "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
+ "Sebastian Dröge <slomo@circular-chaos.org>");
}
static void
g_param_spec_string ("location", "Location", "URI location to read from",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstGioSrc:file
+ *
+ * %GFile to read from.
+ *
+ * Since: 0.10.20
+ **/
+ g_object_class_install_property (gobject_class, ARG_FILE,
+ g_param_spec_object ("file", "File", "GFile to read from",
+ G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_src_start);
}
{
GstGioSrc *src = GST_GIO_SRC (object);
- if (src->location) {
- g_free (src->location);
- src->location = NULL;
+ if (src->file) {
+ g_object_unref (src->file);
+ src->file = NULL;
}
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
GstGioSrc *src = GST_GIO_SRC (object);
switch (prop_id) {
- case ARG_LOCATION:
+ case ARG_LOCATION:{
+ const gchar *uri = NULL;
+
if (GST_STATE (src) == GST_STATE_PLAYING ||
- GST_STATE (src) == GST_STATE_PAUSED)
+ GST_STATE (src) == GST_STATE_PAUSED) {
+ GST_WARNING
+ ("Setting a new location or GFile not supported in PLAYING or PAUSED state");
break;
+ }
+
+ GST_OBJECT_LOCK (GST_OBJECT (src));
+ if (src->file)
+ g_object_unref (src->file);
+
+ uri = g_value_get_string (value);
+
+ if (uri) {
+ src->file = g_file_new_for_uri (uri);
- g_free (src->location);
- src->location = g_strdup (g_value_get_string (value));
+ if (!src->file) {
+ GST_ERROR ("Could not create GFile for URI '%s'", uri);
+ }
+ } else {
+ src->file = NULL;
+ }
+ GST_OBJECT_UNLOCK (GST_OBJECT (src));
+ break;
+ }
+ case ARG_FILE:
+ if (GST_STATE (src) == GST_STATE_PLAYING ||
+ GST_STATE (src) == GST_STATE_PAUSED) {
+ GST_WARNING
+ ("Setting a new location or GFile not supported in PLAYING or PAUSED state");
+ break;
+ }
+
+ GST_OBJECT_LOCK (GST_OBJECT (src));
+ if (src->file)
+ g_object_unref (src->file);
+
+ src->file = g_value_dup_object (value);
+
+ GST_OBJECT_UNLOCK (GST_OBJECT (src));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
GstGioSrc *src = GST_GIO_SRC (object);
switch (prop_id) {
- case ARG_LOCATION:
- g_value_set_string (value, src->location);
+ case ARG_LOCATION:{
+ gchar *uri;
+
+ GST_OBJECT_LOCK (GST_OBJECT (src));
+ if (src->file) {
+ uri = g_file_get_uri (src->file);
+ g_value_set_string (value, uri);
+ g_free (uri);
+ } else {
+ g_value_set_string (value, NULL);
+ }
+ GST_OBJECT_UNLOCK (GST_OBJECT (src));
+ break;
+ }
+ case ARG_FILE:
+ GST_OBJECT_LOCK (GST_OBJECT (src));
+ g_value_set_object (value, src->file);
+ GST_OBJECT_UNLOCK (GST_OBJECT (src));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
gst_gio_src_start (GstBaseSrc * base_src)
{
GstGioSrc *src = GST_GIO_SRC (base_src);
- GFile *file;
GError *err = NULL;
GInputStream *stream;
GCancellable *cancel = GST_GIO_BASE_SRC (src)->cancel;
+ gchar *uri = NULL;
- if (src->location == NULL) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No location given"));
- return FALSE;
- }
-
- file = g_file_new_for_uri (src->location);
-
- if (file == NULL) {
+ if (src->file == NULL) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Malformed URI or protocol not supported (%s)", src->location));
+ ("No location or GFile given"));
return FALSE;
}
- stream = G_INPUT_STREAM (g_file_read (file, cancel, &err));
+ uri = g_file_get_uri (src->file);
+ if (!uri)
+ uri = g_strdup ("(null)");
- g_object_unref (file);
+ stream = G_INPUT_STREAM (g_file_read (src->file, cancel, &err));
if (stream == NULL && !gst_gio_error (src, "g_file_read", &err, NULL)) {
-
if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND)) {
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
- ("Could not open location %s for reading: %s",
- src->location, err->message));
+ ("Could not open location %s for reading: %s", uri, err->message));
} else {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Could not open location %s for reading: %s",
- src->location, err->message));
+ ("Could not open location %s for reading: %s", uri, err->message));
}
+ g_free (uri);
g_clear_error (&err);
return FALSE;
} else if (stream == NULL) {
+ g_free (uri);
return FALSE;
}
gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src), stream);
- GST_DEBUG_OBJECT (src, "opened location %s", src->location);
+ GST_DEBUG_OBJECT (src, "opened location %s", uri);
+ g_free (uri);
return GST_BASE_SRC_CLASS (parent_class)->start (base_src);
}
GstGioBaseSrc src;
/*< private >*/
- gchar *location;
-
- GMainLoop *loop;
- gboolean mount_successful;
+ GFile *file;
};
struct _GstGioSrcClass