2000-12-28 22:12:02 +00:00
/* GStreamer
* Copyright ( C ) 1999 , 2000 Erik Walthinsen < omega @ cse . ogi . edu >
* 2000 Wim Taymans < wtay @ chello . be >
*
* gstelement . c : The base element , all elements derive from this
2000-01-30 09:03:00 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*/
2001-12-14 22:59:21 +00:00
/* #define GST_DEBUG_ENABLED */
2001-12-04 22:12:50 +00:00
# include <glib.h>
2001-12-13 23:37:47 +00:00
# include <stdarg.h>
2002-05-26 03:23:25 +00:00
# include <gobject/gvaluecollector.h>
2000-12-28 22:12:02 +00:00
# include "gst_private.h"
2000-12-15 01:57:34 +00:00
# include "gstelement.h"
2001-01-13 13:51:08 +00:00
# include "gstbin.h"
2001-05-25 21:00:07 +00:00
# include "gstscheduler.h"
2001-12-18 19:03:07 +00:00
# include "gstevent.h"
2001-03-03 17:38:26 +00:00
# include "gstutils.h"
2002-07-08 19:22:02 +00:00
# include "gstlog.h"
2000-01-30 09:03:00 +00:00
/* Element signals and args */
enum {
STATE_CHANGE ,
NEW_PAD ,
2001-05-25 21:00:07 +00:00
PAD_REMOVED ,
2000-01-30 09:03:00 +00:00
ERROR ,
2000-12-29 02:28:04 +00:00
EOS ,
2000-01-30 09:03:00 +00:00
LAST_SIGNAL
} ;
enum {
ARG_0 ,
/* FILL ME */
} ;
2001-01-29 00:06:02 +00:00
static void gst_element_class_init ( GstElementClass * klass ) ;
static void gst_element_init ( GstElement * element ) ;
2001-05-26 22:58:15 +00:00
static void gst_element_base_class_init ( GstElementClass * klass ) ;
2000-01-30 09:03:00 +00:00
2002-05-26 03:23:25 +00:00
static void gst_element_real_set_property ( GObject * object , guint prop_id ,
2001-08-21 20:16:48 +00:00
const GValue * value , GParamSpec * pspec ) ;
2002-05-26 03:23:25 +00:00
static void gst_element_real_get_property ( GObject * object , guint prop_id , GValue * value ,
2001-08-21 20:16:48 +00:00
GParamSpec * pspec ) ;
2001-05-25 21:00:07 +00:00
2001-09-28 19:16:02 +00:00
static void gst_element_dispose ( GObject * object ) ;
2000-07-17 17:14:15 +00:00
2001-01-29 00:06:02 +00:00
static GstElementStateReturn gst_element_change_state ( GstElement * element ) ;
2002-02-06 19:05:19 +00:00
static void gst_element_error_func ( GstElement * element , GstElement * source , gchar * errormsg ) ;
2001-01-29 00:06:02 +00:00
2001-06-25 06:45:56 +00:00
# ifndef GST_DISABLE_LOADSAVE
2001-01-29 00:06:02 +00:00
static xmlNodePtr gst_element_save_thyself ( GstObject * object , xmlNodePtr parent ) ;
2002-01-11 15:49:47 +00:00
static void gst_element_restore_thyself ( GstObject * parent , xmlNodePtr self ) ;
2001-06-24 21:18:28 +00:00
# endif
2000-07-17 17:14:15 +00:00
2001-10-17 10:21:27 +00:00
GType _gst_element_type = 0 ;
2000-01-30 09:03:00 +00:00
static GstObjectClass * parent_class = NULL ;
static guint gst_element_signals [ LAST_SIGNAL ] = { 0 } ;
2001-10-17 10:21:27 +00:00
GType gst_element_get_type ( void )
{
if ( ! _gst_element_type ) {
2001-06-25 01:20:11 +00:00
static const GTypeInfo element_info = {
2000-01-30 09:03:00 +00:00
sizeof ( GstElementClass ) ,
2001-06-25 01:20:11 +00:00
( GBaseInitFunc ) gst_element_base_class_init ,
NULL ,
( GClassInitFunc ) gst_element_class_init ,
NULL ,
NULL ,
sizeof ( GstElement ) ,
0 ,
( GInstanceInitFunc ) gst_element_init ,
2001-09-14 22:16:47 +00:00
NULL
2000-01-30 09:03:00 +00:00
} ;
2002-05-01 20:02:40 +00:00
_gst_element_type = g_type_register_static ( GST_TYPE_OBJECT , " GstElement " ,
& element_info , G_TYPE_FLAG_ABSTRACT ) ;
2000-01-30 09:03:00 +00:00
}
2001-10-17 10:21:27 +00:00
return _gst_element_type ;
2000-01-30 09:03:00 +00:00
}
2001-01-20 03:10:44 +00:00
static void
gst_element_class_init ( GstElementClass * klass )
2000-11-11 15:13:50 +00:00
{
2001-06-25 01:20:11 +00:00
GObjectClass * gobject_class ;
2001-01-29 00:06:02 +00:00
GstObjectClass * gstobject_class ;
2000-01-30 09:03:00 +00:00
2001-06-25 01:20:11 +00:00
gobject_class = ( GObjectClass * ) klass ;
2001-01-29 00:06:02 +00:00
gstobject_class = ( GstObjectClass * ) klass ;
2000-01-30 09:03:00 +00:00
2001-06-25 01:20:11 +00:00
parent_class = g_type_class_ref ( GST_TYPE_OBJECT ) ;
2000-01-30 09:03:00 +00:00
gst_element_signals [ STATE_CHANGE ] =
2001-12-18 19:03:07 +00:00
g_signal_new ( " state_change " , G_TYPE_FROM_CLASS ( klass ) , G_SIGNAL_RUN_LAST ,
2001-12-04 22:12:50 +00:00
G_STRUCT_OFFSET ( GstElementClass , state_change ) , NULL , NULL ,
gst_marshal_VOID__INT_INT , G_TYPE_NONE , 2 ,
G_TYPE_INT , G_TYPE_INT ) ;
2000-01-30 09:03:00 +00:00
gst_element_signals [ NEW_PAD ] =
2001-12-18 19:03:07 +00:00
g_signal_new ( " new_pad " , G_TYPE_FROM_CLASS ( klass ) , G_SIGNAL_RUN_LAST ,
2001-12-04 22:12:50 +00:00
G_STRUCT_OFFSET ( GstElementClass , new_pad ) , NULL , NULL ,
2002-03-24 11:32:03 +00:00
gst_marshal_VOID__OBJECT , G_TYPE_NONE , 1 ,
G_TYPE_OBJECT ) ;
2001-05-25 21:00:07 +00:00
gst_element_signals [ PAD_REMOVED ] =
2001-12-18 19:03:07 +00:00
g_signal_new ( " pad_removed " , G_TYPE_FROM_CLASS ( klass ) , G_SIGNAL_RUN_LAST ,
2001-12-04 22:12:50 +00:00
G_STRUCT_OFFSET ( GstElementClass , pad_removed ) , NULL , NULL ,
2002-03-24 11:32:03 +00:00
gst_marshal_VOID__OBJECT , G_TYPE_NONE , 1 ,
G_TYPE_OBJECT ) ;
2000-01-30 09:03:00 +00:00
gst_element_signals [ ERROR ] =
2001-12-18 19:03:07 +00:00
g_signal_new ( " error " , G_TYPE_FROM_CLASS ( klass ) , G_SIGNAL_RUN_LAST ,
2001-12-04 22:12:50 +00:00
G_STRUCT_OFFSET ( GstElementClass , error ) , NULL , NULL ,
2002-02-06 19:05:19 +00:00
gst_marshal_VOID__OBJECT_STRING , G_TYPE_NONE , 2 ,
G_TYPE_OBJECT , G_TYPE_STRING ) ;
2000-12-29 02:28:04 +00:00
gst_element_signals [ EOS ] =
2001-12-18 19:03:07 +00:00
g_signal_new ( " eos " , G_TYPE_FROM_CLASS ( klass ) , G_SIGNAL_RUN_LAST ,
2001-12-04 22:12:50 +00:00
G_STRUCT_OFFSET ( GstElementClass , eos ) , NULL , NULL ,
gst_marshal_VOID__VOID , G_TYPE_NONE , 0 ) ;
2000-01-30 09:03:00 +00:00
2002-05-26 03:23:25 +00:00
gobject_class - > set_property = GST_DEBUG_FUNCPTR ( gst_element_real_set_property ) ;
gobject_class - > get_property = GST_DEBUG_FUNCPTR ( gst_element_real_get_property ) ;
2002-05-05 17:45:41 +00:00
2001-12-04 22:12:50 +00:00
gobject_class - > dispose = GST_DEBUG_FUNCPTR ( gst_element_dispose ) ;
2001-01-29 00:06:02 +00:00
2001-06-25 06:45:56 +00:00
# ifndef GST_DISABLE_LOADSAVE
2001-12-04 22:12:50 +00:00
gstobject_class - > save_thyself = GST_DEBUG_FUNCPTR ( gst_element_save_thyself ) ;
gstobject_class - > restore_thyself = GST_DEBUG_FUNCPTR ( gst_element_restore_thyself ) ;
2001-06-24 21:18:28 +00:00
# endif
2001-01-29 00:06:02 +00:00
2001-12-04 22:12:50 +00:00
klass - > change_state = GST_DEBUG_FUNCPTR ( gst_element_change_state ) ;
2002-02-06 19:05:19 +00:00
klass - > error = GST_DEBUG_FUNCPTR ( gst_element_error_func ) ;
2001-12-18 19:03:07 +00:00
klass - > elementfactory = NULL ;
klass - > padtemplates = NULL ;
klass - > numpadtemplates = 0 ;
2000-01-30 09:03:00 +00:00
}
2001-05-26 22:58:15 +00:00
static void
gst_element_base_class_init ( GstElementClass * klass )
{
2001-06-25 01:20:11 +00:00
GObjectClass * gobject_class ;
2001-05-26 22:58:15 +00:00
2001-06-25 01:20:11 +00:00
gobject_class = ( GObjectClass * ) klass ;
2001-05-26 22:58:15 +00:00
2002-05-26 03:23:25 +00:00
gobject_class - > set_property = GST_DEBUG_FUNCPTR ( gst_element_real_set_property ) ;
gobject_class - > get_property = GST_DEBUG_FUNCPTR ( gst_element_real_get_property ) ;
2001-05-26 22:58:15 +00:00
}
2001-01-20 03:10:44 +00:00
static void
gst_element_init ( GstElement * element )
2000-11-11 15:13:50 +00:00
{
2000-07-17 17:14:15 +00:00
element - > current_state = GST_STATE_NULL ;
2001-12-18 19:03:07 +00:00
element - > pending_state = GST_STATE_VOID_PENDING ;
2000-01-30 09:03:00 +00:00
element - > numpads = 0 ;
2000-12-20 09:39:43 +00:00
element - > numsrcpads = 0 ;
element - > numsinkpads = 0 ;
2000-01-30 09:03:00 +00:00
element - > pads = NULL ;
element - > loopfunc = NULL ;
2001-05-25 21:00:07 +00:00
element - > sched = NULL ;
2002-05-26 21:54:27 +00:00
element - > clock = NULL ;
2001-12-22 21:18:17 +00:00
element - > sched_private = NULL ;
2001-12-18 19:03:07 +00:00
element - > state_mutex = g_mutex_new ( ) ;
element - > state_cond = g_cond_new ( ) ;
2000-01-30 09:03:00 +00:00
}
2001-05-25 21:00:07 +00:00
static void
2002-05-26 03:23:25 +00:00
gst_element_real_set_property ( GObject * object , guint prop_id , const GValue * value , GParamSpec * pspec )
2001-05-25 21:00:07 +00:00
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass = GST_ELEMENT_GET_CLASS ( object ) ;
2001-05-25 21:00:07 +00:00
2001-06-25 01:20:11 +00:00
if ( oclass - > set_property )
2002-02-03 20:07:09 +00:00
( oclass - > set_property ) ( object , prop_id , value , pspec ) ;
2001-05-25 21:00:07 +00:00
}
static void
2002-05-26 03:23:25 +00:00
gst_element_real_get_property ( GObject * object , guint prop_id , GValue * value , GParamSpec * pspec )
2001-05-25 21:00:07 +00:00
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass = GST_ELEMENT_GET_CLASS ( object ) ;
2001-05-25 21:00:07 +00:00
2001-06-25 01:20:11 +00:00
if ( oclass - > get_property )
2002-02-03 20:07:09 +00:00
( oclass - > get_property ) ( object , prop_id , value , pspec ) ;
2001-05-25 21:00:07 +00:00
}
2002-07-30 19:17:25 +00:00
/**
* gst_element_default_error :
2002-08-30 14:02:15 +00:00
* @ object : a # GObject that signalled the error .
* @ orig : the # GstObject that initiated the error .
* @ error : the error message .
2002-07-30 19:17:25 +00:00
*
2002-08-30 14:02:15 +00:00
* Adds a default error signal callback to an
2002-07-30 19:17:25 +00:00
* element . The user data passed to the g_signal_connect is
* ignored .
2002-08-30 14:02:15 +00:00
* The default handler will simply print the error string
2002-07-30 19:17:25 +00:00
* using g_print .
*/
void
gst_element_default_error ( GObject * object , GstObject * orig , gchar * error )
{
2002-11-20 21:13:07 +00:00
gchar * name = gst_object_get_path_string ( orig ) ;
g_print ( " ERROR: %s: %s \n " , name , error ) ;
g_free ( name ) ;
2002-07-30 19:17:25 +00:00
}
2002-05-26 03:23:25 +00:00
typedef struct {
const GParamSpec * pspec ;
2002-09-02 18:49:40 +00:00
GValue value ;
2002-05-26 03:23:25 +00:00
} prop_value_t ;
static void
element_set_property ( GstElement * element , const GParamSpec * pspec , const GValue * value )
{
prop_value_t * prop_value = g_new0 ( prop_value_t , 1 ) ;
prop_value - > pspec = pspec ;
2002-09-02 18:49:40 +00:00
prop_value - > value = * value ;
2002-05-26 03:23:25 +00:00
g_async_queue_push ( element - > prop_value_queue , prop_value ) ;
}
static void
element_get_property ( GstElement * element , const GParamSpec * pspec , GValue * value )
{
g_mutex_lock ( element - > property_mutex ) ;
g_object_get_property ( ( GObject * ) element , pspec - > name , value ) ;
g_mutex_unlock ( element - > property_mutex ) ;
}
static void
gst_element_threadsafe_properties_pre_run ( GstElement * element )
{
GST_DEBUG ( GST_CAT_THREAD , " locking element %s " , GST_OBJECT_NAME ( element ) ) ;
2002-05-27 04:48:57 +00:00
g_mutex_lock ( element - > property_mutex ) ;
2002-05-26 03:23:25 +00:00
gst_element_set_pending_properties ( element ) ;
}
static void
gst_element_threadsafe_properties_post_run ( GstElement * element )
{
GST_DEBUG ( GST_CAT_THREAD , " unlocking element %s " , GST_OBJECT_NAME ( element ) ) ;
2002-05-27 04:48:57 +00:00
g_mutex_unlock ( element - > property_mutex ) ;
2002-05-26 03:23:25 +00:00
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_enable_threadsafe_properties :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to enable threadsafe properties on .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Installs an asynchronous queue , a mutex and pre - and post - run functions on
2002-07-24 21:06:17 +00:00
* this element so that properties on the element can be set in a
* threadsafe way .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_enable_threadsafe_properties ( GstElement * element )
{
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
GST_FLAG_SET ( element , GST_ELEMENT_USE_THREADSAFE_PROPERTIES ) ;
element - > pre_run_func = gst_element_threadsafe_properties_pre_run ;
element - > post_run_func = gst_element_threadsafe_properties_post_run ;
if ( ! element - > prop_value_queue )
element - > prop_value_queue = g_async_queue_new ( ) ;
if ( ! element - > property_mutex )
element - > property_mutex = g_mutex_new ( ) ;
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_disable_threadsafe_properties :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to disable threadsafe properties on .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Removes the threadsafe properties , post - and pre - run locks from
2002-07-24 21:06:17 +00:00
* this element .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_disable_threadsafe_properties ( GstElement * element )
{
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
GST_FLAG_UNSET ( element , GST_ELEMENT_USE_THREADSAFE_PROPERTIES ) ;
element - > pre_run_func = NULL ;
element - > post_run_func = NULL ;
/* let's keep around that async queue */
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_set_pending_properties :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set the pending properties on .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Sets all pending properties on the threadsafe properties enabled
2002-07-24 21:06:17 +00:00
* element .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_set_pending_properties ( GstElement * element )
{
prop_value_t * prop_value ;
while ( ( prop_value = g_async_queue_try_pop ( element - > prop_value_queue ) ) ) {
2002-09-02 18:49:40 +00:00
g_object_set_property ( ( GObject * ) element , prop_value - > pspec - > name , & prop_value - > value ) ;
g_value_unset ( & prop_value - > value ) ;
2002-05-26 03:23:25 +00:00
g_free ( prop_value ) ;
}
}
/* following 6 functions taken mostly from gobject.c */
2002-07-24 21:06:17 +00:00
/**
* gst_element_set :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set properties on .
* @ first_property_name : the first property to set .
* @ . . . : value of the first property , and more properties to set , ending
* with NULL .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Sets properties on an element . If the element uses threadsafe properties ,
* they will be queued and set on the object when it is scheduled again .
2002-07-24 21:06:17 +00:00
*/
2002-05-26 03:23:25 +00:00
void
gst_element_set ( GstElement * element , const gchar * first_property_name , . . . )
{
va_list var_args ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
va_start ( var_args , first_property_name ) ;
gst_element_set_valist ( element , first_property_name , var_args ) ;
va_end ( var_args ) ;
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_get :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get properties of .
* @ first_property_name : the first property to get .
* @ . . . : pointer to a variable to store the first property in , as well as
* more properties to get , ending with NULL .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Gets properties from an element . If the element uses threadsafe properties ,
2002-07-24 21:06:17 +00:00
* the element will be locked before getting the given properties .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_get ( GstElement * element , const gchar * first_property_name , . . . )
{
va_list var_args ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
va_start ( var_args , first_property_name ) ;
gst_element_get_valist ( element , first_property_name , var_args ) ;
va_end ( var_args ) ;
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_set_valist :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set properties on .
* @ first_property_name : the first property to set .
* @ var_args : the var_args list of other properties to get .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Sets properties on an element . If the element uses threadsafe properties ,
2002-07-24 21:06:17 +00:00
* the property change will be put on the async queue .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_set_valist ( GstElement * element , const gchar * first_property_name , va_list var_args )
{
const gchar * name ;
GObject * object ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
2002-10-01 11:42:32 +00:00
object = ( GObject * ) element ;
GST_DEBUG ( GST_CAT_PROPERTIES ,
" setting valist of properties starting with %s on element %s " ,
first_property_name , gst_element_get_name ( element ) ) ;
2002-05-26 03:23:25 +00:00
if ( ! GST_FLAG_IS_SET ( element , GST_ELEMENT_USE_THREADSAFE_PROPERTIES ) ) {
g_object_set_valist ( object , first_property_name , var_args ) ;
return ;
}
g_object_ref ( object ) ;
name = first_property_name ;
while ( name )
{
GValue value = { 0 , } ;
GParamSpec * pspec ;
gchar * error = NULL ;
pspec = g_object_class_find_property ( G_OBJECT_GET_CLASS ( object ) , name ) ;
if ( ! pspec )
{
g_warning ( " %s: object class `%s' has no property named `%s' " ,
G_STRLOC ,
G_OBJECT_TYPE_NAME ( object ) ,
name ) ;
break ;
}
if ( ! ( pspec - > flags & G_PARAM_WRITABLE ) )
{
g_warning ( " %s: property `%s' of object class `%s' is not writable " ,
G_STRLOC ,
pspec - > name ,
G_OBJECT_TYPE_NAME ( object ) ) ;
break ;
}
g_value_init ( & value , G_PARAM_SPEC_VALUE_TYPE ( pspec ) ) ;
G_VALUE_COLLECT ( & value , var_args , 0 , & error ) ;
if ( error )
{
g_warning ( " %s: %s " , G_STRLOC , error ) ;
g_free ( error ) ;
/* we purposely leak the value here, it might not be
* in a sane state if an error condition occoured
*/
break ;
}
element_set_property ( element , pspec , & value ) ;
g_value_unset ( & value ) ;
name = va_arg ( var_args , gchar * ) ;
}
g_object_unref ( object ) ;
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_get_valist :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get properties of .
* @ first_property_name : the first property to get .
* @ var_args : the var_args list of other properties to get .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Gets properties from an element . If the element uses threadsafe properties ,
2002-07-24 21:06:17 +00:00
* the element will be locked before getting the given properties .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_get_valist ( GstElement * element , const gchar * first_property_name , va_list var_args )
{
const gchar * name ;
GObject * object ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
object = ( GObject * ) element ;
if ( ! GST_FLAG_IS_SET ( element , GST_ELEMENT_USE_THREADSAFE_PROPERTIES ) ) {
g_object_get_valist ( object , first_property_name , var_args ) ;
return ;
}
g_object_ref ( object ) ;
name = first_property_name ;
while ( name )
{
GValue value = { 0 , } ;
GParamSpec * pspec ;
gchar * error ;
pspec = g_object_class_find_property ( G_OBJECT_GET_CLASS ( object ) , name ) ;
if ( ! pspec )
{
g_warning ( " %s: object class `%s' has no property named `%s' " ,
G_STRLOC ,
G_OBJECT_TYPE_NAME ( object ) ,
name ) ;
break ;
}
if ( ! ( pspec - > flags & G_PARAM_READABLE ) )
{
g_warning ( " %s: property `%s' of object class `%s' is not readable " ,
G_STRLOC ,
pspec - > name ,
G_OBJECT_TYPE_NAME ( object ) ) ;
break ;
}
g_value_init ( & value , G_PARAM_SPEC_VALUE_TYPE ( pspec ) ) ;
element_get_property ( element , pspec , & value ) ;
G_VALUE_LCOPY ( & value , var_args , 0 , & error ) ;
if ( error )
{
g_warning ( " %s: %s " , G_STRLOC , error ) ;
g_free ( error ) ;
g_value_unset ( & value ) ;
break ;
}
g_value_unset ( & value ) ;
name = va_arg ( var_args , gchar * ) ;
}
g_object_unref ( object ) ;
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_set_property :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set properties on .
* @ property_name : the first property to get .
* @ value : the # GValue that holds the value to set .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Sets a property on an element . If the element uses threadsafe properties ,
2002-07-24 21:06:17 +00:00
* the property will be put on the async queue .
*/
2002-05-26 03:23:25 +00:00
void
2002-10-01 11:42:32 +00:00
gst_element_set_property ( GstElement * element , const gchar * property_name ,
const GValue * value )
2002-05-26 03:23:25 +00:00
{
GParamSpec * pspec ;
GObject * object ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( property_name ! = NULL ) ;
g_return_if_fail ( G_IS_VALUE ( value ) ) ;
2002-10-01 11:42:32 +00:00
object = ( GObject * ) element ;
2002-05-26 03:23:25 +00:00
2002-10-01 11:42:32 +00:00
GST_DEBUG ( GST_CAT_PROPERTIES , " setting property %s on element %s " ,
property_name , gst_element_get_name ( element ) ) ;
2002-05-26 03:23:25 +00:00
if ( ! GST_FLAG_IS_SET ( element , GST_ELEMENT_USE_THREADSAFE_PROPERTIES ) ) {
g_object_set_property ( object , property_name , value ) ;
return ;
}
g_object_ref ( object ) ;
2002-10-01 11:42:32 +00:00
pspec = g_object_class_find_property ( G_OBJECT_GET_CLASS ( object ) ,
property_name ) ;
2002-05-26 03:23:25 +00:00
if ( ! pspec )
g_warning ( " %s: object class `%s' has no property named `%s' " ,
G_STRLOC ,
G_OBJECT_TYPE_NAME ( object ) ,
property_name ) ;
else
element_set_property ( element , pspec , value ) ;
g_object_unref ( object ) ;
}
2002-07-24 21:06:17 +00:00
/**
* gst_element_get_property :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get properties of .
* @ property_name : the first property to get .
* @ value : the # GValue to store the property value in .
2002-07-24 21:06:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Gets a property from an element . If the element uses threadsafe properties ,
2002-07-24 21:06:17 +00:00
* the element will be locked before getting the given property .
*/
2002-05-26 03:23:25 +00:00
void
gst_element_get_property ( GstElement * element , const gchar * property_name , GValue * value )
{
GParamSpec * pspec ;
GObject * object ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( property_name ! = NULL ) ;
g_return_if_fail ( G_IS_VALUE ( value ) ) ;
object = ( GObject * ) element ;
if ( ! GST_FLAG_IS_SET ( element , GST_ELEMENT_USE_THREADSAFE_PROPERTIES ) ) {
g_object_get_property ( object , property_name , value ) ;
return ;
}
g_object_ref ( object ) ;
pspec = g_object_class_find_property ( G_OBJECT_GET_CLASS ( object ) , property_name ) ;
if ( ! pspec )
g_warning ( " %s: object class `%s' has no property named `%s' " ,
G_STRLOC ,
G_OBJECT_TYPE_NAME ( object ) ,
property_name ) ;
else
{
GValue * prop_value , tmp_value = { 0 , } ;
/* auto-conversion of the callers value type
*/
if ( G_VALUE_TYPE ( value ) = = G_PARAM_SPEC_VALUE_TYPE ( pspec ) )
{
g_value_reset ( value ) ;
prop_value = value ;
}
else if ( ! g_value_type_transformable ( G_PARAM_SPEC_VALUE_TYPE ( pspec ) , G_VALUE_TYPE ( value ) ) )
{
g_warning ( " can't retrieve property `%s' of type `%s' as value of type `%s' " ,
pspec - > name ,
g_type_name ( G_PARAM_SPEC_VALUE_TYPE ( pspec ) ) ,
G_VALUE_TYPE_NAME ( value ) ) ;
g_object_unref ( object ) ;
return ;
}
else
{
g_value_init ( & tmp_value , G_PARAM_SPEC_VALUE_TYPE ( pspec ) ) ;
prop_value = & tmp_value ;
}
element_get_property ( element , pspec , prop_value ) ;
if ( prop_value ! = value )
{
g_value_transform ( prop_value , value ) ;
g_value_unset ( & tmp_value ) ;
}
}
g_object_unref ( object ) ;
}
2002-04-07 23:32:16 +00:00
static GstPad *
gst_element_request_pad ( GstElement * element , GstPadTemplate * templ , const gchar * name )
{
GstPad * newpad = NULL ;
GstElementClass * oclass ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
2002-04-07 23:32:16 +00:00
if ( oclass - > request_new_pad )
newpad = ( oclass - > request_new_pad ) ( element , templ , name ) ;
return newpad ;
}
2002-06-12 22:26:36 +00:00
/**
* gst_element_release_request_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to release the request pad of .
* @ pad : the # GstPad to release .
2002-06-12 22:26:36 +00:00
*
2002-08-30 14:02:15 +00:00
* Makes the element free the previously requested pad as obtained
2002-06-12 22:26:36 +00:00
* with gst_element_get_request_pad ( ) .
*/
2002-04-28 13:27:32 +00:00
void
gst_element_release_request_pad ( GstElement * element , GstPad * pad )
{
GstElementClass * oclass ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( GST_IS_PAD ( pad ) ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
2002-04-28 13:27:32 +00:00
if ( oclass - > release_pad )
( oclass - > release_pad ) ( element , pad ) ;
}
2002-11-27 20:47:39 +00:00
/**
* gst_element_requires_clock :
* @ element : a # GstElement to query
*
* Query if the element requiresd a clock
*
* Returns : TRUE if the element requires a clock
*/
gboolean
gst_element_requires_clock ( GstElement * element )
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
2002-12-19 21:31:03 +00:00
return ( GST_ELEMENT_GET_CLASS ( element ) - > set_clock ! = NULL ) ;
2002-11-27 20:47:39 +00:00
}
/**
* gst_element_provides_clock :
* @ element : a # GstElement to query
*
* Query if the element provides a clock
*
* Returns : TRUE if the element provides a clock
*/
gboolean
gst_element_provides_clock ( GstElement * element )
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
2002-12-19 21:31:03 +00:00
return ( GST_ELEMENT_GET_CLASS ( element ) - > get_clock ! = NULL ) ;
2002-11-27 20:47:39 +00:00
}
2002-02-03 20:07:09 +00:00
/**
* gst_element_set_clock :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set the clock for .
* @ clock : the # GstClock to set for the element .
2002-02-03 20:07:09 +00:00
*
2002-04-23 15:02:35 +00:00
* Sets the clock for the element .
2002-02-03 20:07:09 +00:00
*/
void
gst_element_set_clock ( GstElement * element , GstClock * clock )
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-02-03 20:07:09 +00:00
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > set_clock )
oclass - > set_clock ( element , clock ) ;
2002-05-26 21:54:27 +00:00
2003-02-02 19:49:29 +00:00
gst_object_replace ( ( GstObject * * ) & element - > clock , ( GstObject * ) clock ) ;
2002-02-03 20:07:09 +00:00
}
/**
* gst_element_get_clock :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get the clock of .
2002-02-03 20:07:09 +00:00
*
2002-04-23 15:02:35 +00:00
* Gets the clock of the element .
2002-03-31 14:04:50 +00:00
*
2002-04-23 15:02:35 +00:00
* Returns : the # GstClock of the element .
2002-02-03 20:07:09 +00:00
*/
GstClock *
gst_element_get_clock ( GstElement * element )
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-02-03 20:07:09 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
2002-02-03 20:07:09 +00:00
2002-12-19 21:31:03 +00:00
if ( oclass - > get_clock )
return oclass - > get_clock ( element ) ;
2002-02-03 20:07:09 +00:00
return NULL ;
}
/**
* gst_element_clock_wait :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement .
2002-12-27 22:57:13 +00:00
* @ id : the # GstClock to use .
2002-08-30 14:02:15 +00:00
* @ jitter : the difference between requested time and actual time .
2002-02-03 20:07:09 +00:00
*
2002-04-23 15:02:35 +00:00
* Waits for a specific time on the clock .
2002-03-31 14:04:50 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the # GstClockReturn result of the wait operation .
2002-02-03 20:07:09 +00:00
*/
GstClockReturn
2002-12-27 22:57:13 +00:00
gst_element_clock_wait ( GstElement * element , GstClockID id , GstClockTimeDiff * jitter )
2002-02-03 20:07:09 +00:00
{
2002-05-26 21:54:27 +00:00
GstClockReturn res ;
2002-02-03 20:07:09 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , GST_CLOCK_ERROR ) ;
2002-03-30 17:05:03 +00:00
if ( GST_ELEMENT_SCHED ( element ) ) {
2002-12-27 22:57:13 +00:00
res = gst_scheduler_clock_wait ( GST_ELEMENT_SCHED ( element ) , element , id , jitter ) ;
2002-03-30 17:05:03 +00:00
}
else
2002-05-26 21:54:27 +00:00
res = GST_CLOCK_TIMEOUT ;
return res ;
}
2003-02-10 20:32:32 +00:00
# ifndef GST_DISABLE_INDEX
2002-12-14 13:02:16 +00:00
/**
* gst_element_is_indexable :
* @ element : a # GstElement .
*
* Queries if the element can be indexed /
*
* Returns : TRUE if the element can be indexed .
*/
2002-11-27 20:47:39 +00:00
gboolean
2002-12-14 13:02:16 +00:00
gst_element_is_indexable ( GstElement * element )
2002-11-27 20:47:39 +00:00
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
2002-12-19 21:31:03 +00:00
return ( GST_ELEMENT_GET_CLASS ( element ) - > set_index ! = NULL ) ;
2002-11-27 20:47:39 +00:00
}
2002-12-14 13:02:16 +00:00
/**
* gst_element_set_index :
* @ element : a # GstElement .
* @ index : a # GstIndex .
*
* Set the specified GstIndex on the element .
*/
2002-11-27 20:47:39 +00:00
void
2002-12-12 22:14:36 +00:00
gst_element_set_index ( GstElement * element , GstIndex * index )
2002-11-27 20:47:39 +00:00
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-11-27 20:47:39 +00:00
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
2002-12-12 22:14:36 +00:00
g_return_if_fail ( GST_IS_INDEX ( index ) ) ;
2002-11-27 20:47:39 +00:00
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > set_index )
oclass - > set_index ( element , index ) ;
2002-11-27 20:47:39 +00:00
}
2002-12-14 13:02:16 +00:00
/**
* gst_element_get_index :
* @ element : a # GstElement .
*
* Gets the index from the element .
*
* Returns : a # GstIndex or NULL when no index was set on the
* element .
*/
2002-12-12 22:14:36 +00:00
GstIndex *
gst_element_get_index ( GstElement * element )
2002-11-27 20:47:39 +00:00
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-11-27 20:47:39 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > get_index )
return oclass - > get_index ( element ) ;
2002-11-27 20:47:39 +00:00
return NULL ;
}
2003-02-10 20:32:32 +00:00
# endif
2002-11-27 20:47:39 +00:00
2002-05-26 21:54:27 +00:00
/**
* gst_element_release_locks :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to release all locks on .
2002-05-26 21:54:27 +00:00
*
2002-06-12 22:26:36 +00:00
* Instruct the element to release all the locks it is holding , such as
2002-05-26 21:54:27 +00:00
* blocking reads , waiting for the clock , . . .
*
* Returns : TRUE if the locks could be released .
*/
gboolean
gst_element_release_locks ( GstElement * element )
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-05-26 21:54:27 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > release_locks )
return oclass - > release_locks ( element ) ;
2002-05-26 21:54:27 +00:00
return TRUE ;
2002-02-03 20:07:09 +00:00
}
2000-01-30 09:03:00 +00:00
/**
* gst_element_add_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to add the pad to .
* @ pad : the # GstPad to add to the element .
2000-01-30 09:03:00 +00:00
*
2003-01-09 14:15:37 +00:00
* Add a pad ( link point ) to the element , setting the parent of the
2000-01-30 09:03:00 +00:00
* pad to the element ( and thus adding a reference ) .
*/
2001-01-20 03:10:44 +00:00
void
gst_element_add_pad ( GstElement * element , GstPad * pad )
2000-11-11 15:13:50 +00:00
{
g_return_if_fail ( element ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( pad ! = NULL ) ;
g_return_if_fail ( GST_IS_PAD ( pad ) ) ;
2000-01-30 09:03:00 +00:00
2001-12-14 22:59:21 +00:00
/* first check to make sure the pad's parent is already set */
2001-05-25 21:00:07 +00:00
g_return_if_fail ( GST_PAD_PARENT ( pad ) = = NULL ) ;
2001-12-14 22:59:21 +00:00
/* then check to see if there's already a pad by that name here */
2001-05-25 21:00:07 +00:00
g_return_if_fail ( gst_object_check_uniqueness ( element - > pads , GST_PAD_NAME ( pad ) ) = = TRUE ) ;
2000-01-30 09:03:00 +00:00
/* set the pad's parent */
2002-03-24 22:07:09 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " setting parent of pad '%s' to '%s' " ,
2001-05-25 21:00:07 +00:00
GST_PAD_NAME ( pad ) , GST_ELEMENT_NAME ( element ) ) ;
2001-01-29 00:06:02 +00:00
gst_object_set_parent ( GST_OBJECT ( pad ) , GST_OBJECT ( element ) ) ;
2000-01-30 09:03:00 +00:00
/* add it to the list */
2000-11-11 15:13:50 +00:00
element - > pads = g_list_append ( element - > pads , pad ) ;
2000-01-30 09:03:00 +00:00
element - > numpads + + ;
2000-12-20 09:39:43 +00:00
if ( gst_pad_get_direction ( pad ) = = GST_PAD_SRC )
element - > numsrcpads + + ;
else
element - > numsinkpads + + ;
2000-01-30 09:03:00 +00:00
/* emit the NEW_PAD signal */
2001-06-25 01:20:11 +00:00
g_signal_emit ( G_OBJECT ( element ) , gst_element_signals [ NEW_PAD ] , 0 , pad ) ;
2000-01-30 09:03:00 +00:00
}
2001-05-25 21:00:07 +00:00
/**
* gst_element_remove_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to remove pad from .
* @ pad : the # GstPad to remove from the element .
2001-05-25 21:00:07 +00:00
*
2003-01-09 14:15:37 +00:00
* Remove a pad ( link point ) from the element .
2001-05-25 21:00:07 +00:00
*/
void
gst_element_remove_pad ( GstElement * element , GstPad * pad )
{
g_return_if_fail ( element ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( pad ! = NULL ) ;
g_return_if_fail ( GST_IS_PAD ( pad ) ) ;
g_return_if_fail ( GST_PAD_PARENT ( pad ) = = element ) ;
2002-02-03 20:07:09 +00:00
2003-01-09 14:15:37 +00:00
/* check to see if the pad is still linked */
2002-01-27 22:35:08 +00:00
/* FIXME: what if someone calls _remove_pad instead of
2002-02-03 20:07:09 +00:00
_remove_ghost_pad ? */
if ( GST_IS_REAL_PAD ( pad ) ) {
2002-01-27 22:35:08 +00:00
g_return_if_fail ( GST_RPAD_PEER ( pad ) = = NULL ) ;
}
/* remove it from the list */
2001-05-25 21:00:07 +00:00
element - > pads = g_list_remove ( element - > pads , pad ) ;
element - > numpads - - ;
if ( gst_pad_get_direction ( pad ) = = GST_PAD_SRC )
element - > numsrcpads - - ;
else
element - > numsinkpads - - ;
2001-06-25 01:20:11 +00:00
g_signal_emit ( G_OBJECT ( element ) , gst_element_signals [ PAD_REMOVED ] , 0 , pad ) ;
2001-05-25 21:00:07 +00:00
gst_object_unparent ( GST_OBJECT ( pad ) ) ;
}
2000-01-30 09:03:00 +00:00
/**
* gst_element_add_ghost_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to add the ghost pad to .
* @ pad : the # GstPad from which the new ghost pad will be created .
* @ name : the name of the new ghost pad .
2000-01-30 09:03:00 +00:00
*
2002-08-30 14:02:15 +00:00
* Creates a ghost pad from the given pad , and adds it to the list of pads
2001-01-20 02:57:46 +00:00
* for this element .
2002-01-26 20:55:59 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the added ghost # GstPad , or NULL , if no ghost pad was created .
2000-01-30 09:03:00 +00:00
*/
2002-01-26 20:55:59 +00:00
GstPad *
2002-08-12 16:40:50 +00:00
gst_element_add_ghost_pad ( GstElement * element , GstPad * pad , const gchar * name )
2000-11-11 15:13:50 +00:00
{
2001-01-20 02:57:46 +00:00
GstPad * ghostpad ;
2002-01-26 20:55:59 +00:00
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( pad ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_PAD ( pad ) , NULL ) ;
2000-01-30 09:03:00 +00:00
2001-12-14 22:59:21 +00:00
/* then check to see if there's already a pad by that name here */
2002-01-26 20:55:59 +00:00
g_return_val_if_fail ( gst_object_check_uniqueness ( element - > pads , name ) = = TRUE , NULL ) ;
2001-05-25 21:00:07 +00:00
2002-08-12 16:40:50 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS ,
" creating new ghost pad called %s, from pad %s:%s " ,
name , GST_DEBUG_PAD_NAME ( pad ) ) ;
2001-01-20 02:57:46 +00:00
ghostpad = gst_ghost_pad_new ( name , pad ) ;
2000-01-30 09:03:00 +00:00
/* add it to the list */
2002-03-24 22:07:09 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " adding ghost pad %s to element %s " ,
2001-05-25 21:00:07 +00:00
name , GST_ELEMENT_NAME ( element ) ) ;
2001-01-20 02:57:46 +00:00
element - > pads = g_list_append ( element - > pads , ghostpad ) ;
2000-01-30 09:03:00 +00:00
element - > numpads + + ;
2001-12-14 22:59:21 +00:00
/* set the parent of the ghostpad */
2001-01-29 00:06:02 +00:00
gst_object_set_parent ( GST_OBJECT ( ghostpad ) , GST_OBJECT ( element ) ) ;
2001-01-20 02:57:46 +00:00
2002-03-24 22:07:09 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " added ghostpad %s:%s " , GST_DEBUG_PAD_NAME ( ghostpad ) ) ;
2000-01-30 09:03:00 +00:00
2000-12-31 22:18:05 +00:00
/* emit the NEW_GHOST_PAD signal */
2001-12-04 22:12:50 +00:00
g_signal_emit ( G_OBJECT ( element ) , gst_element_signals [ NEW_PAD ] , 0 , ghostpad ) ;
2002-01-26 20:55:59 +00:00
return ghostpad ;
2000-01-30 09:03:00 +00:00
}
2001-01-01 17:25:43 +00:00
/**
* gst_element_remove_ghost_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to remove the ghost pad from .
* @ pad : ghost # GstPad to remove .
2001-01-01 17:25:43 +00:00
*
2002-08-30 14:02:15 +00:00
* Removes a ghost pad from an element .
2001-01-01 17:25:43 +00:00
*/
2000-12-31 22:18:05 +00:00
void
gst_element_remove_ghost_pad ( GstElement * element , GstPad * pad )
{
g_return_if_fail ( element ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( pad ! = NULL ) ;
2001-07-11 12:33:17 +00:00
g_return_if_fail ( GST_IS_GHOST_PAD ( pad ) ) ;
2000-12-31 22:18:05 +00:00
2001-12-14 22:59:21 +00:00
/* FIXME this is redundant?
* wingo 10 - july - 2001 : I don ' t think so , you have to actually remove the pad
* from the element . gst_pad_remove_ghost_pad just removes the ghostpad from
* the real pad ' s ghost pad list
*/
2001-07-11 12:33:17 +00:00
gst_pad_remove_ghost_pad ( GST_PAD ( GST_PAD_REALIZE ( pad ) ) , pad ) ;
gst_element_remove_pad ( element , pad ) ;
2000-12-31 22:18:05 +00:00
}
2000-01-30 09:03:00 +00:00
/**
* gst_element_get_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to find pad of .
* @ name : the name of the pad to retrieve .
2000-01-30 09:03:00 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves a pad from the element by name .
2000-01-30 09:03:00 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : requested # GstPad if found , otherwise NULL .
2000-01-30 09:03:00 +00:00
*/
2000-11-11 15:13:50 +00:00
GstPad *
2001-01-20 03:10:44 +00:00
gst_element_get_pad ( GstElement * element , const gchar * name )
2000-11-11 15:13:50 +00:00
{
2002-04-07 23:32:16 +00:00
GstPad * pad ;
2000-01-30 09:03:00 +00:00
2000-11-11 15:13:50 +00:00
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
2001-01-03 20:44:28 +00:00
g_return_val_if_fail ( name ! = NULL , NULL ) ;
2002-11-02 13:19:30 +00:00
pad = gst_element_get_static_pad ( element , name ) ;
if ( ! pad )
pad = gst_element_get_request_pad ( element , name ) ;
2002-04-07 23:32:16 +00:00
return pad ;
}
/**
* gst_element_get_static_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to find a static pad of .
* @ name : the name of the static # GstPad to retrieve .
2002-04-07 23:32:16 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves a pad from the element by name . This version only retrieves
2002-04-07 23:32:16 +00:00
* already - existing ( i . e . ' static ' ) pads .
*
2002-08-30 14:02:15 +00:00
* Returns : the requested # GstPad if found , otherwise NULL .
2002-04-07 23:32:16 +00:00
*/
GstPad *
gst_element_get_static_pad ( GstElement * element , const gchar * name )
{
GList * walk ;
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( name ! = NULL , NULL ) ;
2000-01-30 09:03:00 +00:00
walk = element - > pads ;
while ( walk ) {
2002-03-30 17:05:03 +00:00
GstPad * pad ;
pad = GST_PAD ( walk - > data ) ;
2002-04-07 23:32:16 +00:00
if ( strcmp ( GST_PAD_NAME ( pad ) , name ) = = 0 ) {
GST_INFO ( GST_CAT_ELEMENT_PADS , " found pad %s:%s " , GST_DEBUG_PAD_NAME ( pad ) ) ;
2001-01-29 00:06:02 +00:00
return pad ;
2001-01-03 20:44:28 +00:00
}
2000-11-11 15:13:50 +00:00
walk = g_list_next ( walk ) ;
2000-01-30 09:03:00 +00:00
}
2002-04-07 23:32:16 +00:00
GST_INFO ( GST_CAT_ELEMENT_PADS , " no such pad '%s' in element \" %s \" " , name , GST_OBJECT_NAME ( element ) ) ;
2000-01-30 09:03:00 +00:00
return NULL ;
}
2002-04-07 23:32:16 +00:00
/**
* gst_element_get_request_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to find a request pad of .
* @ name : the name of the request # GstPad to retrieve .
2002-04-07 23:32:16 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves a pad from the element by name . This version only retrieves
2002-04-07 23:32:16 +00:00
* request pads .
*
2002-08-30 14:02:15 +00:00
* Returns : requested # GstPad if found , otherwise NULL .
2002-04-07 23:32:16 +00:00
*/
GstPad *
gst_element_get_request_pad ( GstElement * element , const gchar * name )
{
GstPadTemplate * templ = NULL ;
GstPad * pad ;
const gchar * req_name = NULL ;
gboolean templ_found = FALSE ;
GList * list ;
gint n ;
const gchar * data ;
gchar * str , * endptr = NULL ;
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( name ! = NULL , NULL ) ;
if ( strstr ( name , " % " ) ) {
2002-04-11 20:35:18 +00:00
templ = gst_element_get_pad_template ( element , name ) ;
2002-04-07 23:32:16 +00:00
req_name = NULL ;
if ( templ )
templ_found = TRUE ;
} else {
2002-04-11 20:35:18 +00:00
list = gst_element_get_pad_template_list ( element ) ;
2002-04-07 23:32:16 +00:00
while ( ! templ_found & & list ) {
templ = ( GstPadTemplate * ) list - > data ;
if ( templ - > presence = = GST_PAD_REQUEST ) {
/* we know that %s and %d are the only possibilities because of sanity
2002-04-11 20:35:18 +00:00
checks in gst_pad_template_new */
2002-04-07 23:32:16 +00:00
GST_DEBUG ( GST_CAT_PADS , " comparing %s to %s " , name , templ - > name_template ) ;
if ( ( str = strchr ( templ - > name_template , ' % ' ) ) & &
strncmp ( templ - > name_template , name , str - templ - > name_template ) = = 0 & &
strlen ( name ) > str - templ - > name_template ) {
data = name + ( str - templ - > name_template ) ;
if ( * ( str + 1 ) = = ' d ' ) {
/* it's an int */
n = ( gint ) strtol ( data , & endptr , 10 ) ;
if ( endptr & & * endptr = = ' \0 ' ) {
templ_found = TRUE ;
req_name = name ;
break ;
}
} else {
/* it's a string */
templ_found = TRUE ;
req_name = name ;
break ;
}
}
}
list = list - > next ;
}
}
if ( ! templ_found )
return NULL ;
pad = gst_element_request_pad ( element , templ , req_name ) ;
return pad ;
}
2000-01-30 09:03:00 +00:00
/**
* gst_element_get_pad_list :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get pads of .
2000-01-30 09:03:00 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves a list of the pads associated with the element .
2000-01-30 09:03:00 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the # GList of pads .
2000-01-30 09:03:00 +00:00
*/
2002-09-12 20:52:03 +00:00
const GList *
2001-01-20 03:10:44 +00:00
gst_element_get_pad_list ( GstElement * element )
2000-11-11 15:13:50 +00:00
{
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
2000-01-30 09:03:00 +00:00
2000-11-23 20:39:54 +00:00
/* return the list of pads */
2000-01-30 09:03:00 +00:00
return element - > pads ;
}
2001-07-11 12:33:17 +00:00
/**
2002-04-11 20:35:18 +00:00
* gst_element_class_add_pad_template :
2002-08-30 14:02:15 +00:00
* @ klass : the # GstElementClass to add the pad template to .
* @ templ : a # GstPadTemplate to add to the element class .
2001-07-11 12:33:17 +00:00
*
2002-08-30 14:02:15 +00:00
* Adds a padtemplate to an element class .
* This is useful if you have derived a custom bin and wish to provide
* an on - request pad at runtime . Plug - in writers should use
2002-04-11 20:35:18 +00:00
* gst_element_factory_add_pad_template instead .
2001-07-11 12:33:17 +00:00
*/
void
2002-08-30 14:02:15 +00:00
gst_element_class_add_pad_template ( GstElementClass * klass ,
GstPadTemplate * templ )
2001-07-11 12:33:17 +00:00
{
g_return_if_fail ( klass ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT_CLASS ( klass ) ) ;
g_return_if_fail ( templ ! = NULL ) ;
2002-04-11 20:35:18 +00:00
g_return_if_fail ( GST_IS_PAD_TEMPLATE ( templ ) ) ;
2001-07-11 12:33:17 +00:00
klass - > padtemplates = g_list_append ( klass - > padtemplates , templ ) ;
klass - > numpadtemplates + + ;
}
2000-12-28 00:18:26 +00:00
/**
2002-04-11 20:35:18 +00:00
* gst_element_get_pad_template_list :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get pad templates of .
2000-12-28 00:18:26 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves a list of the pad templates associated with the element .
2000-12-28 00:18:26 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the # GList of padtemplates .
2000-12-28 00:18:26 +00:00
*/
GList *
2002-04-11 20:35:18 +00:00
gst_element_get_pad_template_list ( GstElement * element )
2000-12-28 00:18:26 +00:00
{
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
2002-12-19 21:31:03 +00:00
return GST_ELEMENT_GET_CLASS ( element ) - > padtemplates ;
2000-12-28 00:18:26 +00:00
}
2001-01-18 23:46:15 +00:00
/**
2002-04-11 20:35:18 +00:00
* gst_element_get_pad_template :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get the pad template of .
* @ name : the name of the # GstPadTemplate to get .
2001-01-18 23:46:15 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves a padtemplate from this element with the
2001-01-18 23:46:15 +00:00
* given name .
*
2002-08-30 14:02:15 +00:00
* Returns : the # GstPadTemplate with the given name , or NULL if none was found .
* No unreferencing is necessary .
2001-01-18 23:46:15 +00:00
*/
GstPadTemplate *
2002-08-12 16:59:39 +00:00
gst_element_get_pad_template ( GstElement * element , const gchar * name )
2001-01-18 23:46:15 +00:00
{
GList * padlist ;
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( name ! = NULL , NULL ) ;
2002-04-11 20:35:18 +00:00
padlist = gst_element_get_pad_template_list ( element ) ;
2001-01-18 23:46:15 +00:00
while ( padlist ) {
GstPadTemplate * padtempl = ( GstPadTemplate * ) padlist - > data ;
if ( ! strcmp ( padtempl - > name_template , name ) )
return padtempl ;
2001-01-19 22:15:21 +00:00
2001-01-18 23:46:15 +00:00
padlist = g_list_next ( padlist ) ;
}
return NULL ;
}
2001-01-23 18:42:23 +00:00
/**
2002-04-12 20:06:14 +00:00
* gst_element_get_compatible_pad_template :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get a compatible pad template for .
* @ compattempl : the # GstPadTemplate to find a compatible template for .
2001-01-23 18:42:23 +00:00
*
2002-08-30 14:02:15 +00:00
* Generates a pad template for this element compatible with the given
2003-01-09 14:15:37 +00:00
* template ( meaning it is able to link with it ) .
2001-01-23 18:42:23 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the # GstPadTemplate of the element that is compatible with
2003-01-09 14:15:37 +00:00
* the given GstPadTemplate , or NULL if none was found . No unreferencing
2002-08-30 14:02:15 +00:00
* is necessary .
2001-01-23 18:42:23 +00:00
*/
2002-04-12 20:06:14 +00:00
GstPadTemplate *
2003-01-09 14:15:37 +00:00
gst_element_get_compatible_pad_template ( GstElement * element ,
2002-08-30 14:02:15 +00:00
GstPadTemplate * compattempl )
2001-01-23 18:42:23 +00:00
{
GstPadTemplate * newtempl = NULL ;
GList * padlist ;
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " gst_element_get_compatible_pad_template() " ) ;
2001-01-23 18:42:23 +00:00
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( compattempl ! = NULL , NULL ) ;
2002-04-11 20:35:18 +00:00
padlist = gst_element_get_pad_template_list ( element ) ;
2001-01-23 18:42:23 +00:00
while ( padlist ) {
GstPadTemplate * padtempl = ( GstPadTemplate * ) padlist - > data ;
2002-08-30 14:02:15 +00:00
gboolean comp = FALSE ;
2001-01-23 18:42:23 +00:00
2001-12-14 22:59:21 +00:00
/* Ignore name
* Ignore presence
* Check direction ( must be opposite )
* Check caps
*/
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_CAPS , " checking direction and caps " ) ;
2001-01-23 18:42:23 +00:00
if ( padtempl - > direction = = GST_PAD_SRC & &
compattempl - > direction = = GST_PAD_SINK ) {
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_CAPS , " compatible direction: found src pad template " ) ;
2002-10-02 07:51:54 +00:00
comp = gst_caps_is_always_compatible ( GST_PAD_TEMPLATE_CAPS ( padtempl ) ,
2002-08-30 14:02:15 +00:00
GST_PAD_TEMPLATE_CAPS ( compattempl ) ) ;
GST_DEBUG ( GST_CAT_CAPS , " caps are %scompatible " , ( comp ? " " : " not " ) ) ;
2001-01-23 18:42:23 +00:00
} else if ( padtempl - > direction = = GST_PAD_SINK & &
compattempl - > direction = = GST_PAD_SRC ) {
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_CAPS , " compatible direction: found sink pad template " ) ;
2002-10-02 07:51:54 +00:00
comp = gst_caps_is_always_compatible ( GST_PAD_TEMPLATE_CAPS ( compattempl ) ,
2002-08-30 14:02:15 +00:00
GST_PAD_TEMPLATE_CAPS ( padtempl ) ) ;
GST_DEBUG ( GST_CAT_CAPS , " caps are %scompatible " , ( comp ? " " : " not " ) ) ;
2001-01-23 18:42:23 +00:00
}
2002-08-30 14:02:15 +00:00
if ( comp ) {
2001-01-23 18:42:23 +00:00
newtempl = padtempl ;
break ;
}
padlist = g_list_next ( padlist ) ;
}
return newtempl ;
}
/**
* gst_element_request_compatible_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to request a new pad from .
2003-01-09 14:15:37 +00:00
* @ templ : the # GstPadTemplate to which the new pad should be able to link .
2001-01-23 18:42:23 +00:00
*
2002-08-30 14:02:15 +00:00
* Requests a new pad from the element . The template will
2001-01-23 18:42:23 +00:00
* be used to decide what type of pad to create . This function
* is typically used for elements with a padtemplate with presence
* GST_PAD_REQUEST .
*
2002-08-30 14:02:15 +00:00
* Returns : the new # GstPad that was created , or NULL if none could be created .
2001-01-23 18:42:23 +00:00
*/
GstPad *
gst_element_request_compatible_pad ( GstElement * element , GstPadTemplate * templ )
{
GstPadTemplate * templ_new ;
GstPad * pad = NULL ;
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( templ ! = NULL , NULL ) ;
2002-04-12 20:06:14 +00:00
templ_new = gst_element_get_compatible_pad_template ( element , templ ) ;
2001-03-07 21:52:56 +00:00
if ( templ_new ! = NULL )
2001-10-17 10:21:27 +00:00
pad = gst_element_request_pad ( element , templ_new , NULL ) ;
2001-01-23 18:42:23 +00:00
return pad ;
}
2001-01-18 23:46:15 +00:00
2002-01-28 00:51:39 +00:00
/**
* gst_element_get_compatible_pad_filtered :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement in which the pad should be found .
* @ pad : the # GstPad to find a compatible one for .
* @ filtercaps : the # GstCaps to use as a filter .
2002-01-28 00:51:39 +00:00
*
2003-01-09 14:15:37 +00:00
* Looks for an unlinked pad to which the given pad can link to .
* It is not guaranteed that linking the pads will work , though
2002-01-28 00:51:39 +00:00
* it should work in most cases .
*
2003-01-09 14:15:37 +00:00
* Returns : the # GstPad to which a link can be made .
2002-01-28 00:51:39 +00:00
*/
2003-01-09 14:15:37 +00:00
GstPad *
gst_element_get_compatible_pad_filtered ( GstElement * element , GstPad * pad ,
2002-08-30 14:02:15 +00:00
GstCaps * filtercaps )
2002-01-28 00:51:39 +00:00
{
2002-09-12 20:52:03 +00:00
const GList * pads ;
2002-01-28 00:51:39 +00:00
GstPadTemplate * templ ;
2002-02-20 21:31:16 +00:00
GstCaps * templcaps ;
2002-01-28 00:51:39 +00:00
GstPad * foundpad = NULL ;
2003-01-09 14:15:37 +00:00
2002-01-28 00:51:39 +00:00
/* checks */
g_return_val_if_fail ( element ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
g_return_val_if_fail ( pad ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_IS_PAD ( pad ) , NULL ) ;
2003-01-09 14:15:37 +00:00
2002-01-28 00:51:39 +00:00
/* let's use the real pad */
pad = ( GstPad * ) GST_PAD_REALIZE ( pad ) ;
g_return_val_if_fail ( pad ! = NULL , NULL ) ;
g_return_val_if_fail ( GST_RPAD_PEER ( pad ) = = NULL , NULL ) ;
2003-01-09 14:15:37 +00:00
/* try to get an existing unlinked pad */
2002-01-28 00:51:39 +00:00
pads = gst_element_get_pad_list ( element ) ;
2002-02-18 00:40:56 +00:00
while ( pads ) {
2002-01-28 00:51:39 +00:00
GstPad * current = GST_PAD ( pads - > data ) ;
if ( ( GST_PAD_PEER ( GST_PAD_REALIZE ( current ) ) = = NULL ) & &
2003-01-09 14:15:37 +00:00
gst_pad_can_link_filtered ( pad , current , filtercaps ) ) {
2002-01-28 00:51:39 +00:00
return current ;
}
pads = g_list_next ( pads ) ;
}
2003-01-09 14:15:37 +00:00
2002-01-28 00:51:39 +00:00
/* try to create a new one */
/* requesting is a little crazy, we need a template. Let's create one */
2002-02-18 00:40:56 +00:00
if ( filtercaps ! = NULL ) {
2002-02-19 05:59:07 +00:00
templcaps = gst_caps_intersect ( filtercaps , ( GstCaps * ) GST_RPAD_CAPS ( pad ) ) ;
if ( templcaps = = NULL )
2002-01-28 00:51:39 +00:00
return NULL ;
2002-02-19 05:59:07 +00:00
} else {
2003-02-02 19:49:29 +00:00
templcaps = gst_pad_get_caps ( pad ) ;
2002-01-28 00:51:39 +00:00
}
2003-01-09 14:15:37 +00:00
2002-04-11 20:35:18 +00:00
templ = gst_pad_template_new ( ( gchar * ) GST_PAD_NAME ( pad ) , GST_RPAD_DIRECTION ( pad ) ,
2002-02-19 05:59:07 +00:00
GST_PAD_ALWAYS , templcaps , NULL ) ;
2002-01-28 00:51:39 +00:00
foundpad = gst_element_request_compatible_pad ( element , templ ) ;
2002-02-19 05:59:07 +00:00
gst_object_unref ( GST_OBJECT ( templ ) ) ; /* this will take care of the caps too */
2003-01-09 14:15:37 +00:00
2002-02-19 05:59:07 +00:00
/* FIXME: this is broken, but it's in here so autoplugging elements that don't
2003-01-09 14:15:37 +00:00
have caps on their source padtemplates ( spider ) can link . . . */
2002-02-19 05:59:07 +00:00
if ( ! foundpad & & ! filtercaps ) {
2002-04-11 20:35:18 +00:00
templ = gst_pad_template_new ( ( gchar * ) GST_PAD_NAME ( pad ) , GST_RPAD_DIRECTION ( pad ) ,
2002-02-19 05:59:07 +00:00
GST_PAD_ALWAYS , NULL , NULL ) ;
foundpad = gst_element_request_compatible_pad ( element , templ ) ;
gst_object_unref ( GST_OBJECT ( templ ) ) ;
}
2002-01-28 00:51:39 +00:00
return foundpad ;
}
/**
* gst_element_get_compatible_pad :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement in which the pad should be found .
* @ pad : the # GstPad to find a compatible one for .
2002-01-28 00:51:39 +00:00
*
2003-01-09 14:15:37 +00:00
* Looks for an unlinked pad to which the given pad can link to .
* It is not guaranteed that linking the pads will work , though
2002-01-28 00:51:39 +00:00
* it should work in most cases .
*
2003-01-09 14:15:37 +00:00
* Returns : the # GstPad to which a link can be made , or NULL if none
2002-08-30 14:02:15 +00:00
* could be found .
2002-01-28 00:51:39 +00:00
*/
GstPad *
gst_element_get_compatible_pad ( GstElement * element , GstPad * pad )
{
return gst_element_get_compatible_pad_filtered ( element , pad , NULL ) ;
}
2002-02-21 14:44:27 +00:00
2002-01-28 00:51:39 +00:00
/**
2003-04-08 21:14:23 +00:00
* gst_element_link_pads_filtered :
2002-08-30 14:02:15 +00:00
* @ src : a # GstElement containing the source pad .
2003-04-08 21:14:23 +00:00
* @ srcpadname : the name of the # GstPad in source element or NULL for any element .
2002-08-30 14:02:15 +00:00
* @ dest : the # GstElement containing the destination pad .
2003-04-08 21:14:23 +00:00
* @ destpadname : the name of the # GstPad in destination element or NULL for any element .
2002-08-30 14:02:15 +00:00
* @ filtercaps : the # GstCaps to use as a filter .
2002-01-28 00:51:39 +00:00
*
2003-04-08 21:14:23 +00:00
* Links the two named pads of the source and destination elements .
* Side effect is that if one of the pads has no parent , it becomes a
* child of the parent of the other element . If they have different
* parents , the link fails .
2002-01-28 00:51:39 +00:00
*
2003-04-08 21:14:23 +00:00
* Returns : TRUE if the pads could be linked .
2002-01-28 00:51:39 +00:00
*/
gboolean
2003-04-08 21:14:23 +00:00
gst_element_link_pads_filtered ( GstElement * src , const gchar * srcpadname ,
GstElement * dest , const gchar * destpadname ,
GstCaps * filtercaps )
2002-01-28 00:51:39 +00:00
{
2002-09-12 20:52:03 +00:00
const GList * srcpads , * destpads , * srctempls , * desttempls , * l ;
2002-01-28 00:51:39 +00:00
GstPad * srcpad , * destpad ;
2002-02-18 00:40:56 +00:00
GstPadTemplate * srctempl , * desttempl ;
2002-01-28 00:51:39 +00:00
/* checks */
2002-10-01 11:42:32 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( src ) , FALSE ) ;
g_return_val_if_fail ( GST_IS_ELEMENT ( dest ) , FALSE ) ;
2003-04-08 21:14:23 +00:00
g_return_val_if_fail ( GST_STATE ( src ) ! = GST_STATE_PLAYING , FALSE ) ;
g_return_val_if_fail ( GST_STATE ( dest ) ! = GST_STATE_PLAYING , FALSE ) ;
GST_INFO ( GST_CAT_ELEMENT_PADS , " trying to link element %s:%s to element %s:%s " ,
GST_ELEMENT_NAME ( src ) , srcpadname ? srcpadname : " (any) " ,
GST_ELEMENT_NAME ( dest ) , destpadname ? destpadname : " (any) " ) ;
/* now get the pads we're trying to link and a list of all remaining pads */
if ( srcpadname ) {
srcpad = gst_element_get_pad ( src , srcpadname ) ;
if ( ! srcpad ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " no pad %s:%s " , GST_ELEMENT_NAME ( src ) , srcpadname ) ;
return FALSE ;
} else {
if ( ! ( GST_RPAD_DIRECTION ( srcpad ) = = GST_PAD_SRC ) ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " pad %s:%s is no src pad " , GST_DEBUG_PAD_NAME ( srcpad ) ) ;
return FALSE ;
}
if ( GST_PAD_PEER ( srcpad ) ! = NULL ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " pad %s:%s is already linked " , GST_DEBUG_PAD_NAME ( srcpad ) ) ;
return FALSE ;
}
}
srcpads = NULL ;
} else {
srcpads = gst_element_get_pad_list ( src ) ;
srcpad = srcpads ? ( GstPad * ) GST_PAD_REALIZE ( srcpads - > data ) : NULL ;
}
if ( destpadname ) {
destpad = gst_element_get_pad ( dest , destpadname ) ;
if ( ! destpad ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " no pad %s:%s " , GST_ELEMENT_NAME ( dest ) , destpadname ) ;
return FALSE ;
} else {
if ( ! ( GST_RPAD_DIRECTION ( destpad ) = = GST_PAD_SINK ) ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " pad %s:%s is no sink pad " , GST_DEBUG_PAD_NAME ( destpad ) ) ;
return FALSE ;
}
if ( GST_PAD_PEER ( destpad ) ! = NULL ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " pad %s:%s is already linked " , GST_DEBUG_PAD_NAME ( destpad ) ) ;
return FALSE ;
}
}
destpads = NULL ;
} else {
destpads = gst_element_get_pad_list ( dest ) ;
destpad = destpads ? ( GstPad * ) GST_PAD_REALIZE ( destpads - > data ) : NULL ;
}
2002-01-28 00:51:39 +00:00
2003-04-08 21:14:23 +00:00
if ( srcpadname & & destpadname ) {
/* two explicitly specified pads */
return gst_pad_link_filtered ( srcpad , destpad , filtercaps ) ;
}
if ( srcpad ) {
/* loop through the allowed pads in the source, trying to find a
2002-10-01 11:42:32 +00:00
* compatible destination pad */
2003-04-08 21:14:23 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " looping through allowed src and dest pads " ) ;
do {
2002-10-02 07:51:54 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " trying src pad %s:%s " ,
GST_DEBUG_PAD_NAME ( srcpad ) ) ;
2002-02-18 00:40:56 +00:00
if ( ( GST_RPAD_DIRECTION ( srcpad ) = = GST_PAD_SRC ) & &
( GST_PAD_PEER ( srcpad ) = = NULL ) ) {
2003-04-08 21:14:23 +00:00
GstPad * temp = gst_element_get_compatible_pad_filtered ( dest , srcpad ,
2002-08-30 14:02:15 +00:00
filtercaps ) ;
2003-04-08 21:14:23 +00:00
if ( temp & & gst_pad_link_filtered ( srcpad , temp , filtercaps ) ) {
2003-01-09 14:15:37 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " linked pad %s:%s to pad %s:%s " ,
2003-04-08 21:14:23 +00:00
GST_DEBUG_PAD_NAME ( srcpad ) , GST_DEBUG_PAD_NAME ( temp ) ) ;
2002-02-18 00:40:56 +00:00
return TRUE ;
}
2002-01-28 00:51:39 +00:00
}
2003-04-08 21:14:23 +00:00
/* find a better way for this mess */
if ( srcpads ) {
srcpads = g_list_next ( srcpads ) ;
if ( srcpads )
srcpad = ( GstPad * ) GST_PAD_REALIZE ( srcpads - > data ) ;
}
} while ( srcpads ) ;
}
if ( srcpadname ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " no link possible from %s:%s to %s " ,
GST_DEBUG_PAD_NAME ( srcpad ) , GST_ELEMENT_NAME ( dest ) ) ;
return FALSE ;
}
if ( destpad ) {
2002-02-18 00:40:56 +00:00
/* loop through the existing pads in the destination */
2003-04-08 21:14:23 +00:00
do {
2002-10-02 07:51:54 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " trying dest pad %s:%s " ,
GST_DEBUG_PAD_NAME ( destpad ) ) ;
2002-02-18 00:40:56 +00:00
if ( ( GST_RPAD_DIRECTION ( destpad ) = = GST_PAD_SINK ) & &
( GST_PAD_PEER ( destpad ) = = NULL ) ) {
2003-04-08 21:14:23 +00:00
GstPad * temp = gst_element_get_compatible_pad_filtered ( src , destpad ,
2002-08-30 14:02:15 +00:00
filtercaps ) ;
2003-04-08 21:14:23 +00:00
if ( temp & & gst_pad_link_filtered ( temp , destpad , filtercaps ) ) {
2003-01-09 14:15:37 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " linked pad %s:%s to pad %s:%s " ,
2003-04-08 21:14:23 +00:00
GST_DEBUG_PAD_NAME ( temp ) , GST_DEBUG_PAD_NAME ( destpad ) ) ;
2002-02-18 00:40:56 +00:00
return TRUE ;
}
}
2003-04-08 21:14:23 +00:00
if ( destpads ) {
destpads = g_list_next ( destpads ) ;
if ( destpads )
destpad = ( GstPad * ) GST_PAD_REALIZE ( destpads - > data ) ;
}
} while ( destpads ) ;
}
if ( destpadname ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " no link possible from %s to %s:%s " ,
GST_ELEMENT_NAME ( src ) , GST_DEBUG_PAD_NAME ( destpad ) ) ;
return FALSE ;
2002-01-28 00:51:39 +00:00
}
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS ,
" we might have request pads on both sides, checking... " ) ;
2002-04-11 20:35:18 +00:00
srctempls = gst_element_get_pad_template_list ( src ) ;
desttempls = gst_element_get_pad_template_list ( dest ) ;
2002-02-18 00:40:56 +00:00
if ( srctempls & & desttempls ) {
while ( srctempls ) {
srctempl = ( GstPadTemplate * ) srctempls - > data ;
if ( srctempl - > presence = = GST_PAD_REQUEST ) {
for ( l = desttempls ; l ; l = l - > next ) {
desttempl = ( GstPadTemplate * ) desttempls - > data ;
2002-08-30 14:02:15 +00:00
if ( desttempl - > presence = = GST_PAD_REQUEST & &
desttempl - > direction ! = srctempl - > direction ) {
2002-10-02 07:51:54 +00:00
if ( gst_caps_is_always_compatible ( gst_pad_template_get_caps ( srctempl ) ,
2002-04-11 20:35:18 +00:00
gst_pad_template_get_caps ( desttempl ) ) ) {
2002-08-30 14:02:15 +00:00
srcpad = gst_element_get_request_pad ( src ,
srctempl - > name_template ) ;
destpad = gst_element_get_request_pad ( dest ,
desttempl - > name_template ) ;
2003-01-09 14:15:37 +00:00
if ( gst_pad_link_filtered ( srcpad , destpad , filtercaps ) ) {
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS ,
2003-01-09 14:15:37 +00:00
" linked pad %s:%s to pad %s:%s " ,
2002-08-30 14:02:15 +00:00
GST_DEBUG_PAD_NAME ( srcpad ) ,
GST_DEBUG_PAD_NAME ( destpad ) ) ;
2002-02-18 00:40:56 +00:00
return TRUE ;
}
/* FIXME: we have extraneous request pads lying around */
}
}
}
2002-01-28 00:51:39 +00:00
}
2002-02-18 00:40:56 +00:00
srctempls = srctempls - > next ;
2002-01-28 00:51:39 +00:00
}
}
2002-02-18 00:40:56 +00:00
2003-01-09 14:15:37 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " no link possible from %s to %s " ,
2002-08-30 14:02:15 +00:00
GST_ELEMENT_NAME ( src ) , GST_ELEMENT_NAME ( dest ) ) ;
2002-01-28 00:51:39 +00:00
return FALSE ;
}
2003-04-08 21:14:23 +00:00
/**
* gst_element_link_filtered :
* @ src : a # GstElement containing the source pad .
* @ dest : the # GstElement containing the destination pad .
* @ filtercaps : the # GstCaps to use as a filter .
*
* Links the source to the destination element using the filtercaps .
* The link must be from source to destination , the other
* direction will not be tried .
* The functions looks for existing pads that aren ' t linked yet .
* It will use request pads if possible . But both pads will not be requested .
* If multiple links are possible , only one is established .
*
* Returns : TRUE if the elements could be linked .
*/
gboolean
gst_element_link_filtered ( GstElement * src , GstElement * dest ,
GstCaps * filtercaps )
{
return gst_element_link_pads_filtered ( src , NULL , dest , NULL , filtercaps ) ;
}
2002-01-28 00:51:39 +00:00
2002-02-21 14:44:27 +00:00
/**
2003-01-09 14:15:37 +00:00
* gst_element_link_many :
* @ element_1 : the first # GstElement in the link chain .
* @ element_2 : the second # GstElement in the link chain .
* @ . . . : the NULL - terminated list of elements to link in order .
2002-02-21 14:44:27 +00:00
*
2003-01-09 14:15:37 +00:00
* Chain together a series of elements . Uses # gst_element_link .
2002-02-21 14:44:27 +00:00
*
* Returns : TRUE on success , FALSE otherwise .
2002-03-31 14:04:50 +00:00
*/
2002-02-21 14:44:27 +00:00
gboolean
2003-01-09 14:15:37 +00:00
gst_element_link_many ( GstElement * element_1 , GstElement * element_2 , . . . )
2002-02-21 14:44:27 +00:00
{
va_list args ;
g_return_val_if_fail ( element_1 ! = NULL & & element_2 ! = NULL , FALSE ) ;
2002-08-30 14:02:15 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element_1 ) & &
GST_IS_ELEMENT ( element_2 ) , FALSE ) ;
2002-02-21 14:44:27 +00:00
va_start ( args , element_2 ) ;
while ( element_2 ) {
2003-01-09 14:15:37 +00:00
if ( ! gst_element_link ( element_1 , element_2 ) )
2002-02-21 14:44:27 +00:00
return FALSE ;
element_1 = element_2 ;
element_2 = va_arg ( args , GstElement * ) ;
}
va_end ( args ) ;
return TRUE ;
}
2002-01-28 00:51:39 +00:00
/**
2003-01-09 14:15:37 +00:00
* gst_element_link :
2002-08-30 14:02:15 +00:00
* @ src : a # GstElement containing the source pad .
* @ dest : the # GstElement containing the destination pad .
2002-01-28 00:51:39 +00:00
*
2003-01-09 22:59:37 +00:00
* Links the source to the destination element .
2003-01-09 14:15:37 +00:00
* The link must be from source to destination , the other
2002-01-28 00:51:39 +00:00
* direction will not be tried .
* The functions looks for existing pads and request pads that aren ' t
2003-01-09 14:15:37 +00:00
* linked yet . If multiple links are possible , only one is
2002-01-28 00:51:39 +00:00
* established .
*
2003-01-09 14:15:37 +00:00
* Returns : TRUE if the elements could be linked .
2002-01-28 00:51:39 +00:00
*/
gboolean
2003-01-09 14:15:37 +00:00
gst_element_link ( GstElement * src , GstElement * dest )
2002-01-28 00:51:39 +00:00
{
2003-04-08 21:14:23 +00:00
return gst_element_link_pads_filtered ( src , NULL , dest , NULL , NULL ) ;
2002-01-13 22:22:42 +00:00
}
/**
2003-01-09 14:15:37 +00:00
* gst_element_link_pads :
2002-08-30 14:02:15 +00:00
* @ src : a # GstElement containing the source pad .
* @ srcpadname : the name of the # GstPad in the source element .
* @ dest : the # GstElement containing the destination pad .
* @ destpadname : the name of the # GstPad in destination element .
2002-01-13 22:22:42 +00:00
*
2003-01-09 22:59:37 +00:00
* Links the two named pads of the source and destination elements .
2002-01-13 22:22:42 +00:00
* Side effect is that if one of the pads has no parent , it becomes a
* child of the parent of the other element . If they have different
2003-01-09 14:15:37 +00:00
* parents , the link fails .
2002-01-13 22:22:42 +00:00
*
2003-01-09 14:15:37 +00:00
* Returns : TRUE if the pads could be linked .
2002-01-13 22:22:42 +00:00
*/
gboolean
2003-01-09 14:15:37 +00:00
gst_element_link_pads ( GstElement * src , const gchar * srcpadname ,
2002-04-07 23:32:16 +00:00
GstElement * dest , const gchar * destpadname )
2002-01-13 22:22:42 +00:00
{
2003-01-09 14:15:37 +00:00
return gst_element_link_pads_filtered ( src , srcpadname , dest , destpadname , NULL ) ;
2000-01-30 09:03:00 +00:00
}
2001-01-06 02:35:17 +00:00
/**
2003-01-09 14:15:37 +00:00
* gst_element_unlink_pads :
2002-08-30 14:02:15 +00:00
* @ src : a # GstElement containing the source pad .
* @ srcpadname : the name of the # GstPad in source element .
* @ dest : a # GstElement containing the destination pad .
* @ destpadname : the name of the # GstPad in destination element .
2001-01-06 02:35:17 +00:00
*
2003-01-09 14:15:37 +00:00
* Unlinks the two named pads of the source and destination elements .
2001-01-06 02:35:17 +00:00
*/
2001-01-20 03:10:44 +00:00
void
2003-01-09 14:15:37 +00:00
gst_element_unlink_pads ( GstElement * src , const gchar * srcpadname ,
2002-04-07 23:32:16 +00:00
GstElement * dest , const gchar * destpadname )
2001-01-06 02:35:17 +00:00
{
GstPad * srcpad , * destpad ;
g_return_if_fail ( src ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT ( src ) ) ;
g_return_if_fail ( srcpadname ! = NULL ) ;
g_return_if_fail ( dest ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT ( dest ) ) ;
g_return_if_fail ( destpadname ! = NULL ) ;
/* obtain the pads requested */
srcpad = gst_element_get_pad ( src , srcpadname ) ;
if ( srcpad = = NULL ) {
GST_ERROR ( src , " source element has no pad \" %s \" " , srcpadname ) ;
return ;
}
destpad = gst_element_get_pad ( dest , destpadname ) ;
if ( srcpad = = NULL ) {
GST_ERROR ( dest , " destination element has no pad \" %s \" " , destpadname ) ;
return ;
}
2003-01-09 14:15:37 +00:00
/* we're satisified they can be unlinked, let's do it */
gst_pad_unlink ( srcpad , destpad ) ;
2001-01-06 02:35:17 +00:00
}
2002-02-18 00:40:56 +00:00
/**
2003-01-09 14:15:37 +00:00
* gst_element_unlink_many :
* @ element_1 : the first # GstElement in the link chain .
* @ element_2 : the second # GstElement in the link chain .
* @ . . . : the NULL - terminated list of elements to unlink in order .
2002-04-07 23:32:16 +00:00
*
2003-01-09 14:15:37 +00:00
* Unlinks a series of elements . Uses # gst_element_unlink .
2002-04-07 23:32:16 +00:00
*/
void
2003-01-09 14:15:37 +00:00
gst_element_unlink_many ( GstElement * element_1 , GstElement * element_2 , . . . )
2002-04-07 23:32:16 +00:00
{
va_list args ;
g_return_if_fail ( element_1 ! = NULL & & element_2 ! = NULL ) ;
g_return_if_fail ( GST_IS_ELEMENT ( element_1 ) & & GST_IS_ELEMENT ( element_2 ) ) ;
va_start ( args , element_2 ) ;
while ( element_2 ) {
2003-01-09 14:15:37 +00:00
gst_element_unlink ( element_1 , element_2 ) ;
2002-04-07 23:32:16 +00:00
element_1 = element_2 ;
element_2 = va_arg ( args , GstElement * ) ;
}
va_end ( args ) ;
}
/**
2003-01-09 14:15:37 +00:00
* gst_element_unlink :
* @ src : the source # GstElement to unlink .
* @ dest : the sink # GstElement to unlink .
2002-02-18 00:40:56 +00:00
*
2003-01-09 14:15:37 +00:00
* Unlinks all source pads of the source element with all sink pads
* of the sink element to which they are linked .
2002-02-18 00:40:56 +00:00
*/
void
2003-01-09 14:15:37 +00:00
gst_element_unlink ( GstElement * src , GstElement * dest )
2002-02-18 00:40:56 +00:00
{
2002-09-12 20:52:03 +00:00
const GList * srcpads ;
2002-02-20 21:31:16 +00:00
GstPad * pad ;
2002-02-18 00:40:56 +00:00
2002-08-30 14:02:15 +00:00
g_return_if_fail ( GST_IS_ELEMENT ( src ) ) ;
g_return_if_fail ( GST_IS_ELEMENT ( dest ) ) ;
2002-02-18 00:40:56 +00:00
2003-01-09 14:15:37 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " unlinking \" %s \" and \" %s \" " ,
2002-08-30 14:02:15 +00:00
GST_ELEMENT_NAME ( src ) , GST_ELEMENT_NAME ( dest ) ) ;
2002-06-05 18:56:31 +00:00
2002-02-18 00:40:56 +00:00
srcpads = gst_element_get_pad_list ( src ) ;
2002-02-20 21:31:16 +00:00
while ( srcpads ) {
2002-05-30 19:03:30 +00:00
pad = GST_PAD_CAST ( srcpads - > data ) ;
2003-01-09 14:15:37 +00:00
2003-02-11 20:28:29 +00:00
/* we only care about real src pads */
if ( GST_IS_REAL_PAD ( pad ) & & GST_PAD_IS_SRC ( pad ) ) {
2002-06-05 18:56:31 +00:00
GstPad * peerpad = GST_PAD_PEER ( pad ) ;
2003-02-11 20:28:29 +00:00
/* see if the pad is connected and is really a pad
* of dest */
if ( peerpad & &
( GST_OBJECT_PARENT ( peerpad ) = = ( GstObject * ) dest ) )
{
2003-01-09 14:15:37 +00:00
gst_pad_unlink ( pad , peerpad ) ;
2002-06-05 18:56:31 +00:00
}
}
2002-02-20 21:31:16 +00:00
srcpads = g_list_next ( srcpads ) ;
}
2002-02-18 00:40:56 +00:00
}
2001-12-18 19:03:07 +00:00
static void
2002-08-30 14:02:15 +00:00
gst_element_error_func ( GstElement * element , GstElement * source ,
gchar * errormsg )
2001-12-18 19:03:07 +00:00
{
2002-02-06 19:05:19 +00:00
/* tell the parent */
2002-02-06 21:12:52 +00:00
if ( GST_OBJECT_PARENT ( element ) ) {
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_EVENT , " forwarding error \" %s \" from %s to %s " ,
errormsg , GST_ELEMENT_NAME ( element ) ,
GST_OBJECT_NAME ( GST_OBJECT_PARENT ( element ) ) ) ;
2002-02-06 21:12:52 +00:00
gst_object_ref ( GST_OBJECT ( element ) ) ;
2002-08-30 14:02:15 +00:00
g_signal_emit ( G_OBJECT ( GST_OBJECT_PARENT ( element ) ) ,
gst_element_signals [ ERROR ] , 0 , source , errormsg ) ;
2002-02-06 21:12:52 +00:00
gst_object_unref ( GST_OBJECT ( element ) ) ;
2002-02-06 19:05:19 +00:00
}
2001-12-18 19:03:07 +00:00
}
2002-04-07 23:32:16 +00:00
2002-12-30 17:42:11 +00:00
static GstPad *
gst_element_get_random_pad ( GstElement * element , GstPadDirection dir )
2002-05-30 19:03:30 +00:00
{
GList * pads = element - > pads ;
2002-12-31 10:52:09 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " getting a random pad " ) ;
2002-05-30 19:03:30 +00:00
while ( pads ) {
GstPad * pad = GST_PAD_CAST ( pads - > data ) ;
2002-12-31 10:52:09 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " checking pad %s:%s " ,
GST_DEBUG_PAD_NAME ( pad ) ) ;
2002-12-30 17:42:11 +00:00
if ( GST_PAD_DIRECTION ( pad ) = = dir ) {
2003-01-09 20:02:34 +00:00
if ( GST_PAD_IS_LINKED ( pad ) ) {
2002-12-30 17:42:11 +00:00
return pad ;
2002-05-30 19:03:30 +00:00
}
2002-12-31 14:51:54 +00:00
else {
2003-01-09 14:15:37 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " pad %s:%s is not linked " ,
2002-12-31 10:52:09 +00:00
GST_DEBUG_PAD_NAME ( pad ) ) ;
2002-12-31 14:51:54 +00:00
}
2002-05-30 19:03:30 +00:00
}
2002-12-31 14:51:54 +00:00
else {
2002-12-31 10:52:09 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " pad %s:%s is in wrong direction " ,
GST_DEBUG_PAD_NAME ( pad ) ) ;
2002-12-31 14:51:54 +00:00
}
2002-05-30 19:03:30 +00:00
pads = g_list_next ( pads ) ;
}
2002-12-30 17:42:11 +00:00
return NULL ;
}
/**
* gst_element_get_event_masks :
* @ element : a # GstElement to query
*
* Get an array of event masks from the element .
* If the element doesn ' t
* implement an event masks function , the query will be forwarded
2003-01-09 14:15:37 +00:00
* to a random linked sink pad .
2002-12-30 17:42:11 +00:00
*
* Returns : An array of # GstEventMask elements .
*/
const GstEventMask *
gst_element_get_event_masks ( GstElement * element )
{
GstElementClass * oclass ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > get_event_masks )
return oclass - > get_event_masks ( element ) ;
else {
GstPad * pad = gst_element_get_random_pad ( element , GST_PAD_SINK ) ;
if ( pad )
return gst_pad_get_event_masks ( GST_PAD_PEER ( pad ) ) ;
}
return FALSE ;
2002-05-30 19:03:30 +00:00
}
2002-06-12 22:26:36 +00:00
/**
* gst_element_send_event :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to send the event to .
* @ event : the # GstEvent to send to the element .
2002-06-12 22:26:36 +00:00
*
2002-12-31 10:34:35 +00:00
* Sends an event to an element . If the element doesn ' t
2002-06-12 22:26:36 +00:00
* implement an event handler , the event will be forwarded
2002-08-30 14:02:15 +00:00
* to a random sink pad .
2002-12-31 10:34:35 +00:00
*
2002-06-12 22:26:36 +00:00
* Returns : TRUE if the event was handled .
*/
2002-05-30 19:03:30 +00:00
gboolean
gst_element_send_event ( GstElement * element , GstEvent * event )
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-05-30 19:03:30 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
g_return_val_if_fail ( event ! = NULL , FALSE ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > send_event )
return oclass - > send_event ( element , event ) ;
2002-12-30 17:42:11 +00:00
else {
GstPad * pad = gst_element_get_random_pad ( element , GST_PAD_SINK ) ;
2002-12-31 10:34:35 +00:00
if ( pad ) {
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " sending event to random pad %s:%s " ,
GST_DEBUG_PAD_NAME ( pad ) ) ;
2002-12-30 17:42:11 +00:00
return gst_pad_send_event ( GST_PAD_PEER ( pad ) , event ) ;
2002-12-31 10:34:35 +00:00
}
2002-12-30 17:42:11 +00:00
}
2002-12-31 10:34:35 +00:00
GST_DEBUG ( GST_CAT_ELEMENT_PADS , " can't send event on element %s " ,
GST_ELEMENT_NAME ( element ) ) ;
2002-05-30 19:03:30 +00:00
return FALSE ;
}
2002-12-30 17:42:11 +00:00
/**
* gst_element_get_query_types :
* @ element : a # GstElement to query
*
* Get an array of query types from the element .
* If the element doesn ' t
* implement a query types function , the query will be forwarded
* to a random sink pad .
*
* Returns : An array of # GstQueryType elements .
*/
const GstQueryType *
gst_element_get_query_types ( GstElement * element )
2002-06-08 14:59:34 +00:00
{
2002-12-30 17:42:11 +00:00
GstElementClass * oclass ;
2002-06-08 14:59:34 +00:00
2002-12-30 17:42:11 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > get_query_types )
return oclass - > get_query_types ( element ) ;
else {
GstPad * pad = gst_element_get_random_pad ( element , GST_PAD_SINK ) ;
if ( pad )
return gst_pad_get_query_types ( GST_PAD_PEER ( pad ) ) ;
2002-06-08 14:59:34 +00:00
}
2002-12-30 17:42:11 +00:00
return FALSE ;
2002-06-08 14:59:34 +00:00
}
2002-06-12 22:26:36 +00:00
/**
* gst_element_query :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to perform the query on .
2002-12-30 17:42:11 +00:00
* @ type : the # GstQueryType .
2002-08-30 14:02:15 +00:00
* @ format : the # GstFormat pointer to hold the format of the result .
* @ value : the pointer to the value of the result .
2002-06-12 22:26:36 +00:00
*
2002-08-30 14:02:15 +00:00
* Performs a query on the given element . If the format is set
2002-06-12 22:26:36 +00:00
* to GST_FORMAT_DEFAULT and this function returns TRUE , the
* format pointer will hold the default format .
* For element that don ' t implement a query handler , this function
2002-12-30 17:42:11 +00:00
* forwards the query to a random usable sinkpad of this element .
2002-06-12 22:26:36 +00:00
*
* Returns : TRUE if the query could be performed .
*/
2002-06-08 14:59:34 +00:00
gboolean
2002-12-30 17:42:11 +00:00
gst_element_query ( GstElement * element , GstQueryType type ,
2002-06-08 14:59:34 +00:00
GstFormat * format , gint64 * value )
{
2002-12-19 21:31:03 +00:00
GstElementClass * oclass ;
2002-06-08 14:59:34 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
g_return_val_if_fail ( format ! = NULL , FALSE ) ;
g_return_val_if_fail ( value ! = NULL , FALSE ) ;
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
2002-06-08 14:59:34 +00:00
2002-12-19 21:31:03 +00:00
if ( oclass - > query )
return oclass - > query ( element , type , format , value ) ;
2002-12-30 17:42:11 +00:00
else {
GstPad * pad = gst_element_get_random_pad ( element , GST_PAD_SINK ) ;
if ( pad )
return gst_pad_query ( GST_PAD_PEER ( pad ) , type , format , value ) ;
}
return FALSE ;
}
/**
* gst_element_get_formats :
* @ element : a # GstElement to query
*
* Get an array of formst from the element .
* If the element doesn ' t
* implement a formats function , the query will be forwarded
* to a random sink pad .
*
* Returns : An array of # GstFormat elements .
*/
const GstFormat *
gst_element_get_formats ( GstElement * element )
{
GstElementClass * oclass ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > get_formats )
return oclass - > get_formats ( element ) ;
else {
GstPad * pad = gst_element_get_random_pad ( element , GST_PAD_SINK ) ;
if ( pad )
return gst_pad_get_formats ( GST_PAD_PEER ( pad ) ) ;
}
return FALSE ;
}
/**
* gst_element_convert :
* @ element : a # GstElement to invoke the converter on .
* @ src_format : the source # GstFormat .
* @ src_value : the source value .
* @ dest_format : a pointer to the destination # GstFormat .
* @ dest_value : a pointer to the destination value .
*
* Invokes a conversion on the element .
* If the element doesn ' t
* implement a convert function , the query will be forwarded
* to a random sink pad .
*
* Returns : TRUE if the conversion could be performed .
*/
gboolean
gst_element_convert ( GstElement * element ,
GstFormat src_format , gint64 src_value ,
GstFormat * dest_format , gint64 * dest_value )
{
GstElementClass * oclass ;
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
g_return_val_if_fail ( dest_format ! = NULL , FALSE ) ;
g_return_val_if_fail ( dest_value ! = NULL , FALSE ) ;
if ( src_format = = * dest_format ) {
* dest_value = src_value ;
return TRUE ;
}
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
if ( oclass - > convert )
return oclass - > convert ( element ,
src_format , src_value ,
dest_format , dest_value ) ;
else {
GstPad * pad = gst_element_get_random_pad ( element , GST_PAD_SINK ) ;
if ( pad )
return gst_pad_convert ( GST_PAD_PEER ( pad ) ,
src_format , src_value ,
dest_format , dest_value ) ;
}
2002-06-08 14:59:34 +00:00
return FALSE ;
}
2000-02-02 06:26:44 +00:00
/**
* gst_element_error :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement with the error .
* @ error : the printf - style string describing the error .
* @ . . . : the optional arguments for the string .
2000-02-02 06:26:44 +00:00
*
2002-08-30 14:02:15 +00:00
* signals an error condition on an element .
* This function is used internally by elements .
* It results in the " error " signal .
2000-02-02 06:26:44 +00:00
*/
2001-01-20 03:10:44 +00:00
void
2001-12-18 19:03:07 +00:00
gst_element_error ( GstElement * element , const gchar * error , . . . )
{
va_list var_args ;
2002-02-06 19:05:19 +00:00
gchar * string ;
2001-12-18 19:03:07 +00:00
2002-02-06 19:05:19 +00:00
/* checks */
2001-12-22 21:18:17 +00:00
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
g_return_if_fail ( error ! = NULL ) ;
2002-02-06 19:05:19 +00:00
/* create error message */
2001-12-18 19:03:07 +00:00
va_start ( var_args , error ) ;
2002-02-06 19:05:19 +00:00
string = g_strdup_vprintf ( error , var_args ) ;
2001-12-18 19:03:07 +00:00
va_end ( var_args ) ;
2002-02-06 19:05:19 +00:00
GST_INFO ( GST_CAT_EVENT , " ERROR in %s: %s " , GST_ELEMENT_NAME ( element ) , string ) ;
2001-12-22 21:18:17 +00:00
2002-02-06 19:05:19 +00:00
/* emit the signal, make sure the element stays available */
2002-02-06 21:12:52 +00:00
gst_object_ref ( GST_OBJECT ( element ) ) ;
2002-02-06 19:05:19 +00:00
g_signal_emit ( G_OBJECT ( element ) , gst_element_signals [ ERROR ] , 0 , element , string ) ;
/* tell the scheduler */
2001-12-22 21:18:17 +00:00
if ( element - > sched ) {
gst_scheduler_error ( element - > sched , element ) ;
2002-02-06 19:05:19 +00:00
}
2001-12-22 21:18:17 +00:00
2003-01-01 04:28:33 +00:00
if ( GST_STATE ( element ) = = GST_STATE_PLAYING )
gst_element_set_state ( element , GST_STATE_PAUSED ) ;
2002-12-27 22:57:13 +00:00
2002-02-06 19:05:19 +00:00
/* cleanup */
2002-02-06 21:12:52 +00:00
gst_object_unref ( GST_OBJECT ( element ) ) ;
2002-02-06 19:05:19 +00:00
g_free ( string ) ;
2001-12-18 19:03:07 +00:00
}
2003-04-08 21:14:23 +00:00
/**
* gst_element_is_state_locked :
* @ element : a # GstElement .
*
* Checks if the state of an element is locked .
* If the state of an element is locked , state changes of the parent don ' t
* affect the element .
* This way you can leave currently unused elements inside bins . Just lock their
* state before changing the state from # GST_STATE_NULL .
*
* Returns : TRUE , if the element ' s state is locked .
*/
gboolean
gst_element_is_state_locked ( GstElement * element )
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
return GST_FLAG_IS_SET ( element , GST_ELEMENT_LOCKED_STATE ) ? TRUE : FALSE ;
}
/**
* gst_element_lock_state :
* @ element : a # GstElement .
*
* Locks the state of an element , so state changes of the parent don ' t affect
* this element anymore .
*
* Returns : TRUE , if the element ' s state could be locked .
*/
gboolean
gst_element_lock_state ( GstElement * element )
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
GST_INFO ( GST_CAT_STATES , " locking state of element %s \n " , GST_ELEMENT_NAME ( element ) ) ;
GST_FLAG_SET ( element , GST_ELEMENT_LOCKED_STATE ) ;
return TRUE ;
}
/**
* gst_element_unlock_state :
* @ element : a # GstElement .
*
* Unlocks the state of an element and synchronises the state with the parent .
* If this function succeeds , the state of this element is identical to the
* state of it ' s bin .
* When this function fails , the state of the element is undefined .
*
* Returns : TRUE , if the element ' s state could be unlocked .
*/
gboolean
gst_element_unlock_state ( GstElement * element )
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , FALSE ) ;
GST_INFO ( GST_CAT_STATES , " unlocking state of element %s \n " , GST_ELEMENT_NAME ( element ) ) ;
GST_FLAG_UNSET ( element , GST_ELEMENT_LOCKED_STATE ) ;
if ( GST_ELEMENT_PARENT ( element ) ) {
GST_DEBUG ( GST_CAT_STATES , " setting state of unlocked element %s to %s \n " , GST_ELEMENT_NAME ( element ) , gst_element_state_get_name ( GST_STATE ( GST_ELEMENT_PARENT ( element ) ) ) ) ;
GstElementState old_state = GST_STATE ( element ) ;
if ( gst_element_set_state ( element , GST_STATE ( GST_ELEMENT_PARENT ( element ) ) ) = = GST_STATE_FAILURE ) {
GST_DEBUG ( GST_CAT_STATES , " state change of unlocked element %s to %s stopped at %s, resetting \n " , GST_ELEMENT_NAME ( element ) ,
gst_element_state_get_name ( GST_STATE ( GST_ELEMENT_PARENT ( element ) ) ) , gst_element_state_get_name ( GST_STATE ( element ) ) ) ;
gst_element_set_state ( element , old_state ) ;
return FALSE ;
}
}
return TRUE ;
}
2001-10-21 18:00:31 +00:00
/**
* gst_element_get_state :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get the state of .
2001-10-21 18:00:31 +00:00
*
* Gets the state of the element .
*
2002-08-30 14:02:15 +00:00
* Returns : the # GstElementState of the element .
2001-10-21 18:00:31 +00:00
*/
2001-10-17 10:21:27 +00:00
GstElementState
2001-10-21 18:00:31 +00:00
gst_element_get_state ( GstElement * element )
2001-10-17 10:21:27 +00:00
{
2001-10-21 18:00:31 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , GST_STATE_VOID_PENDING ) ;
2001-10-17 10:21:27 +00:00
2001-10-21 18:00:31 +00:00
return GST_STATE ( element ) ;
2001-10-17 10:21:27 +00:00
}
2001-12-09 13:17:54 +00:00
/**
* gst_element_wait_state_change :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to wait for a state change on .
2001-12-09 13:17:54 +00:00
*
2002-04-23 10:32:16 +00:00
* Waits and blocks until the element changed its state .
2001-12-09 13:17:54 +00:00
*/
2001-12-04 22:12:50 +00:00
void
gst_element_wait_state_change ( GstElement * element )
{
2001-12-18 19:03:07 +00:00
g_mutex_lock ( element - > state_mutex ) ;
g_cond_wait ( element - > state_cond , element - > state_mutex ) ;
g_mutex_unlock ( element - > state_mutex ) ;
2001-12-04 22:12:50 +00:00
}
2002-04-07 23:32:16 +00:00
2000-01-30 09:03:00 +00:00
/**
* gst_element_set_state :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to change state of .
* @ state : the element ' s new # GstElementState .
2000-01-30 09:03:00 +00:00
*
2002-04-23 10:32:16 +00:00
* Sets the state of the element . This function will try to set the
* requested state by going through all the intermediary states and calling
* the class ' s state change function for each .
2000-01-30 09:03:00 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : TRUE if the state was successfully set .
2002-04-23 10:32:16 +00:00
* ( using # GstElementStateReturn ) .
2000-01-30 09:03:00 +00:00
*/
2002-10-29 17:53:42 +00:00
GstElementStateReturn
2001-01-20 03:10:44 +00:00
gst_element_set_state ( GstElement * element , GstElementState state )
2000-11-11 15:13:50 +00:00
{
2000-01-30 09:03:00 +00:00
GstElementClass * oclass ;
2000-11-23 08:13:43 +00:00
GstElementState curpending ;
2000-07-17 17:14:15 +00:00
GstElementStateReturn return_val = GST_STATE_SUCCESS ;
2000-01-30 09:03:00 +00:00
2000-11-11 15:13:50 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , GST_STATE_FAILURE ) ;
2001-05-25 21:00:07 +00:00
2000-11-23 20:39:54 +00:00
/* start with the current state */
2000-11-23 08:13:43 +00:00
curpending = GST_STATE ( element ) ;
2000-11-23 20:39:54 +00:00
2002-04-03 18:26:03 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element , " setting state from %s to %s " ,
2002-04-23 11:15:18 +00:00
gst_element_state_get_name ( curpending ) ,
gst_element_state_get_name ( state ) ) ;
2002-03-30 17:05:03 +00:00
2000-11-23 20:39:54 +00:00
/* loop until the final requested state is set */
2002-04-23 09:48:48 +00:00
while ( GST_STATE ( element ) ! = state
& & GST_STATE ( element ) ! = GST_STATE_VOID_PENDING ) {
2000-11-23 20:39:54 +00:00
/* move the curpending state in the correct direction */
2002-01-20 16:04:16 +00:00
if ( curpending < state )
2002-04-23 09:48:48 +00:00
curpending < < = 1 ;
2002-01-20 16:04:16 +00:00
else
2002-04-23 09:48:48 +00:00
curpending > > = 1 ;
2000-01-30 09:03:00 +00:00
2000-11-23 20:39:54 +00:00
/* set the pending state variable */
2001-12-14 22:59:21 +00:00
/* FIXME: should probably check to see that we don't already have one */
2000-11-23 08:13:43 +00:00
GST_STATE_PENDING ( element ) = curpending ;
2002-01-20 16:04:16 +00:00
2002-03-30 17:05:03 +00:00
if ( curpending ! = state ) {
2002-04-23 09:48:48 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element ,
" intermediate: setting state from %s to %s " ,
2002-05-05 17:45:41 +00:00
gst_element_state_get_name ( GST_STATE ( element ) ) ,
2002-04-23 11:15:18 +00:00
gst_element_state_get_name ( curpending ) ) ;
2002-03-30 17:05:03 +00:00
}
2000-11-23 08:13:43 +00:00
2000-11-23 20:39:54 +00:00
/* call the state change function so it can set the state */
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
2000-11-23 08:13:43 +00:00
if ( oclass - > change_state )
2002-01-20 16:04:16 +00:00
return_val = ( oclass - > change_state ) ( element ) ;
2000-11-23 08:13:43 +00:00
2001-12-04 22:12:50 +00:00
switch ( return_val ) {
case GST_STATE_FAILURE :
2002-08-30 14:02:15 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element ,
" have failed change_state return " ) ;
2002-04-28 13:27:32 +00:00
goto exit ;
2001-12-04 22:12:50 +00:00
case GST_STATE_ASYNC :
2002-08-30 14:02:15 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element ,
" element will change state async " ) ;
2002-04-28 13:27:32 +00:00
goto exit ;
2002-04-23 09:48:48 +00:00
case GST_STATE_SUCCESS :
2001-12-04 22:12:50 +00:00
/* Last thing we do is verify that a successful state change really
* did change the state . . . */
2002-01-20 16:04:16 +00:00
if ( GST_STATE ( element ) ! = curpending ) {
2002-03-30 17:05:03 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element ,
2002-08-30 14:02:15 +00:00
" element claimed state-change success, "
" but state didn't change %s, %s <-> %s " ,
gst_element_state_get_name ( GST_STATE ( element ) ) ,
gst_element_state_get_name ( GST_STATE_PENDING ( element ) ) ,
gst_element_state_get_name ( curpending ) ) ;
2001-12-04 22:12:50 +00:00
return GST_STATE_FAILURE ;
}
break ;
2002-04-23 09:48:48 +00:00
default :
/* somebody added a GST_STATE_ and forgot to do stuff here ! */
g_assert_not_reached ( ) ;
2000-12-28 22:12:02 +00:00
}
2001-12-04 22:12:50 +00:00
}
2002-04-28 13:27:32 +00:00
exit :
2001-08-06 20:37:21 +00:00
2001-12-04 22:12:50 +00:00
return return_val ;
}
2002-01-20 11:55:35 +00:00
static gboolean
gst_element_negotiate_pads ( GstElement * element )
{
GList * pads = GST_ELEMENT_PADS ( element ) ;
2002-04-03 18:26:03 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_CAPS , element , " negotiating pads " ) ;
2002-01-20 16:04:16 +00:00
2002-01-20 11:55:35 +00:00
while ( pads ) {
2002-01-20 16:04:16 +00:00
GstPad * pad = GST_PAD ( pads - > data ) ;
GstRealPad * srcpad ;
pads = g_list_next ( pads ) ;
if ( ! GST_IS_REAL_PAD ( pad ) )
continue ;
srcpad = GST_PAD_REALIZE ( pad ) ;
2002-01-20 11:55:35 +00:00
2003-01-09 14:15:37 +00:00
/* if we have a link on this pad and it doesn't have caps
2002-01-20 16:04:16 +00:00
* allready , try to negotiate */
2003-01-09 20:02:34 +00:00
if ( GST_PAD_IS_LINKED ( srcpad ) & & ! GST_PAD_CAPS ( srcpad ) ) {
2002-01-20 16:04:16 +00:00
GstRealPad * sinkpad ;
GstElementState otherstate ;
GstElement * parent ;
sinkpad = GST_RPAD_PEER ( GST_PAD_REALIZE ( srcpad ) ) ;
2002-01-20 11:55:35 +00:00
2002-01-20 16:04:16 +00:00
/* check the parent of the peer pad, if there is no parent do nothing */
parent = GST_PAD_PARENT ( sinkpad ) ;
if ( ! parent )
continue ;
2003-01-01 03:09:39 +00:00
/* skips pads that were already negotiating */
if ( GST_FLAG_IS_SET ( sinkpad , GST_PAD_NEGOTIATING ) | |
GST_FLAG_IS_SET ( srcpad , GST_PAD_NEGOTIATING ) )
continue ;
2002-01-20 16:04:16 +00:00
otherstate = GST_STATE ( parent ) ;
/* swap pads if needed */
2002-01-20 11:55:35 +00:00
if ( ! GST_PAD_IS_SRC ( srcpad ) ) {
GstRealPad * temp ;
temp = srcpad ;
srcpad = sinkpad ;
sinkpad = temp ;
}
2002-01-20 16:04:16 +00:00
/* only try to negotiate if the peer element is in PAUSED or higher too */
if ( otherstate > = GST_STATE_READY ) {
2002-08-30 14:02:15 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_CAPS , element ,
" perform negotiate for %s:%s and %s:%s " ,
GST_DEBUG_PAD_NAME ( srcpad ) ,
GST_DEBUG_PAD_NAME ( sinkpad ) ) ;
2002-01-20 16:04:16 +00:00
if ( ! gst_pad_perform_negotiate ( GST_PAD ( srcpad ) , GST_PAD ( sinkpad ) ) )
return FALSE ;
}
else {
2002-08-30 14:02:15 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_CAPS , element ,
" not negotiating %s:%s and %s:%s, not in READY yet " ,
GST_DEBUG_PAD_NAME ( srcpad ) ,
GST_DEBUG_PAD_NAME ( sinkpad ) ) ;
2002-01-20 16:04:16 +00:00
}
2002-01-20 11:55:35 +00:00
}
}
return TRUE ;
}
2002-01-20 16:04:16 +00:00
static void
gst_element_clear_pad_caps ( GstElement * element )
{
GList * pads = GST_ELEMENT_PADS ( element ) ;
2002-04-03 18:26:03 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_CAPS , element , " clearing pad caps " ) ;
2002-01-20 16:04:16 +00:00
while ( pads ) {
GstRealPad * pad = GST_PAD_REALIZE ( pads - > data ) ;
2003-02-02 19:49:29 +00:00
gst_caps_replace ( & GST_PAD_CAPS ( pad ) , NULL ) ;
2002-01-20 16:04:16 +00:00
pads = g_list_next ( pads ) ;
}
}
2002-12-27 22:57:13 +00:00
static void
gst_element_pads_activate ( GstElement * element , gboolean active )
{
GList * pads = element - > pads ;
while ( pads ) {
GstPad * pad = GST_PAD_CAST ( pads - > data ) ;
pads = g_list_next ( pads ) ;
if ( ! GST_IS_REAL_PAD ( pad ) )
continue ;
gst_pad_set_active ( pad , active ) ;
}
}
2001-12-04 22:12:50 +00:00
static GstElementStateReturn
gst_element_change_state ( GstElement * element )
{
GstElementState old_state ;
2001-12-22 21:18:17 +00:00
GstObject * parent ;
2002-01-20 16:04:16 +00:00
gint old_pending , old_transition ;
2001-12-04 22:12:50 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , GST_STATE_FAILURE ) ;
old_state = GST_STATE ( element ) ;
2002-01-20 16:04:16 +00:00
old_pending = GST_STATE_PENDING ( element ) ;
old_transition = GST_STATE_TRANSITION ( element ) ;
2001-12-04 22:12:50 +00:00
2002-08-30 14:02:15 +00:00
if ( old_pending = = GST_STATE_VOID_PENDING | |
old_state = = GST_STATE_PENDING ( element ) ) {
GST_INFO ( GST_CAT_STATES ,
" no state change needed for element %s (VOID_PENDING) " ,
GST_ELEMENT_NAME ( element ) ) ;
2001-12-04 22:12:50 +00:00
return GST_STATE_SUCCESS ;
}
2002-12-27 22:57:13 +00:00
GST_INFO ( GST_CAT_STATES , " %s default handler sets state from %s to %s %04x " ,
2002-08-30 14:02:15 +00:00
GST_ELEMENT_NAME ( element ) ,
gst_element_state_get_name ( old_state ) ,
gst_element_state_get_name ( old_pending ) ,
2002-12-27 22:57:13 +00:00
old_transition ) ;
2001-12-04 22:12:50 +00:00
2002-01-20 16:04:16 +00:00
/* we set the state change early for the negotiation functions */
GST_STATE ( element ) = old_pending ;
GST_STATE_PENDING ( element ) = GST_STATE_VOID_PENDING ;
2002-07-24 21:06:17 +00:00
switch ( old_transition ) {
2002-12-27 22:57:13 +00:00
case GST_STATE_PLAYING_TO_PAUSED :
gst_element_pads_activate ( element , FALSE ) ;
break ;
case GST_STATE_PAUSED_TO_PLAYING :
gst_element_pads_activate ( element , TRUE ) ;
break ;
2002-07-24 21:06:17 +00:00
/* if we are going to paused, we try to negotiate the pads */
case GST_STATE_READY_TO_PAUSED :
if ( ! gst_element_negotiate_pads ( element ) )
goto failure ;
break ;
/* going to the READY state clears all pad caps */
case GST_STATE_PAUSED_TO_READY :
gst_element_clear_pad_caps ( element ) ;
break ;
default :
break ;
2002-01-20 11:55:35 +00:00
}
2001-12-22 21:18:17 +00:00
parent = GST_ELEMENT_PARENT ( element ) ;
2002-08-30 14:02:15 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element ,
" signaling state change from %s to %s " ,
2002-07-28 01:46:38 +00:00
gst_element_state_get_name ( old_state ) ,
gst_element_state_get_name ( GST_STATE ( element ) ) ) ;
2002-11-02 13:19:30 +00:00
2002-11-19 23:15:23 +00:00
/* tell the scheduler if we have one */
if ( element - > sched ) {
if ( gst_scheduler_state_transition ( element - > sched , element ,
old_transition ) ! = GST_STATE_SUCCESS ) {
2003-01-23 19:51:26 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_STATES , element ,
" scheduler could change state " ) ;
2002-11-19 23:15:23 +00:00
goto failure ;
}
}
2002-07-28 01:46:38 +00:00
g_signal_emit ( G_OBJECT ( element ) , gst_element_signals [ STATE_CHANGE ] ,
2002-08-30 14:02:15 +00:00
0 , old_state , GST_STATE ( element ) ) ;
2002-07-28 01:46:38 +00:00
2002-01-20 16:04:16 +00:00
/* tell our parent about the state change */
2001-12-22 21:18:17 +00:00
if ( parent & & GST_IS_BIN ( parent ) ) {
2002-08-30 14:02:15 +00:00
gst_bin_child_state_change ( GST_BIN ( parent ) , old_state ,
GST_STATE ( element ) , element ) ;
2001-12-18 19:03:07 +00:00
}
2001-12-04 22:12:50 +00:00
2002-01-20 16:04:16 +00:00
/* signal the state change in case somebody is waiting for us */
2001-12-25 02:15:46 +00:00
g_mutex_lock ( element - > state_mutex ) ;
g_cond_signal ( element - > state_cond ) ;
g_mutex_unlock ( element - > state_mutex ) ;
2001-12-04 22:12:50 +00:00
return GST_STATE_SUCCESS ;
2002-01-20 16:04:16 +00:00
failure :
/* undo the state change */
GST_STATE ( element ) = old_state ;
GST_STATE_PENDING ( element ) = old_pending ;
return GST_STATE_FAILURE ;
2000-01-30 09:03:00 +00:00
}
2000-09-14 20:31:03 +00:00
/**
* gst_element_get_factory :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to request the element factory of .
2000-09-14 20:31:03 +00:00
*
2002-08-30 14:02:15 +00:00
* Retrieves the factory that was used to create this element .
2000-09-14 20:31:03 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the # GstElementFactory used for creating this element .
2000-09-14 20:31:03 +00:00
*/
2000-11-11 15:13:50 +00:00
GstElementFactory *
2001-01-20 03:10:44 +00:00
gst_element_get_factory ( GstElement * element )
2000-11-11 15:13:50 +00:00
{
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
2001-01-20 03:10:44 +00:00
2002-12-19 21:31:03 +00:00
return GST_ELEMENT_GET_CLASS ( element ) - > elementfactory ;
2000-08-21 21:20:38 +00:00
}
2001-05-25 21:00:07 +00:00
static void
2001-09-28 19:16:02 +00:00
gst_element_dispose ( GObject * object )
2001-05-25 21:00:07 +00:00
{
GstElement * element = GST_ELEMENT ( object ) ;
2002-02-20 21:31:16 +00:00
GList * pads ;
2001-09-28 19:16:02 +00:00
GstPad * pad ;
2003-01-09 14:15:37 +00:00
2002-04-03 18:26:03 +00:00
GST_DEBUG_ELEMENT ( GST_CAT_REFCOUNTING , element , " dispose " ) ;
2001-05-25 21:00:07 +00:00
2002-02-17 19:58:29 +00:00
gst_element_set_state ( element , GST_STATE_NULL ) ;
2003-01-09 14:15:37 +00:00
/* first we break all our links with the ouside */
2001-05-25 21:00:07 +00:00
if ( element - > pads ) {
GList * orig ;
orig = pads = g_list_copy ( element - > pads ) ;
while ( pads ) {
pad = GST_PAD ( pads - > data ) ;
2002-02-03 20:07:09 +00:00
if ( GST_PAD_PEER ( pad ) ) {
2003-01-09 14:15:37 +00:00
GST_DEBUG ( GST_CAT_REFCOUNTING , " unlinking pad '%s' " ,
2002-08-30 14:02:15 +00:00
GST_OBJECT_NAME ( GST_OBJECT ( GST_PAD ( GST_PAD_PEER ( pad ) ) ) ) ) ;
2003-01-09 14:15:37 +00:00
gst_pad_unlink ( pad , GST_PAD ( GST_PAD_PEER ( pad ) ) ) ;
2002-01-27 22:35:08 +00:00
}
gst_element_remove_pad ( element , pad ) ;
2002-02-03 20:07:09 +00:00
2001-05-25 21:00:07 +00:00
pads = g_list_next ( pads ) ;
}
g_list_free ( orig ) ;
g_list_free ( element - > pads ) ;
element - > pads = NULL ;
2000-01-30 09:03:00 +00:00
}
2001-05-25 21:00:07 +00:00
element - > numsrcpads = 0 ;
element - > numsinkpads = 0 ;
2001-12-15 22:37:35 +00:00
element - > numpads = 0 ;
2001-12-18 19:03:07 +00:00
g_mutex_free ( element - > state_mutex ) ;
g_cond_free ( element - > state_cond ) ;
2001-05-25 21:00:07 +00:00
2002-05-26 03:23:25 +00:00
if ( element - > prop_value_queue )
g_async_queue_unref ( element - > prop_value_queue ) ;
element - > prop_value_queue = NULL ;
if ( element - > property_mutex )
g_mutex_free ( element - > property_mutex ) ;
2003-01-09 14:15:37 +00:00
2003-02-02 19:49:29 +00:00
gst_object_replace ( ( GstObject * * ) & element - > sched , NULL ) ;
gst_object_replace ( ( GstObject * * ) & element - > clock , NULL ) ;
2003-01-17 18:50:07 +00:00
2001-09-28 19:16:02 +00:00
G_OBJECT_CLASS ( parent_class ) - > dispose ( object ) ;
2000-01-30 09:03:00 +00:00
}
2001-06-25 06:45:56 +00:00
# ifndef GST_DISABLE_LOADSAVE
2000-03-27 19:53:43 +00:00
/**
* gst_element_save_thyself :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to save .
* @ parent : the xml parent node .
2000-03-27 19:53:43 +00:00
*
2002-08-30 14:02:15 +00:00
* Saves the element as part of the given XML structure .
2000-03-27 19:53:43 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the new # xmlNodePtr .
2000-03-27 19:53:43 +00:00
*/
2001-01-29 00:06:02 +00:00
static xmlNodePtr
gst_element_save_thyself ( GstObject * object ,
2001-01-20 03:10:44 +00:00
xmlNodePtr parent )
2000-11-11 15:13:50 +00:00
{
2000-01-30 09:03:00 +00:00
GList * pads ;
GstElementClass * oclass ;
2002-01-11 15:49:47 +00:00
GParamSpec * * specs , * spec ;
gint nspecs , i ;
2002-02-06 19:05:19 +00:00
GValue value = { 0 , } ;
2001-01-29 00:06:02 +00:00
GstElement * element ;
g_return_val_if_fail ( GST_IS_ELEMENT ( object ) , parent ) ;
element = GST_ELEMENT ( object ) ;
2000-01-30 09:03:00 +00:00
2002-12-19 21:31:03 +00:00
oclass = GST_ELEMENT_GET_CLASS ( element ) ;
2000-01-30 09:03:00 +00:00
2001-05-25 21:00:07 +00:00
xmlNewChild ( parent , NULL , " name " , GST_ELEMENT_NAME ( element ) ) ;
2001-01-29 00:06:02 +00:00
2000-01-30 09:03:00 +00:00
if ( oclass - > elementfactory ! = NULL ) {
2001-01-29 00:06:02 +00:00
GstElementFactory * factory = ( GstElementFactory * ) oclass - > elementfactory ;
2001-08-21 20:16:48 +00:00
xmlNewChild ( parent , NULL , " type " , GST_OBJECT_NAME ( factory ) ) ;
2001-01-29 00:06:02 +00:00
xmlNewChild ( parent , NULL , " version " , factory - > details - > version ) ;
2000-01-30 09:03:00 +00:00
}
2002-01-11 15:49:47 +00:00
/* FIXME: what is this? */
2001-12-14 22:59:21 +00:00
/* if (element->manager) */
/* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2001-05-25 21:00:07 +00:00
2002-01-11 15:49:47 +00:00
/* params */
specs = g_object_class_list_properties ( G_OBJECT_GET_CLASS ( object ) , & nspecs ) ;
for ( i = 0 ; i < nspecs ; i + + ) {
spec = specs [ i ] ;
if ( spec - > flags & G_PARAM_READABLE ) {
xmlNodePtr param ;
2002-09-08 18:27:36 +00:00
char * contents ;
2002-01-11 15:49:47 +00:00
g_value_init ( & value , G_PARAM_SPEC_VALUE_TYPE ( spec ) ) ;
g_object_get_property ( G_OBJECT ( element ) , spec - > name , & value ) ;
param = xmlNewChild ( parent , NULL , " param " , NULL ) ;
xmlNewChild ( param , NULL , " name " , spec - > name ) ;
if ( G_IS_PARAM_SPEC_STRING ( spec ) )
2002-09-08 18:27:36 +00:00
contents = g_value_dup_string ( & value ) ;
2002-01-11 15:49:47 +00:00
else if ( G_IS_PARAM_SPEC_ENUM ( spec ) )
2002-09-08 18:27:36 +00:00
contents = g_strdup_printf ( " %d " , g_value_get_enum ( & value ) ) ;
2002-02-06 19:05:19 +00:00
else if ( G_IS_PARAM_SPEC_INT64 ( spec ) )
2002-12-11 21:33:07 +00:00
contents = g_strdup_printf ( " % " G_GINT64_FORMAT ,
g_value_get_int64 ( & value ) ) ;
2002-01-11 15:49:47 +00:00
else
2002-09-08 18:27:36 +00:00
contents = g_strdup_value_contents ( & value ) ;
xmlNewChild ( param , NULL , " value " , contents ) ;
g_free ( contents ) ;
2002-01-11 15:49:47 +00:00
g_value_unset ( & value ) ;
2000-01-30 09:03:00 +00:00
}
}
2001-03-07 21:52:56 +00:00
pads = GST_ELEMENT_PADS ( element ) ;
2000-12-28 00:18:26 +00:00
while ( pads ) {
2001-01-29 00:06:02 +00:00
GstPad * pad = GST_PAD ( pads - > data ) ;
2001-12-14 22:59:21 +00:00
/* figure out if it's a direct pad or a ghostpad */
2001-03-07 21:52:56 +00:00
if ( GST_ELEMENT ( GST_OBJECT_PARENT ( pad ) ) = = element ) {
xmlNodePtr padtag = xmlNewChild ( parent , NULL , " pad " , NULL ) ;
2001-01-29 00:06:02 +00:00
gst_object_save_thyself ( GST_OBJECT ( pad ) , padtag ) ;
2001-03-07 21:52:56 +00:00
}
2000-12-28 00:18:26 +00:00
pads = g_list_next ( pads ) ;
}
2001-01-29 00:06:02 +00:00
return parent ;
2000-01-30 09:03:00 +00:00
}
2002-01-11 15:49:47 +00:00
static void
gst_element_restore_thyself ( GstObject * object , xmlNodePtr self )
2000-11-11 15:13:50 +00:00
{
2002-01-11 15:49:47 +00:00
xmlNodePtr children ;
2000-09-27 19:33:10 +00:00
GstElement * element ;
2002-08-12 16:59:39 +00:00
gchar * name = NULL ;
gchar * value = NULL ;
2000-09-27 19:33:10 +00:00
2002-01-11 15:49:47 +00:00
element = GST_ELEMENT ( object ) ;
g_return_if_fail ( element ! = NULL ) ;
2000-09-27 19:33:10 +00:00
2002-01-11 15:49:47 +00:00
/* parameters */
2001-01-29 00:06:02 +00:00
children = self - > xmlChildrenNode ;
2000-09-27 19:33:10 +00:00
while ( children ) {
2002-01-11 15:49:47 +00:00
if ( ! strcmp ( children - > name , " param " ) ) {
2001-01-18 11:16:53 +00:00
xmlNodePtr child = children - > xmlChildrenNode ;
2000-09-27 19:33:10 +00:00
while ( child ) {
2000-11-11 15:13:50 +00:00
if ( ! strcmp ( child - > name , " name " ) ) {
2001-09-13 20:12:17 +00:00
name = xmlNodeGetContent ( child ) ;
2000-09-27 19:33:10 +00:00
}
2000-11-11 15:13:50 +00:00
else if ( ! strcmp ( child - > name , " value " ) ) {
2001-09-13 20:12:17 +00:00
value = xmlNodeGetContent ( child ) ;
2000-09-27 19:33:10 +00:00
}
child = child - > next ;
}
2002-01-11 15:49:47 +00:00
/* FIXME: can this just be g_object_set ? */
2002-08-30 14:02:15 +00:00
gst_util_set_object_arg ( G_OBJECT ( element ) , name , value ) ;
2000-09-27 19:33:10 +00:00
}
2000-12-28 00:18:26 +00:00
children = children - > next ;
}
2002-01-11 15:49:47 +00:00
/* pads */
2001-01-29 00:06:02 +00:00
children = self - > xmlChildrenNode ;
2000-12-28 00:18:26 +00:00
while ( children ) {
if ( ! strcmp ( children - > name , " pad " ) ) {
2003-01-09 14:15:37 +00:00
gst_pad_load_and_link ( children , GST_OBJECT ( element ) ) ;
2000-12-28 00:18:26 +00:00
}
2000-09-27 19:33:10 +00:00
children = children - > next ;
}
2002-12-19 21:31:03 +00:00
if ( GST_OBJECT_CLASS ( parent_class ) - > restore_thyself )
( GST_OBJECT_CLASS ( parent_class ) - > restore_thyself ) ( object , self ) ;
2000-09-27 19:33:10 +00:00
}
2001-10-17 10:21:27 +00:00
# endif /* GST_DISABLE_LOADSAVE */
2000-09-27 19:33:10 +00:00
2002-01-01 15:58:51 +00:00
/**
* gst_element_yield :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to yield .
2002-01-01 15:58:51 +00:00
*
2002-08-30 14:02:15 +00:00
* Requests a yield operation for the element . The scheduler will typically
2002-01-01 15:58:51 +00:00
* give control to another element .
*/
2001-12-22 23:19:17 +00:00
void
gst_element_yield ( GstElement * element )
{
if ( GST_ELEMENT_SCHED ( element ) ) {
gst_scheduler_yield ( GST_ELEMENT_SCHED ( element ) , element ) ;
}
}
2002-01-01 15:58:51 +00:00
/**
* gst_element_interrupt :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to interrupt .
2002-01-01 15:58:51 +00:00
*
2002-08-30 14:02:15 +00:00
* Requests the scheduler of this element to interrupt the execution of
2002-01-01 15:58:51 +00:00
* this element and scheduler another one .
*
2002-08-30 14:02:15 +00:00
* Returns : TRUE if the element should exit its chain / loop / get
2002-01-01 15:58:51 +00:00
* function ASAP , depending on the scheduler implementation .
*/
2001-12-27 00:47:41 +00:00
gboolean
2001-12-22 23:19:17 +00:00
gst_element_interrupt ( GstElement * element )
{
if ( GST_ELEMENT_SCHED ( element ) ) {
2001-12-27 00:47:41 +00:00
return gst_scheduler_interrupt ( GST_ELEMENT_SCHED ( element ) , element ) ;
2001-12-22 23:19:17 +00:00
}
2001-12-27 00:47:41 +00:00
else
2003-01-11 16:27:45 +00:00
return TRUE ;
2001-12-22 23:19:17 +00:00
}
2000-02-02 06:26:44 +00:00
/**
2002-05-25 15:36:59 +00:00
* gst_element_set_scheduler :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set the scheduler of .
* @ sched : the # GstScheduler to set .
2000-02-02 06:26:44 +00:00
*
2001-05-25 21:00:07 +00:00
* Sets the scheduler of the element . For internal use only , unless you ' re
2000-02-02 06:26:44 +00:00
* writing a new bin subclass .
*/
2001-01-20 03:10:44 +00:00
void
2002-05-25 15:36:59 +00:00
gst_element_set_scheduler ( GstElement * element ,
2002-03-30 17:05:03 +00:00
GstScheduler * sched )
2000-11-11 15:13:50 +00:00
{
2001-12-28 20:20:26 +00:00
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
GST_INFO_ELEMENT ( GST_CAT_PARENTAGE , element , " setting scheduler to %p " , sched ) ;
2003-02-02 19:49:29 +00:00
gst_object_replace ( ( GstObject * * ) & GST_ELEMENT_SCHED ( element ) , GST_OBJECT ( sched ) ) ;
2000-01-30 09:03:00 +00:00
}
2000-02-02 06:26:44 +00:00
/**
2002-05-25 15:36:59 +00:00
* gst_element_get_scheduler :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get the scheduler of .
2000-02-02 06:26:44 +00:00
*
2001-05-25 21:00:07 +00:00
* Returns the scheduler of the element .
2000-02-02 06:26:44 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the element ' s # GstScheduler .
2000-02-02 06:26:44 +00:00
*/
2001-12-04 22:12:50 +00:00
GstScheduler *
2002-05-25 15:36:59 +00:00
gst_element_get_scheduler ( GstElement * element )
2000-11-11 15:13:50 +00:00
{
2001-12-28 20:20:26 +00:00
g_return_val_if_fail ( GST_IS_ELEMENT ( element ) , NULL ) ;
2002-09-13 23:02:54 +00:00
return GST_ELEMENT_SCHED ( element ) ;
2000-01-30 09:03:00 +00:00
}
2000-02-02 06:26:44 +00:00
/**
* gst_element_set_loop_function :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set the loop function of .
* @ loop : Pointer to # GstElementLoopFunction .
2000-02-02 06:26:44 +00:00
*
* This sets the loop function for the element . The function pointed to
* can deviate from the GstElementLoopFunction definition in type of
* pointer only .
2000-11-23 21:49:09 +00:00
*
* NOTE : in order for this to take effect , the current loop function * must *
* exit . Assuming the loop function itself is the only one who will cause
* a new loopfunc to be assigned , this should be no problem .
2000-02-02 06:26:44 +00:00
*/
2001-01-20 03:10:44 +00:00
void
2002-03-30 17:05:03 +00:00
gst_element_set_loop_function ( GstElement * element ,
GstElementLoopFunction loop )
2000-11-11 15:13:50 +00:00
{
2003-02-03 23:13:36 +00:00
gboolean need_notify = FALSE ;
2001-12-28 20:20:26 +00:00
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
2003-02-03 23:13:36 +00:00
/* if the element changed from loop based to chain/get based
* or vice versa , we need to inform the scheduler about that */
if ( ( element - > loopfunc = = NULL & & loop ! = NULL ) | |
( element - > loopfunc ! = NULL & & loop = = NULL ) )
{
need_notify = TRUE ;
}
2000-11-23 21:49:09 +00:00
/* set the loop function */
2000-01-30 09:03:00 +00:00
element - > loopfunc = loop ;
2000-11-23 21:49:09 +00:00
2003-02-03 23:13:36 +00:00
if ( need_notify ) {
/* set the NEW_LOOPFUNC flag so everyone knows to go try again */
GST_FLAG_SET ( element , GST_ELEMENT_NEW_LOOPFUNC ) ;
2002-12-15 12:18:04 +00:00
2003-02-03 23:13:36 +00:00
if ( GST_ELEMENT_SCHED ( element ) ) {
gst_scheduler_scheduling_change ( GST_ELEMENT_SCHED ( element ) , element ) ;
}
2002-12-15 12:18:04 +00:00
}
2000-01-30 09:03:00 +00:00
}
2000-12-29 02:28:04 +00:00
/**
2001-12-28 20:20:26 +00:00
* gst_element_set_eos :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to set to the EOS state .
2001-01-20 03:10:44 +00:00
*
2001-12-28 20:20:26 +00:00
* Perform the actions needed to bring the element in the EOS state .
2000-12-29 02:28:04 +00:00
*/
void
2001-12-28 20:20:26 +00:00
gst_element_set_eos ( GstElement * element )
2001-01-13 13:51:08 +00:00
{
g_return_if_fail ( GST_IS_ELEMENT ( element ) ) ;
2002-08-30 14:02:15 +00:00
GST_DEBUG ( GST_CAT_EVENT , " setting EOS on element %s " ,
GST_OBJECT_NAME ( element ) ) ;
2001-12-28 20:20:26 +00:00
gst_element_set_state ( element , GST_STATE_PAUSED ) ;
2001-06-25 01:20:11 +00:00
g_signal_emit ( G_OBJECT ( element ) , gst_element_signals [ EOS ] , 0 ) ;
2001-01-13 13:51:08 +00:00
}
2001-05-25 21:00:07 +00:00
2001-10-21 18:00:31 +00:00
/**
2002-04-23 11:15:18 +00:00
* gst_element_state_get_name :
2002-08-30 14:02:15 +00:00
* @ state : a # GstElementState to get the name of .
2001-10-21 18:00:31 +00:00
*
* Gets a string representing the given state .
*
2002-08-30 14:02:15 +00:00
* Returns : a string with the name of the state .
2001-10-21 18:00:31 +00:00
*/
const gchar *
2002-04-23 11:15:18 +00:00
gst_element_state_get_name ( GstElementState state )
2001-10-21 18:00:31 +00:00
{
2001-05-25 21:00:07 +00:00
switch ( state ) {
# ifdef GST_DEBUG_COLOR
2001-06-25 01:20:11 +00:00
case GST_STATE_VOID_PENDING : return " NONE_PENDING " ; break ;
2001-05-25 21:00:07 +00:00
case GST_STATE_NULL : return " \033 [01;37mNULL \033 [00m " ; break ;
case GST_STATE_READY : return " \033 [01;31mREADY \033 [00m " ; break ;
case GST_STATE_PLAYING : return " \033 [01;32mPLAYING \033 [00m " ; break ;
case GST_STATE_PAUSED : return " \033 [01;33mPAUSED \033 [00m " ; break ;
2002-09-08 18:27:36 +00:00
default :
/* This is a memory leak */
2002-08-30 14:02:15 +00:00
return g_strdup_printf ( " \033 [01;37;41mUNKNOWN! \033 [00m(%d) " , state ) ;
2001-05-25 21:00:07 +00:00
# else
2001-06-25 01:20:11 +00:00
case GST_STATE_VOID_PENDING : return " NONE_PENDING " ; break ;
2001-05-25 21:00:07 +00:00
case GST_STATE_NULL : return " NULL " ; break ;
case GST_STATE_READY : return " READY " ; break ;
case GST_STATE_PLAYING : return " PLAYING " ; break ;
case GST_STATE_PAUSED : return " PAUSED " ; break ;
default : return " UNKNOWN! " ;
# endif
}
return " " ;
}
2001-12-13 23:37:47 +00:00
static void
2002-08-30 14:02:15 +00:00
gst_element_populate_std_props ( GObjectClass * klass , const gchar * prop_name ,
guint arg_id , GParamFlags flags )
2001-12-13 23:37:47 +00:00
{
2001-12-14 00:02:21 +00:00
GQuark prop_id = g_quark_from_string ( prop_name ) ;
2001-12-14 11:11:54 +00:00
GParamSpec * pspec ;
2001-12-14 00:02:21 +00:00
static GQuark fd_id = 0 ;
static GQuark blocksize_id ;
static GQuark bytesperread_id ;
static GQuark dump_id ;
static GQuark filesize_id ;
static GQuark mmapsize_id ;
static GQuark location_id ;
static GQuark offset_id ;
static GQuark silent_id ;
static GQuark touch_id ;
if ( ! fd_id ) {
fd_id = g_quark_from_static_string ( " fd " ) ;
blocksize_id = g_quark_from_static_string ( " blocksize " ) ;
bytesperread_id = g_quark_from_static_string ( " bytesperread " ) ;
dump_id = g_quark_from_static_string ( " dump " ) ;
filesize_id = g_quark_from_static_string ( " filesize " ) ;
mmapsize_id = g_quark_from_static_string ( " mmapsize " ) ;
location_id = g_quark_from_static_string ( " location " ) ;
offset_id = g_quark_from_static_string ( " offset " ) ;
silent_id = g_quark_from_static_string ( " silent " ) ;
touch_id = g_quark_from_static_string ( " touch " ) ;
}
if ( prop_id = = fd_id ) {
2001-12-14 11:11:54 +00:00
pspec = g_param_spec_int ( " fd " , " File-descriptor " ,
2001-12-14 18:11:52 +00:00
" File-descriptor for the file being read " ,
0 , G_MAXINT , 0 , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = blocksize_id ) {
pspec = g_param_spec_ulong ( " blocksize " , " Block Size " ,
2001-12-14 18:11:52 +00:00
" Block size to read per buffer " ,
0 , G_MAXULONG , 4096 , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = bytesperread_id ) {
2002-05-01 20:02:40 +00:00
pspec = g_param_spec_int ( " bytesperread " , " Bytes per read " ,
" Number of bytes to read per buffer " ,
2001-12-14 00:02:21 +00:00
G_MININT , G_MAXINT , 0 , flags ) ;
}
else if ( prop_id = = dump_id ) {
2002-08-30 14:02:15 +00:00
pspec = g_param_spec_boolean ( " dump " , " Dump " ,
" Dump bytes to stdout " ,
FALSE , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = filesize_id ) {
pspec = g_param_spec_int64 ( " filesize " , " File Size " ,
2001-12-14 18:11:52 +00:00
" Size of the file being read " ,
0 , G_MAXINT64 , 0 , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = mmapsize_id ) {
pspec = g_param_spec_ulong ( " mmapsize " , " mmap() Block Size " ,
" Size in bytes of mmap()d regions " ,
0 , G_MAXULONG , 4 * 1048576 , flags ) ;
}
else if ( prop_id = = location_id ) {
pspec = g_param_spec_string ( " location " , " File Location " ,
2001-12-14 18:11:52 +00:00
" Location of the file to read " ,
NULL , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = offset_id ) {
pspec = g_param_spec_int64 ( " offset " , " File Offset " ,
2001-12-14 18:11:52 +00:00
" Byte offset of current read pointer " ,
0 , G_MAXINT64 , 0 , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = silent_id ) {
2002-05-01 20:02:40 +00:00
pspec = g_param_spec_boolean ( " silent " , " Silent " , " Don't produce events " ,
2001-12-14 18:11:52 +00:00
FALSE , flags ) ;
2001-12-14 00:02:21 +00:00
}
else if ( prop_id = = touch_id ) {
pspec = g_param_spec_boolean ( " touch " , " Touch read data " ,
2001-12-14 18:11:52 +00:00
" Touch data to force disk read before "
" push () " , TRUE , flags ) ;
2001-12-14 00:02:21 +00:00
}
2001-12-14 11:11:54 +00:00
else {
2001-12-14 12:25:12 +00:00
g_warning ( " Unknown - 'standard' property '%s' id %d from klass %s " ,
prop_name , arg_id , g_type_name ( G_OBJECT_CLASS_TYPE ( klass ) ) ) ;
2001-12-14 11:11:54 +00:00
pspec = NULL ;
}
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
if ( pspec ) {
g_object_class_install_property ( klass , arg_id , pspec ) ;
}
2001-12-13 23:37:47 +00:00
}
/**
2002-03-18 04:41:37 +00:00
* gst_element_class_install_std_props :
2002-08-30 14:02:15 +00:00
* @ klass : the # GstElementClass to add the properties to .
* @ first_name : the name of the first property .
* in a NULL terminated
* @ . . . : the id and flags of the first property , followed by
* further ' name ' , ' id ' , ' flags ' triplets and terminated by NULL .
2001-12-13 23:37:47 +00:00
*
2002-08-30 14:02:15 +00:00
* Adds a list of standardized properties with types to the @ klass .
2001-12-13 23:37:47 +00:00
* the id is for the property switch in your get_prop method , and
* the flags determine readability / writeability .
* */
void
2002-08-30 14:02:15 +00:00
gst_element_class_install_std_props ( GstElementClass * klass ,
const gchar * first_name , . . . )
2001-12-13 23:37:47 +00:00
{
2001-12-14 00:02:21 +00:00
const char * name ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
va_list args ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
g_return_if_fail ( GST_IS_ELEMENT_CLASS ( klass ) ) ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
va_start ( args , first_name ) ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
name = first_name ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
while ( name ) {
int arg_id = va_arg ( args , int ) ;
int flags = va_arg ( args , int ) ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
gst_element_populate_std_props ( ( GObjectClass * ) klass , name , arg_id , flags ) ;
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
name = va_arg ( args , char * ) ;
}
2001-12-13 23:37:47 +00:00
2001-12-14 00:02:21 +00:00
va_end ( args ) ;
}
2002-03-06 16:14:34 +00:00
2002-03-18 04:41:37 +00:00
/**
* gst_element_get_managing_bin :
2002-08-30 14:02:15 +00:00
* @ element : a # GstElement to get the managing bin of .
2002-03-18 04:41:37 +00:00
*
2002-04-23 15:02:35 +00:00
* Gets the managing bin ( a pipeline or a thread , for example ) of an element .
2002-03-18 04:41:37 +00:00
*
2002-08-30 14:02:15 +00:00
* Returns : the # GstBin , or NULL on failure .
2002-03-18 04:41:37 +00:00
* */
2002-03-06 16:14:34 +00:00
GstBin *
gst_element_get_managing_bin ( GstElement * element )
{
GstBin * bin ;
g_return_val_if_fail ( element ! = NULL , NULL ) ;
bin = GST_BIN ( gst_object_get_parent ( GST_OBJECT_CAST ( element ) ) ) ;
while ( bin & & ! GST_FLAG_IS_SET ( GST_OBJECT_CAST ( bin ) , GST_BIN_FLAG_MANAGER ) )
bin = GST_BIN ( gst_object_get_parent ( GST_OBJECT_CAST ( bin ) ) ) ;
return bin ;
}