1 /* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2004 Wim Taymans <wim@fluendo.com>
4 *
5 * gstelement.c: The base element, all elements derive from this
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
23 /**
24 * SECTION:gstelement
25 * @short_description: Abstract base class for all pipeline elements
26 * @see_also: #GstElementFactory, #GstPad
27 *
28 * GstElement is the abstract base class needed to construct an element that
29 * can be used in a GStreamer pipeline. Please refer to the plugin writers
30 * guide for more information on creating #GstElement subclasses.
31 *
32 * The name of a #GstElement can be get with gst_element_get_name() and set with
33 * gst_element_set_name(). For speed, GST_ELEMENT_NAME() can be used in the
34 * core when using the appropriate locking. Do not use this in plug-ins or
35 * applications in order to retain ABI compatibility.
36 *
37 * All elements have pads (of the type #GstPad). These pads link to pads on
38 * other elements. #GstBuffer flow between these linked pads.
39 * A #GstElement has a #GList of #GstPad structures for all their input (or sink)
40 * and output (or source) pads.
41 * Core and plug-in writers can add and remove pads with gst_element_add_pad()
42 * and gst_element_remove_pad().
43 *
44 * A pad of an element can be retrieved by name with gst_element_get_pad().
45 * An iterator of all pads can be retrieved with gst_element_iterate_pads().
46 *
47 * Elements can be linked through their pads.
48 * If the link is straightforward, use the gst_element_link()
49 * convenience function to link two elements, or gst_element_link_many()
50 * for more elements in a row.
51 * Use gst_element_link_filtered() to link two elements constrained by
52 * a specified set of #GstCaps.
53 * For finer control, use gst_element_link_pads() and
54 * gst_element_link_pads_filtered() to specify the pads to link on
55 * each element by name.
56 *
57 * Each element has a state (see #GstState). You can get and set the state
58 * of an element with gst_element_get_state() and gst_element_set_state().
59 * To get a string representation of a #GstState, use
60 * gst_element_state_get_name().
61 *
62 * You can get and set a #GstClock on an element using gst_element_get_clock()
63 * and gst_element_set_clock().
64 * Some elements can provide a clock for the pipeline if
65 * gst_element_provides_clock() returns %TRUE. With the
66 * gst_element_provide_clock() method one can retrieve the clock provided by
67 * such an element.
68 * Not all elements require a clock to operate correctly. If
69 * gst_element_requires_clock() returns %TRUE, a clock should be set on the
70 * element with gst_element_set_clock().
71 *
72 * Note that clock slection and distribution is normally handled by the
73 * toplevel #GstPipeline so the clock functions are only to be used in very
74 * specific situations.
75 *
76 * Last reviewed on 2006-03-12 (0.10.5)
77 */
79 #include "gst_private.h"
80 #include <glib.h>
81 #include <stdarg.h>
82 #include <gobject/gvaluecollector.h>
84 #include "gstelement.h"
85 #include "gstenumtypes.h"
86 #include "gstbus.h"
87 #include "gstmarshal.h"
88 #include "gsterror.h"
89 #include "gstevent.h"
90 #include "gstutils.h"
91 #include "gstinfo.h"
92 #include "gst-i18n-lib.h"
94 /* Element signals and args */
95 enum
96 {
97 PAD_ADDED,
98 PAD_REMOVED,
99 NO_MORE_PADS,
100 /* add more above */
101 LAST_SIGNAL
102 };
104 enum
105 {
106 ARG_0
107 /* FILL ME */
108 };
110 extern void __gst_element_details_clear (GstElementDetails * dp);
111 extern void __gst_element_details_copy (GstElementDetails * dest,
112 const GstElementDetails * src);
114 static void gst_element_class_init (GstElementClass * klass);
115 static void gst_element_init (GstElement * element);
116 static void gst_element_base_class_init (gpointer g_class);
117 static void gst_element_base_class_finalize (gpointer g_class);
119 static void gst_element_dispose (GObject * object);
120 static void gst_element_finalize (GObject * object);
122 static GstStateChangeReturn gst_element_change_state_func (GstElement * element,
123 GstStateChange transition);
124 static GstStateChangeReturn gst_element_get_state_func (GstElement * element,
125 GstState * state, GstState * pending, GstClockTime timeout);
126 static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
127 GstState state);
128 static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
130 static gboolean gst_element_default_send_event (GstElement * element,
131 GstEvent * event);
132 static gboolean gst_element_default_query (GstElement * element,
133 GstQuery * query);
135 static GstPadTemplate
136 * gst_element_class_get_request_pad_template (GstElementClass *
137 element_class, const gchar * name);
139 #ifndef GST_DISABLE_LOADSAVE
140 static xmlNodePtr gst_element_save_thyself (GstObject * object,
141 xmlNodePtr parent);
142 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
143 #endif
145 static GstObjectClass *parent_class = NULL;
146 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
148 GType
149 gst_element_get_type (void)
150 {
151 static GType gst_element_type = 0;
153 if (G_UNLIKELY (gst_element_type == 0)) {
154 static const GTypeInfo element_info = {
155 sizeof (GstElementClass),
156 gst_element_base_class_init,
157 gst_element_base_class_finalize,
158 (GClassInitFunc) gst_element_class_init,
159 NULL,
160 NULL,
161 sizeof (GstElement),
162 0,
163 (GInstanceInitFunc) gst_element_init,
164 NULL
165 };
167 gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
168 &element_info, G_TYPE_FLAG_ABSTRACT);
169 }
170 return gst_element_type;
171 }
173 static void
174 gst_element_class_init (GstElementClass * klass)
175 {
176 GObjectClass *gobject_class;
177 GstObjectClass *gstobject_class;
179 gobject_class = (GObjectClass *) klass;
180 gstobject_class = (GstObjectClass *) klass;
182 parent_class = g_type_class_peek_parent (klass);
184 /**
185 * GstElement::pad-added:
186 * @gstelement: the object which received the signal
187 * @new_pad: the pad that has been added
188 *
189 * a new #GstPad has been added to the element.
190 */
191 gst_element_signals[PAD_ADDED] =
192 g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
193 G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
194 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
195 /**
196 * GstElement::pad-removed:
197 * @gstelement: the object which received the signal
198 * @old_pad: the pad that has been removed
199 *
200 * a #GstPad has been removed from the element
201 */
202 gst_element_signals[PAD_REMOVED] =
203 g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
204 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
205 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
206 /**
207 * GstElement::no-more-pads:
208 * @gstelement: the object which received the signal
209 *
210 * This signals that the element will not generate more dynamic pads.
211 */
212 gst_element_signals[NO_MORE_PADS] =
213 g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
214 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
215 NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
217 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
218 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
220 #ifndef GST_DISABLE_LOADSAVE
221 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
222 gstobject_class->restore_thyself =
223 GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
224 #endif
226 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
227 klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
228 klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
229 klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
230 klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
231 klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
232 klass->numpadtemplates = 0;
234 klass->elementfactory = NULL;
235 }
237 static void
238 gst_element_base_class_init (gpointer g_class)
239 {
240 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
242 /* FIXME 0.11: Copy the element details and instead of clearing the
243 * pad template list copy the list and increase the refcount of
244 * the pad templates by one.
245 *
246 * This will make it possible to add pad templates and set element
247 * details in the class_init functions and is the real GObject way
248 * of doing things.
249 * See http://bugzilla.gnome.org/show_bug.cgi?id=491501
250 */
251 memset (&element_class->details, 0, sizeof (GstElementDetails));
252 element_class->padtemplates = NULL;
253 }
255 static void
256 gst_element_base_class_finalize (gpointer g_class)
257 {
258 GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
260 g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
261 g_list_free (klass->padtemplates);
262 __gst_element_details_clear (&klass->details);
263 }
265 static void
266 gst_element_init (GstElement * element)
267 {
268 GST_STATE (element) = GST_STATE_NULL;
269 GST_STATE_TARGET (element) = GST_STATE_NULL;
270 GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
271 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
272 GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
274 element->state_lock = g_new0 (GStaticRecMutex, 1);
275 g_static_rec_mutex_init (element->state_lock);
276 element->state_cond = g_cond_new ();
277 }
279 /**
280 * gst_element_default_error:
281 * @object: a #GObject that signalled the error.
282 * @orig: the #GstObject that initiated the error.
283 * @error: the GError.
284 * @debug: an additional debug information string, or %NULL.
285 *
286 * A default error signal callback to attach to an element.
287 * The user data passed to the g_signal_connect is ignored.
288 *
289 * The default handler will simply print the error string using g_print.
290 *
291 * MT safe.
292 */
293 void
294 gst_element_default_error (GObject * object, GstObject * source, GError * error,
295 gchar * debug)
296 {
297 gchar *name = gst_object_get_path_string (source);
299 g_print (_("ERROR: from element %s: %s\n"), name, error->message);
300 if (debug)
301 g_print (_("Additional debug info:\n%s\n"), debug);
303 g_free (name);
304 }
306 /**
307 * gst_element_release_request_pad:
308 * @element: a #GstElement to release the request pad of.
309 * @pad: the #GstPad to release.
310 *
311 * Makes the element free the previously requested pad as obtained
312 * with gst_element_get_request_pad().
313 *
314 * MT safe.
315 */
316 void
317 gst_element_release_request_pad (GstElement * element, GstPad * pad)
318 {
319 GstElementClass *oclass;
321 g_return_if_fail (GST_IS_ELEMENT (element));
322 g_return_if_fail (GST_IS_PAD (pad));
324 oclass = GST_ELEMENT_GET_CLASS (element);
326 /* if the element implements a custom release function we call that, else we
327 * simply remove the pad from the element */
328 if (oclass->release_pad)
329 (oclass->release_pad) (element, pad);
330 else
331 gst_element_remove_pad (element, pad);
332 }
334 /**
335 * gst_element_requires_clock:
336 * @element: a #GstElement to query
337 *
338 * Query if the element requires a clock.
339 *
340 * Returns: %TRUE if the element requires a clock
341 *
342 * MT safe.
343 */
344 gboolean
345 gst_element_requires_clock (GstElement * element)
346 {
347 gboolean result;
349 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
351 result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
353 return result;
354 }
356 /**
357 * gst_element_provides_clock:
358 * @element: a #GstElement to query
359 *
360 * Query if the element provides a clock. A #GstClock provided by an
361 * element can be used as the global #GstClock for the pipeline.
362 * An element that can provide a clock is only required to do so in the PAUSED
363 * state, this means when it is fully negotiated and has allocated the resources
364 * to operate the clock.
365 *
366 * Returns: %TRUE if the element provides a clock
367 *
368 * MT safe.
369 */
370 gboolean
371 gst_element_provides_clock (GstElement * element)
372 {
373 gboolean result;
375 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
377 result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
379 return result;
380 }
382 /**
383 * gst_element_provide_clock:
384 * @element: a #GstElement to query
385 *
386 * Get the clock provided by the given element.
387 * <note>An element is only required to provide a clock in the PAUSED
388 * state. Some elements can provide a clock in other states.</note>
389 *
390 * Returns: the GstClock provided by the element or %NULL
391 * if no clock could be provided. Unref after usage.
392 *
393 * MT safe.
394 */
395 GstClock *
396 gst_element_provide_clock (GstElement * element)
397 {
398 GstClock *result = NULL;
399 GstElementClass *oclass;
401 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
403 oclass = GST_ELEMENT_GET_CLASS (element);
405 if (oclass->provide_clock)
406 result = oclass->provide_clock (element);
408 return result;
409 }
411 /**
412 * gst_element_set_clock:
413 * @element: a #GstElement to set the clock for.
414 * @clock: the #GstClock to set for the element.
415 *
416 * Sets the clock for the element. This function increases the
417 * refcount on the clock. Any previously set clock on the object
418 * is unreffed.
419 *
420 * Returns: %TRUE if the element accepted the clock. An element can refuse a
421 * clock when it, for example, is not able to slave its internal clock to the
422 * @clock or when it requires a specific clock to operate.
423 *
424 * MT safe.
425 */
426 gboolean
427 gst_element_set_clock (GstElement * element, GstClock * clock)
428 {
429 GstElementClass *oclass;
430 gboolean res = TRUE;
431 GstClock **clock_p;
433 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
435 oclass = GST_ELEMENT_GET_CLASS (element);
437 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, "setting clock %p", clock);
439 if (oclass->set_clock)
440 res = oclass->set_clock (element, clock);
442 if (res) {
443 /* only update the clock pointer if the element accepted the clock */
444 GST_OBJECT_LOCK (element);
445 clock_p = &element->clock;
446 gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
447 GST_OBJECT_UNLOCK (element);
448 }
449 return res;
450 }
452 /**
453 * gst_element_get_clock:
454 * @element: a #GstElement to get the clock of.
455 *
456 * Gets the currently configured clock of the element. This is the clock as was
457 * last set with gst_element_set_clock().
458 *
459 * Returns: the #GstClock of the element. unref after usage.
460 *
461 * MT safe.
462 */
463 GstClock *
464 gst_element_get_clock (GstElement * element)
465 {
466 GstClock *result;
468 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
470 GST_OBJECT_LOCK (element);
471 if ((result = element->clock))
472 gst_object_ref (result);
473 GST_OBJECT_UNLOCK (element);
475 return result;
476 }
478 /**
479 * gst_element_set_base_time:
480 * @element: a #GstElement.
481 * @time: the base time to set.
482 *
483 * Set the base time of an element. See gst_element_get_base_time().
484 *
485 * MT safe.
486 */
487 void
488 gst_element_set_base_time (GstElement * element, GstClockTime time)
489 {
490 GstClockTime old;
492 g_return_if_fail (GST_IS_ELEMENT (element));
494 GST_OBJECT_LOCK (element);
495 old = element->base_time;
496 element->base_time = time;
497 GST_OBJECT_UNLOCK (element);
499 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element,
500 "set base_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT,
501 GST_TIME_ARGS (time), GST_TIME_ARGS (old));
502 }
504 /**
505 * gst_element_get_base_time:
506 * @element: a #GstElement.
507 *
508 * Returns the base time of the element. The base time is the
509 * absolute time of the clock when this element was last put to
510 * PLAYING. Subtracting the base time from the clock time gives
511 * the stream time of the element.
512 *
513 * Returns: the base time of the element.
514 *
515 * MT safe.
516 */
517 GstClockTime
518 gst_element_get_base_time (GstElement * element)
519 {
520 GstClockTime result;
522 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
524 GST_OBJECT_LOCK (element);
525 result = element->base_time;
526 GST_OBJECT_UNLOCK (element);
528 return result;
529 }
531 /**
532 * gst_element_is_indexable:
533 * @element: a #GstElement.
534 *
535 * Queries if the element can be indexed.
536 *
537 * Returns: TRUE if the element can be indexed.
538 *
539 * MT safe.
540 */
541 gboolean
542 gst_element_is_indexable (GstElement * element)
543 {
544 gboolean result;
546 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
548 result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
550 return result;
551 }
553 /**
554 * gst_element_set_index:
555 * @element: a #GstElement.
556 * @index: a #GstIndex.
557 *
558 * Set @index on the element. The refcount of the index
559 * will be increased, any previously set index is unreffed.
560 *
561 * MT safe.
562 */
563 void
564 gst_element_set_index (GstElement * element, GstIndex * index)
565 {
566 GstElementClass *oclass;
568 g_return_if_fail (GST_IS_ELEMENT (element));
569 g_return_if_fail (GST_IS_INDEX (index));
571 oclass = GST_ELEMENT_GET_CLASS (element);
573 if (oclass->set_index)
574 oclass->set_index (element, index);
575 }
577 /**
578 * gst_element_get_index:
579 * @element: a #GstElement.
580 *
581 * Gets the index from the element.
582 *
583 * Returns: a #GstIndex or %NULL when no index was set on the
584 * element. unref after usage.
585 *
586 * MT safe.
587 */
588 GstIndex *
589 gst_element_get_index (GstElement * element)
590 {
591 GstElementClass *oclass;
592 GstIndex *result = NULL;
594 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
596 oclass = GST_ELEMENT_GET_CLASS (element);
598 if (oclass->get_index)
599 result = oclass->get_index (element);
601 return result;
602 }
604 /**
605 * gst_element_add_pad:
606 * @element: a #GstElement to add the pad to.
607 * @pad: the #GstPad to add to the element.
608 *
609 * Adds a pad (link point) to @element. @pad's parent will be set to @element;
610 * see gst_object_set_parent() for refcounting information.
611 *
612 * Pads are not automatically activated so elements should perform the needed
613 * steps to activate the pad in case this pad is added in the PAUSED or PLAYING
614 * state. See gst_pad_set_active() for more information about activating pads.
615 *
616 * The pad and the element should be unlocked when calling this function.
617 *
618 * This function will emit the #GstElement::pad-added signal on the element.
619 *
620 * Returns: %TRUE if the pad could be added. This function can fail when
621 * a pad with the same name already existed or the pad already had another
622 * parent.
623 *
624 * MT safe.
625 */
626 gboolean
627 gst_element_add_pad (GstElement * element, GstPad * pad)
628 {
629 gchar *pad_name;
630 gboolean flushing;
632 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
633 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
635 /* locking pad to look at the name */
636 GST_OBJECT_LOCK (pad);
637 pad_name = g_strdup (GST_PAD_NAME (pad));
638 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
639 GST_STR_NULL (pad_name));
640 flushing = GST_PAD_IS_FLUSHING (pad);
641 GST_OBJECT_UNLOCK (pad);
643 /* then check to see if there's already a pad by that name here */
644 GST_OBJECT_LOCK (element);
645 if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name)))
646 goto name_exists;
648 /* try to set the pad's parent */
649 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad),
650 GST_OBJECT_CAST (element))))
651 goto had_parent;
653 /* check for flushing pads */
654 if (flushing && (GST_STATE (element) > GST_STATE_READY ||
655 GST_STATE_NEXT (element) == GST_STATE_PAUSED)) {
656 g_warning ("adding flushing pad '%s' to running element '%s'",
657 GST_STR_NULL (pad_name), GST_ELEMENT_NAME (element));
658 /* unset flushing */
659 GST_OBJECT_LOCK (pad);
660 GST_PAD_UNSET_FLUSHING (pad);
661 GST_OBJECT_UNLOCK (pad);
662 }
664 g_free (pad_name);
666 /* add it to the list */
667 switch (gst_pad_get_direction (pad)) {
668 case GST_PAD_SRC:
669 element->srcpads = g_list_prepend (element->srcpads, pad);
670 element->numsrcpads++;
671 break;
672 case GST_PAD_SINK:
673 element->sinkpads = g_list_prepend (element->sinkpads, pad);
674 element->numsinkpads++;
675 break;
676 default:
677 goto no_direction;
678 }
679 element->pads = g_list_prepend (element->pads, pad);
680 element->numpads++;
681 element->pads_cookie++;
682 GST_OBJECT_UNLOCK (element);
684 /* emit the PAD_ADDED signal */
685 g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad);
687 return TRUE;
689 /* ERROR cases */
690 name_exists:
691 {
692 g_critical ("Padname %s is not unique in element %s, not adding",
693 pad_name, GST_ELEMENT_NAME (element));
694 GST_OBJECT_UNLOCK (element);
695 g_free (pad_name);
696 return FALSE;
697 }
698 had_parent:
699 {
700 g_critical
701 ("Pad %s already has parent when trying to add to element %s",
702 pad_name, GST_ELEMENT_NAME (element));
703 GST_OBJECT_UNLOCK (element);
704 g_free (pad_name);
705 return FALSE;
706 }
707 no_direction:
708 {
709 GST_OBJECT_LOCK (pad);
710 g_critical
711 ("Trying to add pad %s to element %s, but it has no direction",
712 GST_OBJECT_NAME (pad), GST_ELEMENT_NAME (element));
713 GST_OBJECT_UNLOCK (pad);
714 GST_OBJECT_UNLOCK (element);
715 return FALSE;
716 }
717 }
719 /**
720 * gst_element_remove_pad:
721 * @element: a #GstElement to remove pad from.
722 * @pad: the #GstPad to remove from the element.
723 *
724 * Removes @pad from @element. @pad will be destroyed if it has not been
725 * referenced elsewhere using gst_object_unparent().
726 *
727 * This function is used by plugin developers and should not be used
728 * by applications. Pads that were dynamically requested from elements
729 * with gst_element_get_request_pad() should be released with the
730 * gst_element_release_request_pad() function instead.
731 *
732 * Pads are not automatically deactivated so elements should perform the needed
733 * steps to deactivate the pad in case this pad is removed in the PAUSED or
734 * PLAYING state. See gst_pad_set_active() for more information about
735 * deactivating pads.
736 *
737 * The pad and the element should be unlocked when calling this function.
738 *
739 * This function will emit the #GstElement::pad-removed signal on the element.
740 *
741 * Returns: %TRUE if the pad could be removed. Can return %FALSE if the
742 * pad does not belong to the provided element.
743 *
744 * MT safe.
745 */
746 gboolean
747 gst_element_remove_pad (GstElement * element, GstPad * pad)
748 {
749 GstPad *peer;
751 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
752 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
754 /* locking pad to look at the name and parent */
755 GST_OBJECT_LOCK (pad);
756 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'",
757 GST_STR_NULL (GST_PAD_NAME (pad)));
759 if (G_UNLIKELY (GST_PAD_PARENT (pad) != element))
760 goto not_our_pad;
761 GST_OBJECT_UNLOCK (pad);
763 /* unlink */
764 if ((peer = gst_pad_get_peer (pad))) {
765 /* window for MT unsafeness, someone else could unlink here
766 * and then we call unlink with wrong pads. The unlink
767 * function would catch this and safely return failed. */
768 if (GST_PAD_IS_SRC (pad))
769 gst_pad_unlink (pad, peer);
770 else
771 gst_pad_unlink (peer, pad);
773 gst_object_unref (peer);
774 }
776 GST_OBJECT_LOCK (element);
777 /* remove it from the list */
778 switch (gst_pad_get_direction (pad)) {
779 case GST_PAD_SRC:
780 element->srcpads = g_list_remove (element->srcpads, pad);
781 element->numsrcpads--;
782 break;
783 case GST_PAD_SINK:
784 element->sinkpads = g_list_remove (element->sinkpads, pad);
785 element->numsinkpads--;
786 break;
787 default:
788 g_critical ("Removing pad without direction???");
789 break;
790 }
791 element->pads = g_list_remove (element->pads, pad);
792 element->numpads--;
793 element->pads_cookie++;
794 GST_OBJECT_UNLOCK (element);
796 /* emit the PAD_REMOVED signal before unparenting and losing the last ref. */
797 g_signal_emit (element, gst_element_signals[PAD_REMOVED], 0, pad);
799 gst_object_unparent (GST_OBJECT_CAST (pad));
801 return TRUE;
803 /* ERRORS */
804 not_our_pad:
805 {
806 /* FIXME, locking order? */
807 GST_OBJECT_LOCK (element);
808 g_critical ("Padname %s:%s does not belong to element %s when removing",
809 GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
810 GST_OBJECT_UNLOCK (element);
811 GST_OBJECT_UNLOCK (pad);
812 return FALSE;
813 }
814 }
816 /**
817 * gst_element_no_more_pads:
818 * @element: a #GstElement
819 *
820 * Use this function to signal that the element does not expect any more pads
821 * to show up in the current pipeline. This function should be called whenever
822 * pads have been added by the element itself. Elements with #GST_PAD_SOMETIMES
823 * pad templates use this in combination with autopluggers to figure out that
824 * the element is done initializing its pads.
825 *
826 * This function emits the #GstElement::no-more-pads signal.
827 *
828 * MT safe.
829 */
830 void
831 gst_element_no_more_pads (GstElement * element)
832 {
833 g_return_if_fail (GST_IS_ELEMENT (element));
835 g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
836 }
838 static gint
839 pad_compare_name (GstPad * pad1, const gchar * name)
840 {
841 gint result;
843 GST_OBJECT_LOCK (pad1);
844 result = strcmp (GST_PAD_NAME (pad1), name);
845 GST_OBJECT_UNLOCK (pad1);
847 return result;
848 }
850 /**
851 * gst_element_get_static_pad:
852 * @element: a #GstElement to find a static pad of.
853 * @name: the name of the static #GstPad to retrieve.
854 *
855 * Retrieves a pad from @element by name. This version only retrieves
856 * already-existing (i.e. 'static') pads.
857 *
858 * Returns: the requested #GstPad if found, otherwise %NULL. unref after
859 * usage.
860 *
861 * MT safe.
862 */
863 GstPad *
864 gst_element_get_static_pad (GstElement * element, const gchar * name)
865 {
866 GList *find;
867 GstPad *result = NULL;
869 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
870 g_return_val_if_fail (name != NULL, NULL);
872 GST_OBJECT_LOCK (element);
873 find =
874 g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
875 if (find) {
876 result = GST_PAD_CAST (find->data);
877 gst_object_ref (result);
878 }
880 if (result == NULL) {
881 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
882 name, GST_ELEMENT_NAME (element));
883 } else {
884 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
885 GST_ELEMENT_NAME (element), name);
886 }
887 GST_OBJECT_UNLOCK (element);
889 return result;
890 }
892 static GstPad *
893 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
894 const gchar * name)
895 {
896 GstPad *newpad = NULL;
897 GstElementClass *oclass;
899 oclass = GST_ELEMENT_GET_CLASS (element);
901 if (oclass->request_new_pad)
902 newpad = (oclass->request_new_pad) (element, templ, name);
904 if (newpad)
905 gst_object_ref (newpad);
907 return newpad;
908 }
910 /**
911 * gst_element_get_request_pad:
912 * @element: a #GstElement to find a request pad of.
913 * @name: the name of the request #GstPad to retrieve.
914 *
915 * Retrieves a pad from the element by name. This version only retrieves
916 * request pads. The pad should be released with
917 * gst_element_release_request_pad().
918 *
919 * Returns: requested #GstPad if found, otherwise %NULL. Release after usage.
920 */
921 GstPad *
922 gst_element_get_request_pad (GstElement * element, const gchar * name)
923 {
924 GstPadTemplate *templ = NULL;
925 GstPad *pad;
926 const gchar *req_name = NULL;
927 gboolean templ_found = FALSE;
928 GList *list;
929 gint n;
930 const gchar *data;
931 gchar *str, *endptr = NULL;
932 GstElementClass *class;
934 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
935 g_return_val_if_fail (name != NULL, NULL);
937 class = GST_ELEMENT_GET_CLASS (element);
939 /* if the name contains a %, we assume it's the complete template name. Get
940 * the template and try to get a pad */
941 if (strstr (name, "%")) {
942 templ = gst_element_class_get_request_pad_template (class, name);
943 req_name = NULL;
944 if (templ)
945 templ_found = TRUE;
946 } else {
947 /* there is no % in the name, try to find a matching template */
948 list = gst_element_class_get_pad_template_list (class);
949 while (!templ_found && list) {
950 templ = (GstPadTemplate *) list->data;
951 if (templ->presence == GST_PAD_REQUEST) {
952 GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
953 templ->name_template);
954 /* see if we find an exact match */
955 if (strcmp (name, templ->name_template) == 0) {
956 templ_found = TRUE;
957 req_name = name;
958 break;
959 }
960 /* Because of sanity checks in gst_pad_template_new(), we know that %s
961 and %d, occurring at the end of the name_template, are the only
962 possibilities. */
963 else if ((str = strchr (templ->name_template, '%'))
964 && strncmp (templ->name_template, name,
965 str - templ->name_template) == 0
966 && strlen (name) > str - templ->name_template) {
967 data = name + (str - templ->name_template);
968 if (*(str + 1) == 'd') {
969 /* it's an int */
970 n = (gint) strtol (data, &endptr, 10);
971 if (endptr && *endptr == '\0') {
972 templ_found = TRUE;
973 req_name = name;
974 break;
975 }
976 } else {
977 /* it's a string */
978 templ_found = TRUE;
979 req_name = name;
980 break;
981 }
982 }
983 }
984 list = list->next;
985 }
986 }
988 if (!templ_found)
989 return NULL;
991 pad = gst_element_request_pad (element, templ, req_name);
993 return pad;
994 }
996 /**
997 * gst_element_get_pad:
998 * @element: a #GstElement.
999 * @name: the name of the pad to retrieve.
1000 *
1001 * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
1002 * first, then gst_element_get_request_pad().
1003 *
1004 * Deprecated: This function is deprecated as it's unclear if the reference
1005 * to the result pad should be released with gst_object_unref() in case of a static pad
1006 * or gst_element_release_request_pad() in case of a request pad.
1007 * Use gst_element_get_static_pad() or gst_element_get_request_pad() instead.
1008 *
1009 * Returns: the #GstPad if found, otherwise %NULL. Unref or Release after usage,
1010 * depending on the type of the pad.
1011 */
1012 #ifndef GST_REMOVE_DEPRECATED
1013 GstPad *
1014 gst_element_get_pad (GstElement * element, const gchar * name)
1015 {
1016 GstPad *pad;
1018 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1019 g_return_val_if_fail (name != NULL, NULL);
1021 pad = gst_element_get_static_pad (element, name);
1022 if (!pad)
1023 pad = gst_element_get_request_pad (element, name);
1025 return pad;
1026 }
1027 #endif /* GST_REMOVE_DEPRECATED */
1029 static GstIteratorItem
1030 iterate_pad (GstIterator * it, GstPad * pad)
1031 {
1032 gst_object_ref (pad);
1033 return GST_ITERATOR_ITEM_PASS;
1034 }
1036 static GstIterator *
1037 gst_element_iterate_pad_list (GstElement * element, GList ** padlist)
1038 {
1039 GstIterator *result;
1041 GST_OBJECT_LOCK (element);
1042 gst_object_ref (element);
1043 result = gst_iterator_new_list (GST_TYPE_PAD,
1044 GST_OBJECT_GET_LOCK (element),
1045 &element->pads_cookie,
1046 padlist,
1047 element,
1048 (GstIteratorItemFunction) iterate_pad,
1049 (GstIteratorDisposeFunction) gst_object_unref);
1050 GST_OBJECT_UNLOCK (element);
1052 return result;
1053 }
1055 /**
1056 * gst_element_iterate_pads:
1057 * @element: a #GstElement to iterate pads of.
1058 *
1059 * Retrieves an iterattor of @element's pads. The iterator should
1060 * be freed after usage.
1061 *
1062 * Returns: the #GstIterator of #GstPad. Unref each pad after use.
1063 *
1064 * MT safe.
1065 */
1066 GstIterator *
1067 gst_element_iterate_pads (GstElement * element)
1068 {
1069 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1071 return gst_element_iterate_pad_list (element, &element->pads);
1072 }
1074 /**
1075 * gst_element_iterate_src_pads:
1076 * @element: a #GstElement.
1077 *
1078 * Retrieves an iterator of @element's source pads.
1079 *
1080 * Returns: the #GstIterator of #GstPad. Unref each pad after use.
1081 *
1082 * MT safe.
1083 */
1084 GstIterator *
1085 gst_element_iterate_src_pads (GstElement * element)
1086 {
1087 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1089 return gst_element_iterate_pad_list (element, &element->srcpads);
1090 }
1092 /**
1093 * gst_element_iterate_sink_pads:
1094 * @element: a #GstElement.
1095 *
1096 * Retrieves an iterator of @element's sink pads.
1097 *
1098 * Returns: the #GstIterator of #GstPad. Unref each pad after use.
1099 *
1100 * MT safe.
1101 */
1102 GstIterator *
1103 gst_element_iterate_sink_pads (GstElement * element)
1104 {
1105 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1107 return gst_element_iterate_pad_list (element, &element->sinkpads);
1108 }
1110 /**
1111 * gst_element_class_add_pad_template:
1112 * @klass: the #GstElementClass to add the pad template to.
1113 * @templ: a #GstPadTemplate to add to the element class.
1114 *
1115 * Adds a padtemplate to an element class. This is mainly used in the _base_init
1116 * functions of classes.
1117 */
1118 void
1119 gst_element_class_add_pad_template (GstElementClass * klass,
1120 GstPadTemplate * templ)
1121 {
1122 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1123 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1125 /* FIXME 0.11: allow replacing the pad templates by
1126 * calling this with the same name as an already existing pad
1127 * template. For this we _must_ _not_ ref the added pad template
1128 * a second time and _must_ document that this function takes
1129 * ownership of the pad template. Otherwise we will leak pad templates
1130 * or the caller unref's the pad template and it disappears */
1131 /* avoid registering pad templates with the same name */
1132 g_return_if_fail (gst_element_class_get_pad_template (klass,
1133 templ->name_template) == NULL);
1135 klass->padtemplates = g_list_append (klass->padtemplates,
1136 gst_object_ref (templ));
1137 klass->numpadtemplates++;
1138 }
1140 /**
1141 * gst_element_class_set_details:
1142 * @klass: class to set details for
1143 * @details: details to set
1144 *
1145 * Sets the detailed information for a #GstElementClass.
1146 * <note>This function is for use in _base_init functions only.</note>
1147 *
1148 * The @details are copied.
1149 */
1150 void
1151 gst_element_class_set_details (GstElementClass * klass,
1152 const GstElementDetails * details)
1153 {
1154 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1155 g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
1157 __gst_element_details_copy (&klass->details, details);
1158 }
1160 /**
1161 * gst_element_class_set_details_simple:
1162 * @klass: class to set details for
1163 * @longname: The long English name of the element. E.g. "File Sink"
1164 * @classification: String describing the type of element, as an unordered list
1165 * separated with slashes ('/'). See draft-klass.txt of the design docs
1166 * for more details and common types. E.g: "Sink/File"
1167 * @description: Sentence describing the purpose of the element.
1168 * E.g: "Write stream to a file"
1169 * @author: Name and contact details of the author(s). Use \n to separate
1170 * multiple author details. E.g: "Joe Bloggs <joe.blogs at foo.com>"
1171 *
1172 * Sets the detailed information for a #GstElementClass. Simpler version of
1173 * gst_element_class_set_details() that generates less linker overhead.
1174 * <note>This function is for use in _base_init functions only.</note>
1175 *
1176 * The detail parameter strings are copied into the #GstElementDetails for
1177 * the element class.
1178 *
1179 * Since: 0.10.14
1180 */
1181 void
1182 gst_element_class_set_details_simple (GstElementClass * klass,
1183 const gchar * longname, const gchar * classification,
1184 const gchar * description, const gchar * author)
1185 {
1186 const GstElementDetails details =
1187 GST_ELEMENT_DETAILS ((gchar *) longname, (gchar *) classification,
1188 (gchar *) description, (gchar *) author);
1190 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1192 __gst_element_details_copy (&klass->details, &details);
1193 }
1195 /**
1196 * gst_element_class_get_pad_template_list:
1197 * @element_class: a #GstElementClass to get pad templates of.
1198 *
1199 * Retrieves a list of the pad templates associated with @element_class. The
1200 * list must not be modified by the calling code.
1201 * <note>If you use this function in the #GInstanceInitFunc of an object class
1202 * that has subclasses, make sure to pass the g_class parameter of the
1203 * #GInstanceInitFunc here.</note>
1204 *
1205 * Returns: the #GList of padtemplates.
1206 */
1207 GList *
1208 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1209 {
1210 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1212 return element_class->padtemplates;
1213 }
1215 /**
1216 * gst_element_class_get_pad_template:
1217 * @element_class: a #GstElementClass to get the pad template of.
1218 * @name: the name of the #GstPadTemplate to get.
1219 *
1220 * Retrieves a padtemplate from @element_class with the given name.
1221 * <note>If you use this function in the #GInstanceInitFunc of an object class
1222 * that has subclasses, make sure to pass the g_class parameter of the
1223 * #GInstanceInitFunc here.</note>
1224 *
1225 * Returns: the #GstPadTemplate with the given name, or %NULL if none was found.
1226 * No unreferencing is necessary.
1227 */
1228 GstPadTemplate *
1229 gst_element_class_get_pad_template (GstElementClass * element_class,
1230 const gchar * name)
1231 {
1232 GList *padlist;
1234 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1235 g_return_val_if_fail (name != NULL, NULL);
1237 padlist = gst_element_class_get_pad_template_list (element_class);
1239 while (padlist) {
1240 GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1242 if (strcmp (padtempl->name_template, name) == 0)
1243 return padtempl;
1245 padlist = g_list_next (padlist);
1246 }
1248 return NULL;
1249 }
1251 static GstPadTemplate *
1252 gst_element_class_get_request_pad_template (GstElementClass * element_class,
1253 const gchar * name)
1254 {
1255 GstPadTemplate *tmpl;
1257 tmpl = gst_element_class_get_pad_template (element_class, name);
1258 if (tmpl != NULL && tmpl->presence == GST_PAD_REQUEST)
1259 return tmpl;
1261 return NULL;
1262 }
1264 /* get a random pad on element of the given direction.
1265 * The pad is random in a sense that it is the first pad that is (optionaly) linked.
1266 */
1267 static GstPad *
1268 gst_element_get_random_pad (GstElement * element, gboolean need_linked,
1269 GstPadDirection dir)
1270 {
1271 GstPad *result = NULL;
1272 GList *pads;
1274 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
1276 switch (dir) {
1277 case GST_PAD_SRC:
1278 GST_OBJECT_LOCK (element);
1279 pads = element->srcpads;
1280 break;
1281 case GST_PAD_SINK:
1282 GST_OBJECT_LOCK (element);
1283 pads = element->sinkpads;
1284 break;
1285 default:
1286 goto wrong_direction;
1287 }
1288 for (; pads; pads = g_list_next (pads)) {
1289 GstPad *pad = GST_PAD_CAST (pads->data);
1291 GST_OBJECT_LOCK (pad);
1292 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
1293 GST_DEBUG_PAD_NAME (pad));
1295 if (need_linked && !GST_PAD_IS_LINKED (pad)) {
1296 /* if we require a linked pad, and it is not linked, continue the
1297 * search */
1298 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
1299 GST_DEBUG_PAD_NAME (pad));
1300 GST_OBJECT_UNLOCK (pad);
1301 continue;
1302 } else {
1303 /* found a pad, stop search */
1304 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
1305 GST_DEBUG_PAD_NAME (pad));
1306 GST_OBJECT_UNLOCK (pad);
1307 result = pad;
1308 break;
1309 }
1310 }
1311 if (result)
1312 gst_object_ref (result);
1314 GST_OBJECT_UNLOCK (element);
1316 return result;
1318 /* ERROR handling */
1319 wrong_direction:
1320 {
1321 g_warning ("unknown pad direction %d", dir);
1322 return NULL;
1323 }
1324 }
1326 static gboolean
1327 gst_element_default_send_event (GstElement * element, GstEvent * event)
1328 {
1329 gboolean result = FALSE;
1330 GstPad *pad;
1332 pad = GST_EVENT_IS_DOWNSTREAM (event) ?
1333 gst_element_get_random_pad (element, TRUE, GST_PAD_SRC) :
1334 gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1336 if (pad) {
1337 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1338 "pushing %s event to random %s pad %s:%s",
1339 GST_EVENT_TYPE_NAME (event),
1340 (GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"),
1341 GST_DEBUG_PAD_NAME (pad));
1343 result = gst_pad_push_event (pad, event);
1344 gst_object_unref (pad);
1345 } else {
1346 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s",
1347 GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
1348 }
1349 return result;
1350 }
1352 /**
1353 * gst_element_send_event:
1354 * @element: a #GstElement to send the event to.
1355 * @event: the #GstEvent to send to the element.
1356 *
1357 * Sends an event to an element. If the element doesn't implement an
1358 * event handler, the event will be pushed on a random linked sink pad for
1359 * upstream events or a random linked source pad for downstream events.
1360 *
1361 * This function takes owership of the provided event so you should
1362 * gst_event_ref() it if you want to reuse the event after this call.
1363 *
1364 * Returns: %TRUE if the event was handled.
1365 *
1366 * MT safe.
1367 */
1368 gboolean
1369 gst_element_send_event (GstElement * element, GstEvent * event)
1370 {
1371 GstElementClass *oclass;
1372 gboolean result = FALSE;
1374 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1375 g_return_val_if_fail (event != NULL, FALSE);
1377 oclass = GST_ELEMENT_GET_CLASS (element);
1379 GST_STATE_LOCK (element);
1380 if (oclass->send_event) {
1381 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
1382 GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
1383 result = oclass->send_event (element, event);
1384 } else {
1385 result = gst_element_default_send_event (element, event);
1386 }
1387 GST_STATE_UNLOCK (element);
1389 return result;
1390 }
1392 /**
1393 * gst_element_seek:
1394 * @element: a #GstElement to send the event to.
1395 * @rate: The new playback rate
1396 * @format: The format of the seek values
1397 * @flags: The optional seek flags.
1398 * @cur_type: The type and flags for the new current position
1399 * @cur: The value of the new current position
1400 * @stop_type: The type and flags for the new stop position
1401 * @stop: The value of the new stop position
1402 *
1403 * Sends a seek event to an element. See gst_event_new_seek() for the details of
1404 * the parameters. The seek event is sent to the element using
1405 * gst_element_send_event().
1406 *
1407 * Returns: %TRUE if the event was handled.
1408 *
1409 * MT safe.
1410 */
1411 gboolean
1412 gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
1413 GstSeekFlags flags, GstSeekType cur_type, gint64 cur,
1414 GstSeekType stop_type, gint64 stop)
1415 {
1416 GstEvent *event;
1417 gboolean result;
1419 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1421 event =
1422 gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop);
1423 result = gst_element_send_event (element, event);
1425 return result;
1426 }
1428 /**
1429 * gst_element_get_query_types:
1430 * @element: a #GstElement to query
1431 *
1432 * Get an array of query types from the element.
1433 * If the element doesn't implement a query types function,
1434 * the query will be forwarded to the peer of a random linked sink pad.
1435 *
1436 * Returns: An array of #GstQueryType elements that should not
1437 * be freed or modified.
1438 *
1439 * MT safe.
1440 */
1441 const GstQueryType *
1442 gst_element_get_query_types (GstElement * element)
1443 {
1444 GstElementClass *oclass;
1445 const GstQueryType *result = NULL;
1447 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1449 oclass = GST_ELEMENT_GET_CLASS (element);
1451 if (oclass->get_query_types) {
1452 result = oclass->get_query_types (element);
1453 } else {
1454 GstPad *pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1456 if (pad) {
1457 GstPad *peer = gst_pad_get_peer (pad);
1459 if (peer) {
1460 result = gst_pad_get_query_types (peer);
1462 gst_object_unref (peer);
1463 }
1464 gst_object_unref (pad);
1465 }
1466 }
1467 return result;
1468 }
1470 static gboolean
1471 gst_element_default_query (GstElement * element, GstQuery * query)
1472 {
1473 gboolean result = FALSE;
1474 GstPad *pad;
1476 pad = gst_element_get_random_pad (element, FALSE, GST_PAD_SRC);
1477 if (pad) {
1478 result = gst_pad_query (pad, query);
1480 gst_object_unref (pad);
1481 } else {
1482 pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1483 if (pad) {
1484 GstPad *peer = gst_pad_get_peer (pad);
1486 if (peer) {
1487 result = gst_pad_query (peer, query);
1489 gst_object_unref (peer);
1490 }
1491 gst_object_unref (pad);
1492 }
1493 }
1494 return result;
1495 }
1497 /**
1498 * gst_element_query:
1499 * @element: a #GstElement to perform the query on.
1500 * @query: the #GstQuery.
1501 *
1502 * Performs a query on the given element.
1503 *
1504 * For elements that don't implement a query handler, this function
1505 * forwards the query to a random srcpad or to the peer of a
1506 * random linked sinkpad of this element.
1507 *
1508 * Returns: TRUE if the query could be performed.
1509 *
1510 * MT safe.
1511 */
1512 gboolean
1513 gst_element_query (GstElement * element, GstQuery * query)
1514 {
1515 GstElementClass *oclass;
1516 gboolean result = FALSE;
1518 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1519 g_return_val_if_fail (query != NULL, FALSE);
1521 oclass = GST_ELEMENT_GET_CLASS (element);
1523 if (oclass->query) {
1524 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
1525 GST_ELEMENT_NAME (element));
1526 result = oclass->query (element, query);
1527 } else {
1528 result = gst_element_default_query (element, query);
1529 }
1530 return result;
1531 }
1533 /**
1534 * gst_element_post_message:
1535 * @element: a #GstElement posting the message
1536 * @message: a #GstMessage to post
1537 *
1538 * Post a message on the element's #GstBus. This function takes ownership of the
1539 * message; if you want to access the message after this call, you should add an
1540 * additional reference before calling.
1541 *
1542 * Returns: %TRUE if the message was successfully posted. The function returns
1543 * %FALSE if the element did not have a bus.
1544 *
1545 * MT safe.
1546 */
1547 gboolean
1548 gst_element_post_message (GstElement * element, GstMessage * message)
1549 {
1550 GstBus *bus;
1551 gboolean result = FALSE;
1553 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1554 g_return_val_if_fail (message != NULL, FALSE);
1556 GST_OBJECT_LOCK (element);
1557 bus = element->bus;
1559 if (G_UNLIKELY (bus == NULL))
1560 goto no_bus;
1562 gst_object_ref (bus);
1563 GST_OBJECT_UNLOCK (element);
1565 /* we release the element lock when posting the message so that any
1566 * (synchronous) message handlers can operate on the element */
1567 result = gst_bus_post (bus, message);
1568 gst_object_unref (bus);
1570 return result;
1572 /* ERRORS */
1573 no_bus:
1574 {
1575 GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element,
1576 "not posting message %p: no bus", message);
1577 GST_OBJECT_UNLOCK (element);
1578 gst_message_unref (message);
1579 return FALSE;
1580 }
1581 }
1583 /**
1584 * _gst_element_error_printf:
1585 * @format: the printf-like format to use, or %NULL
1586 *
1587 * This function is only used internally by the gst_element_error() macro.
1588 *
1589 * Returns: a newly allocated string, or %NULL if the format was %NULL or ""
1590 *
1591 * MT safe.
1592 */
1593 gchar *
1594 _gst_element_error_printf (const gchar * format, ...)
1595 {
1596 va_list args;
1597 gchar *buffer;
1599 if (format == NULL)
1600 return NULL;
1601 if (format[0] == 0)
1602 return NULL;
1604 va_start (args, format);
1605 buffer = g_strdup_vprintf (format, args);
1606 va_end (args);
1607 return buffer;
1608 }
1610 /**
1611 * gst_element_message_full:
1612 * @element: a #GstElement to send message from
1613 * @type: the #GstMessageType
1614 * @domain: the GStreamer GError domain this message belongs to
1615 * @code: the GError code belonging to the domain
1616 * @text: an allocated text string to be used as a replacement for the
1617 * default message connected to code, or %NULL
1618 * @debug: an allocated debug message to be used as a replacement for the
1619 * default debugging information, or %NULL
1620 * @file: the source code file where the error was generated
1621 * @function: the source code function where the error was generated
1622 * @line: the source code line where the error was generated
1623 *
1624 * Post an error, warning or info message on the bus from inside an element.
1625 *
1626 * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or
1627 * #GST_MESSAGE_INFO.
1628 *
1629 * MT safe.
1630 */
1631 void gst_element_message_full
1632 (GstElement * element, GstMessageType type,
1633 GQuark domain, gint code, gchar * text,
1634 gchar * debug, const gchar * file, const gchar * function, gint line)
1635 {
1636 GError *gerror = NULL;
1637 gchar *name;
1638 gchar *sent_text;
1639 gchar *sent_debug;
1640 gboolean has_debug = TRUE;
1641 GstMessage *message = NULL;
1643 /* checks */
1644 GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element, "start");
1645 g_return_if_fail (GST_IS_ELEMENT (element));
1646 g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
1647 (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO));
1649 /* check if we send the given text or the default error text */
1650 if ((text == NULL) || (text[0] == 0)) {
1651 /* text could have come from g_strdup_printf (""); */
1652 g_free (text);
1653 sent_text = gst_error_get_message (domain, code);
1654 } else
1655 sent_text = text;
1657 /* construct a sent_debug with extra information from source */
1658 if ((debug == NULL) || (debug[0] == 0)) {
1659 /* debug could have come from g_strdup_printf (""); */
1660 has_debug = FALSE;
1661 }
1663 name = gst_object_get_path_string (GST_OBJECT_CAST (element));
1664 if (has_debug)
1665 sent_debug = g_strdup_printf ("%s(%d): %s (): %s:\n%s",
1666 file, line, function, name, debug);
1667 else
1668 sent_debug = g_strdup_printf ("%s(%d): %s (): %s",
1669 file, line, function, name);
1670 g_free (name);
1671 g_free (debug);
1673 /* create gerror and post message */
1674 GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
1675 sent_text);
1676 gerror = g_error_new_literal (domain, code, sent_text);
1678 switch (type) {
1679 case GST_MESSAGE_ERROR:
1680 message =
1681 gst_message_new_error (GST_OBJECT_CAST (element), gerror, sent_debug);
1682 break;
1683 case GST_MESSAGE_WARNING:
1684 message = gst_message_new_warning (GST_OBJECT_CAST (element), gerror,
1685 sent_debug);
1686 break;
1687 case GST_MESSAGE_INFO:
1688 message = gst_message_new_info (GST_OBJECT_CAST (element), gerror,
1689 sent_debug);
1690 break;
1691 default:
1692 g_assert_not_reached ();
1693 break;
1694 }
1695 gst_element_post_message (element, message);
1697 GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted %s message: %s",
1698 (type == GST_MESSAGE_ERROR ? "error" : "warning"), sent_text);
1700 /* cleanup */
1701 g_error_free (gerror);
1702 g_free (sent_debug);
1703 g_free (sent_text);
1704 }
1706 /**
1707 * gst_element_is_locked_state:
1708 * @element: a #GstElement.
1709 *
1710 * Checks if the state of an element is locked.
1711 * If the state of an element is locked, state changes of the parent don't
1712 * affect the element.
1713 * This way you can leave currently unused elements inside bins. Just lock their
1714 * state before changing the state from #GST_STATE_NULL.
1715 *
1716 * MT safe.
1717 *
1718 * Returns: TRUE, if the element's state is locked.
1719 */
1720 gboolean
1721 gst_element_is_locked_state (GstElement * element)
1722 {
1723 gboolean result;
1725 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1727 GST_OBJECT_LOCK (element);
1728 result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1729 GST_OBJECT_UNLOCK (element);
1731 return result;
1732 }
1734 /**
1735 * gst_element_set_locked_state:
1736 * @element: a #GstElement
1737 * @locked_state: TRUE to lock the element's state
1738 *
1739 * Locks the state of an element, so state changes of the parent don't affect
1740 * this element anymore.
1741 *
1742 * MT safe.
1743 *
1744 * Returns: TRUE if the state was changed, FALSE if bad parameters were given
1745 * or the elements state-locking needed no change.
1746 */
1747 gboolean
1748 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
1749 {
1750 gboolean old;
1752 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1754 GST_OBJECT_LOCK (element);
1755 old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1757 if (G_UNLIKELY (old == locked_state))
1758 goto was_ok;
1760 if (locked_state) {
1761 GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
1762 GST_ELEMENT_NAME (element));
1763 GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
1764 } else {
1765 GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
1766 GST_ELEMENT_NAME (element));
1767 GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
1768 }
1769 GST_OBJECT_UNLOCK (element);
1771 return TRUE;
1773 was_ok:
1774 {
1775 GST_CAT_DEBUG (GST_CAT_STATES, "elements %s was in locked state %d",
1776 GST_ELEMENT_NAME (element), old);
1777 GST_OBJECT_UNLOCK (element);
1779 return FALSE;
1780 }
1781 }
1783 /**
1784 * gst_element_sync_state_with_parent:
1785 * @element: a #GstElement.
1786 *
1787 * Tries to change the state of the element to the same as its parent.
1788 * If this function returns FALSE, the state of element is undefined.
1789 *
1790 * Returns: TRUE, if the element's state could be synced to the parent's state.
1791 *
1792 * MT safe.
1793 */
1794 gboolean
1795 gst_element_sync_state_with_parent (GstElement * element)
1796 {
1797 GstElement *parent;
1798 GstState target;
1799 GstStateChangeReturn ret;
1801 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1803 if ((parent = GST_ELEMENT_CAST (gst_element_get_parent (element)))) {
1804 GstState parent_current, parent_pending;
1806 GST_OBJECT_LOCK (parent);
1807 parent_current = GST_STATE (parent);
1808 parent_pending = GST_STATE_PENDING (parent);
1809 GST_OBJECT_UNLOCK (parent);
1811 /* set to pending if there is one, else we set it to the current state of
1812 * the parent */
1813 if (parent_pending != GST_STATE_VOID_PENDING)
1814 target = parent_pending;
1815 else
1816 target = parent_current;
1818 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1819 "syncing state (%s) to parent %s %s (%s, %s)",
1820 gst_element_state_get_name (GST_STATE (element)),
1821 GST_ELEMENT_NAME (parent), gst_element_state_get_name (target),
1822 gst_element_state_get_name (parent_current),
1823 gst_element_state_get_name (parent_pending));
1825 ret = gst_element_set_state (element, target);
1826 if (ret == GST_STATE_CHANGE_FAILURE)
1827 goto failed;
1829 gst_object_unref (parent);
1831 return TRUE;
1832 } else {
1833 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "element has no parent");
1834 }
1835 return FALSE;
1837 /* ERROR */
1838 failed:
1839 {
1840 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1841 "syncing state failed (%s)",
1842 gst_element_state_change_return_get_name (ret));
1843 gst_object_unref (parent);
1844 return FALSE;
1845 }
1846 }
1848 /* MT safe */
1849 static GstStateChangeReturn
1850 gst_element_get_state_func (GstElement * element,
1851 GstState * state, GstState * pending, GstClockTime timeout)
1852 {
1853 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
1854 GstState old_pending;
1856 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "getting state, timeout %"
1857 GST_TIME_FORMAT, GST_TIME_ARGS (timeout));
1859 GST_OBJECT_LOCK (element);
1860 ret = GST_STATE_RETURN (element);
1861 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "RETURN is %s",
1862 gst_element_state_change_return_get_name (ret));
1864 /* we got an error, report immediatly */
1865 if (ret == GST_STATE_CHANGE_FAILURE)
1866 goto done;
1868 /* we got no_preroll, report immediatly */
1869 if (ret == GST_STATE_CHANGE_NO_PREROLL)
1870 goto done;
1872 /* no need to wait async if we are not async */
1873 if (ret != GST_STATE_CHANGE_ASYNC)
1874 goto done;
1876 old_pending = GST_STATE_PENDING (element);
1877 if (old_pending != GST_STATE_VOID_PENDING) {
1878 GTimeVal *timeval, abstimeout;
1879 guint32 cookie;
1881 if (timeout != GST_CLOCK_TIME_NONE) {
1882 glong add = timeout / 1000;
1884 if (add == 0)
1885 goto done;
1887 /* make timeout absolute */
1888 g_get_current_time (&abstimeout);
1889 g_time_val_add (&abstimeout, add);
1890 timeval = &abstimeout;
1891 } else {
1892 timeval = NULL;
1893 }
1894 /* get cookie to dected state change during waiting */
1895 cookie = element->state_cookie;
1897 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1898 "waiting for element to commit state");
1900 /* we have a pending state change, wait for it to complete */
1901 if (!GST_STATE_TIMED_WAIT (element, timeval)) {
1902 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
1903 /* timeout triggered */
1904 ret = GST_STATE_CHANGE_ASYNC;
1905 } else {
1906 if (cookie != element->state_cookie)
1907 goto interrupted;
1909 /* could be success or failure */
1910 if (old_pending == GST_STATE (element)) {
1911 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got success");
1912 ret = GST_STATE_CHANGE_SUCCESS;
1913 } else {
1914 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got failure");
1915 ret = GST_STATE_CHANGE_FAILURE;
1916 }
1917 }
1918 /* if nothing is pending anymore we can return SUCCESS */
1919 if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
1920 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "nothing pending");
1921 ret = GST_STATE_CHANGE_SUCCESS;
1922 }
1923 }
1925 done:
1926 if (state)
1927 *state = GST_STATE (element);
1928 if (pending)
1929 *pending = GST_STATE_PENDING (element);
1931 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1932 "state current: %s, pending: %s, result: %s",
1933 gst_element_state_get_name (GST_STATE (element)),
1934 gst_element_state_get_name (GST_STATE_PENDING (element)),
1935 gst_element_state_change_return_get_name (ret));
1936 GST_OBJECT_UNLOCK (element);
1938 return ret;
1940 interrupted:
1941 {
1942 if (state)
1943 *state = GST_STATE_VOID_PENDING;
1944 if (pending)
1945 *pending = GST_STATE_VOID_PENDING;
1947 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "interruped");
1949 GST_OBJECT_UNLOCK (element);
1951 return GST_STATE_CHANGE_FAILURE;
1952 }
1953 }
1955 /**
1956 * gst_element_get_state:
1957 * @element: a #GstElement to get the state of.
1958 * @state: a pointer to #GstState to hold the state. Can be %NULL.
1959 * @pending: a pointer to #GstState to hold the pending state.
1960 * Can be %NULL.
1961 * @timeout: a #GstClockTime to specify the timeout for an async
1962 * state change or %GST_CLOCK_TIME_NONE for infinite timeout.
1963 *
1964 * Gets the state of the element.
1965 *
1966 * For elements that performed an ASYNC state change, as reported by
1967 * gst_element_set_state(), this function will block up to the
1968 * specified timeout value for the state change to complete.
1969 * If the element completes the state change or goes into
1970 * an error, this function returns immediately with a return value of
1971 * %GST_STATE_CHANGE_SUCCESS or %GST_STATE_CHANGE_FAILURE respectively.
1972 *
1973 * For elements that did not return %GST_STATE_CHANGE_ASYNC, this function
1974 * returns the current and pending state immediately.
1975 *
1976 * This function returns %GST_STATE_CHANGE_NO_PREROLL if the element
1977 * successfully changed its state but is not able to provide data yet.
1978 * This mostly happens for live sources that only produce data in the PLAYING
1979 * state. While the state change return is equivalent to
1980 * %GST_STATE_CHANGE_SUCCESS, it is returned to the application to signal that
1981 * some sink elements might not be able to complete their state change because
1982 * an element is not producing data to complete the preroll. When setting the
1983 * element to playing, the preroll will complete and playback will start.
1984 *
1985 * Returns: %GST_STATE_CHANGE_SUCCESS if the element has no more pending state
1986 * and the last state change succeeded, %GST_STATE_CHANGE_ASYNC if the
1987 * element is still performing a state change or
1988 * %GST_STATE_CHANGE_FAILURE if the last state change failed.
1989 *
1990 * MT safe.
1991 */
1992 GstStateChangeReturn
1993 gst_element_get_state (GstElement * element,
1994 GstState * state, GstState * pending, GstClockTime timeout)
1995 {
1996 GstElementClass *oclass;
1997 GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
1999 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2001 oclass = GST_ELEMENT_GET_CLASS (element);
2003 if (oclass->get_state)
2004 result = (oclass->get_state) (element, state, pending, timeout);
2006 return result;
2007 }
2009 /**
2010 * gst_element_abort_state:
2011 * @element: a #GstElement to abort the state of.
2012 *
2013 * Abort the state change of the element. This function is used
2014 * by elements that do asynchronous state changes and find out
2015 * something is wrong.
2016 *
2017 * This function should be called with the STATE_LOCK held.
2018 *
2019 * MT safe.
2020 */
2021 void
2022 gst_element_abort_state (GstElement * element)
2023 {
2024 GstState pending;
2026 #ifndef GST_DISABLE_GST_DEBUG
2027 GstState old_state;
2028 #endif
2030 g_return_if_fail (GST_IS_ELEMENT (element));
2032 GST_OBJECT_LOCK (element);
2033 pending = GST_STATE_PENDING (element);
2035 if (pending == GST_STATE_VOID_PENDING ||
2036 GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
2037 goto nothing_aborted;
2039 #ifndef GST_DISABLE_GST_DEBUG
2040 old_state = GST_STATE (element);
2042 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2043 "aborting state from %s to %s", gst_element_state_get_name (old_state),
2044 gst_element_state_get_name (pending));
2045 #endif
2047 /* flag error */
2048 GST_STATE_RETURN (element) = GST_STATE_CHANGE_FAILURE;
2050 GST_STATE_BROADCAST (element);
2051 GST_OBJECT_UNLOCK (element);
2053 return;
2055 nothing_aborted:
2056 {
2057 GST_OBJECT_UNLOCK (element);
2058 return;
2059 }
2060 }
2062 /**
2063 * gst_element_continue_state:
2064 * @element: a #GstElement to continue the state change of.
2065 * @ret: The previous state return value
2066 *
2067 * Commit the state change of the element and proceed to the next
2068 * pending state if any. This function is used
2069 * by elements that do asynchronous state changes.
2070 * The core will normally call this method automatically when an
2071 * element returned %GST_STATE_CHANGE_SUCCESS from the state change function.
2072 *
2073 * If after calling this method the element still has not reached
2074 * the pending state, the next state change is performed.
2075 *
2076 * This method is used internally and should normally not be called by plugins
2077 * or applications.
2078 *
2079 * Returns: The result of the commit state change.
2080 *
2081 * MT safe.
2082 */
2083 GstStateChangeReturn
2084 gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
2085 {
2086 GstStateChangeReturn old_ret;
2087 GstState old_state, old_next;
2088 GstState current, next, pending;
2089 GstMessage *message;
2090 GstStateChange transition;
2092 GST_OBJECT_LOCK (element);
2093 old_ret = GST_STATE_RETURN (element);
2094 GST_STATE_RETURN (element) = ret;
2095 pending = GST_STATE_PENDING (element);
2097 /* check if there is something to commit */
2098 if (pending == GST_STATE_VOID_PENDING)
2099 goto nothing_pending;
2101 old_state = GST_STATE (element);
2102 /* this is the state we should go to next */
2103 old_next = GST_STATE_NEXT (element);
2104 /* update current state */
2105 current = GST_STATE (element) = old_next;
2107 /* see if we reached the final state */
2108 if (pending == current)
2109 goto complete;
2111 next = GST_STATE_GET_NEXT (current, pending);
2112 transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
2114 GST_STATE_NEXT (element) = next;
2115 /* mark busy */
2116 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2117 GST_OBJECT_UNLOCK (element);
2119 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2120 "committing state from %s to %s, pending %s",
2121 gst_element_state_get_name (old_state),
2122 gst_element_state_get_name (old_next),
2123 gst_element_state_get_name (pending));
2125 message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
2126 old_state, old_next, pending);
2127 gst_element_post_message (element, message);
2129 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2130 "continue state change %s to %s, final %s",
2131 gst_element_state_get_name (current),
2132 gst_element_state_get_name (next), gst_element_state_get_name (pending));
2134 ret = gst_element_change_state (element, transition);
2136 return ret;
2138 nothing_pending:
2139 {
2140 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
2141 GST_OBJECT_UNLOCK (element);
2142 return ret;
2143 }
2144 complete:
2145 {
2146 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2147 GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
2149 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2150 "completed state change to %s", gst_element_state_get_name (pending));
2151 GST_OBJECT_UNLOCK (element);
2153 /* don't post silly messages with the same state. This can happen
2154 * when an element state is changed to what it already was. For bins
2155 * this can be the result of a lost state, which we check with the
2156 * previous return value.
2157 * We do signal the cond though as a _get_state() might be blocking
2158 * on it. */
2159 if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
2160 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2161 "posting state-changed %s to %s",
2162 gst_element_state_get_name (old_state),
2163 gst_element_state_get_name (old_next));
2164 message =
2165 gst_message_new_state_changed (GST_OBJECT_CAST (element), old_state,
2166 old_next, GST_STATE_VOID_PENDING);
2167 gst_element_post_message (element, message);
2168 }
2170 GST_STATE_BROADCAST (element);
2172 return ret;
2173 }
2174 }
2176 /**
2177 * gst_element_lost_state:
2178 * @element: a #GstElement the state is lost of
2179 *
2180 * Brings the element to the lost state. The current state of the
2181 * element is copied to the pending state so that any call to
2182 * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
2183 *
2184 * An ASYNC_START message is posted with an indication to distribute a new
2185 * base_time to the element.
2186 * If the element was PLAYING, it will go to PAUSED. The element
2187 * will be restored to its PLAYING state by the parent pipeline when it
2188 * prerolls again.
2189 *
2190 * This is mostly used for elements that lost their preroll buffer
2191 * in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush,
2192 * they will go to their pending state again when a new preroll buffer is
2193 * queued. This function can only be called when the element is currently
2194 * not in error or an async state change.
2195 *
2196 * This function is used internally and should normally not be called from
2197 * plugins or applications.
2198 *
2199 * MT safe.
2200 */
2201 void
2202 gst_element_lost_state (GstElement * element)
2203 {
2204 GstState old_state, new_state;
2205 GstMessage *message;
2207 g_return_if_fail (GST_IS_ELEMENT (element));
2209 GST_OBJECT_LOCK (element);
2210 if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING ||
2211 GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
2212 goto nothing_lost;
2214 old_state = GST_STATE (element);
2216 /* when we were PLAYING, the new state is PAUSED. We will also not
2217 * automatically go to PLAYING but let the parent bin(s) set us to PLAYING
2218 * when we preroll. */
2219 if (old_state > GST_STATE_PAUSED)
2220 new_state = GST_STATE_PAUSED;
2221 else
2222 new_state = old_state;
2224 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2225 "lost state of %s to %s", gst_element_state_get_name (old_state),
2226 gst_element_state_get_name (new_state));
2228 GST_STATE (element) = new_state;
2229 GST_STATE_NEXT (element) = new_state;
2230 GST_STATE_PENDING (element) = new_state;
2231 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2232 GST_OBJECT_UNLOCK (element);
2234 message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
2235 new_state, new_state, new_state);
2236 gst_element_post_message (element, message);
2238 message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE);
2239 gst_element_post_message (element, message);
2241 return;
2243 nothing_lost:
2244 {
2245 GST_OBJECT_UNLOCK (element);
2246 return;
2247 }
2248 }
2250 /**
2251 * gst_element_set_state:
2252 * @element: a #GstElement to change state of.
2253 * @state: the element's new #GstState.
2254 *
2255 * Sets the state of the element. This function will try to set the
2256 * requested state by going through all the intermediary states and calling
2257 * the class's state change function for each.
2258 *
2259 * This function can return #GST_STATE_CHANGE_ASYNC, in which case the
2260 * element will perform the remainder of the state change asynchronously in
2261 * another thread.
2262 * An application can use gst_element_get_state() to wait for the completion
2263 * of the state change or it can wait for a state change message on the bus.
2264 *
2265 * State changes to %GST_STATE_READY or %GST_STATE_NULL never return
2266 * #GST_STATE_CHANGE_ASYNC.
2267 *
2268 * Returns: Result of the state change using #GstStateChangeReturn.
2269 *
2270 * MT safe.
2271 */
2272 GstStateChangeReturn
2273 gst_element_set_state (GstElement * element, GstState state)
2274 {
2275 GstElementClass *oclass;
2276 GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2278 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2280 oclass = GST_ELEMENT_GET_CLASS (element);
2282 if (oclass->set_state)
2283 result = (oclass->set_state) (element, state);
2285 return result;
2286 }
2288 /*
2289 * default set state function, calculates the next state based
2290 * on current state and calls the change_state function
2291 */
2292 static GstStateChangeReturn
2293 gst_element_set_state_func (GstElement * element, GstState state)
2294 {
2295 GstState current, next, old_pending;
2296 GstStateChangeReturn ret;
2297 GstStateChange transition;
2298 GstStateChangeReturn old_ret;
2300 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2302 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "set_state to %s",
2303 gst_element_state_get_name (state));
2305 /* state lock is taken to protect the set_state() and get_state()
2306 * procedures, it does not lock any variables. */
2307 GST_STATE_LOCK (element);
2309 /* now calculate how to get to the new state */
2310 GST_OBJECT_LOCK (element);
2311 old_ret = GST_STATE_RETURN (element);
2312 /* previous state change returned an error, remove all pending
2313 * and next states */
2314 if (old_ret == GST_STATE_CHANGE_FAILURE) {
2315 GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
2316 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2317 GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
2318 }
2320 current = GST_STATE (element);
2321 next = GST_STATE_NEXT (element);
2322 old_pending = GST_STATE_PENDING (element);
2324 /* this is the (new) state we should go to. TARGET is the last state we set on
2325 * the element. */
2326 if (state != GST_STATE_TARGET (element)) {
2327 GST_STATE_TARGET (element) = state;
2328 /* increment state cookie so that we can track each state change. We only do
2329 * this if this is actually a new state change. */
2330 element->state_cookie++;
2331 }
2332 GST_STATE_PENDING (element) = state;
2334 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2335 "current %s, old_pending %s, next %s, old return %s",
2336 gst_element_state_get_name (current),
2337 gst_element_state_get_name (old_pending),
2338 gst_element_state_get_name (next),
2339 gst_element_state_change_return_get_name (old_ret));
2341 /* if the element was busy doing a state change, we just update the
2342 * target state, it'll get to it async then. */
2343 if (old_pending != GST_STATE_VOID_PENDING) {
2344 /* upwards state change will happen ASYNC */
2345 if (old_pending <= state)
2346 goto was_busy;
2347 /* element is going to this state already */
2348 else if (next == state)
2349 goto was_busy;
2350 /* element was performing an ASYNC upward state change and
2351 * we request to go downward again. Start from the next pending
2352 * state then. */
2353 else if (next > state
2354 && GST_STATE_RETURN (element) == GST_STATE_CHANGE_ASYNC) {
2355 current = next;
2356 }
2357 }
2358 next = GST_STATE_GET_NEXT (current, state);
2359 /* now we store the next state */
2360 GST_STATE_NEXT (element) = next;
2361 /* mark busy, we need to check that there is actually a state change
2362 * to be done else we could accidentally override SUCCESS/NO_PREROLL and
2363 * the default element change_state function has no way to know what the
2364 * old value was... could consider this a FIXME...*/
2365 if (current != next)
2366 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2368 transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
2370 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2371 "%s: setting state from %s to %s",
2372 (next != state ? "intermediate" : "final"),
2373 gst_element_state_get_name (current), gst_element_state_get_name (next));
2375 /* now signal any waiters, they will error since the cookie was incremented */
2376 GST_STATE_BROADCAST (element);
2378 GST_OBJECT_UNLOCK (element);
2380 ret = gst_element_change_state (element, transition);
2382 GST_STATE_UNLOCK (element);
2384 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "returned %s",
2385 gst_element_state_change_return_get_name (ret));
2387 return ret;
2389 was_busy:
2390 {
2391 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2392 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2393 "element was busy with async state change");
2394 GST_OBJECT_UNLOCK (element);
2396 GST_STATE_UNLOCK (element);
2398 return GST_STATE_CHANGE_ASYNC;
2399 }
2400 }
2402 /**
2403 * gst_element_change_state:
2404 * @element: a #GstElement
2405 * @transition: the requested transition
2406 *
2407 * Perform @transition on @element.
2408 *
2409 * This function must be called with STATE_LOCK held and is mainly used
2410 * internally.
2411 *
2412 * Returns: the #GstStateChangeReturn of the state transition.
2413 */
2414 GstStateChangeReturn
2415 gst_element_change_state (GstElement * element, GstStateChange transition)
2416 {
2417 GstElementClass *oclass;
2418 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2419 GstState current;
2420 GstState next;
2422 oclass = GST_ELEMENT_GET_CLASS (element);
2424 /* start with the current state. */
2425 current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
2426 next = GST_STATE_TRANSITION_NEXT (transition);
2428 /* call the state change function so it can set the state */
2429 if (oclass->change_state)
2430 ret = (oclass->change_state) (element, transition);
2431 else
2432 ret = GST_STATE_CHANGE_FAILURE;
2434 switch (ret) {
2435 case GST_STATE_CHANGE_FAILURE:
2436 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2437 "have FAILURE change_state return");
2438 /* state change failure */
2439 gst_element_abort_state (element);
2440 break;
2441 case GST_STATE_CHANGE_ASYNC:
2442 {
2443 GstState target;
2445 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2446 "element will change state ASYNC");
2448 target = GST_STATE_TARGET (element);
2450 if (target > GST_STATE_READY)
2451 goto async;
2453 /* else we just continue the state change downwards */
2454 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2455 "forcing commit state %s <= %s",
2456 gst_element_state_get_name (target),
2457 gst_element_state_get_name (GST_STATE_READY));
2459 ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS);
2460 break;
2461 }
2462 case GST_STATE_CHANGE_SUCCESS:
2463 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2464 "element changed state SUCCESS");
2465 /* we can commit the state now which will proceeed to
2466 * the next state */
2467 ret = gst_element_continue_state (element, ret);
2468 break;
2469 case GST_STATE_CHANGE_NO_PREROLL:
2470 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2471 "element changed state NO_PREROLL");
2472 /* we can commit the state now which will proceeed to
2473 * the next state */
2474 ret = gst_element_continue_state (element, ret);
2475 break;
2476 default:
2477 goto invalid_return;
2478 }
2480 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit state change %d", ret);
2482 return ret;
2484 async:
2485 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit async state change %d",
2486 ret);
2488 return ret;
2490 /* ERROR */
2491 invalid_return:
2492 {
2493 GST_OBJECT_LOCK (element);
2494 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2495 g_critical ("%s: unknown return value %d from a state change function",
2496 GST_ELEMENT_NAME (element), ret);
2498 /* we are in error now */
2499 ret = GST_STATE_CHANGE_FAILURE;
2500 GST_STATE_RETURN (element) = ret;
2501 GST_OBJECT_UNLOCK (element);
2503 return ret;
2504 }
2505 }
2507 /* gst_iterator_fold functions for pads_activate
2508 * Note how we don't stop the iterator when we fail an activation. This is
2509 * probably a FIXME since when one pad activation fails, we don't want to
2510 * continue our state change. */
2511 static gboolean
2512 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
2513 {
2514 if (!gst_pad_set_active (pad, *active))
2515 g_value_set_boolean (ret, FALSE);
2517 /* unref the object that was reffed for us by _fold */
2518 gst_object_unref (pad);
2519 return TRUE;
2520 }
2522 /* set the caps on the pad to NULL */
2523 static gboolean
2524 clear_caps (GstPad * pad, GValue * ret, gboolean * active)
2525 {
2526 gst_pad_set_caps (pad, NULL);
2527 gst_object_unref (pad);
2528 return TRUE;
2529 }
2531 /* returns false on error or early cutout (will never happen because the fold
2532 * function always returns TRUE, see FIXME above) of the fold, true if all
2533 * pads in @iter were (de)activated successfully. */
2534 static gboolean
2535 iterator_activate_fold_with_resync (GstIterator * iter,
2536 GstIteratorFoldFunction func, gpointer user_data)
2537 {
2538 GstIteratorResult ires;
2539 GValue ret = { 0 };
2541 /* no need to unset this later, it's just a boolean */
2542 g_value_init (&ret, G_TYPE_BOOLEAN);
2543 g_value_set_boolean (&ret, TRUE);
2545 while (1) {
2546 ires = gst_iterator_fold (iter, func, &ret, user_data);
2547 switch (ires) {
2548 case GST_ITERATOR_RESYNC:
2549 /* need to reset the result again */
2550 g_value_set_boolean (&ret, TRUE);
2551 gst_iterator_resync (iter);
2552 break;
2553 case GST_ITERATOR_DONE:
2554 /* all pads iterated, return collected value */
2555 goto done;
2556 default:
2557 /* iterator returned _ERROR or premature end with _OK,
2558 * mark an error and exit */
2559 g_value_set_boolean (&ret, FALSE);
2560 goto done;
2561 }
2562 }
2563 done:
2564 /* return collected value */
2565 return g_value_get_boolean (&ret);
2566 }
2568 /* is called with STATE_LOCK
2569 *
2570 * Pads are activated from source pads to sinkpads.
2571 */
2572 static gboolean
2573 gst_element_pads_activate (GstElement * element, gboolean active)
2574 {
2575 GstIterator *iter;
2576 gboolean res;
2578 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
2579 "pads_activate with active %d", active);
2581 iter = gst_element_iterate_src_pads (element);
2582 res =
2583 iterator_activate_fold_with_resync (iter,
2584 (GstIteratorFoldFunction) activate_pads, &active);
2585 gst_iterator_free (iter);
2586 if (G_UNLIKELY (!res))
2587 goto src_failed;
2589 iter = gst_element_iterate_sink_pads (element);
2590 res =
2591 iterator_activate_fold_with_resync (iter,
2592 (GstIteratorFoldFunction) activate_pads, &active);
2593 gst_iterator_free (iter);
2594 if (G_UNLIKELY (!res))
2595 goto sink_failed;
2597 if (!active) {
2598 /* clear the caps on all pads, this should never fail */
2599 iter = gst_element_iterate_pads (element);
2600 res =
2601 iterator_activate_fold_with_resync (iter,
2602 (GstIteratorFoldFunction) clear_caps, &active);
2603 gst_iterator_free (iter);
2604 if (G_UNLIKELY (!res))
2605 goto caps_failed;
2606 }
2608 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
2609 "pads_activate successful");
2611 return TRUE;
2613 /* ERRORS */
2614 src_failed:
2615 {
2616 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
2617 "source pads_activate failed");
2618 return FALSE;
2619 }
2620 sink_failed:
2621 {
2622 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
2623 "sink pads_activate failed");
2624 return FALSE;
2625 }
2626 caps_failed:
2627 {
2628 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
2629 "failed to clear caps on pads");
2630 return FALSE;
2631 }
2632 }
2634 /* is called with STATE_LOCK */
2635 static GstStateChangeReturn
2636 gst_element_change_state_func (GstElement * element, GstStateChange transition)
2637 {
2638 GstState state, next;
2639 GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
2641 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2643 state = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
2644 next = GST_STATE_TRANSITION_NEXT (transition);
2646 /* if the element already is in the given state, we just return success */
2647 if (next == GST_STATE_VOID_PENDING || state == next)
2648 goto was_ok;
2650 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2651 "default handler tries setting state from %s to %s (%04x)",
2652 gst_element_state_get_name (state),
2653 gst_element_state_get_name (next), transition);
2655 switch (transition) {
2656 case GST_STATE_CHANGE_NULL_TO_READY:
2657 break;
2658 case GST_STATE_CHANGE_READY_TO_PAUSED:
2659 if (!gst_element_pads_activate (element, TRUE)) {
2660 result = GST_STATE_CHANGE_FAILURE;
2661 }
2662 break;
2663 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2664 break;
2665 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2666 break;
2667 case GST_STATE_CHANGE_PAUSED_TO_READY:
2668 case GST_STATE_CHANGE_READY_TO_NULL:
2669 /* deactivate pads in both cases, since they are activated on
2670 ready->paused but the element might not have made it to paused */
2671 if (!gst_element_pads_activate (element, FALSE)) {
2672 result = GST_STATE_CHANGE_FAILURE;
2673 } else {
2674 gst_element_set_base_time (element, 0);
2675 }
2676 break;
2677 default:
2678 /* this will catch real but unhandled state changes;
2679 * can only be caused by:
2680 * - a new state was added
2681 * - somehow the element was asked to jump across an intermediate state
2682 */
2683 g_warning ("Unhandled state change from %s to %s",
2684 gst_element_state_get_name (state),
2685 gst_element_state_get_name (next));
2686 break;
2687 }
2688 return result;
2690 was_ok:
2691 {
2692 GST_OBJECT_LOCK (element);
2693 result = GST_STATE_RETURN (element);
2694 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2695 "element is already in the %s state",
2696 gst_element_state_get_name (state));
2697 GST_OBJECT_UNLOCK (element);
2699 return result;
2700 }
2701 }
2703 /**
2704 * gst_element_get_factory:
2705 * @element: a #GstElement to request the element factory of.
2706 *
2707 * Retrieves the factory that was used to create this element.
2708 *
2709 * Returns: the #GstElementFactory used for creating this element.
2710 * no refcounting is needed.
2711 */
2712 GstElementFactory *
2713 gst_element_get_factory (GstElement * element)
2714 {
2715 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2717 return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2718 }
2720 static void
2721 gst_element_dispose (GObject * object)
2722 {
2723 GstElement *element = GST_ELEMENT (object);
2724 GstClock **clock_p;
2725 GstBus **bus_p;
2727 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2729 if (GST_STATE (element) != GST_STATE_NULL)
2730 goto not_null;
2732 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
2733 "removing %d pads", g_list_length (element->pads));
2734 /* first we break all our links with the outside */
2735 while (element->pads && element->pads->data) {
2736 /* don't call _remove_pad with NULL */
2737 gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
2738 }
2739 if (G_UNLIKELY (element->pads != 0)) {
2740 g_critical ("could not remove pads from element %s",
2741 GST_STR_NULL (GST_OBJECT_NAME (object)));
2742 }
2744 GST_OBJECT_LOCK (element);
2745 clock_p = &element->clock;
2746 bus_p = &element->bus;
2747 gst_object_replace ((GstObject **) clock_p, NULL);
2748 gst_object_replace ((GstObject **) bus_p, NULL);
2749 GST_OBJECT_UNLOCK (element);
2751 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "parent class dispose");
2753 G_OBJECT_CLASS (parent_class)->dispose (object);
2755 return;
2757 /* ERRORS */
2758 not_null:
2759 {
2760 g_critical
2761 ("\nTrying to dispose element %s, but it is not in the NULL state.\n"
2762 "You need to explicitly set elements to the NULL state before\n"
2763 "dropping the final reference, to allow them to clean up.\n",
2764 GST_OBJECT_NAME (element));
2765 return;
2766 }
2767 }
2769 static void
2770 gst_element_finalize (GObject * object)
2771 {
2772 GstElement *element = GST_ELEMENT (object);
2774 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
2776 GST_STATE_LOCK (element);
2777 if (element->state_cond)
2778 g_cond_free (element->state_cond);
2779 element->state_cond = NULL;
2780 GST_STATE_UNLOCK (element);
2781 g_static_rec_mutex_free (element->state_lock);
2782 g_free (element->state_lock);
2783 element->state_lock = NULL;
2785 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
2787 G_OBJECT_CLASS (parent_class)->finalize (object);
2788 }
2790 #ifndef GST_DISABLE_LOADSAVE
2791 /**
2792 * gst_element_save_thyself:
2793 * @element: a #GstElement to save.
2794 * @parent: the xml parent node.
2795 *
2796 * Saves the element as part of the given XML structure.
2797 *
2798 * Returns: the new #xmlNodePtr.
2799 */
2800 static xmlNodePtr
2801 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2802 {
2803 GList *pads;
2804 GstElementClass *oclass;
2805 GParamSpec **specs, *spec;
2806 guint nspecs;
2807 guint i;
2808 GValue value = { 0, };
2809 GstElement *element;
2811 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2813 element = GST_ELEMENT (object);
2815 oclass = GST_ELEMENT_GET_CLASS (element);
2817 xmlNewChild (parent, NULL, (xmlChar *) "name",
2818 (xmlChar *) GST_ELEMENT_NAME (element));
2820 if (oclass->elementfactory != NULL) {
2821 GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2823 xmlNewChild (parent, NULL, (xmlChar *) "type",
2824 (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
2825 }
2827 /* params */
2828 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2830 for (i = 0; i < nspecs; i++) {
2831 spec = specs[i];
2832 if (spec->flags & G_PARAM_READABLE) {
2833 xmlNodePtr param;
2834 char *contents;
2836 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2838 g_object_get_property (G_OBJECT (element), spec->name, &value);
2839 param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
2840 xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
2842 if (G_IS_PARAM_SPEC_STRING (spec))
2843 contents = g_value_dup_string (&value);
2844 else if (G_IS_PARAM_SPEC_ENUM (spec))
2845 contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2846 else if (G_IS_PARAM_SPEC_INT64 (spec))
2847 contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2848 g_value_get_int64 (&value));
2849 else
2850 contents = g_strdup_value_contents (&value);
2852 xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
2853 g_free (contents);
2855 g_value_unset (&value);
2856 }
2857 }
2859 g_free (specs);
2861 pads = GST_ELEMENT_PADS (element);
2863 while (pads) {
2864 GstPad *pad = GST_PAD_CAST (pads->data);
2866 /* figure out if it's a direct pad or a ghostpad */
2867 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2868 xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
2870 gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag);
2871 }
2872 pads = g_list_next (pads);
2873 }
2875 return parent;
2876 }
2878 static void
2879 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2880 {
2881 xmlNodePtr children;
2882 GstElement *element;
2883 gchar *name = NULL;
2884 gchar *value = NULL;
2886 element = GST_ELEMENT (object);
2887 g_return_if_fail (element != NULL);
2889 /* parameters */
2890 children = self->xmlChildrenNode;
2891 while (children) {
2892 if (!strcmp ((char *) children->name, "param")) {
2893 xmlNodePtr child = children->xmlChildrenNode;
2895 while (child) {
2896 if (!strcmp ((char *) child->name, "name")) {
2897 name = (gchar *) xmlNodeGetContent (child);
2898 } else if (!strcmp ((char *) child->name, "value")) {
2899 value = (gchar *) xmlNodeGetContent (child);
2900 }
2901 child = child->next;
2902 }
2903 /* FIXME: can this just be g_object_set ? */
2904 gst_util_set_object_arg (G_OBJECT (element), name, value);
2905 /* g_object_set (G_OBJECT (element), name, value, NULL); */
2906 g_free (name);
2907 g_free (value);
2908 }
2909 children = children->next;
2910 }
2912 /* pads */
2913 children = self->xmlChildrenNode;
2914 while (children) {
2915 if (!strcmp ((char *) children->name, "pad")) {
2916 gst_pad_load_and_link (children, GST_OBJECT_CAST (element));
2917 }
2918 children = children->next;
2919 }
2921 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2922 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2923 }
2924 #endif /* GST_DISABLE_LOADSAVE */
2926 static void
2927 gst_element_set_bus_func (GstElement * element, GstBus * bus)
2928 {
2929 GstBus **bus_p;
2931 g_return_if_fail (GST_IS_ELEMENT (element));
2933 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
2935 GST_OBJECT_LOCK (element);
2936 bus_p = &GST_ELEMENT_BUS (element);
2937 gst_object_replace ((GstObject **) bus_p, GST_OBJECT_CAST (bus));
2938 GST_OBJECT_UNLOCK (element);
2939 }
2941 /**
2942 * gst_element_set_bus:
2943 * @element: a #GstElement to set the bus of.
2944 * @bus: the #GstBus to set.
2945 *
2946 * Sets the bus of the element. Increases the refcount on the bus.
2947 * For internal use only, unless you're testing elements.
2948 *
2949 * MT safe.
2950 */
2951 void
2952 gst_element_set_bus (GstElement * element, GstBus * bus)
2953 {
2954 GstElementClass *oclass;
2956 g_return_if_fail (GST_IS_ELEMENT (element));
2958 oclass = GST_ELEMENT_GET_CLASS (element);
2960 if (oclass->set_bus)
2961 oclass->set_bus (element, bus);
2962 }
2964 /**
2965 * gst_element_get_bus:
2966 * @element: a #GstElement to get the bus of.
2967 *
2968 * Returns the bus of the element. Note that only a #GstPipeline will provide a
2969 * bus for the application.
2970 *
2971 * Returns: the element's #GstBus. unref after usage.
2972 *
2973 * MT safe.
2974 */
2975 GstBus *
2976 gst_element_get_bus (GstElement * element)
2977 {
2978 GstBus *result = NULL;
2980 g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2982 GST_OBJECT_LOCK (element);
2983 if ((result = GST_ELEMENT_BUS (element)))
2984 gst_object_ref (result);
2985 GST_OBJECT_UNLOCK (element);
2987 GST_CAT_DEBUG_OBJECT (GST_CAT_BUS, element, "got bus %" GST_PTR_FORMAT,
2988 result);
2990 return result;
2991 }