diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-08-31 18:20:00 +0200 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-08-31 18:48:04 +0200 |
commit | 53f654150b558ed75ac13f8fabec6217fc72751a (patch) | |
tree | ee1e8d3e535eeebc77008574e4e6da1fe00b6799 | |
parent | 2127cf3e8c61b45efea8babe7378d3ab6beefcda (diff) | |
download | gstreamer-plugins-bad-53f654150b558ed75ac13f8fabec6217fc72751a.tar.gz |
wildmidi: use state machine
Use a state machine to keep track of the current state.
Add chain function and event function on the sinkpad.
Remove some unused code.
-rw-r--r-- | ext/timidity/gstwildmidi.c | 268 | ||||
-rw-r--r-- | ext/timidity/gstwildmidi.h | 15 |
2 files changed, 154 insertions, 129 deletions
diff --git a/ext/timidity/gstwildmidi.c b/ext/timidity/gstwildmidi.c index 43359d8e3..5a37491fd 100644 --- a/ext/timidity/gstwildmidi.c +++ b/ext/timidity/gstwildmidi.c @@ -83,7 +83,9 @@ enum static void gst_wildmidi_base_init (gpointer g_class); static void gst_wildmidi_class_init (GstWildmidiClass * klass); +static void gst_wildmidi_finalize (GObject * object); +static gboolean gst_wildmidi_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_wildmidi_src_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn gst_wildmidi_change_state (GstElement * element, @@ -92,6 +94,7 @@ static gboolean gst_wildmidi_activate (GstPad * pad); static gboolean gst_wildmidi_activatepull (GstPad * pad, gboolean active); static void gst_wildmidi_loop (GstPad * sinkpad); +static GstFlowReturn gst_wildmidi_chain (GstPad * sinkpad, GstBuffer * buffer); static gboolean gst_wildmidi_src_query (GstPad * pad, GstQuery * query); @@ -230,7 +233,7 @@ gst_wildmidi_class_init (GstWildmidiClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - gstelement_class->change_state = gst_wildmidi_change_state; + gobject_class->finalize = gst_wildmidi_finalize; gobject_class->set_property = gst_wildmidi_set_property; gobject_class->get_property = gst_wildmidi_get_property; @@ -241,6 +244,8 @@ gst_wildmidi_class_init (GstWildmidiClass * klass) g_object_class_install_property (gobject_class, ARG_HIGH_QUALITY, g_param_spec_boolean ("high-quality", "High Quality", "High Quality", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + gstelement_class->change_state = gst_wildmidi_change_state; } /* initialize the new element @@ -260,6 +265,8 @@ gst_wildmidi_init (GstWildmidi * filter, GstWildmidiClass * g_class) gst_pad_set_activatepull_function (filter->sinkpad, gst_wildmidi_activatepull); gst_pad_set_activate_function (filter->sinkpad, gst_wildmidi_activate); + gst_pad_set_event_function (filter->sinkpad, gst_wildmidi_sink_event); + gst_pad_set_chain_function (filter->sinkpad, gst_wildmidi_chain); gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); filter->srcpad = @@ -274,10 +281,18 @@ gst_wildmidi_init (GstWildmidi * filter, GstWildmidiClass * g_class) gst_segment_init (filter->o_segment, GST_FORMAT_DEFAULT); + filter->adapter = gst_adapter_new (); + filter->bytes_per_frame = WILDMIDI_BPS; filter->time_per_frame = GST_SECOND / WILDMIDI_RATE; } +static void +gst_wildmidi_finalize (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static gboolean gst_wildmidi_src_convert (GstWildmidi * wildmidi, GstFormat src_format, gint64 src_value, @@ -381,20 +396,6 @@ gst_wildmidi_src_query (GstPad * pad, GstQuery * query) return res; } -static gboolean -gst_wildmidi_get_upstream_size (GstWildmidi * wildmidi, gint64 * size) -{ - GstFormat format = GST_FORMAT_BYTES; - gboolean res = FALSE; - GstPad *peer = gst_pad_get_peer (wildmidi->sinkpad); - - if (peer != NULL) - res = gst_pad_query_duration (peer, &format, size) && *size >= 0; - - gst_object_unref (peer); - return res; -} - static GstSegment * gst_wildmidi_get_segment (GstWildmidi * wildmidi, GstFormat format, gboolean update) @@ -521,6 +522,7 @@ gst_wildmidi_src_event (GstPad * pad, GstEvent * event) return res; } + static gboolean gst_wildmidi_activate (GstPad * sinkpad) { @@ -643,123 +645,58 @@ gst_wildmidi_get_buffer (GstWildmidi * wildmidi) return gst_wildmidi_clip_buffer (wildmidi, out); } -static void -gst_wildmidi_loop (GstPad * sinkpad) +static gboolean +gst_wildmidi_parse_song (GstWildmidi * wildmidi) { - GstWildmidi *wildmidi = GST_WILDMIDI (GST_PAD_PARENT (sinkpad)); - GstBuffer *out; - GstFlowReturn ret; + struct _WM_Info *info; GstCaps *outcaps; + guint8 *data; + guint size; - if (wildmidi->mididata_size == 0) { - if (!gst_wildmidi_get_upstream_size (wildmidi, &wildmidi->mididata_size)) { - GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), - ("Unable to get song length")); - goto paused; - } - - if (wildmidi->mididata) - free (wildmidi->mididata); - - wildmidi->mididata = malloc (wildmidi->mididata_size); - wildmidi->mididata_offset = 0; - return; - } - - if (wildmidi->mididata_offset < wildmidi->mididata_size) { - GstBuffer *buffer; - gint64 size; + GST_DEBUG_OBJECT (wildmidi, "Parsing song"); - GST_DEBUG_OBJECT (wildmidi, "loading song"); - - ret = - gst_pad_pull_range (wildmidi->sinkpad, wildmidi->mididata_offset, - -1, &buffer); - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), - ("Unable to load song")); - goto paused; - } - - size = wildmidi->mididata_size - wildmidi->mididata_offset; - if (GST_BUFFER_SIZE (buffer) < size) - size = GST_BUFFER_SIZE (buffer); - - memmove (wildmidi->mididata + wildmidi->mididata_offset, - GST_BUFFER_DATA (buffer), size); - gst_buffer_unref (buffer); + size = gst_adapter_available (wildmidi->adapter); + data = gst_adapter_take (wildmidi->adapter, size); - wildmidi->mididata_offset += size; - GST_DEBUG_OBJECT (wildmidi, "Song loaded"); - return; - } + /* this method takes our memory block */ + wildmidi->song = WildMidi_OpenBuffer (data, size); if (!wildmidi->song) { - struct _WM_Info *info; - - GST_DEBUG_OBJECT (wildmidi, "Parsing song"); - - /* this method takes our memory block */ - wildmidi->song = - WildMidi_OpenBuffer ((unsigned char *) wildmidi->mididata, - wildmidi->mididata_size); - wildmidi->mididata_size = 0; - wildmidi->mididata = NULL; - - if (!wildmidi->song) { - GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), - ("Unable to parse midi")); - goto paused; - } - - WildMidi_LoadSamples (wildmidi->song); - - WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME, - wildmidi->linear_volume); - WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION, - wildmidi->high_quality); - - info = WildMidi_GetInfo (wildmidi->song); - wildmidi->o_len = info->approx_total_samples; - - outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (wildmidi->srcpad)); - gst_pad_set_caps (wildmidi->srcpad, outcaps); - gst_caps_unref (outcaps); + GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), + ("Unable to parse midi")); + return FALSE; + } - gst_segment_set_newsegment (wildmidi->o_segment, FALSE, 1.0, - GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); + WildMidi_LoadSamples (wildmidi->song); - gst_pad_push_event (wildmidi->srcpad, - gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME, FALSE)); + WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME, + wildmidi->linear_volume); + WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION, + wildmidi->high_quality); - GST_DEBUG_OBJECT (wildmidi, "Parsing song done"); - return; - } + info = WildMidi_GetInfo (wildmidi->song); + wildmidi->o_len = info->approx_total_samples; - if (wildmidi->o_segment_changed) { - GstSegment *segment; + outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (wildmidi->srcpad)); + gst_pad_set_caps (wildmidi->srcpad, outcaps); + gst_caps_unref (outcaps); - GST_DEBUG_OBJECT (wildmidi, "segment changed"); + gst_segment_set_newsegment (wildmidi->o_segment, FALSE, 1.0, + GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); - segment = gst_wildmidi_get_segment (wildmidi, GST_FORMAT_TIME, - !wildmidi->o_new_segment); + gst_pad_push_event (wildmidi->srcpad, + gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME, FALSE)); - GST_LOG_OBJECT (wildmidi, - "sending newsegment from %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT - ", pos=%" GST_TIME_FORMAT, GST_TIME_ARGS ((guint64) segment->start), - GST_TIME_ARGS ((guint64) segment->stop), - GST_TIME_ARGS ((guint64) segment->time)); + GST_DEBUG_OBJECT (wildmidi, "Parsing song done"); - if (wildmidi->o_segment->flags & GST_SEEK_FLAG_SEGMENT) { - gst_element_post_message (GST_ELEMENT (wildmidi), - gst_message_new_segment_start (GST_OBJECT (wildmidi), - segment->format, segment->start)); - } + return TRUE; +} - gst_segment_free (segment); - wildmidi->o_segment_changed = FALSE; - return; - } +static GstFlowReturn +gst_wildmidi_do_play (GstWildmidi * wildmidi) +{ + GstBuffer *out; + GstFlowReturn ret; if (wildmidi->o_seek) { unsigned long int sample; @@ -781,7 +718,7 @@ gst_wildmidi_loop (GstPad * sinkpad) GST_LOG_OBJECT (wildmidi, "Song ended, generating eos"); gst_pad_push_event (wildmidi->srcpad, gst_event_new_eos ()); wildmidi->o_seek = FALSE; - goto paused; + return GST_FLOW_UNEXPECTED; } if (wildmidi->o_seek) { @@ -792,9 +729,94 @@ gst_wildmidi_loop (GstPad * sinkpad) gst_buffer_set_caps (out, GST_PAD_CAPS (wildmidi->srcpad)); ret = gst_pad_push (wildmidi->srcpad, out); - if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) - goto error; + return ret; +} + +static gboolean +gst_wildmidi_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res = FALSE; + GstWildmidi *wildmidi = GST_WILDMIDI (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (pad, "%s event received", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + wildmidi->state = GST_WILDMIDI_STATE_PARSE; + /* now start the parsing task */ + gst_pad_start_task (wildmidi->sinkpad, + (GstTaskFunction) gst_wildmidi_loop, wildmidi->sinkpad); + gst_event_unref (event); + break; + default: + res = gst_pad_push_event (wildmidi->srcpad, event); + break; + } + return res; +} + +static GstFlowReturn +gst_wildmidi_chain (GstPad * sinkpad, GstBuffer * buffer) +{ + GstFlowReturn ret; + GstWildmidi *wildmidi; + + wildmidi = GST_WILDMIDI (GST_PAD_PARENT (sinkpad)); + + gst_adapter_push (wildmidi->adapter, buffer); + ret = GST_FLOW_OK; + + return ret; +} + +static void +gst_wildmidi_loop (GstPad * sinkpad) +{ + GstWildmidi *wildmidi = GST_WILDMIDI (GST_PAD_PARENT (sinkpad)); + GstFlowReturn ret; + + switch (wildmidi->state) { + case GST_WILDMIDI_STATE_LOAD: + { + GstBuffer *buffer; + + GST_DEBUG_OBJECT (wildmidi, "loading song"); + + ret = + gst_pad_pull_range (wildmidi->sinkpad, wildmidi->offset, -1, &buffer); + + if (ret == GST_FLOW_UNEXPECTED) { + GST_DEBUG_OBJECT (wildmidi, "Song loaded"); + wildmidi->state = GST_WILDMIDI_STATE_PARSE; + } else if (ret != GST_FLOW_OK) { + GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), + ("Unable to load song")); + goto paused; + } else { + GST_DEBUG_OBJECT (wildmidi, "pushing buffer"); + gst_adapter_push (wildmidi->adapter, buffer); + wildmidi->offset += GST_BUFFER_SIZE (buffer); + } + break; + } + case GST_WILDMIDI_STATE_PARSE: + { + if (!wildmidi->song) { + if (!gst_wildmidi_parse_song (wildmidi)) + goto paused; + } + wildmidi->state = GST_WILDMIDI_STATE_PLAY; + break; + } + case GST_WILDMIDI_STATE_PLAY: + ret = gst_wildmidi_do_play (wildmidi); + if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) + goto error; + break; + default: + break; + } return; paused: @@ -821,10 +843,10 @@ gst_wildmidi_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - wildmidi->mididata = NULL; break; case GST_STATE_CHANGE_READY_TO_PAUSED: - wildmidi->mididata_size = 0; + wildmidi->offset = 0; + wildmidi->state = GST_WILDMIDI_STATE_LOAD; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; @@ -841,9 +863,7 @@ gst_wildmidi_change_state (GstElement * element, GstStateChange transition) if (wildmidi->song) WildMidi_Close (wildmidi->song); wildmidi->song = NULL; - if (wildmidi->mididata) - free (wildmidi->mididata); - wildmidi->mididata = NULL; + gst_adapter_clear (wildmidi->adapter); break; case GST_STATE_CHANGE_READY_TO_NULL: break; diff --git a/ext/timidity/gstwildmidi.h b/ext/timidity/gstwildmidi.h index 84802f735..c33f5005e 100644 --- a/ext/timidity/gstwildmidi.h +++ b/ext/timidity/gstwildmidi.h @@ -47,6 +47,12 @@ G_BEGIN_DECLS typedef struct _GstWildmidi GstWildmidi; typedef struct _GstWildmidiClass GstWildmidiClass; +typedef enum { + GST_WILDMIDI_STATE_LOAD, + GST_WILDMIDI_STATE_PARSE, + GST_WILDMIDI_STATE_PLAY +} GstWildmidiState; + struct _GstWildmidi { GstElement element; @@ -54,14 +60,13 @@ struct _GstWildmidi GstPad *sinkpad, *srcpad; /* input stream properties */ - gint64 mididata_size, mididata_offset; - gchar *mididata; - gboolean mididata_filled; - + GstWildmidiState state; + GstAdapter *adapter; midi *song; + guint64 offset; /* output data */ - gboolean o_new_segment, o_segment_changed, o_seek; + gboolean o_new_segment, o_seek; GstSegment o_segment[1]; gint64 o_len; |