templates = templates->next;
}
+ self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
+
self->audio_in = g_new0 (gfloat *, klass->num_audio_in);
self->control_in = g_new0 (gfloat, klass->num_control_in);
self->audio_out = g_new0 (gfloat *, klass->num_audio_out);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static gboolean
+gst_signal_processor_setup (GstSignalProcessor * self, guint sample_rate)
+{
+ GstSignalProcessorClass *klass;
+ gboolean ret = TRUE;
+
+ klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+ g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_NULL, FALSE);
+
+ if (klass->setup)
+ ret = klass->setup (self, sample_rate);
+
+ if (!ret)
+ goto setup_failed;
+
+ self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED;
+
+ return ret;
+
+setup_failed:
+ {
+ GST_INFO_OBJECT (self, "setup() failed at %u Hz", sample_rate);
+ return ret;
+ }
+}
+
+static gboolean
+gst_signal_processor_start (GstSignalProcessor * self)
+{
+ GstSignalProcessorClass *klass;
+ gboolean ret = TRUE;
+
+ klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+ g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED,
+ FALSE);
+
+ if (klass->start)
+ ret = klass->start (self);
+
+ if (!ret)
+ goto start_failed;
+
+ self->state = GST_SIGNAL_PROCESSOR_STATE_RUNNING;
+
+ return ret;
+
+start_failed:
+ {
+ GST_INFO_OBJECT (self, "start() failed");
+ return ret;
+ }
+}
+
+static void
+gst_signal_processor_stop (GstSignalProcessor * self)
+{
+ GstSignalProcessorClass *klass;
+
+ klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+ g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING);
+
+ if (klass->stop)
+ klass->stop (self);
+
+ /* should also flush our buffers perhaps? */
+
+ self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED;
+}
+
+static void
+gst_signal_processor_cleanup (GstSignalProcessor * self)
+{
+ GstSignalProcessorClass *klass;
+
+ klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+ g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED);
+
+ if (klass->cleanup)
+ klass->cleanup (self);
+
+ self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
+}
+
static gboolean
gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
{
GstSignalProcessor *self;
- GstSignalProcessorClass *klass;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
- klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
/* the whole processor has one caps; if the sample rate changes, let subclass
implementations know */
GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate);
}
- if (!klass->setup (self, sample_rate)) {
- goto setup_failed;
+ if (!gst_signal_processor_setup (self, sample_rate)) {
+ goto start_failed;
+ } else if (!gst_signal_processor_start (self)) {
+ goto start_failed;
} else {
self->sample_rate = sample_rate;
gst_caps_replace (&self->caps, caps);
return TRUE;
-setup_failed:
+start_failed:
{
- GST_INFO_OBJECT (self, "setup() failed");
gst_object_unref (self);
return FALSE;
}
gst_signal_processor_prepare (GstSignalProcessor * self)
{
GstElement *elem = (GstElement *) self;
+ GstSignalProcessorClass *klass;
GList *sinks, *srcs;
guint samples_avail = G_MAXUINT;
+ klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
/* first, assign audio_in pointers, and determine the number of samples that
* we can process */
for (sinks = elem->sinkpads; sinks; sinks = sinks->next) {
is the exact size of the number of samples we are processing. */
sinks = elem->sinkpads;
srcs = elem->srcpads;
- while (sinks && srcs) {
- GstSignalProcessorPad *sinkpad, *srcpad;
+ if (GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE (klass)) {
+ while (sinks && srcs) {
+ GstSignalProcessorPad *sinkpad, *srcpad;
- sinkpad = (GstSignalProcessorPad *) sinks->data;
- srcpad = (GstSignalProcessorPad *) srcs->data;
+ sinkpad = (GstSignalProcessorPad *) sinks->data;
+ srcpad = (GstSignalProcessorPad *) srcs->data;
- if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) {
- /* reusable, yay */
- g_assert (sinkpad->samples_avail == samples_avail);
- srcpad->pen = sinkpad->pen;
- sinkpad->pen = NULL;
- self->audio_out[srcpad->index] = sinkpad->data;
- self->pending_out++;
+ if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) {
+ /* reusable, yay */
+ g_assert (sinkpad->samples_avail == samples_avail);
+ srcpad->pen = sinkpad->pen;
+ sinkpad->pen = NULL;
+ self->audio_out[srcpad->index] = sinkpad->data;
+ self->pending_out++;
- srcs = srcs->next;
- }
+ srcs = srcs->next;
+ }
- sinks = sinks->next;
+ sinks = sinks->next;
+ }
}
/* now allocate for any remaining outputs */
ret =
gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1,
- samples_avail, GST_PAD_CAPS (srcpad), &srcpad->pen);
+ samples_avail * sizeof (gfloat), GST_PAD_CAPS (srcpad), &srcpad->pen);
if (ret != GST_FLOW_OK) {
- self->state = ret;
+ self->flow_state = ret;
return 0;
} else {
self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen);
flow_error:
{
GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d",
- self->state);
+ self->flow_state);
return;
}
}
ret = gst_pad_pull_range (GST_PAD (spad), -1, nframes, &buf);
if (ret != GST_FLOW_OK) {
- self->state = ret;
+ self->flow_state = ret;
gst_signal_processor_flush (self);
return;
} else if (!buf) {
g_critical ("Pull failed to make a buffer!");
- self->state = GST_FLOW_ERROR;
+ self->flow_state = GST_FLOW_ERROR;
return;
} else {
gst_signal_processor_pen_buffer (self, GST_PAD (spad), buf);
if (self->pending_in != 0) {
g_critical ("Something wierd happened...");
- self->state = GST_FLOW_ERROR;
+ self->flow_state = GST_FLOW_ERROR;
} else {
gst_signal_processor_process (self);
}
if (!spad->pen) {
/* this is an error condition */
*buffer = NULL;
- ret = self->state;
+ ret = self->flow_state;
} else {
*buffer = spad->pen;
spad->pen = NULL;
ret = gst_pad_push (GST_PAD (spad), spad->pen);
if (ret != GST_FLOW_OK) {
- self->state = ret;
+ self->flow_state = ret;
gst_signal_processor_flush (self);
return;
} else {
if (self->pending_out != 0) {
g_critical ("Something wierd happened...");
- self->state = GST_FLOW_ERROR;
+ self->flow_state = GST_FLOW_ERROR;
}
}
gst_object_unref (self);
- return self->state;
+ return self->flow_state;
}
static void
gst_signal_processor_change_state (GstElement * element,
GstStateChange transition)
{
- /* GstSignalProcessor *self;
- GstSignalProcessorClass *klass; */
+ GstSignalProcessor *self;
GstStateChangeReturn result;
- /* self = GST_SIGNAL_PROCESSOR (element);
- klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); */
-
+ self = GST_SIGNAL_PROCESSOR (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self))
+ gst_signal_processor_stop (self);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
- /* gst_signal_processor_cleanup (self); */
+ if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self))
+ gst_signal_processor_cleanup (self);
break;
default:
break;
G_BEGIN_DECLS
+typedef enum
+{
+ GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE = 1<<0
+} GstSignalProcessorClassFlags;
+
+#define GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE(klass) \
+ (GST_SIGNAL_PROCESSOR_CLASS (klass)->flags & \
+ GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE)
+#define GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE(klass) \
+ GST_SIGNAL_PROCESSOR_CLASS (klass)->flags |= \
+ GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE
+
+typedef enum
+{
+ GST_SIGNAL_PROCESSOR_STATE_NULL,
+ GST_SIGNAL_PROCESSOR_STATE_INITIALIZED,
+ GST_SIGNAL_PROCESSOR_STATE_RUNNING
+} GstSignalProcessorState;
+
+
#define GST_TYPE_SIGNAL_PROCESSOR (gst_signal_processor_get_type())
#define GST_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessor))
#define GST_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass))
#define GST_IS_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIGNAL_PROCESSOR))
#define GST_IS_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIGNAL_PROCESSOR))
+#define GST_SIGNAL_PROCESSOR_IS_INITIALIZED(obj) \
+ (GST_SIGNAL_PROCESSOR (obj)->state >= GST_SIGNAL_PROCESSOR_STATE_INITIALIZED)
+#define GST_SIGNAL_PROCESSOR_IS_RUNNING(obj) \
+ (GST_SIGNAL_PROCESSOR (obj)->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING)
typedef struct _GstSignalProcessor GstSignalProcessor;
typedef struct _GstSignalProcessorClass GstSignalProcessorClass;
guint sample_rate;
- GstFlowReturn state;
+ GstSignalProcessorState state;
+
+ GstFlowReturn flow_state;
GstActivateMode mode;
guint num_control_out;
guint num_audio_out;
+ guint flags;
+
/* virtual methods for subclasses */
gboolean (*setup) (GstSignalProcessor *self, guint sample_rate);