#include "gstgiobasesrc.h"
+#include <gst/base/gsttypefindhelper.h>
+
GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug);
#define GST_CAT_DEFAULT gst_gio_base_src_debug
gst_gio_base_src_class_init (GstGioBaseSrcClass * klass)
{
GObjectClass *gobject_class;
-
GstElementClass *gstelement_class;
-
GstBaseSrcClass *gstbasesrc_class;
gobject_class = (GObjectClass *) klass;
gst_gio_base_src_start (GstBaseSrc * base_src)
{
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
+ GstGioBaseSrcClass *gbsrc_class = GST_GIO_BASE_SRC_GET_CLASS (src);
- if (!G_IS_INPUT_STREAM (src->stream)) {
+ src->position = 0;
+
+ /* FIXME: This will likely block */
+ src->stream = gbsrc_class->get_stream (src);
+ if (G_UNLIKELY (!G_IS_INPUT_STREAM (src->stream))) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("No stream given yet"));
+ ("No input stream provided by subclass"));
return FALSE;
}
- src->position = 0;
-
- GST_DEBUG_OBJECT (src, "started stream");
+ GST_DEBUG_OBJECT (src, "started source");
return TRUE;
}
gst_gio_base_src_stop (GstBaseSrc * base_src)
{
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
gboolean success;
-
GError *err = NULL;
if (G_IS_INPUT_STREAM (src->stream)) {
if (G_IS_FILE_INPUT_STREAM (src->stream)) {
GFileInfo *info;
-
GError *err = NULL;
info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream),
if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) {
goffset old;
-
goffset stream_size;
-
gboolean ret;
-
GSeekable *seekable = G_SEEKABLE (src->stream);
-
GError *err = NULL;
old = g_seekable_tell (seekable);
} else {
GST_WARNING_OBJECT (src, "Seeking to end of stream failed");
}
-
return FALSE;
}
} else {
GST_ERROR_OBJECT (src, "Seeking to the old position faile");
}
-
return FALSE;
}
gst_gio_base_src_is_seekable (GstBaseSrc * base_src)
{
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
gboolean seekable;
seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream);
static gboolean
gst_gio_base_src_check_get_range (GstBaseSrc * base_src)
{
- /* FIXME: Implement dry-run variant using guesswork like gnomevfssrc? */
-
return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS,
check_get_range, (base_src), FALSE);
}
* over DBus if our backend is GVfs and this is painfully slow. */
if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) &&
offset + size <= GST_BUFFER_OFFSET_END (src->cache)) {
-
GST_DEBUG_OBJECT (src, "Creating subbuffer from cached buffer: offset %"
G_GUINT64_FORMAT " length %u", offset, size);
GST_BUFFER_SIZE (buf) = size;
} else {
guint cachesize = MAX (4096, size);
-
gssize read, res;
-
gboolean success, eos;
-
GError *err = NULL;
if (src->cache) {
return ret;
}
-
-void
-gst_gio_base_src_set_stream (GstGioBaseSrc * src, GInputStream * stream)
-{
- gboolean success;
-
- GError *err = NULL;
-
- g_return_if_fail (G_IS_INPUT_STREAM (stream));
- g_return_if_fail ((GST_STATE (src) != GST_STATE_PLAYING &&
- GST_STATE (src) != GST_STATE_PAUSED));
-
- if (G_IS_INPUT_STREAM (src->stream)) {
- GST_DEBUG_OBJECT (src, "closing old stream");
-
- /* FIXME: can block but unfortunately we can't use async operations
- * here because they require a running main loop */
- success = g_input_stream_close (src->stream, src->cancel, &err);
-
- if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
- GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
- ("g_input_stream_close failed: %s", err->message));
- g_clear_error (&err);
- } else if (!success) {
- GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
- ("g_input_stream_close failed"));
- } else {
- GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
- }
-
- g_object_unref (src->stream);
- src->stream = NULL;
- }
-
- src->stream = stream;
-}
(gst_gio_base_src_get_type())
#define GST_GIO_BASE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrc))
+#define GST_GIO_BASE_SRC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GIO_BASE_SRC, GstGioBaseSrcClass))
#define GST_GIO_BASE_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass))
#define GST_IS_GIO_BASE_SRC(obj) \
struct _GstGioBaseSrcClass
{
GstBaseSrcClass parent_class;
+
+ GInputStream * (*get_stream) (GstGioBaseSrc *bsrc);
};
GType gst_gio_base_src_get_type (void);
-void gst_gio_base_src_set_stream (GstGioBaseSrc *src, GInputStream *stream);
-
G_END_DECLS
#endif /* __GST_GIO_BASE_SRC_H__ */
static void gst_gio_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static gboolean gst_gio_src_start (GstBaseSrc * base_src);
+static GInputStream *gst_gio_src_get_stream (GstGioBaseSrc * bsrc);
static gboolean gst_gio_src_check_get_range (GstBaseSrc * base_src);
gst_gio_src_class_init (GstGioSrcClass * klass)
{
GObjectClass *gobject_class;
-
- GstElementClass *gstelement_class;
-
GstBaseSrcClass *gstbasesrc_class;
+ GstGioBaseSrcClass *gstgiobasesrc_class;
gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstgiobasesrc_class = (GstGioBaseSrcClass *) klass;
gobject_class->finalize = gst_gio_src_finalize;
gobject_class->set_property = gst_gio_src_set_property;
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);
gstbasesrc_class->check_get_range =
GST_DEBUG_FUNCPTR (gst_gio_src_check_get_range);
+
+ gstgiobasesrc_class->get_stream = GST_DEBUG_FUNCPTR (gst_gio_src_get_stream);
}
static void
}
-static gboolean
-gst_gio_src_start (GstBaseSrc * base_src)
+static GInputStream *
+gst_gio_src_get_stream (GstGioBaseSrc * bsrc)
{
- GstGioSrc *src = GST_GIO_SRC (base_src);
-
+ GstGioSrc *src = GST_GIO_SRC (bsrc);
GError *err = NULL;
-
GInputStream *stream;
-
- GCancellable *cancel = GST_GIO_BASE_SRC (src)->cancel;
-
+ GCancellable *cancel = bsrc->cancel;
gchar *uri = NULL;
if (src->file == NULL) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
("No location or GFile given"));
- return FALSE;
+ return NULL;
}
uri = g_file_get_uri (src->file);
g_free (uri);
g_clear_error (&err);
- return FALSE;
+ return NULL;
} else if (stream == NULL) {
g_free (uri);
- return FALSE;
+ return NULL;
}
- gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src), stream);
-
GST_DEBUG_OBJECT (src, "opened location %s", uri);
g_free (uri);
- return GST_BASE_SRC_CLASS (parent_class)->start (base_src);
+ return stream;
}
enum
{
- ARG_0,
- ARG_STREAM
+ PROP_0,
+ PROP_STREAM
};
GST_BOILERPLATE (GstGioStreamSrc, gst_gio_stream_src, GstGioBaseSrc,
const GValue * value, GParamSpec * pspec);
static void gst_gio_stream_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+static GInputStream *gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc);
static void
gst_gio_stream_src_base_init (gpointer gclass)
gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
+ GstGioBaseSrcClass *gstgiobasesrc_class;
gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstgiobasesrc_class = (GstGioBaseSrcClass *) klass;
gobject_class->finalize = gst_gio_stream_src_finalize;
gobject_class->set_property = gst_gio_stream_src_set_property;
gobject_class->get_property = gst_gio_stream_src_get_property;
- g_object_class_install_property (gobject_class, ARG_STREAM,
+ g_object_class_install_property (gobject_class, PROP_STREAM,
g_param_spec_object ("stream", "Stream", "Stream to read from",
G_TYPE_INPUT_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gstgiobasesrc_class->get_stream =
+ GST_DEBUG_FUNCPTR (gst_gio_stream_src_get_stream);
}
static void
static void
gst_gio_stream_src_finalize (GObject * object)
{
+ GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
+
+ if (src->stream) {
+ g_object_unref (src->stream);
+ src->stream = NULL;
+ }
+
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
switch (prop_id) {
- case ARG_STREAM:{
+ case PROP_STREAM:{
GObject *stream;
if (GST_STATE (src) == GST_STATE_PLAYING ||
- GST_STATE (src) == GST_STATE_PAUSED)
+ GST_STATE (src) == GST_STATE_PAUSED) {
+ GST_WARNING
+ ("Setting a new stream not supported in PLAYING or PAUSED state");
break;
+ }
stream = g_value_dup_object (value);
- if (G_IS_INPUT_STREAM (stream))
- gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src),
- G_INPUT_STREAM (stream));
-
+ if (src->stream)
+ g_object_unref (src->stream);
+ src->stream = G_INPUT_STREAM (stream);
break;
}
default:
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
switch (prop_id) {
- case ARG_STREAM:
- g_value_set_object (value, GST_GIO_BASE_SRC (src)->stream);
+ case PROP_STREAM:
+ g_value_set_object (value, src->stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+
+static GInputStream *
+gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc)
+{
+ GstGioStreamSrc *src = GST_GIO_STREAM_SRC (bsrc);
+
+ return (src->stream) ? g_object_ref (src->stream) : NULL;
+}
struct _GstGioStreamSrc
{
GstGioBaseSrc src;
+
+ /* < private > */
+ GInputStream *stream;
};
struct _GstGioStreamSrcClass