GST_DEBUG_FUNCPTR_NAME (event));
}
+static gboolean
+event_wrap (GstPad * pad, GstObject * object, GstEvent * event)
+{
+ GstFlowReturn ret;
+
+ ret = GST_PAD_EVENTFULLFUNC (pad) (pad, object, event);
+ if (ret == GST_FLOW_OK)
+ return TRUE;
+ return FALSE;
+}
+
+/**
+ * gst_pad_set_event_full_function:
+ * @p: a #GstPad of either direction.
+ * @f: the #GstPadEventFullFunction to set.
+ *
+ * Calls gst_pad_set_event_full_function_full() with %NULL for the user_data and
+ * notify.
+ */
+/**
+ * gst_pad_set_event_full_function_full:
+ * @pad: a #GstPad of either direction.
+ * @event: the #GstPadEventFullFunction to set.
+ * @user_data: user_data passed to @notify
+ * @notify: notify called when @event will not be used anymore.
+ *
+ * Sets the given event handler for the pad.
+ */
+void
+gst_pad_set_event_full_function_full (GstPad * pad,
+ GstPadEventFullFunction event, gpointer user_data, GDestroyNotify notify)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+
+ if (pad->eventnotify)
+ pad->eventnotify (pad->eventdata);
+ GST_PAD_EVENTFULLFUNC (pad) = event;
+ GST_PAD_EVENTFUNC (pad) = event_wrap;
+ pad->eventdata = user_data;
+ pad->eventnotify = notify;
+
+ GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfullfunc for set to %s",
+ GST_DEBUG_FUNCPTR_NAME (event));
+}
+
/**
* gst_pad_set_query_function:
* @p: a #GstPad of either direction.
GstEventType event_type;
gboolean serialized, need_unlock = FALSE, sticky;
GstPadEventFunction eventfunc;
+ GstPadEventFullFunction eventfullfunc = NULL;
GstObject *parent;
GST_OBJECT_LOCK (pad);
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
- if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
+ eventfullfunc = GST_PAD_EVENTFULLFUNC (pad);
+ eventfunc = GST_PAD_EVENTFUNC (pad);
+ if (G_UNLIKELY (eventfunc == NULL && eventfullfunc == NULL))
goto no_function;
ACQUIRE_PARENT (pad, parent, no_parent);
if (sticky)
gst_event_ref (event);
- if (eventfunc (pad, parent, event)) {
+ if (eventfullfunc) {
+ ret = eventfullfunc (pad, parent, event);
+ } else if (eventfunc (pad, parent, event)) {
ret = GST_FLOW_OK;
} else {
/* something went wrong */
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstObject *parent,
GstEvent *event);
+/**
+ * GstPadEventFullFunction:
+ * @pad: the #GstPad to handle the event.
+ * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT
+ * flag is set, @parent is guaranteed to be not-%NULL and remain valid
+ * during the execution of this function.
+ * @event: (transfer full): the #GstEvent to handle.
+ *
+ * Function signature to handle an event for the pad.
+ *
+ * This variant is for specific elements that will take into account the
+ * last downstream flow return (from a pad push), in which case they can
+ * return it.
+ *
+ * Returns: %GST_FLOW_OK if the event was handled properly, or any other
+ * #GstFlowReturn dependent on downstream state.
+ */
+typedef GstFlowReturn (*GstPadEventFullFunction) (GstPad *pad, GstObject *parent,
+ GstEvent *event);
+
/* internal links */
/**
gpointer _gst_reserved[GST_PADDING];
struct {
GstFlowReturn last_flowret;
+ GstPadEventFullFunction eventfullfunc;
} abi;
} ABI;
};
*/
#define GST_PAD_EVENTFUNC(pad) (GST_PAD_CAST(pad)->eventfunc)
/**
+ * GST_PAD_EVENTFULLFUNC:
+ * @pad: a #GstPad
+ *
+ * Get the #GstPadEventFullFunction from the given @pad, which
+ * is the function that handles events on the pad. You can
+ * use this to set your own event handling function on a pad
+ * after you create it. If your element derives from a base
+ * class, use the base class's virtual functions instead.
+ */
+#define GST_PAD_EVENTFULLFUNC(pad) (GST_PAD_CAST(pad)->ABI.abi.eventfullfunc)
+/**
* GST_PAD_QUERYFUNC:
* @pad: a #GstPad
*
GstPadEventFunction event,
gpointer user_data,
GDestroyNotify notify);
+void gst_pad_set_event_full_function_full (GstPad *pad,
+ GstPadEventFullFunction event,
+ gpointer user_data,
+ GDestroyNotify notify);
#define gst_pad_set_activate_function(p,f) gst_pad_set_activate_function_full((p),(f),NULL,NULL)
#define gst_pad_set_activatemode_function(p,f) gst_pad_set_activatemode_function_full((p),(f),NULL,NULL)
#define gst_pad_set_chain_list_function(p,f) gst_pad_set_chain_list_function_full((p),(f),NULL,NULL)
#define gst_pad_set_getrange_function(p,f) gst_pad_set_getrange_function_full((p),(f),NULL,NULL)
#define gst_pad_set_event_function(p,f) gst_pad_set_event_function_full((p),(f),NULL,NULL)
+#define gst_pad_set_event_full_function(p,f) gst_pad_set_event_full_function_full((p),(f),NULL,NULL)
/* pad links */
void gst_pad_set_link_function_full (GstPad *pad,
return res;
}
-static gboolean
+static GstFlowReturn
gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstSingleQueue *sq;
GstMultiQueue *mq;
guint32 curid;
GstMultiQueueItem *item;
- gboolean res;
+ gboolean res = TRUE;
+ GstFlowReturn flowret = GST_FLOW_OK;
GstEventType type;
GstEvent *sref = NULL;
default:
break;
}
+
done:
- return res;
+ if (res == FALSE) {
+ if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
+ flowret = GST_FLOW_NOT_NEGOTIATED;
+ else
+ flowret = GST_FLOW_ERROR;
+ }
+ GST_DEBUG_OBJECT (mq, "SingleQueue %d : returning %s", sq->id,
+ gst_flow_get_name (flowret));
+ return flowret;
flushing:
{
if (sref)
gst_event_unref (sref);
gst_multi_queue_item_destroy (item);
- goto done;
+ return sq->srcresult;
}
was_eos:
{
- GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return FALSE");
+ GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return GST_FLOW_EOS");
gst_event_unref (event);
res = FALSE;
- goto done;
+ return GST_FLOW_EOS;
}
}
GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
gst_pad_set_activatemode_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));
- gst_pad_set_event_function (sq->sinkpad,
+ gst_pad_set_event_full_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
gst_pad_set_query_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));
static GstFlowReturn gst_queue_push_one (GstQueue * queue);
static void gst_queue_loop (GstPad * pad);
-static gboolean gst_queue_handle_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
+static GstFlowReturn gst_queue_handle_sink_event (GstPad * pad,
+ GstObject * parent, GstEvent * event);
static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent,
GstQuery * query);
gst_pad_set_chain_list_function (queue->sinkpad, gst_queue_chain_list);
gst_pad_set_activatemode_function (queue->sinkpad,
gst_queue_sink_activate_mode);
- gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event);
+ gst_pad_set_event_full_function (queue->sinkpad, gst_queue_handle_sink_event);
gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query);
GST_PAD_SET_PROXY_CAPS (queue->sinkpad);
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
}
}
-static gboolean
+static GstFlowReturn
gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
gboolean ret = TRUE;
}
break;
}
- return ret;
+ if (ret == FALSE) {
+ if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
+ return GST_FLOW_NOT_NEGOTIATED;
+ return GST_FLOW_ERROR;
+ }
+ return GST_FLOW_OK;
/* ERRORS */
out_eos:
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
GST_QUEUE_MUTEX_UNLOCK (queue);
gst_event_unref (event);
- return FALSE;
+ return GST_FLOW_EOS;
}
out_flow_error:
{
"refusing event, we have a downstream flow error: %s",
gst_flow_get_name (queue->srcresult));
gst_event_unref (event);
- return FALSE;
+ return queue->srcresult;
}
}
gst_pad_set_chain_function_full
gst_pad_set_chain_list_function_full
gst_pad_set_element_private
+ gst_pad_set_event_full_function_full
gst_pad_set_event_function_full
gst_pad_set_getrange_function_full
gst_pad_set_iterate_internal_links_function_full