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