This could happen because for example /usr/lib is linked to /usr/lib64 and both are loaded. The frei0r specification says that the plugin init function must only be called once and for some plugin weird things (including crashes) are happening. Fixes bug #623710.
675 lines
20 KiB
C
675 lines
20 KiB
C
/* 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., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "gstfrei0r.h"
|
|
#include "gstfrei0rfilter.h"
|
|
#include "gstfrei0rsrc.h"
|
|
#include "gstfrei0rmixer.h"
|
|
|
|
#include <gst/controller/gstcontroller.h>
|
|
#include <string.h>
|
|
|
|
GST_DEBUG_CATEGORY (frei0r_debug);
|
|
#define GST_CAT_DEFAULT frei0r_debug
|
|
|
|
GstCaps *
|
|
gst_frei0r_caps_from_color_model (gint color_model)
|
|
{
|
|
switch (color_model) {
|
|
case F0R_COLOR_MODEL_BGRA8888:
|
|
return gst_caps_from_string (GST_VIDEO_CAPS_BGRA);
|
|
case F0R_COLOR_MODEL_RGBA8888:
|
|
return gst_caps_from_string (GST_VIDEO_CAPS_RGBA);
|
|
case F0R_COLOR_MODEL_PACKED32:
|
|
return gst_caps_from_string (GST_VIDEO_CAPS_BGRA " ; "
|
|
GST_VIDEO_CAPS_RGBA " ; "
|
|
GST_VIDEO_CAPS_ABGR " ; "
|
|
GST_VIDEO_CAPS_ARGB " ; "
|
|
GST_VIDEO_CAPS_BGRx " ; "
|
|
GST_VIDEO_CAPS_RGBx " ; "
|
|
GST_VIDEO_CAPS_xBGR " ; "
|
|
GST_VIDEO_CAPS_xRGB " ; " GST_VIDEO_CAPS_YUV ("AYUV"));
|
|
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);
|
|
|
|
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,
|
|
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 <= G_MAXDOUBLE && def >= -G_MAXDOUBLE))
|
|
def = 0.0;
|
|
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_double (prop_name, param_info->name,
|
|
param_info->explanation, -G_MAXDOUBLE, G_MAXDOUBLE, 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, param_info->name,
|
|
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, param_info->name,
|
|
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, param_info->name,
|
|
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, "-X", NULL);
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_double (prop_name_full, param_info->name,
|
|
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 * 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, &info, &ftable);
|
|
break;
|
|
case F0R_PLUGIN_TYPE_SOURCE:
|
|
ret = gst_frei0r_src_register (plugin, &info, &ftable);
|
|
break;
|
|
case F0R_PLUGIN_TYPE_MIXER2:
|
|
case F0R_PLUGIN_TYPE_MIXER3:
|
|
ret = gst_frei0r_mixer_register (plugin, &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)
|
|
{
|
|
GDir *dir;
|
|
gchar *filename;
|
|
const gchar *entry_name;
|
|
gboolean ret = FALSE, this_ret;
|
|
|
|
GST_DEBUG ("Scanning director '%s' for frei0r plugins", path);
|
|
|
|
dir = g_dir_open (path, 0, NULL);
|
|
if (!dir)
|
|
return FALSE;
|
|
|
|
while ((entry_name = g_dir_read_name (dir))) {
|
|
this_ret = FALSE;
|
|
|
|
if (g_hash_table_lookup_extended (plugin_names, entry_name, NULL, NULL))
|
|
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)) {
|
|
this_ret = register_plugin (plugin, filename);
|
|
} else if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
|
|
this_ret = register_plugins (plugin, plugin_names, filename);
|
|
}
|
|
if (this_ret)
|
|
g_hash_table_insert (plugin_names, g_strdup (entry_name), NULL);
|
|
ret = ret && this_ret;
|
|
g_free (filename);
|
|
}
|
|
g_dir_close (dir);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static gboolean
|
|
plugin_init (GstPlugin * plugin)
|
|
{
|
|
const gchar *homedir;
|
|
gchar *path;
|
|
GHashTable *plugin_names;
|
|
|
|
GST_DEBUG_CATEGORY_INIT (frei0r_debug, "frei0r", 0, "frei0r");
|
|
|
|
gst_controller_init (NULL, NULL);
|
|
|
|
gst_plugin_add_dependency_simple (plugin,
|
|
"HOME/.frei0r-1/lib",
|
|
"/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);
|
|
|
|
homedir = g_get_home_dir ();
|
|
path = g_build_filename (homedir, ".frei0r-1", NULL);
|
|
register_plugins (plugin, plugin_names, path);
|
|
g_free (path);
|
|
|
|
register_plugins (plugin, plugin_names, "/usr/local/lib/frei0r-1");
|
|
register_plugins (plugin, plugin_names, "/usr/lib/frei0r-1");
|
|
register_plugins (plugin, plugin_names, "/usr/local/lib32/frei0r-1");
|
|
register_plugins (plugin, plugin_names, "/usr/lib32/frei0r-1");
|
|
register_plugins (plugin, plugin_names, "/usr/local/lib64/frei0r-1");
|
|
register_plugins (plugin, plugin_names, "/usr/lib64/frei0r-1");
|
|
|
|
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)
|