| /* GStreamer |
| * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> |
| * |
| * 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., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include "gstfrei0r.h" |
| #include "gstfrei0rfilter.h" |
| #include "gstfrei0rsrc.h" |
| #include "gstfrei0rmixer.h" |
| |
| #include <string.h> |
| #include <gmodule.h> |
| |
| GST_DEBUG_CATEGORY (frei0r_debug); |
| #define GST_CAT_DEFAULT frei0r_debug |
| |
| static GstStaticCaps bgra8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE |
| ("BGRA")); |
| static GstStaticCaps rgba8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE |
| ("RGBA")); |
| static GstStaticCaps packed32_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE |
| ("{ BGRA, RGBA, ABGR, ARGB, BGRx, RGBx, xBGR, xRGB, AYUV }")); |
| |
| GstCaps * |
| gst_frei0r_caps_from_color_model (gint color_model) |
| { |
| switch (color_model) { |
| case F0R_COLOR_MODEL_BGRA8888: |
| return gst_static_caps_get (&bgra8888_caps); |
| case F0R_COLOR_MODEL_RGBA8888: |
| return gst_static_caps_get (&rgba8888_caps); |
| case F0R_COLOR_MODEL_PACKED32: |
| return gst_static_caps_get (&packed32_caps); |
| default: |
| break; |
| } |
| |
| return NULL; |
| } |
| |
| void |
| gst_frei0r_klass_install_properties (GObjectClass * gobject_class, |
| GstFrei0rFuncTable * ftable, GstFrei0rProperty * properties, |
| gint n_properties) |
| { |
| gint i, count = 1; |
| f0r_instance_t *instance = ftable->construct (640, 480); |
| |
| g_assert (instance); |
| |
| for (i = 0; i < n_properties; i++) { |
| f0r_param_info_t *param_info = &properties[i].info; |
| gchar *prop_name; |
| |
| ftable->get_param_info (param_info, i); |
| |
| if (!param_info->name) { |
| GST_ERROR ("Property %d of %s without a valid name", i, |
| g_type_name (G_TYPE_FROM_CLASS (gobject_class))); |
| continue; |
| } |
| |
| prop_name = g_ascii_strdown (param_info->name, -1); |
| g_strcanon (prop_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-'); |
| /* satisfy glib2 (argname[0] must be [A-Za-z]) */ |
| if (!((prop_name[0] >= 'a' && prop_name[0] <= 'z') || |
| (prop_name[0] >= 'A' && prop_name[0] <= 'Z'))) { |
| gchar *tempstr = prop_name; |
| |
| prop_name = g_strconcat ("param-", prop_name, NULL); |
| g_free (tempstr); |
| } |
| |
| properties[i].prop_id = count; |
| properties[i].prop_idx = i; |
| |
| ftable->get_param_value (instance, &properties[i].default_value, i); |
| if (param_info->type == F0R_PARAM_STRING) |
| properties[i].default_value.data.s = |
| g_strdup (properties[i].default_value.data.s); |
| |
| switch (param_info->type) { |
| case F0R_PARAM_BOOL: |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_boolean (prop_name, param_info->name, |
| param_info->explanation, |
| properties[i].default_value.data.b ? TRUE : FALSE, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| properties[i].n_prop_ids = 1; |
| break; |
| case F0R_PARAM_DOUBLE:{ |
| gdouble def = properties[i].default_value.data.d; |
| |
| /* If the default is NAN, +-INF we use 0.0 */ |
| if (!(def >= 0.0 && def <= 1.0)) |
| def = 0.0; |
| |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_double (prop_name, param_info->name, |
| param_info->explanation, 0.0, 1.0, def, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| properties[i].n_prop_ids = 1; |
| break; |
| } |
| case F0R_PARAM_STRING: |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_string (prop_name, param_info->name, |
| param_info->explanation, properties[i].default_value.data.s, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| properties[i].n_prop_ids = 1; |
| break; |
| case F0R_PARAM_COLOR:{ |
| gchar *prop_name_full; |
| gchar *prop_nick_full; |
| gdouble def; |
| |
| def = properties[i].default_value.data.color.r; |
| /* If the default is out of range we use 0.0 */ |
| if (!(def <= 1.0 && def >= 0.0)) |
| def = 0.0; |
| prop_name_full = g_strconcat (prop_name, "-r", NULL); |
| prop_nick_full = g_strconcat (param_info->name, " (R)", NULL); |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_float (prop_name_full, prop_nick_full, |
| param_info->explanation, 0.0, 1.0, def, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| g_free (prop_name_full); |
| g_free (prop_nick_full); |
| |
| def = properties[i].default_value.data.color.g; |
| /* If the default is out of range we use 0.0 */ |
| if (!(def <= 1.0 && def >= 0.0)) |
| def = 0.0; |
| prop_name_full = g_strconcat (prop_name, "-g", NULL); |
| prop_nick_full = g_strconcat (param_info->name, " (G)", NULL); |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_float (prop_name_full, prop_nick_full, |
| param_info->explanation, 0.0, 1.0, def, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| g_free (prop_name_full); |
| g_free (prop_nick_full); |
| |
| def = properties[i].default_value.data.color.b; |
| /* If the default is out of range we use 0.0 */ |
| if (!(def <= 1.0 && def >= 0.0)) |
| def = 0.0; |
| prop_name_full = g_strconcat (prop_name, "-b", NULL); |
| prop_nick_full = g_strconcat (param_info->name, " (B)", NULL); |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_float (prop_name_full, prop_nick_full, |
| param_info->explanation, 0.0, 1.0, def, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| g_free (prop_name_full); |
| g_free (prop_nick_full); |
| |
| properties[i].n_prop_ids = 3; |
| break; |
| } |
| case F0R_PARAM_POSITION:{ |
| gchar *prop_name_full; |
| gchar *prop_nick_full; |
| gdouble def; |
| |
| def = properties[i].default_value.data.position.x; |
| /* If the default is out of range we use 0.0 */ |
| if (!(def <= 1.0 && def >= 0.0)) |
| def = 0.0; |
| prop_name_full = g_strconcat (prop_name, "-x", NULL); |
| prop_nick_full = g_strconcat (param_info->name, " (X)", NULL); |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_double (prop_name_full, prop_nick_full, |
| param_info->explanation, 0.0, 1.0, def, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| g_free (prop_name_full); |
| g_free (prop_nick_full); |
| |
| def = properties[i].default_value.data.position.y; |
| /* If the default is out of range we use 0.0 */ |
| if (!(def <= 1.0 && def >= 0.0)) |
| def = 0.0; |
| prop_name_full = g_strconcat (prop_name, "-Y", NULL); |
| prop_nick_full = g_strconcat (param_info->name, " (Y)", NULL); |
| g_object_class_install_property (gobject_class, count++, |
| g_param_spec_double (prop_name_full, prop_nick_full, |
| param_info->explanation, 0.0, 1.0, def, |
| G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); |
| g_free (prop_name_full); |
| g_free (prop_nick_full); |
| |
| properties[i].n_prop_ids = 2; |
| break; |
| } |
| default: |
| g_assert_not_reached (); |
| break; |
| } |
| |
| g_free (prop_name); |
| } |
| |
| ftable->destruct (instance); |
| } |
| |
| GstFrei0rPropertyValue * |
| gst_frei0r_property_cache_init (GstFrei0rProperty * properties, |
| gint n_properties) |
| { |
| gint i; |
| GstFrei0rPropertyValue *ret = g_new0 (GstFrei0rPropertyValue, n_properties); |
| |
| for (i = 0; i < n_properties; i++) { |
| memcpy (&ret[i].data, &properties[i].default_value, |
| sizeof (GstFrei0rPropertyValue)); |
| |
| if (properties[i].info.type == F0R_PARAM_STRING) |
| ret[i].data.s = g_strdup (ret[i].data.s); |
| } |
| |
| return ret; |
| } |
| |
| void |
| gst_frei0r_property_cache_free (GstFrei0rProperty * properties, |
| GstFrei0rPropertyValue * property_cache, gint n_properties) |
| { |
| gint i; |
| |
| for (i = 0; i < n_properties; i++) { |
| if (properties[i].info.type == F0R_PARAM_STRING) |
| g_free (property_cache[i].data.s); |
| } |
| g_free (property_cache); |
| } |
| |
| f0r_instance_t * |
| gst_frei0r_instance_construct (GstFrei0rFuncTable * ftable, |
| GstFrei0rProperty * properties, gint n_properties, |
| GstFrei0rPropertyValue * property_cache, gint width, gint height) |
| { |
| f0r_instance_t *instance = ftable->construct (width, height); |
| gint i; |
| |
| for (i = 0; i < n_properties; i++) { |
| if (properties[i].info.type == F0R_PARAM_STRING) |
| ftable->set_param_value (instance, property_cache[i].data.s, i); |
| else |
| ftable->set_param_value (instance, &property_cache[i].data, i); |
| } |
| |
| return instance; |
| } |
| |
| gboolean |
| gst_frei0r_get_property (f0r_instance_t * instance, GstFrei0rFuncTable * ftable, |
| GstFrei0rProperty * properties, gint n_properties, |
| GstFrei0rPropertyValue * property_cache, guint prop_id, GValue * value) |
| { |
| gint i; |
| GstFrei0rProperty *prop = NULL; |
| |
| for (i = 0; i < n_properties; i++) { |
| if (properties[i].prop_id <= prop_id && |
| properties[i].prop_id + properties[i].n_prop_ids > prop_id) { |
| prop = &properties[i]; |
| break; |
| } |
| } |
| |
| if (!prop) |
| return FALSE; |
| |
| switch (prop->info.type) { |
| case F0R_PARAM_BOOL:{ |
| gdouble d; |
| |
| if (instance) |
| ftable->get_param_value (instance, &d, prop->prop_idx); |
| else |
| d = property_cache[prop->prop_idx].data.b; |
| |
| g_value_set_boolean (value, (d < 0.5) ? FALSE : TRUE); |
| break; |
| } |
| case F0R_PARAM_DOUBLE:{ |
| gdouble d; |
| |
| if (instance) |
| ftable->get_param_value (instance, &d, prop->prop_idx); |
| else |
| d = property_cache[prop->prop_idx].data.d; |
| |
| g_value_set_double (value, d); |
| break; |
| } |
| case F0R_PARAM_STRING:{ |
| const gchar *s; |
| |
| if (instance) |
| ftable->get_param_value (instance, &s, prop->prop_idx); |
| else |
| s = property_cache[prop->prop_idx].data.s; |
| g_value_set_string (value, s); |
| break; |
| } |
| case F0R_PARAM_COLOR:{ |
| f0r_param_color_t color; |
| |
| if (instance) |
| ftable->get_param_value (instance, &color, prop->prop_idx); |
| else |
| color = property_cache[prop->prop_idx].data.color; |
| |
| switch (prop_id - prop->prop_id) { |
| case 0: |
| g_value_set_float (value, color.r); |
| break; |
| case 1: |
| g_value_set_float (value, color.g); |
| break; |
| case 2: |
| g_value_set_float (value, color.b); |
| break; |
| } |
| break; |
| } |
| case F0R_PARAM_POSITION:{ |
| f0r_param_position_t position; |
| |
| if (instance) |
| ftable->get_param_value (instance, &position, prop->prop_idx); |
| else |
| position = property_cache[prop->prop_idx].data.position; |
| |
| switch (prop_id - prop->prop_id) { |
| case 0: |
| g_value_set_double (value, position.x); |
| break; |
| case 1: |
| g_value_set_double (value, position.y); |
| break; |
| } |
| break; |
| } |
| default: |
| g_assert_not_reached (); |
| break; |
| } |
| |
| return TRUE; |
| } |
| |
| 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) |
| { |
| GstFrei0rProperty *prop = NULL; |
| gint i; |
| |
| for (i = 0; i < n_properties; i++) { |
| if (properties[i].prop_id <= prop_id && |
| properties[i].prop_id + properties[i].n_prop_ids > prop_id) { |
| prop = &properties[i]; |
| break; |
| } |
| } |
| |
| if (!prop) |
| return FALSE; |
| |
| switch (prop->info.type) { |
| case F0R_PARAM_BOOL:{ |
| gboolean b = g_value_get_boolean (value); |
| gdouble d = b ? 1.0 : 0.0; |
| |
| if (instance) |
| ftable->set_param_value (instance, &d, prop->prop_idx); |
| property_cache[prop->prop_idx].data.b = d; |
| break; |
| } |
| case F0R_PARAM_DOUBLE:{ |
| gdouble d = g_value_get_double (value); |
| |
| if (instance) |
| ftable->set_param_value (instance, &d, prop->prop_idx); |
| property_cache[prop->prop_idx].data.d = d; |
| break; |
| } |
| case F0R_PARAM_STRING:{ |
| gchar *s = g_value_dup_string (value); |
| |
| /* Copies the string */ |
| if (instance) |
| ftable->set_param_value (instance, s, prop->prop_idx); |
| property_cache[prop->prop_idx].data.s = s; |
| break; |
| } |
| case F0R_PARAM_COLOR:{ |
| gfloat f = g_value_get_float (value); |
| f0r_param_color_t *color = &property_cache[prop->prop_idx].data.color; |
| |
| switch (prop_id - prop->prop_id) { |
| case 0: |
| color->r = f; |
| break; |
| case 1: |
| color->g = f; |
| break; |
| case 2: |
| color->b = f; |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| |
| if (instance) |
| ftable->set_param_value (instance, color, prop->prop_idx); |
| break; |
| } |
| case F0R_PARAM_POSITION:{ |
| gdouble d = g_value_get_double (value); |
| f0r_param_position_t *position = |
| &property_cache[prop->prop_idx].data.position; |
| |
| switch (prop_id - prop->prop_id) { |
| case 0: |
| position->x = d; |
| break; |
| case 1: |
| position->y = d; |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| if (instance) |
| ftable->set_param_value (instance, position, prop->prop_idx); |
| break; |
| } |
| default: |
| g_assert_not_reached (); |
| break; |
| } |
| |
| return TRUE; |
| } |
| |
| static gboolean |
| register_plugin (GstPlugin * plugin, const gchar * vendor, |
| const gchar * filename) |
| { |
| GModule *module; |
| GstFrei0rPluginRegisterReturn ret = GST_FREI0R_PLUGIN_REGISTER_RETURN_FAILED; |
| GstFrei0rFuncTable ftable = { NULL, }; |
| gint i; |
| f0r_plugin_info_t info = { NULL, }; |
| f0r_instance_t *instance = NULL; |
| |
| GST_DEBUG ("Registering plugin '%s'", filename); |
| |
| module = g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); |
| if (!module) { |
| GST_WARNING ("Failed to load plugin"); |
| return FALSE; |
| } |
| |
| if (!g_module_symbol (module, "f0r_init", (gpointer *) & ftable.init)) { |
| GST_INFO ("No frei0r plugin"); |
| g_module_close (module); |
| return FALSE; |
| } |
| |
| if (!g_module_symbol (module, "f0r_deinit", (gpointer *) & ftable.deinit) || |
| !g_module_symbol (module, "f0r_construct", |
| (gpointer *) & ftable.construct) |
| || !g_module_symbol (module, "f0r_destruct", |
| (gpointer *) & ftable.destruct) |
| || !g_module_symbol (module, "f0r_get_plugin_info", |
| (gpointer *) & ftable.get_plugin_info) |
| || !g_module_symbol (module, "f0r_get_param_info", |
| (gpointer *) & ftable.get_param_info) |
| || !g_module_symbol (module, "f0r_set_param_value", |
| (gpointer *) & ftable.set_param_value) |
| || !g_module_symbol (module, "f0r_get_param_value", |
| (gpointer *) & ftable.get_param_value)) |
| goto invalid_frei0r_plugin; |
| |
| /* One of these must exist */ |
| g_module_symbol (module, "f0r_update", (gpointer *) & ftable.update); |
| g_module_symbol (module, "f0r_update2", (gpointer *) & ftable.update2); |
| |
| if (!ftable.init ()) { |
| GST_WARNING ("Failed to initialize plugin"); |
| g_module_close (module); |
| return FALSE; |
| } |
| |
| if (!ftable.update && !ftable.update2) |
| goto invalid_frei0r_plugin; |
| |
| ftable.get_plugin_info (&info); |
| |
| if (info.frei0r_version > 1) { |
| GST_WARNING ("Unsupported frei0r version %d", info.frei0r_version); |
| ftable.deinit (); |
| g_module_close (module); |
| return FALSE; |
| } |
| |
| if (info.color_model > F0R_COLOR_MODEL_PACKED32) { |
| GST_WARNING ("Unsupported color model %d", info.color_model); |
| ftable.deinit (); |
| g_module_close (module); |
| return FALSE; |
| } |
| |
| for (i = 0; i < info.num_params; i++) { |
| f0r_param_info_t pinfo = { NULL, }; |
| |
| ftable.get_param_info (&pinfo, i); |
| if (pinfo.type > F0R_PARAM_STRING) { |
| GST_WARNING ("Unsupported parameter type %d", pinfo.type); |
| ftable.deinit (); |
| g_module_close (module); |
| return FALSE; |
| } |
| } |
| |
| instance = ftable.construct (640, 480); |
| if (!instance) { |
| GST_WARNING ("Failed to instanciate plugin '%s'", info.name); |
| ftable.deinit (); |
| g_module_close (module); |
| return FALSE; |
| } |
| ftable.destruct (instance); |
| |
| switch (info.plugin_type) { |
| case F0R_PLUGIN_TYPE_FILTER: |
| ret = gst_frei0r_filter_register (plugin, vendor, &info, &ftable); |
| break; |
| case F0R_PLUGIN_TYPE_SOURCE: |
| ret = gst_frei0r_src_register (plugin, vendor, &info, &ftable); |
| break; |
| case F0R_PLUGIN_TYPE_MIXER2: |
| case F0R_PLUGIN_TYPE_MIXER3: |
| ret = gst_frei0r_mixer_register (plugin, vendor, &info, &ftable); |
| break; |
| default: |
| break; |
| } |
| |
| switch (ret) { |
| case GST_FREI0R_PLUGIN_REGISTER_RETURN_OK: |
| return TRUE; |
| case GST_FREI0R_PLUGIN_REGISTER_RETURN_FAILED: |
| GST_ERROR ("Failed to register frei0r plugin"); |
| ftable.deinit (); |
| g_module_close (module); |
| return FALSE; |
| case GST_FREI0R_PLUGIN_REGISTER_RETURN_ALREADY_REGISTERED: |
| GST_DEBUG ("frei0r plugin already registered"); |
| ftable.deinit (); |
| g_module_close (module); |
| return TRUE; |
| default: |
| g_return_val_if_reached (FALSE); |
| } |
| |
| g_return_val_if_reached (FALSE); |
| |
| invalid_frei0r_plugin: |
| GST_ERROR ("Invalid frei0r plugin"); |
| ftable.deinit (); |
| g_module_close (module); |
| |
| return FALSE; |
| } |
| |
| static gboolean |
| register_plugins (GstPlugin * plugin, GHashTable * plugin_names, |
| const gchar * path, const gchar * base_path) |
| { |
| GDir *dir; |
| gchar *filename; |
| const gchar *entry_name; |
| gboolean ret = TRUE; |
| |
| GST_DEBUG ("Scanning directory '%s' for frei0r plugins", path); |
| |
| dir = g_dir_open (path, 0, NULL); |
| if (!dir) |
| return FALSE; |
| |
| while ((entry_name = g_dir_read_name (dir))) { |
| gchar *tmp, *vendor = NULL; |
| gchar *hashtable_name; |
| |
| tmp = g_strdup (path + strlen (base_path)); |
| if (*tmp == G_DIR_SEPARATOR && *(tmp + 1)) |
| vendor = tmp + 1; |
| else if (*tmp) |
| vendor = tmp; |
| |
| if (vendor) |
| hashtable_name = g_strconcat (vendor, "-", entry_name, NULL); |
| else |
| hashtable_name = g_strdup (entry_name); |
| |
| if (g_hash_table_lookup_extended (plugin_names, hashtable_name, NULL, NULL)) { |
| g_free (hashtable_name); |
| continue; |
| } |
| |
| filename = g_build_filename (path, entry_name, NULL); |
| if ((g_str_has_suffix (filename, G_MODULE_SUFFIX) |
| #ifdef GST_EXTRA_MODULE_SUFFIX |
| || g_str_has_suffix (filename, GST_EXTRA_MODULE_SUFFIX) |
| #endif |
| ) && g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { |
| gboolean this_ret; |
| |
| this_ret = register_plugin (plugin, vendor, filename); |
| if (this_ret) |
| g_hash_table_insert (plugin_names, g_strdup (hashtable_name), NULL); |
| |
| ret = ret && this_ret; |
| } else if (g_file_test (filename, G_FILE_TEST_IS_DIR)) { |
| ret = ret && register_plugins (plugin, plugin_names, filename, base_path); |
| } |
| g_free (filename); |
| g_free (hashtable_name); |
| g_free (tmp); |
| } |
| g_dir_close (dir); |
| |
| return ret; |
| } |
| |
| static gboolean |
| plugin_init (GstPlugin * plugin) |
| { |
| const gchar *homedir; |
| gchar *path, *libdir_path; |
| GHashTable *plugin_names; |
| const gchar *frei0r_path; |
| |
| GST_DEBUG_CATEGORY_INIT (frei0r_debug, "frei0r", 0, "frei0r"); |
| |
| gst_plugin_add_dependency_simple (plugin, |
| "FREI0R_PATH:HOME/.frei0r-1/lib", |
| LIBDIR "/frei0r-1:" |
| "/usr/lib/frei0r-1:/usr/local/lib/frei0r-1:" |
| "/usr/lib32/frei0r-1:/usr/local/lib32/frei0r-1:" |
| "/usr/lib64/frei0r-1:/usr/local/lib64/frei0r-1", |
| NULL, GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); |
| |
| plugin_names = |
| g_hash_table_new_full ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal, |
| (GDestroyNotify) g_free, NULL); |
| |
| frei0r_path = g_getenv ("FREI0R_PATH"); |
| if (frei0r_path && *frei0r_path) { |
| gchar **p, **paths = g_strsplit (frei0r_path, ":", -1); |
| |
| for (p = paths; *p; p++) { |
| register_plugins (plugin, plugin_names, *p, *p); |
| } |
| |
| g_strfreev (paths); |
| } else { |
| #define register_plugins2(plugin, pn, p) register_plugins(plugin, pn, p, p) |
| homedir = g_get_home_dir (); |
| path = g_build_filename (homedir, ".frei0r-1", "lib", NULL); |
| libdir_path = g_build_filename (LIBDIR, "frei0r-1", NULL); |
| register_plugins2 (plugin, plugin_names, path); |
| g_free (path); |
| register_plugins2 (plugin, plugin_names, libdir_path); |
| g_free (libdir_path); |
| register_plugins2 (plugin, plugin_names, "/usr/local/lib/frei0r-1"); |
| register_plugins2 (plugin, plugin_names, "/usr/lib/frei0r-1"); |
| register_plugins2 (plugin, plugin_names, "/usr/local/lib32/frei0r-1"); |
| register_plugins2 (plugin, plugin_names, "/usr/lib32/frei0r-1"); |
| register_plugins2 (plugin, plugin_names, "/usr/local/lib64/frei0r-1"); |
| register_plugins2 (plugin, plugin_names, "/usr/lib64/frei0r-1"); |
| #undef register_plugins2 |
| } |
| |
| g_hash_table_unref (plugin_names); |
| |
| return TRUE; |
| } |
| |
| GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, |
| GST_VERSION_MINOR, |
| frei0r, |
| "frei0r plugin library", |
| plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) |