summaryrefslogtreecommitdiffstats
path: root/gst/playondemand
diff options
context:
space:
mode:
Diffstat (limited to 'gst/playondemand')
-rw-r--r--gst/playondemand/Makefile.am10
-rw-r--r--gst/playondemand/filter.func120
-rw-r--r--gst/playondemand/gstplayondemand.c448
-rw-r--r--gst/playondemand/gstplayondemand.h112
4 files changed, 690 insertions, 0 deletions
diff --git a/gst/playondemand/Makefile.am b/gst/playondemand/Makefile.am
new file mode 100644
index 00000000..fc2b93b9
--- /dev/null
+++ b/gst/playondemand/Makefile.am
@@ -0,0 +1,10 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstplayondemand.la
+
+libgstplayondemand_la_SOURCES = gstplayondemand.c
+libgstplayondemand_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = gstplayondemand.h filter.func
+
+# EXTRA_DIST = README
diff --git a/gst/playondemand/filter.func b/gst/playondemand/filter.func
new file mode 100644
index 00000000..6f81c975
--- /dev/null
+++ b/gst/playondemand/filter.func
@@ -0,0 +1,120 @@
+/* -*- C -*- */
+
+_TYPE_ *data_in, *data_out, *filter_data;
+
+filter_data = (_TYPE_ *) filter->buffer;
+num_filter = filter->buffer_size / sizeof(_TYPE_);
+
+/******************************************************************************/
+/* see if we've got any events coming through ... */
+
+do {
+ GST_DEBUG(0, "--- going to events\n");
+
+ while (! filter->eos && GST_IS_EVENT(in)) {
+ if (GST_EVENT_TYPE(in) == GST_EVENT_EOS) {
+ filter->eos = TRUE;
+ } else {
+ gst_pad_push(filter->srcpad, in);
+ }
+
+ in = gst_pad_pull(filter->sinkpad);
+ }
+
+ /******************************************************************************/
+ /* first handle data from the input buffer. */
+
+ GST_DEBUG(0, "--- done with events, going to input\n");
+
+ /* only update the input if there hasn't been an eos yet. */
+ if (! filter->eos) {
+ data_in = (_TYPE_ *) GST_BUFFER_DATA(in);
+ num_in = GST_BUFFER_SIZE(in) / sizeof(_TYPE_);
+
+ w = filter->write;
+
+ /* copy the input data to the filter's internal buffer. */
+ if (filter->follow_stream_tail) {
+ for (j = 0; j < num_in; j++) {
+ filter_data[(w + j) % num_filter] = data_in[j];
+ }
+
+ filter->write = (w + j) % num_filter;
+
+ /* update the start pointer */
+ if ((filter->start != 0) || ((w + j) >= num_filter)) {
+ filter->start = (filter->write + 1) % num_filter;
+ }
+ } else {
+ for (j = 0; (j < num_in) && ((w + j) < num_filter); j++) {
+ filter_data[w + j] = data_in[j];
+ }
+
+ filter->write += j;
+
+ /* if we're not following the stream tail, the buffer is just a straight
+ buffer. so we need to set eos if we've passed the limit of the internal
+ buffer size. */
+ if ((w + j) >= num_filter) {
+ filter->eos = TRUE;
+ }
+ }
+
+ out = in;
+ } else {
+ j = 0;
+
+ if (filter->srcpool) {
+ out = gst_buffer_new_from_pool(filter->srcpool, 0, 0);
+ } else {
+ out = gst_buffer_new();
+
+ GST_BUFFER_DATA(out) = (gchar *) g_new(_TYPE_, POD_GSTBUFSIZE / sizeof(_TYPE_));
+ GST_BUFFER_SIZE(out) = POD_GSTBUFSIZE;
+ }
+ }
+
+ /******************************************************************************/
+ /* now handle output data. */
+
+ GST_DEBUG(0, "--- done with input, going to output\n");
+
+ data_out = (_TYPE_ *) GST_BUFFER_DATA(out);
+ num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_);
+
+ for (k = 0; k < num_out; k++) {
+ data_out[k] = zero;
+ }
+
+ /* output play pointer data. */
+ for (t = 0; t < POD_MAX_PLAYS; t++) {
+ offset = filter->plays[t];
+
+ if (offset != G_MAXUINT) {
+ if (filter->follow_stream_tail) {
+ for (k = 0; k < num_out; k++) {
+ data_out[k] = CLAMP(data_out[k] + filter_data[(offset + k) % num_filter], min, max);
+ }
+ } else {
+ for (k = 0; (k < num_out) && ((offset + k) < (w + j)); k++) {
+ data_out[k] = CLAMP(data_out[k] + filter_data[offset + k], min, max);
+ }
+ }
+
+ if ((offset < w) && ((offset + k) >= (w + j))) {
+ filter->plays[t] = G_MAXUINT;
+ } else {
+ filter->plays[t] = (filter->plays[t] + k) % num_filter;
+ }
+ }
+ }
+
+ GST_DEBUG(0, "--- done with output, pushing buffer %p\n", out);
+
+ gst_pad_push(filter->srcpad, out);
+
+ if (! filter->eos) {
+ in = gst_pad_pull(filter->sinkpad);
+ }
+
+} while (! GST_ELEMENT_IS_COTHREAD_STOPPING(elem));
diff --git a/gst/playondemand/gstplayondemand.c b/gst/playondemand/gstplayondemand.c
new file mode 100644
index 00000000..9d2ebff3
--- /dev/null
+++ b/gst/playondemand/gstplayondemand.c
@@ -0,0 +1,448 @@
+/* GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <gst/gst.h>
+#include <libs/audio/gstaudio.h>
+#include "gstplayondemand.h"
+
+
+#define POD_MAX_PLAYS 192 /* maximum number of simultaneous plays */
+#define POD_GSTBUFSIZE 4096 /* gstreamer buffer size to make if no
+ bufferpool is available, must be divisible
+ by sizeof(gfloat) */
+#define POD_BUFSPERCHUNK 6 /* number of buffers to allocate per chunk in
+ sink buffer pool */
+#define POD_BUFFER_SIZE 882000 /* enough space for 10 seconds of 16-bit audio
+ at 44100 samples per second ... */
+
+static GstElementDetails play_on_demand_details = {
+ "Play On Demand",
+ "Filter/Effect",
+ "Plays a stream whenever it receives a certain signal",
+ VERSION,
+ "Leif Morgan Johnson <lmjohns3@eos.ncsu.edu>",
+ "(C) 2001",
+};
+
+
+/* Filter signals and args */
+enum {
+ /* FILL ME */
+ PLAY_SIGNAL,
+ RESET_SIGNAL,
+ LAST_SIGNAL
+};
+
+enum {
+ ARG_0,
+ ARG_SILENT,
+ ARG_FOLLOWTAIL,
+ ARG_BUFFERSIZE
+};
+
+static GstPadTemplate*
+play_on_demand_sink_factory (void)
+{
+ static GstPadTemplate *template = NULL;
+
+ if (!template) {
+ template = gst_padtemplate_new
+ ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ gst_caps_append(gst_caps_new ("sink_int", "audio/raw",
+ GST_AUDIO_INT_PAD_TEMPLATE_PROPS),
+ gst_caps_new ("sink_float", "audio/raw",
+ GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS)),
+ NULL);
+ }
+ return template;
+}
+
+static GstPadTemplate*
+play_on_demand_src_factory (void)
+{
+ static GstPadTemplate *template = NULL;
+
+ if (!template)
+ template = gst_padtemplate_new
+ ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ gst_caps_append (gst_caps_new ("src_float", "audio/raw",
+ GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS),
+ gst_caps_new ("src_int", "audio/raw",
+ GST_AUDIO_INT_PAD_TEMPLATE_PROPS)),
+ NULL);
+
+ return template;
+}
+
+static void play_on_demand_class_init (GstPlayOnDemandClass *klass);
+static void play_on_demand_init (GstPlayOnDemand *filter);
+
+static void play_on_demand_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void play_on_demand_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static gint play_on_demand_parse_caps (GstPlayOnDemand *filter, GstCaps *caps);
+
+static void play_on_demand_loop (GstElement *elem);
+
+static void play_on_demand_play_handler (GstElement *elem);
+static void play_on_demand_reset_handler (GstElement *elem);
+
+static GstElementClass *parent_class = NULL;
+static guint gst_pod_filter_signals[LAST_SIGNAL] = { 0 };
+
+static GstBufferPool*
+play_on_demand_get_bufferpool (GstPad *pad)
+{
+ GstPlayOnDemand *filter;
+
+ filter = GST_PLAYONDEMAND(gst_pad_get_parent(pad));
+
+ return gst_pad_get_bufferpool(filter->srcpad);
+}
+
+static GstPadNegotiateReturn
+play_on_demand_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+ GstPlayOnDemand* filter = GST_PLAYONDEMAND(gst_pad_get_parent(pad));
+
+ if (*caps == NULL)
+ return GST_PAD_NEGOTIATE_FAIL;
+
+ if (play_on_demand_parse_caps(filter, *caps))
+ return GST_PAD_NEGOTIATE_FAIL;
+
+ return gst_pad_negotiate_proxy(pad, filter->sinkpad, caps);
+}
+
+static GstPadNegotiateReturn
+play_on_demand_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+ GstPlayOnDemand* filter = GST_PLAYONDEMAND(gst_pad_get_parent(pad));
+
+ if (*caps == NULL)
+ return GST_PAD_NEGOTIATE_FAIL;
+
+ if (play_on_demand_parse_caps(filter, *caps))
+ return GST_PAD_NEGOTIATE_FAIL;
+
+ return gst_pad_negotiate_proxy(pad, filter->srcpad, caps);
+}
+
+static gint
+play_on_demand_parse_caps (GstPlayOnDemand *filter, GstCaps *caps)
+{
+ const gchar *format;
+
+ g_return_val_if_fail(filter != NULL, -1);
+ g_return_val_if_fail(caps != NULL, -1);
+
+ format = gst_caps_get_string(caps, "format");
+
+ filter->rate = gst_caps_get_int(caps, "rate");
+ filter->channels = gst_caps_get_int(caps, "channels");
+
+ if (strcmp(format, "int") == 0) {
+ filter->format = GST_PLAYONDEMAND_FORMAT_INT;
+ filter->width = gst_caps_get_int(caps, "width");
+ filter->depth = gst_caps_get_int(caps, "depth");
+ filter->law = gst_caps_get_int(caps, "law");
+ filter->endianness = gst_caps_get_int(caps, "endianness");
+ filter->is_signed = gst_caps_get_int(caps, "signed");
+ if (!filter->silent) {
+ g_print ("PlayOnDemand : channels %d, rate %d\n",
+ filter->channels, filter->rate);
+ g_print ("PlayOnDemand : format int, bit width %d, endianness %d, signed %s\n",
+ filter->width, filter->endianness, filter->is_signed ? "yes" : "no");
+ }
+ } else if (strcmp(format, "float")==0) {
+ filter->format = GST_PLAYONDEMAND_FORMAT_FLOAT;
+ filter->layout = gst_caps_get_string(caps, "layout");
+ filter->intercept = gst_caps_get_float(caps, "intercept");
+ filter->slope = gst_caps_get_float(caps, "slope");
+ if (!filter->silent) {
+ g_print ("PlayOnDemand : channels %d, rate %d\n",
+ filter->channels, filter->rate);
+ g_print ("PlayOnDemand : format float, layout %s, intercept %f, slope %f\n",
+ filter->layout, filter->intercept, filter->slope);
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+
+GType
+gst_play_on_demand_get_type(void) {
+ static GType play_on_demand_type = 0;
+
+ if (! play_on_demand_type) {
+ static const GTypeInfo play_on_demand_info = {
+ sizeof(GstPlayOnDemandClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) play_on_demand_class_init,
+ NULL,
+ NULL,
+ sizeof(GstPlayOnDemand),
+ 0,
+ (GInstanceInitFunc) play_on_demand_init,
+ };
+ play_on_demand_type = g_type_register_static(GST_TYPE_ELEMENT, "GstPlayOnDemand", &play_on_demand_info, 0);
+ }
+ return play_on_demand_type;
+}
+
+static void
+play_on_demand_class_init (GstPlayOnDemandClass *klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+
+ gst_pod_filter_signals[PLAY_SIGNAL] =
+ g_signal_new("play",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GstPlayOnDemandClass, play),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ gst_pod_filter_signals[RESET_SIGNAL] =
+ g_signal_new("reset",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GstPlayOnDemandClass, reset),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ klass->play = play_on_demand_play_handler;
+ klass->reset = play_on_demand_reset_handler;
+
+ parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT,
+ g_param_spec_boolean("silent","silent","silent",
+ TRUE, G_PARAM_READWRITE)); // CHECKME
+
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FOLLOWTAIL,
+ g_param_spec_boolean("follow-stream-tail","follow-stream-tail","follow-stream-tail",
+ FALSE, G_PARAM_READWRITE));
+
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFFERSIZE,
+ g_param_spec_uint("buffer-size","buffer-size","buffer-size",
+ 0, G_MAXUINT - 1, POD_BUFFER_SIZE, G_PARAM_READWRITE));
+
+ gobject_class->set_property = play_on_demand_set_property;
+ gobject_class->get_property = play_on_demand_get_property;
+}
+
+static void
+play_on_demand_init (GstPlayOnDemand *filter)
+{
+ guint i;
+
+ filter->sinkpad = gst_pad_new_from_template(play_on_demand_sink_factory(), "sink");
+ gst_pad_set_negotiate_function(filter->sinkpad, play_on_demand_negotiate_sink);
+ gst_pad_set_bufferpool_function(filter->sinkpad, play_on_demand_get_bufferpool);
+
+ filter->srcpad = gst_pad_new_from_template(play_on_demand_src_factory(), "src");
+ gst_pad_set_negotiate_function(filter->srcpad, play_on_demand_negotiate_src);
+
+ gst_element_add_pad(GST_ELEMENT(filter), filter->sinkpad);
+ gst_element_add_pad(GST_ELEMENT(filter), filter->srcpad);
+
+ gst_element_set_loop_function(GST_ELEMENT(filter), play_on_demand_loop);
+
+ filter->sinkpool = gst_buffer_pool_get_default(POD_GSTBUFSIZE, POD_BUFSPERCHUNK);
+
+ filter->follow_stream_tail = FALSE;
+ filter->silent = TRUE;
+
+ filter->buffer = g_new(gchar, POD_BUFFER_SIZE);
+ filter->buffer_size = POD_BUFFER_SIZE;
+ filter->start = 0;
+ filter->write = 0;
+
+ filter->eos = FALSE;
+
+ /* the plays are stored as an array of buffer offsets. this initializes the
+ array to `blank' values (G_MAXUINT is an invalid index for this filter). */
+ filter->plays = g_new(guint, POD_MAX_PLAYS);
+ for (i = 0; i < POD_MAX_PLAYS; i++) {
+ filter->plays[i] = G_MAXUINT;
+ }
+}
+
+static void
+play_on_demand_loop (GstElement *elem)
+{
+ GstPlayOnDemand *filter = GST_PLAYONDEMAND(elem);
+ guint num_in, num_out, num_filter;
+ GstBuffer *in, *out;
+ register guint j, k, t;
+ guint w, offset;
+
+ g_return_if_fail(filter != NULL);
+ g_return_if_fail(GST_IS_PLAYONDEMAND(filter));
+
+ filter->srcpool = gst_pad_get_bufferpool(filter->srcpad);
+
+ in = gst_pad_pull(filter->sinkpad);
+
+ if (filter->format == GST_PLAYONDEMAND_FORMAT_INT) {
+ if (filter->width == 16) {
+ gint16 min = -32768;
+ gint16 max = 32767;
+ gint16 zero = 0;
+#define _TYPE_ gint16
+#include "filter.func"
+#undef _TYPE_
+ } else if (filter->width == 8) {
+ gint8 min = -128;
+ gint8 max = 127;
+ gint8 zero = 0;
+#define _TYPE_ gint8
+#include "filter.func"
+#undef _TYPE_
+ }
+ } else if (filter->format == GST_PLAYONDEMAND_FORMAT_FLOAT) {
+ gfloat min = -1.0;
+ gfloat max = 1.0;
+ gfloat zero = 0.0;
+#define _TYPE_ gfloat
+#include "filter.func"
+#undef _TYPE_
+ }
+}
+
+static void
+play_on_demand_play_handler(GstElement *elem)
+{
+ GstPlayOnDemand *filter = GST_PLAYONDEMAND(elem);
+ register guint i;
+
+ for (i = 0; i < POD_MAX_PLAYS; i++) {
+ if (filter->plays[i] == G_MAXUINT) {
+ filter->plays[i] = filter->start;
+ break;
+ }
+ }
+}
+
+static void
+play_on_demand_reset_handler(GstElement *elem)
+{
+ GstPlayOnDemand *filter = GST_PLAYONDEMAND(elem);
+ register guint i;
+
+ for (i = 0; i < POD_MAX_PLAYS; i++) {
+ filter->plays[i] = G_MAXUINT;
+ }
+
+ filter->start = 0;
+ filter->write = 0;
+}
+
+static void
+play_on_demand_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GstPlayOnDemand *filter;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_PLAYONDEMAND(object));
+ filter = GST_PLAYONDEMAND(object);
+
+ switch (prop_id) {
+ case ARG_BUFFERSIZE:
+ filter->buffer_size = g_value_get_uint(value);
+
+ /* reallocate space for the buffer with the new size values. */
+ g_free(filter->buffer);
+ filter->buffer = g_new(gchar, filter->buffer_size);
+
+ /* reset the play pointers and read/write indexes. */
+ play_on_demand_reset_handler(GST_ELEMENT(filter));
+ break;
+ case ARG_SILENT:
+ filter->silent = g_value_get_boolean(value);
+ break;
+ case ARG_FOLLOWTAIL:
+ filter->follow_stream_tail = g_value_get_boolean(value);
+ play_on_demand_reset_handler(GST_ELEMENT(filter));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+play_on_demand_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GstPlayOnDemand *filter;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_PLAYONDEMAND(object));
+ filter = GST_PLAYONDEMAND(object);
+
+ switch (prop_id) {
+ case ARG_BUFFERSIZE:
+ g_value_set_uint(value, filter->buffer_size);
+ break;
+ case ARG_SILENT:
+ g_value_set_boolean(value, filter->silent);
+ break;
+ case ARG_FOLLOWTAIL:
+ g_value_set_boolean(value, filter->follow_stream_tail);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+ GstElementFactory *factory;
+
+ factory = gst_elementfactory_new("playondemand",
+ GST_TYPE_PLAYONDEMAND,
+ &play_on_demand_details);
+ g_return_val_if_fail(factory != NULL, FALSE);
+
+ gst_elementfactory_add_padtemplate(factory, play_on_demand_src_factory());
+ gst_elementfactory_add_padtemplate(factory, play_on_demand_sink_factory());
+
+ gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE(factory));
+
+ return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "playondemand",
+ plugin_init
+};
diff --git a/gst/playondemand/gstplayondemand.h b/gst/playondemand/gstplayondemand.h
new file mode 100644
index 00000000..7ca8206e
--- /dev/null
+++ b/gst/playondemand/gstplayondemand.h
@@ -0,0 +1,112 @@
+/* -*- c-basic-offset: 2 -*-
+ * GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_PLAYONDEMAND_H__
+#define __GST_PLAYONDEMAND_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+/* #include <gst/meta/audioraw.h> */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_PLAYONDEMAND \
+ (gst_play_on_demand_get_type())
+#define GST_PLAYONDEMAND(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAYONDEMAND,GstPlayOnDemand))
+#define GST_PLAYONDEMAND_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstPlayOnDemand))
+#define GST_IS_PLAYONDEMAND(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAYONDEMAND))
+#define GST_IS_PLAYONDEMAND_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAYONDEMAND))
+
+typedef struct _GstPlayOnDemand GstPlayOnDemand;
+typedef struct _GstPlayOnDemandClass GstPlayOnDemandClass;
+typedef enum _GstPlayOnDemandFormat GstPlayOnDemandFormat;
+
+enum _GstPlayOnDemandFormat {
+ GST_PLAYONDEMAND_FORMAT_INT,
+ GST_PLAYONDEMAND_FORMAT_FLOAT
+};
+
+struct _GstPlayOnDemand {
+ GstElement element;
+
+ GstPad *sinkpad, *srcpad;
+ GstBufferPool *sinkpool, *srcpool;
+
+ /* these next data elements are for the filter's internal buffers and list of
+ play pointers (offsets in the internal buffers). there are also flags for
+ repeating from the beginning or end of the input stream, and a max buffer
+ size. */
+ gchar *buffer;
+ guint buffer_size;
+
+ guint write;
+ guint start;
+
+ guint *plays;
+
+ gboolean eos;
+
+ gboolean follow_stream_tail;
+
+ gboolean silent;
+
+ /* the next three are valid for both int and float */
+ GstPlayOnDemandFormat format;
+ guint rate;
+ guint channels;
+
+ /* the next five are valid only for format == GST_PLAYONDEMAND_FORMAT_INT */
+ guint width;
+ guint depth;
+ guint endianness;
+ guint law;
+ gboolean is_signed;
+
+ /* the next three are valid only for format == GST_PLAYONDEMAND_FORMAT_FLOAT */
+ const gchar *layout;
+ gfloat slope;
+ gfloat intercept;
+};
+
+struct _GstPlayOnDemandClass {
+ GstElementClass parent_class;
+
+ void (*play) (GstElement *elem);
+ void (*reset) (GstElement *elem);
+};
+
+GType gst_play_on_demand_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_PLAYONDEMAND_H__ */