static void gst_wildmidi_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstWildmidi *wildmidi; g_return_if_fail (GST_IS_WILDMIDI (object)); wildmidi = GST_WILDMIDI (object); switch (prop_id) { case PROP_LINEAR_VOLUME: GST_OBJECT_LOCK (object); g_value_set_boolean (value, wildmidi->linear_volume); GST_OBJECT_UNLOCK (object); break; case PROP_HIGH_QUALITY: GST_OBJECT_LOCK (object); g_value_set_boolean (value, wildmidi->high_quality); GST_OBJECT_UNLOCK (object); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_wildmidi_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstWildmidi *wildmidi; g_return_if_fail (GST_IS_WILDMIDI (object)); wildmidi = GST_WILDMIDI (object); switch (prop_id) { case ARG_LINEAR_VOLUME: GST_OBJECT_LOCK (object); wildmidi->linear_volume = g_value_get_boolean (value); if (wildmidi->song) WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME, wildmidi->linear_volume); GST_OBJECT_UNLOCK (object); break; case ARG_HIGH_QUALITY: GST_OBJECT_LOCK (object); wildmidi->high_quality = g_value_get_boolean (value); if (wildmidi->song) WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION, wildmidi->high_quality); GST_OBJECT_UNLOCK (object); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean gst_wildmidi_src_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstWildmidi *wildmidi = GST_WILDMIDI (gst_pad_get_parent (pad)); GstFormat src_format, dst_format; gint64 src_value, dst_value; if (!wildmidi->song) { gst_object_unref (wildmidi); return FALSE; } switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: gst_query_set_duration (query, GST_FORMAT_TIME, gst_util_uint64_scale_int (wildmidi->o_len, GST_SECOND, WILDMIDI_RATE)); break; case GST_QUERY_POSITION: gst_query_set_position (query, GST_FORMAT_TIME, gst_util_uint64_scale_int (wildmidi->o_segment->last_stop, GST_SECOND, WILDMIDI_RATE)); break; case GST_QUERY_CONVERT: gst_query_parse_convert (query, &src_format, &src_value, &dst_format, NULL); res = gst_wildmidi_src_convert (wildmidi, src_format, src_value, &dst_format, &dst_value); if (res) gst_query_set_convert (query, src_format, src_value, dst_format, dst_value); break; case GST_QUERY_FORMATS: gst_query_set_formats (query, 3, GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT); break; case GST_QUERY_SEGMENT: gst_query_set_segment (query, wildmidi->o_segment->rate, wildmidi->o_segment->format, wildmidi->o_segment->start, wildmidi->o_segment->stop); break; case GST_QUERY_SEEKING: gst_query_set_seeking (query, wildmidi->o_segment->format, TRUE, 0, wildmidi->o_len); break; default: res = FALSE; break; } gst_object_unref (wildmidi); return res; }
static void gst_wildmidi_finalize (GObject * object) { GstWildmidi *wildmidi; wildmidi = GST_WILDMIDI (object); g_object_unref (wildmidi->adapter); G_OBJECT_CLASS (parent_class)->finalize (object); }
static GstFlowReturn gst_wildmidi_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buffer) { GstWildmidi *wildmidi; wildmidi = GST_WILDMIDI (parent); /* push stuff in the adapter, we will start doing something in the sink event * handler when we get EOS */ gst_adapter_push (wildmidi->adapter, buffer); return GST_FLOW_OK; }
static gboolean gst_wildmidi_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = FALSE; GstWildmidi *wildmidi = GST_WILDMIDI (parent); GST_DEBUG_OBJECT (pad, "%s event received", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: res = gst_wildmidi_do_seek (wildmidi, event); break; default: break; } gst_event_unref (event); return res; }
static GstStateChangeReturn gst_wildmidi_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstWildmidi *wildmidi = GST_WILDMIDI (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: wildmidi->offset = 0; wildmidi->state = GST_WILDMIDI_STATE_LOAD; wildmidi->discont = FALSE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_READY: GST_OBJECT_LOCK (wildmidi); if (wildmidi->song) WildMidi_Close (wildmidi->song); wildmidi->song = NULL; GST_OBJECT_UNLOCK (wildmidi); gst_adapter_clear (wildmidi->adapter); break; case GST_STATE_CHANGE_READY_TO_NULL: break; default: break; } return ret; }
static gboolean gst_wildmidi_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res; GstWildmidi *wildmidi = GST_WILDMIDI (parent); 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 */ res = gst_pad_start_task (wildmidi->sinkpad, (GstTaskFunction) gst_wildmidi_loop, wildmidi->sinkpad, NULL); /* don't forward the event */ gst_event_unref (event); break; default: res = gst_pad_event_default (pad, parent, event); break; } return res; }
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 = NULL; GST_DEBUG_OBJECT (wildmidi, "loading song"); ret = gst_pad_pull_range (wildmidi->sinkpad, wildmidi->offset, -1, &buffer); if (ret == GST_FLOW_EOS) { 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 read song")); goto pause; } else { GST_DEBUG_OBJECT (wildmidi, "pushing buffer"); gst_adapter_push (wildmidi->adapter, buffer); wildmidi->offset += gst_buffer_get_size (buffer); } break; } case GST_WILDMIDI_STATE_PARSE: ret = gst_wildmidi_parse_song (wildmidi); if (ret != GST_FLOW_OK) goto pause; wildmidi->state = GST_WILDMIDI_STATE_PLAY; break; case GST_WILDMIDI_STATE_PLAY: ret = gst_wildmidi_do_play (wildmidi); if (ret != GST_FLOW_OK) goto pause; break; default: break; } return; pause: { const gchar *reason = gst_flow_get_name (ret); GstEvent *event; GST_DEBUG_OBJECT (wildmidi, "pausing task, reason %s", reason); gst_pad_pause_task (sinkpad); if (ret == GST_FLOW_EOS) { /* perform EOS logic */ event = gst_event_new_eos (); gst_pad_push_event (wildmidi->srcpad, event); } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { event = gst_event_new_eos (); /* for fatal errors we post an error message, post the error * first so the app knows about the error first. */ GST_ELEMENT_ERROR (wildmidi, STREAM, FAILED, ("Internal data flow error."), ("streaming task paused, reason %s (%d)", reason, ret)); gst_pad_push_event (wildmidi->srcpad, event); } } }
static gboolean gst_wildmidi_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean res = TRUE; GstWildmidi *wildmidi = GST_WILDMIDI (parent); GstFormat src_format, dst_format; gint64 src_value, dst_value; if (!wildmidi->song) return FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: gst_query_set_duration (query, GST_FORMAT_TIME, gst_util_uint64_scale_int (wildmidi->o_len, GST_SECOND, WILDMIDI_RATE)); break; case GST_QUERY_POSITION: gst_query_set_position (query, GST_FORMAT_TIME, gst_util_uint64_scale_int (wildmidi->o_segment->position, GST_SECOND, WILDMIDI_RATE)); break; case GST_QUERY_CONVERT: gst_query_parse_convert (query, &src_format, &src_value, &dst_format, NULL); res = gst_wildmidi_src_convert (wildmidi, src_format, src_value, &dst_format, &dst_value); if (res) gst_query_set_convert (query, src_format, src_value, dst_format, dst_value); break; case GST_QUERY_FORMATS: gst_query_set_formats (query, 3, GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT); break; case GST_QUERY_SEGMENT:{ GstFormat format; gint64 start, stop; format = wildmidi->o_segment->format; start = gst_segment_to_stream_time (wildmidi->o_segment, format, wildmidi->o_segment->start); if ((stop = wildmidi->o_segment->stop) == -1) stop = wildmidi->o_segment->duration; else stop = gst_segment_to_stream_time (wildmidi->o_segment, format, stop); gst_query_set_segment (query, wildmidi->o_segment->rate, format, start, stop); res = TRUE; break; } case GST_QUERY_SEEKING: gst_query_set_seeking (query, wildmidi->o_segment->format, TRUE, 0, wildmidi->o_len); break; default: res = gst_pad_query_default (pad, parent, query); break; } return res; }