38 * |
38 * |
39 * <example> |
39 * <example> |
40 * <title>Using an element factory</title> |
40 * <title>Using an element factory</title> |
41 * <programlisting language="c"> |
41 * <programlisting language="c"> |
42 * #include <gst/gst.h> |
42 * #include <gst/gst.h> |
43 * |
|
44 * GstElement *src; |
43 * GstElement *src; |
45 * GstElementFactory *srcfactory; |
44 * GstElementFactory *srcfactory; |
46 * |
45 * gst_init(&argc,&argv); |
47 * gst_init (&argc, &argv); |
46 * srcfactory = gst_element_factory_find("filesrc"); |
48 * |
47 * g_return_if_fail(srcfactory != NULL); |
49 * srcfactory = gst_element_factory_find ("filesrc"); |
48 * src = gst_element_factory_create(srcfactory,"src"); |
50 * g_return_if_fail (srcfactory != NULL); |
49 * g_return_if_fail(src != NULL); |
51 * src = gst_element_factory_create (srcfactory, "src"); |
|
52 * g_return_if_fail (src != NULL); |
|
53 * ... |
50 * ... |
54 * </programlisting> |
51 * </programlisting> |
55 * </example> |
52 * </example> |
56 * |
53 * |
57 * Last reviewed on 2005-11-23 (0.9.5) |
54 * Last reviewed on 2005-11-23 (0.9.5) |
70 #define GST_CAT_DEFAULT element_factory_debug |
67 #define GST_CAT_DEFAULT element_factory_debug |
71 |
68 |
72 static void gst_element_factory_class_init (GstElementFactoryClass * klass); |
69 static void gst_element_factory_class_init (GstElementFactoryClass * klass); |
73 static void gst_element_factory_init (GstElementFactory * factory); |
70 static void gst_element_factory_init (GstElementFactory * factory); |
74 static void gst_element_factory_finalize (GObject * object); |
71 static void gst_element_factory_finalize (GObject * object); |
75 #ifdef __SYMBIAN32__ |
|
76 IMPORT_C |
|
77 #endif |
|
78 void __gst_element_details_clear (GstElementDetails * dp); |
72 void __gst_element_details_clear (GstElementDetails * dp); |
79 static void gst_element_factory_cleanup (GstElementFactory * factory); |
73 static void gst_element_factory_cleanup (GstElementFactory * factory); |
80 |
74 |
81 static GstPluginFeatureClass *parent_class = NULL; |
75 static GstPluginFeatureClass *parent_class = NULL; |
82 |
76 |
83 /* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */ |
77 /* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */ |
84 |
78 #ifdef __SYMBIAN32__ |
85 /* this is defined in gstelement.c */ |
79 EXPORT_C |
86 extern GQuark _gst_elementclass_factory; |
80 #endif |
87 |
81 |
88 #define _do_init \ |
82 |
89 { \ |
83 GType |
90 GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", \ |
84 gst_element_factory_get_type (void) |
91 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, \ |
85 { |
92 "element factories keep information about installed elements"); \ |
86 static GType elementfactory_type = 0; |
93 } |
87 |
94 |
88 if (G_UNLIKELY (elementfactory_type == 0)) { |
95 G_DEFINE_TYPE_WITH_CODE (GstElementFactory, gst_element_factory, |
89 static const GTypeInfo elementfactory_info = { |
96 GST_TYPE_PLUGIN_FEATURE, _do_init); |
90 sizeof (GstElementFactoryClass), |
97 |
91 NULL, |
|
92 NULL, |
|
93 (GClassInitFunc) gst_element_factory_class_init, |
|
94 NULL, |
|
95 NULL, |
|
96 sizeof (GstElementFactory), |
|
97 0, |
|
98 (GInstanceInitFunc) gst_element_factory_init, |
|
99 NULL |
|
100 }; |
|
101 |
|
102 elementfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, |
|
103 "GstElementFactory", &elementfactory_info, 0); |
|
104 GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", |
|
105 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, |
|
106 "element factories keep information about installed elements"); |
|
107 } |
|
108 return elementfactory_type; |
|
109 } |
98 static void |
110 static void |
99 gst_element_factory_class_init (GstElementFactoryClass * klass) |
111 gst_element_factory_class_init (GstElementFactoryClass * klass) |
100 { |
112 { |
101 GObjectClass *gobject_class = (GObjectClass *) klass; |
113 GObjectClass *gobject_class; |
|
114 GstObjectClass *gstobject_class; |
|
115 GstPluginFeatureClass *gstpluginfeature_class; |
|
116 |
|
117 gobject_class = (GObjectClass *) klass; |
|
118 gstobject_class = (GstObjectClass *) klass; |
|
119 gstpluginfeature_class = (GstPluginFeatureClass *) klass; |
102 |
120 |
103 parent_class = g_type_class_peek_parent (klass); |
121 parent_class = g_type_class_peek_parent (klass); |
104 |
122 |
105 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_factory_finalize); |
123 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_factory_finalize); |
106 } |
124 } |
178 } else { \ |
196 } else { \ |
179 g_warning ("Invalid UTF-8 in " G_STRINGIFY (__entry) ": %s", \ |
197 g_warning ("Invalid UTF-8 in " G_STRINGIFY (__entry) ": %s", \ |
180 __src->__entry); \ |
198 __src->__entry); \ |
181 __dest->__entry = g_strdup ("[ERROR: invalid UTF-8]"); \ |
199 __dest->__entry = g_strdup ("[ERROR: invalid UTF-8]"); \ |
182 } \ |
200 } \ |
183 }G_STMT_END |
201 } G_STMT_END |
184 #ifdef __SYMBIAN32__ |
202 |
185 EXPORT_C |
203 #ifdef __SYMBIAN32__ |
186 #endif |
204 EXPORT_C |
187 |
205 #endif |
188 |
|
189 void |
206 void |
190 __gst_element_details_set (GstElementDetails * dest, |
207 __gst_element_details_set (GstElementDetails * dest, |
191 const GstElementDetails * src) |
208 const GstElementDetails * src) |
192 { |
209 { |
193 VALIDATE_SET (dest, src, longname); |
210 VALIDATE_SET (dest, src, longname); |
272 |
290 |
273 gboolean |
291 gboolean |
274 gst_element_register (GstPlugin * plugin, const gchar * name, guint rank, |
292 gst_element_register (GstPlugin * plugin, const gchar * name, guint rank, |
275 GType type) |
293 GType type) |
276 { |
294 { |
277 GstPluginFeature *existing_feature; |
|
278 GstRegistry *registry; |
|
279 GstElementFactory *factory; |
295 GstElementFactory *factory; |
280 GType *interfaces; |
296 GType *interfaces; |
281 guint n_interfaces, i; |
297 guint n_interfaces, i; |
282 GstElementClass *klass; |
298 GstElementClass *klass; |
283 GList *item; |
299 GList *item; |
284 |
300 |
285 g_return_val_if_fail (name != NULL, FALSE); |
301 g_return_val_if_fail (name != NULL, FALSE); |
286 g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE); |
302 g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE); |
287 |
303 |
288 registry = gst_registry_get_default (); |
304 factory = GST_ELEMENT_FACTORY (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL)); |
289 |
305 gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name); |
290 /* check if feature already exists, if it exists there is no need to update it |
|
291 * when the registry is getting updated, outdated plugins and all there |
|
292 * feature are removed and readded. |
|
293 */ |
|
294 existing_feature = gst_registry_lookup_feature (registry, name); |
|
295 if (existing_feature) { |
|
296 GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", |
|
297 existing_feature, name); |
|
298 factory = GST_ELEMENT_FACTORY_CAST (existing_feature); |
|
299 factory->type = type; |
|
300 existing_feature->loaded = TRUE; |
|
301 g_type_set_qdata (type, _gst_elementclass_factory, factory); |
|
302 gst_object_unref (existing_feature); |
|
303 return TRUE; |
|
304 } |
|
305 |
|
306 factory = |
|
307 GST_ELEMENT_FACTORY_CAST (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL)); |
|
308 gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); |
|
309 GST_LOG_OBJECT (factory, "Created new elementfactory for type %s", |
306 GST_LOG_OBJECT (factory, "Created new elementfactory for type %s", |
310 g_type_name (type)); |
307 g_type_name (type)); |
311 |
308 |
312 klass = GST_ELEMENT_CLASS (g_type_class_ref (type)); |
309 klass = GST_ELEMENT_CLASS (g_type_class_ref (type)); |
313 if ((klass->details.longname == NULL) || |
310 if ((klass->details.longname == NULL) || |
327 newt->static_caps.string = gst_caps_to_string (templ->caps); |
324 newt->static_caps.string = gst_caps_to_string (templ->caps); |
328 factory->staticpadtemplates = |
325 factory->staticpadtemplates = |
329 g_list_append (factory->staticpadtemplates, newt); |
326 g_list_append (factory->staticpadtemplates, newt); |
330 } |
327 } |
331 factory->numpadtemplates = klass->numpadtemplates; |
328 factory->numpadtemplates = klass->numpadtemplates; |
332 g_type_set_qdata (type, _gst_elementclass_factory, factory); |
329 klass->elementfactory = factory; |
333 |
330 |
334 /* special stuff for URI handling */ |
331 /* special stuff for URI handling */ |
335 if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) { |
332 if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) { |
336 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) |
333 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) |
337 g_type_interface_peek (klass, GST_TYPE_URI_HANDLER); |
334 g_type_interface_peek (klass, GST_TYPE_URI_HANDLER); |
358 __gst_element_factory_add_interface (factory, g_type_name (interfaces[i])); |
355 __gst_element_factory_add_interface (factory, g_type_name (interfaces[i])); |
359 } |
356 } |
360 g_free (interfaces); |
357 g_free (interfaces); |
361 |
358 |
362 if (plugin && plugin->desc.name) { |
359 if (plugin && plugin->desc.name) { |
363 GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; |
360 GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name; |
364 } else { |
361 } else { |
365 GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; |
362 GST_PLUGIN_FEATURE (factory)->plugin_name = "NULL"; |
366 } |
363 } |
367 gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); |
364 gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank); |
368 GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; |
365 GST_PLUGIN_FEATURE (factory)->loaded = TRUE; |
369 |
366 |
370 gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory)); |
367 gst_registry_add_feature (gst_registry_get_default (), |
|
368 GST_PLUGIN_FEATURE (factory)); |
371 |
369 |
372 return TRUE; |
370 return TRUE; |
373 |
371 |
374 /* ERRORS */ |
372 /* ERRORS */ |
375 urierror: |
373 urierror: |
435 if (G_UNLIKELY (element == NULL)) |
433 if (G_UNLIKELY (element == NULL)) |
436 goto no_element; |
434 goto no_element; |
437 |
435 |
438 /* fill in the pointer to the factory in the element class. The |
436 /* fill in the pointer to the factory in the element class. The |
439 * class will not be unreffed currently. |
437 * class will not be unreffed currently. |
440 * Be thread safe as there might be 2 threads creating the first instance of |
438 * FIXME: This isn't safe and may leak a refcount on the factory if 2 threads |
441 * an element at the same moment |
439 * create the first instance of an element at the same moment */ |
442 */ |
|
443 oclass = GST_ELEMENT_GET_CLASS (element); |
440 oclass = GST_ELEMENT_GET_CLASS (element); |
444 if (!g_atomic_pointer_compare_and_exchange ( |
441 if (G_UNLIKELY (oclass->elementfactory == NULL)) |
445 (gpointer) & oclass->elementfactory, NULL, factory)) |
442 oclass->elementfactory = factory; |
|
443 else |
446 gst_object_unref (factory); |
444 gst_object_unref (factory); |
447 |
445 |
448 if (name) |
446 if (name) |
449 gst_object_set_name (GST_OBJECT_CAST (element), name); |
447 gst_object_set_name (GST_OBJECT (element), name); |
450 |
448 |
451 GST_DEBUG ("created element \"%s\"", GST_PLUGIN_FEATURE_NAME (factory)); |
449 GST_DEBUG ("created element \"%s\"", GST_PLUGIN_FEATURE_NAME (factory)); |
452 |
450 |
453 return element; |
451 return element; |
454 |
452 |
455 /* ERRORS */ |
453 /* ERRORS */ |
456 load_failed: |
454 load_failed: |
457 { |
455 { |
458 GST_WARNING_OBJECT (factory, |
456 GST_WARNING_OBJECT (factory, "loading plugin returned NULL!"); |
459 "loading plugin containing feature %s returned NULL!", name); |
|
460 return NULL; |
457 return NULL; |
461 } |
458 } |
462 no_type: |
459 no_type: |
463 { |
460 { |
464 GST_WARNING_OBJECT (factory, "factory has no type"); |
461 GST_WARNING_OBJECT (factory, "factory has no type"); |