/** GstXineInput ***********************************************************/ enum { ARG_0, ARG_LOCATION }; GST_BOILERPLATE (GstXineInput, gst_xine_input, GstXine, GST_TYPE_XINE); static void gst_xine_input_dispose (GObject * object); static void gst_xine_input_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_xine_input_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstStateChangeReturn gst_xine_input_change_state (GstElement * element, GstStateChange transition); static void gst_xine_input_base_init (gpointer g_class) { } static void gst_xine_input_class_init (GstXineInputClass * klass) { GstElementClass *element = GST_ELEMENT_CLASS (klass); GObjectClass *object = G_OBJECT_CLASS (klass); element->change_state = gst_xine_input_change_state; object->set_property = gst_xine_input_set_property; object->get_property = gst_xine_input_get_property; object->dispose = gst_xine_input_dispose; g_object_class_install_property (object, ARG_LOCATION, g_param_spec_string ("location", "location", "location", NULL, G_PARAM_READWRITE)); } static void gst_xine_input_init (GstXineInput * xine, GstXineInputClass * g_class) { } static void gst_xine_input_dispose (GObject * object) { GstXineInput *xine = GST_XINE_INPUT (object); g_free (xine->location); xine->location = NULL; GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static void gst_xine_input_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstXineInput *xine = GST_XINE_INPUT (object); switch (prop_id) { case ARG_LOCATION: if (gst_element_get_state (GST_ELEMENT (xine)) != GST_STATE_NULL) return; if (xine->location) g_free (xine->location); xine->location = g_strdup (g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); return; } } static void gst_xine_input_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstXineInput *xine = GST_XINE_INPUT (object); switch (prop_id) { case ARG_LOCATION: g_value_set_string (value, xine->location); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); return; } } #define BUFFER_SIZE 4096 /* FIXME: what size? */ static GstData * gst_xine_input_get (GstPad * pad) { GstXineInput *xine = GST_XINE_INPUT (gst_object_get_parent (GST_OBJECT (pad))); GstBuffer *buf; gint real_size, position; /* FIXME: how does xine figure out EOS? */ position = xine->input->get_current_pos (xine->input); if (position > 0 && position == xine->input->get_length (xine->input)) { gst_element_set_eos (GST_ELEMENT (xine)); return GST_DATA (gst_event_new (GST_EVENT_EOS)); } buf = gst_pad_alloc_buffer_and_set_caps (xine->srcpad, GST_BUFFER_OFFSET_NONE, xine->blocksize); GST_BUFFER_OFFSET (buf) = position; real_size = xine->input->read (xine->input, GST_BUFFER_DATA (buf), GST_BUFFER_MAXSIZE (buf)); GST_BUFFER_SIZE (buf) = real_size; if (real_size < 0) { GST_ELEMENT_ERROR (xine, RESOURCE, READ, (NULL), ("error %d reading data", real_size)); gst_data_unref (GST_DATA (buf)); return NULL; } else if (real_size == 0) { buf_element_t *element; if (xine->input->get_capabilities (xine->input) & INPUT_CAP_BLOCK) element = xine->input->read_block (xine->input, gst_xine_get_stream (GST_XINE (xine))->audio_fifo, xine->blocksize); if (element == NULL) { /* FIXME: is this EOS? */ gst_element_set_eos (GST_ELEMENT (xine)); return GST_DATA (gst_event_new (GST_EVENT_EOS)); } else { GST_BUFFER_SIZE (buf) = element->size; /* FIXME: put buf_element_t data in buffer */ memcpy (GST_BUFFER_DATA (buf), element->mem, element->size); element->free_buffer (element); } } GST_BUFFER_OFFSET_END (buf) = xine->input->get_current_pos (xine->input); return GST_DATA (buf); }
static void gst_mikmod_loop (GstElement * element) { GstMikMod *mikmod; GstBuffer *buffer_in; g_return_if_fail (element != NULL); g_return_if_fail (GST_IS_MIKMOD (element)); mikmod = GST_MIKMOD (element); srcpad = mikmod->srcpad; mikmod->Buffer = NULL; if (!mikmod->initialized) { while ((buffer_in = GST_BUFFER (gst_pad_pull (mikmod->sinkpad)))) { if (GST_IS_EVENT (buffer_in)) { GstEvent *event = GST_EVENT (buffer_in); if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) break; } else { if (mikmod->Buffer) { mikmod->Buffer = gst_buffer_append (mikmod->Buffer, buffer_in); } else { mikmod->Buffer = buffer_in; } } } if (!GST_PAD_CAPS (mikmod->srcpad)) { if (GST_PAD_LINK_SUCCESSFUL (gst_pad_renegotiate (mikmod->srcpad))) { GST_ELEMENT_ERROR (mikmod, CORE, NEGOTIATION, (NULL), (NULL)); return; } } MikMod_RegisterDriver (&drv_gst); MikMod_RegisterAllLoaders (); MikMod_Init (""); reader = GST_READER_new (mikmod); module = Player_LoadGeneric (reader, 64, 0); gst_buffer_unref (mikmod->Buffer); if (!Player_Active ()) Player_Start (module); mikmod->initialized = TRUE; } if (Player_Active ()) { timestamp = (module->sngtime / 1024.0) * GST_SECOND; drv_gst.Update (); } else { gst_element_set_eos (GST_ELEMENT (mikmod)); gst_pad_push (mikmod->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))); } }
/** * gst_event_new_custom: * @type: The type of the new event * @structure: (transfer full): the structure for the event. The event will * take ownership of the structure. * * Create a new custom-typed event. This can be used for anything not * handled by other event-specific functions to pass an event to another * element. * * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro, * assigning a free number and filling in the correct direction and * serialization flags. * * New custom events can also be created by subclassing the event type if * needed. * * Returns: (transfer full): the new custom event. */ GstEvent * gst_event_new_custom (GstEventType type, GstStructure * structure) { GstEvent *event; /* structure must not have a parent */ if (structure) g_return_val_if_fail (structure->parent_refcount == NULL, NULL); event = gst_event_new (type); if (structure) { gst_structure_set_parent_refcount (structure, &event->mini_object.refcount); event->structure = structure; } return event; }
/** * gst_event_new_eos: * * Create a new EOS event. The eos event can only travel downstream * synchronized with the buffer flow. Elements that receive the EOS * event on a pad can return #GST_FLOW_UNEXPECTED as a #GstFlowReturn * when data after the EOS event arrives. * * The EOS event will travel down to the sink elements in the pipeline * which will then post the #GST_MESSAGE_EOS on the bus after they have * finished playing any buffered data. * * When all sinks have posted an EOS message, an EOS message is * forwarded to the application. * * The EOS event itself will not cause any state transitions of the pipeline. * * Returns: (transfer full): the new EOS event. */ GstEvent * gst_event_new_eos (void) { return gst_event_new (GST_EVENT_EOS); }
/** * gst_event_new_flush_stop: * * Allocate a new flush stop event. The flush stop event can be sent * upstream and downstream and travels serialized with the dataflow. * It is typically sent after sending a FLUSH_START event to make the * pads accept data again. * * Elements can process this event synchronized with the dataflow since * the preceeding FLUSH_START event stopped the dataflow. * * This event is typically generated to complete a seek and to resume * dataflow. * * Returns: (transfer full): a new flush stop event. */ GstEvent * gst_event_new_flush_stop (void) { return gst_event_new (GST_EVENT_FLUSH_STOP); }
/** * gst_event_new_flush_start: * * Allocate a new flush start event. The flush start event can be sent * upstream and downstream and travels out-of-bounds with the dataflow. * * It marks pads as being flushing and will make them return * #GST_FLOW_WRONG_STATE when used for data flow with gst_pad_push(), * gst_pad_chain(), gst_pad_alloc_buffer(), gst_pad_get_range() and * gst_pad_pull_range(). Any event (except a #GST_EVENT_FLUSH_STOP) received * on a flushing pad will return %FALSE immediately. * * Elements should unlock any blocking functions and exit their streaming * functions as fast as possible when this event is received. * * This event is typically generated after a seek to flush out all queued data * in the pipeline so that the new media is played as soon as possible. * * Returns: (transfer full): a new flush start event. */ GstEvent * gst_event_new_flush_start (void) { return gst_event_new (GST_EVENT_FLUSH_START); }