• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "gstfrei0r.h"
25 #include "gstfrei0rfilter.h"
26 #include "gstfrei0rsrc.h"
27 #include "gstfrei0rmixer.h"
28 
29 #include <string.h>
30 #include <gmodule.h>
31 
32 GST_DEBUG_CATEGORY (frei0r_debug);
33 #define GST_CAT_DEFAULT frei0r_debug
34 
35 static GstStaticCaps bgra8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
36     ("BGRA"));
37 static GstStaticCaps rgba8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
38     ("RGBA"));
39 static GstStaticCaps packed32_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
40     ("{ BGRA, RGBA, ABGR, ARGB, BGRx, RGBx, xBGR, xRGB, AYUV }"));
41 
42 GstCaps *
gst_frei0r_caps_from_color_model(gint color_model)43 gst_frei0r_caps_from_color_model (gint color_model)
44 {
45   switch (color_model) {
46     case F0R_COLOR_MODEL_BGRA8888:
47       return gst_static_caps_get (&bgra8888_caps);
48     case F0R_COLOR_MODEL_RGBA8888:
49       return gst_static_caps_get (&rgba8888_caps);
50     case F0R_COLOR_MODEL_PACKED32:
51       return gst_static_caps_get (&packed32_caps);
52     default:
53       break;
54   }
55 
56   return NULL;
57 }
58 
59 void
gst_frei0r_klass_install_properties(GObjectClass * gobject_class,GstFrei0rFuncTable * ftable,GstFrei0rProperty * properties,gint n_properties)60 gst_frei0r_klass_install_properties (GObjectClass * gobject_class,
61     GstFrei0rFuncTable * ftable, GstFrei0rProperty * properties,
62     gint n_properties)
63 {
64   gint i, count = 1;
65   f0r_instance_t *instance = ftable->construct (640, 480);
66 
67   g_assert (instance);
68 
69   for (i = 0; i < n_properties; i++) {
70     f0r_param_info_t *param_info = &properties[i].info;
71     gchar *prop_name;
72 
73     ftable->get_param_info (param_info, i);
74 
75     if (!param_info->name) {
76       GST_ERROR ("Property %d of %s without a valid name", i,
77           g_type_name (G_TYPE_FROM_CLASS (gobject_class)));
78       continue;
79     }
80 
81     prop_name = g_ascii_strdown (param_info->name, -1);
82     g_strcanon (prop_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-');
83     /* satisfy glib2 (argname[0] must be [A-Za-z]) */
84     if (!((prop_name[0] >= 'a' && prop_name[0] <= 'z') ||
85             (prop_name[0] >= 'A' && prop_name[0] <= 'Z'))) {
86       gchar *tempstr = prop_name;
87 
88       prop_name = g_strconcat ("param-", prop_name, NULL);
89       g_free (tempstr);
90     }
91 
92     properties[i].prop_id = count;
93     properties[i].prop_idx = i;
94 
95     ftable->get_param_value (instance, &properties[i].default_value, i);
96     if (param_info->type == F0R_PARAM_STRING)
97       properties[i].default_value.data.s =
98           g_strdup (properties[i].default_value.data.s);
99 
100     switch (param_info->type) {
101       case F0R_PARAM_BOOL:
102         g_object_class_install_property (gobject_class, count++,
103             g_param_spec_boolean (prop_name, param_info->name,
104                 param_info->explanation,
105                 properties[i].default_value.data.b ? TRUE : FALSE,
106                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
107                 GST_PARAM_DOC_SHOW_DEFAULT));
108         properties[i].n_prop_ids = 1;
109         break;
110       case F0R_PARAM_DOUBLE:{
111         gdouble def = properties[i].default_value.data.d;
112 
113         /* If the default is NAN, +-INF we use 0.0 */
114         if (!(def >= 0.0 && def <= 1.0))
115           def = 0.0;
116 
117         g_object_class_install_property (gobject_class, count++,
118             g_param_spec_double (prop_name, param_info->name,
119                 param_info->explanation, 0.0, 1.0, def,
120                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
121                 GST_PARAM_DOC_SHOW_DEFAULT));
122         properties[i].n_prop_ids = 1;
123         break;
124       }
125       case F0R_PARAM_STRING:
126         g_object_class_install_property (gobject_class, count++,
127             g_param_spec_string (prop_name, param_info->name,
128                 param_info->explanation, properties[i].default_value.data.s,
129                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
130                 GST_PARAM_DOC_SHOW_DEFAULT));
131         properties[i].n_prop_ids = 1;
132         break;
133       case F0R_PARAM_COLOR:{
134         gchar *prop_name_full;
135         gchar *prop_nick_full;
136         gdouble def;
137 
138         def = properties[i].default_value.data.color.r;
139         /* If the default is out of range we use 0.0 */
140         if (!(def <= 1.0 && def >= 0.0))
141           def = 0.0;
142         prop_name_full = g_strconcat (prop_name, "-r", NULL);
143         prop_nick_full = g_strconcat (param_info->name, " (R)", NULL);
144         g_object_class_install_property (gobject_class, count++,
145             g_param_spec_float (prop_name_full, prop_nick_full,
146                 param_info->explanation, 0.0, 1.0, def,
147                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
148                 GST_PARAM_DOC_SHOW_DEFAULT));
149         g_free (prop_name_full);
150         g_free (prop_nick_full);
151 
152         def = properties[i].default_value.data.color.g;
153         /* If the default is out of range we use 0.0 */
154         if (!(def <= 1.0 && def >= 0.0))
155           def = 0.0;
156         prop_name_full = g_strconcat (prop_name, "-g", NULL);
157         prop_nick_full = g_strconcat (param_info->name, " (G)", NULL);
158         g_object_class_install_property (gobject_class, count++,
159             g_param_spec_float (prop_name_full, prop_nick_full,
160                 param_info->explanation, 0.0, 1.0, def,
161                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
162                 GST_PARAM_DOC_SHOW_DEFAULT));
163         g_free (prop_name_full);
164         g_free (prop_nick_full);
165 
166         def = properties[i].default_value.data.color.b;
167         /* If the default is out of range we use 0.0 */
168         if (!(def <= 1.0 && def >= 0.0))
169           def = 0.0;
170         prop_name_full = g_strconcat (prop_name, "-b", NULL);
171         prop_nick_full = g_strconcat (param_info->name, " (B)", NULL);
172         g_object_class_install_property (gobject_class, count++,
173             g_param_spec_float (prop_name_full, prop_nick_full,
174                 param_info->explanation, 0.0, 1.0, def,
175                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
176                 GST_PARAM_DOC_SHOW_DEFAULT));
177         g_free (prop_name_full);
178         g_free (prop_nick_full);
179 
180         properties[i].n_prop_ids = 3;
181         break;
182       }
183       case F0R_PARAM_POSITION:{
184         gchar *prop_name_full;
185         gchar *prop_nick_full;
186         gdouble def;
187 
188         def = properties[i].default_value.data.position.x;
189         /* If the default is out of range we use 0.0 */
190         if (!(def <= 1.0 && def >= 0.0))
191           def = 0.0;
192         prop_name_full = g_strconcat (prop_name, "-x", NULL);
193         prop_nick_full = g_strconcat (param_info->name, " (X)", NULL);
194         g_object_class_install_property (gobject_class, count++,
195             g_param_spec_double (prop_name_full, prop_nick_full,
196                 param_info->explanation, 0.0, 1.0, def,
197                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
198                 GST_PARAM_DOC_SHOW_DEFAULT));
199         g_free (prop_name_full);
200         g_free (prop_nick_full);
201 
202         def = properties[i].default_value.data.position.y;
203         /* If the default is out of range we use 0.0 */
204         if (!(def <= 1.0 && def >= 0.0))
205           def = 0.0;
206         prop_name_full = g_strconcat (prop_name, "-Y", NULL);
207         prop_nick_full = g_strconcat (param_info->name, " (Y)", NULL);
208         g_object_class_install_property (gobject_class, count++,
209             g_param_spec_double (prop_name_full, prop_nick_full,
210                 param_info->explanation, 0.0, 1.0, def,
211                 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
212                 GST_PARAM_DOC_SHOW_DEFAULT));
213         g_free (prop_name_full);
214         g_free (prop_nick_full);
215 
216         properties[i].n_prop_ids = 2;
217         break;
218       }
219       default:
220         g_assert_not_reached ();
221         break;
222     }
223 
224     g_free (prop_name);
225   }
226 
227   ftable->destruct (instance);
228 }
229 
230 GstFrei0rPropertyValue *
gst_frei0r_property_cache_init(GstFrei0rProperty * properties,gint n_properties)231 gst_frei0r_property_cache_init (GstFrei0rProperty * properties,
232     gint n_properties)
233 {
234   gint i;
235   GstFrei0rPropertyValue *ret = g_new0 (GstFrei0rPropertyValue, n_properties);
236 
237   for (i = 0; i < n_properties; i++) {
238     memcpy (&ret[i].data, &properties[i].default_value,
239         sizeof (GstFrei0rPropertyValue));
240 
241     if (properties[i].info.type == F0R_PARAM_STRING)
242       ret[i].data.s = g_strdup (ret[i].data.s);
243   }
244 
245   return ret;
246 }
247 
248 void
gst_frei0r_property_cache_free(GstFrei0rProperty * properties,GstFrei0rPropertyValue * property_cache,gint n_properties)249 gst_frei0r_property_cache_free (GstFrei0rProperty * properties,
250     GstFrei0rPropertyValue * property_cache, gint n_properties)
251 {
252   gint i;
253 
254   for (i = 0; i < n_properties; i++) {
255     if (properties[i].info.type == F0R_PARAM_STRING)
256       g_free (property_cache[i].data.s);
257   }
258   g_free (property_cache);
259 }
260 
261 f0r_instance_t *
gst_frei0r_instance_construct(GstFrei0rFuncTable * ftable,GstFrei0rProperty * properties,gint n_properties,GstFrei0rPropertyValue * property_cache,gint width,gint height)262 gst_frei0r_instance_construct (GstFrei0rFuncTable * ftable,
263     GstFrei0rProperty * properties, gint n_properties,
264     GstFrei0rPropertyValue * property_cache, gint width, gint height)
265 {
266   f0r_instance_t *instance = ftable->construct (width, height);
267   gint i;
268 
269   for (i = 0; i < n_properties; i++)
270     ftable->set_param_value (instance, &property_cache[i].data, i);
271 
272   return instance;
273 }
274 
275 gboolean
gst_frei0r_get_property(f0r_instance_t * instance,GstFrei0rFuncTable * ftable,GstFrei0rProperty * properties,gint n_properties,GstFrei0rPropertyValue * property_cache,guint prop_id,GValue * value)276 gst_frei0r_get_property (f0r_instance_t * instance, GstFrei0rFuncTable * ftable,
277     GstFrei0rProperty * properties, gint n_properties,
278     GstFrei0rPropertyValue * property_cache, guint prop_id, GValue * value)
279 {
280   gint i;
281   GstFrei0rProperty *prop = NULL;
282 
283   for (i = 0; i < n_properties; i++) {
284     if (properties[i].prop_id <= prop_id &&
285         properties[i].prop_id + properties[i].n_prop_ids > prop_id) {
286       prop = &properties[i];
287       break;
288     }
289   }
290 
291   if (!prop)
292     return FALSE;
293 
294   switch (prop->info.type) {
295     case F0R_PARAM_BOOL:{
296       gdouble d;
297 
298       if (instance)
299         ftable->get_param_value (instance, &d, prop->prop_idx);
300       else
301         d = property_cache[prop->prop_idx].data.b;
302 
303       g_value_set_boolean (value, (d < 0.5) ? FALSE : TRUE);
304       break;
305     }
306     case F0R_PARAM_DOUBLE:{
307       gdouble d;
308 
309       if (instance)
310         ftable->get_param_value (instance, &d, prop->prop_idx);
311       else
312         d = property_cache[prop->prop_idx].data.d;
313 
314       g_value_set_double (value, d);
315       break;
316     }
317     case F0R_PARAM_STRING:{
318       gchar *s;
319 
320       if (instance)
321         ftable->get_param_value (instance, &s, prop->prop_idx);
322       else
323         s = property_cache[prop->prop_idx].data.s;
324       g_value_set_string (value, s);
325       break;
326     }
327     case F0R_PARAM_COLOR:{
328       f0r_param_color_t color;
329 
330       if (instance)
331         ftable->get_param_value (instance, &color, prop->prop_idx);
332       else
333         color = property_cache[prop->prop_idx].data.color;
334 
335       switch (prop_id - prop->prop_id) {
336         case 0:
337           g_value_set_float (value, color.r);
338           break;
339         case 1:
340           g_value_set_float (value, color.g);
341           break;
342         case 2:
343           g_value_set_float (value, color.b);
344           break;
345       }
346       break;
347     }
348     case F0R_PARAM_POSITION:{
349       f0r_param_position_t position;
350 
351       if (instance)
352         ftable->get_param_value (instance, &position, prop->prop_idx);
353       else
354         position = property_cache[prop->prop_idx].data.position;
355 
356       switch (prop_id - prop->prop_id) {
357         case 0:
358           g_value_set_double (value, position.x);
359           break;
360         case 1:
361           g_value_set_double (value, position.y);
362           break;
363       }
364       break;
365     }
366     default:
367       g_assert_not_reached ();
368       break;
369   }
370 
371   return TRUE;
372 }
373 
374 gboolean
gst_frei0r_set_property(f0r_instance_t * instance,GstFrei0rFuncTable * ftable,GstFrei0rProperty * properties,gint n_properties,GstFrei0rPropertyValue * property_cache,guint prop_id,const GValue * value)375 gst_frei0r_set_property (f0r_instance_t * instance, GstFrei0rFuncTable * ftable,
376     GstFrei0rProperty * properties, gint n_properties,
377     GstFrei0rPropertyValue * property_cache, guint prop_id,
378     const GValue * value)
379 {
380   GstFrei0rProperty *prop = NULL;
381   gint i;
382 
383   for (i = 0; i < n_properties; i++) {
384     if (properties[i].prop_id <= prop_id &&
385         properties[i].prop_id + properties[i].n_prop_ids > prop_id) {
386       prop = &properties[i];
387       break;
388     }
389   }
390 
391   if (!prop)
392     return FALSE;
393 
394   switch (prop->info.type) {
395     case F0R_PARAM_BOOL:{
396       gboolean b = g_value_get_boolean (value);
397       gdouble d = b ? 1.0 : 0.0;
398 
399       if (instance)
400         ftable->set_param_value (instance, &d, prop->prop_idx);
401       property_cache[prop->prop_idx].data.b = d;
402       break;
403     }
404     case F0R_PARAM_DOUBLE:{
405       gdouble d = g_value_get_double (value);
406 
407       if (instance)
408         ftable->set_param_value (instance, &d, prop->prop_idx);
409       property_cache[prop->prop_idx].data.d = d;
410       break;
411     }
412     case F0R_PARAM_STRING:{
413       gchar *s = g_value_dup_string (value);
414 
415       /* Copies the string */
416       if (instance)
417         ftable->set_param_value (instance, s, prop->prop_idx);
418       property_cache[prop->prop_idx].data.s = s;
419       break;
420     }
421     case F0R_PARAM_COLOR:{
422       gfloat f = g_value_get_float (value);
423       f0r_param_color_t *color = &property_cache[prop->prop_idx].data.color;
424 
425       switch (prop_id - prop->prop_id) {
426         case 0:
427           color->r = f;
428           break;
429         case 1:
430           color->g = f;
431           break;
432         case 2:
433           color->b = f;
434           break;
435         default:
436           g_assert_not_reached ();
437       }
438 
439       if (instance)
440         ftable->set_param_value (instance, color, prop->prop_idx);
441       break;
442     }
443     case F0R_PARAM_POSITION:{
444       gdouble d = g_value_get_double (value);
445       f0r_param_position_t *position =
446           &property_cache[prop->prop_idx].data.position;
447 
448       switch (prop_id - prop->prop_id) {
449         case 0:
450           position->x = d;
451           break;
452         case 1:
453           position->y = d;
454           break;
455         default:
456           g_assert_not_reached ();
457       }
458       if (instance)
459         ftable->set_param_value (instance, position, prop->prop_idx);
460       break;
461     }
462     default:
463       g_assert_not_reached ();
464       break;
465   }
466 
467   return TRUE;
468 }
469 
470 static gboolean
register_plugin(GstPlugin * plugin,const gchar * vendor,const gchar * filename)471 register_plugin (GstPlugin * plugin, const gchar * vendor,
472     const gchar * filename)
473 {
474   GModule *module;
475   GstFrei0rPluginRegisterReturn ret = GST_FREI0R_PLUGIN_REGISTER_RETURN_FAILED;
476   GstFrei0rFuncTable ftable = { NULL, };
477   gint i;
478   f0r_plugin_info_t info = { NULL, };
479   f0r_instance_t *instance = NULL;
480 
481   GST_DEBUG ("Registering plugin '%s'", filename);
482 
483   module = g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
484   if (!module) {
485     GST_WARNING ("Failed to load plugin");
486     return FALSE;
487   }
488 
489   if (!g_module_symbol (module, "f0r_init", (gpointer *) & ftable.init)) {
490     GST_INFO ("No frei0r plugin");
491     g_module_close (module);
492     return FALSE;
493   }
494 
495   if (!g_module_symbol (module, "f0r_deinit", (gpointer *) & ftable.deinit) ||
496       !g_module_symbol (module, "f0r_construct",
497           (gpointer *) & ftable.construct)
498       || !g_module_symbol (module, "f0r_destruct",
499           (gpointer *) & ftable.destruct)
500       || !g_module_symbol (module, "f0r_get_plugin_info",
501           (gpointer *) & ftable.get_plugin_info)
502       || !g_module_symbol (module, "f0r_get_param_info",
503           (gpointer *) & ftable.get_param_info)
504       || !g_module_symbol (module, "f0r_set_param_value",
505           (gpointer *) & ftable.set_param_value)
506       || !g_module_symbol (module, "f0r_get_param_value",
507           (gpointer *) & ftable.get_param_value))
508     goto invalid_frei0r_plugin;
509 
510   /* One of these must exist */
511   g_module_symbol (module, "f0r_update", (gpointer *) & ftable.update);
512   g_module_symbol (module, "f0r_update2", (gpointer *) & ftable.update2);
513 
514   if (!ftable.init ()) {
515     GST_WARNING ("Failed to initialize plugin");
516     g_module_close (module);
517     return FALSE;
518   }
519 
520   if (!ftable.update && !ftable.update2)
521     goto invalid_frei0r_plugin;
522 
523   ftable.get_plugin_info (&info);
524 
525   if (info.frei0r_version > 1) {
526     GST_WARNING ("Unsupported frei0r version %d", info.frei0r_version);
527     ftable.deinit ();
528     g_module_close (module);
529     return FALSE;
530   }
531 
532   if (info.color_model > F0R_COLOR_MODEL_PACKED32) {
533     GST_WARNING ("Unsupported color model %d", info.color_model);
534     ftable.deinit ();
535     g_module_close (module);
536     return FALSE;
537   }
538 
539   for (i = 0; i < info.num_params; i++) {
540     f0r_param_info_t pinfo = { NULL, };
541 
542     ftable.get_param_info (&pinfo, i);
543     if (pinfo.type > F0R_PARAM_STRING) {
544       GST_WARNING ("Unsupported parameter type %d", pinfo.type);
545       ftable.deinit ();
546       g_module_close (module);
547       return FALSE;
548     }
549   }
550 
551   instance = ftable.construct (640, 480);
552   if (!instance) {
553     GST_WARNING ("Failed to instantiate plugin '%s'", info.name);
554     ftable.deinit ();
555     g_module_close (module);
556     return FALSE;
557   }
558   ftable.destruct (instance);
559 
560   switch (info.plugin_type) {
561     case F0R_PLUGIN_TYPE_FILTER:
562       ret = gst_frei0r_filter_register (plugin, vendor, &info, &ftable);
563       break;
564     case F0R_PLUGIN_TYPE_SOURCE:
565       ret = gst_frei0r_src_register (plugin, vendor, &info, &ftable);
566       break;
567     case F0R_PLUGIN_TYPE_MIXER2:
568     case F0R_PLUGIN_TYPE_MIXER3:
569       ret = gst_frei0r_mixer_register (plugin, vendor, &info, &ftable);
570       break;
571     default:
572       break;
573   }
574 
575   switch (ret) {
576     case GST_FREI0R_PLUGIN_REGISTER_RETURN_OK:
577       return TRUE;
578     case GST_FREI0R_PLUGIN_REGISTER_RETURN_FAILED:
579       GST_ERROR ("Failed to register frei0r plugin");
580       ftable.deinit ();
581       g_module_close (module);
582       return FALSE;
583     case GST_FREI0R_PLUGIN_REGISTER_RETURN_ALREADY_REGISTERED:
584       GST_DEBUG ("frei0r plugin already registered");
585       ftable.deinit ();
586       g_module_close (module);
587       return TRUE;
588     default:
589       g_return_val_if_reached (FALSE);
590   }
591 
592   g_return_val_if_reached (FALSE);
593 
594 invalid_frei0r_plugin:
595   GST_ERROR ("Invalid frei0r plugin");
596   ftable.deinit ();
597   g_module_close (module);
598 
599   return FALSE;
600 }
601 
602 static gboolean
register_plugins(GstPlugin * plugin,GHashTable * plugin_names,const gchar * path,const gchar * base_path)603 register_plugins (GstPlugin * plugin, GHashTable * plugin_names,
604     const gchar * path, const gchar * base_path)
605 {
606   GDir *dir;
607   gchar *filename;
608   const gchar *entry_name;
609   gboolean ret = TRUE;
610 
611   GST_DEBUG ("Scanning directory '%s' for frei0r plugins", path);
612 
613   dir = g_dir_open (path, 0, NULL);
614   if (!dir)
615     return FALSE;
616 
617   while ((entry_name = g_dir_read_name (dir))) {
618     gchar *tmp, *vendor = NULL;
619     gchar *hashtable_name;
620 
621     tmp = g_strdup (path + strlen (base_path));
622     if (*tmp == G_DIR_SEPARATOR && *(tmp + 1))
623       vendor = tmp + 1;
624     else if (*tmp)
625       vendor = tmp;
626 
627     if (vendor)
628       hashtable_name = g_strconcat (vendor, "-", entry_name, NULL);
629     else
630       hashtable_name = g_strdup (entry_name);
631 
632     if (g_hash_table_lookup_extended (plugin_names, hashtable_name, NULL, NULL)) {
633       g_free (hashtable_name);
634       continue;
635     }
636 
637     filename = g_build_filename (path, entry_name, NULL);
638     if ((g_str_has_suffix (filename, G_MODULE_SUFFIX)
639 #ifdef GST_EXTRA_MODULE_SUFFIX
640             || g_str_has_suffix (filename, GST_EXTRA_MODULE_SUFFIX)
641 #endif
642         ) && g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
643       gboolean this_ret;
644 
645       this_ret = register_plugin (plugin, vendor, filename);
646       if (this_ret)
647         g_hash_table_insert (plugin_names, g_strdup (hashtable_name), NULL);
648 
649       ret = ret && this_ret;
650     } else if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
651       ret = ret && register_plugins (plugin, plugin_names, filename, base_path);
652     }
653     g_free (filename);
654     g_free (hashtable_name);
655     g_free (tmp);
656   }
657   g_dir_close (dir);
658 
659   return ret;
660 }
661 
662 static gboolean
plugin_init(GstPlugin * plugin)663 plugin_init (GstPlugin * plugin)
664 {
665   const gchar *homedir;
666   gchar *path, *libdir_path;
667   GHashTable *plugin_names;
668   const gchar *frei0r_path;
669 
670   GST_DEBUG_CATEGORY_INIT (frei0r_debug, "frei0r", 0, "frei0r");
671 
672   gst_plugin_add_dependency_simple (plugin,
673       "FREI0R_PATH:HOME/.frei0r-1/lib",
674       LIBDIR "/frei0r-1:"
675       "/usr/lib/frei0r-1:/usr/local/lib/frei0r-1:"
676       "/usr/lib32/frei0r-1:/usr/local/lib32/frei0r-1:"
677       "/usr/lib64/frei0r-1:/usr/local/lib64/frei0r-1",
678       NULL, GST_PLUGIN_DEPENDENCY_FLAG_RECURSE);
679 
680   plugin_names =
681       g_hash_table_new_full ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal,
682       (GDestroyNotify) g_free, NULL);
683 
684   frei0r_path = g_getenv ("FREI0R_PATH");
685   if (frei0r_path && *frei0r_path) {
686     gchar **p, **paths = g_strsplit (frei0r_path, ":", -1);
687 
688     for (p = paths; *p; p++) {
689       register_plugins (plugin, plugin_names, *p, *p);
690     }
691 
692     g_strfreev (paths);
693   } else {
694 #define register_plugins2(plugin, pn, p) register_plugins(plugin, pn, p, p)
695     homedir = g_get_home_dir ();
696     path = g_build_filename (homedir, ".frei0r-1", "lib", NULL);
697     libdir_path = g_build_filename (LIBDIR, "frei0r-1", NULL);
698     register_plugins2 (plugin, plugin_names, path);
699     g_free (path);
700     register_plugins2 (plugin, plugin_names, libdir_path);
701     g_free (libdir_path);
702     register_plugins2 (plugin, plugin_names, "/usr/local/lib/frei0r-1");
703     register_plugins2 (plugin, plugin_names, "/usr/lib/frei0r-1");
704     register_plugins2 (plugin, plugin_names, "/usr/local/lib32/frei0r-1");
705     register_plugins2 (plugin, plugin_names, "/usr/lib32/frei0r-1");
706     register_plugins2 (plugin, plugin_names, "/usr/local/lib64/frei0r-1");
707     register_plugins2 (plugin, plugin_names, "/usr/lib64/frei0r-1");
708 #undef register_plugins2
709   }
710 
711   g_hash_table_unref (plugin_names);
712 
713   return TRUE;
714 }
715 
716 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
717     GST_VERSION_MINOR,
718     frei0r,
719     "frei0r plugin library",
720     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
721