Logo Search packages:      
Sourcecode: farsight version File versions

farsight-plugin.c

/*
 * farsight-plugin.c - Source for farsight plugin infrastructure
 *
 * Farsight Voice+Video library
 * Copyright (c) 2005 INdT.
 *   @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
 * Copyright 2005,2006 Collabora Ltd.
 * Copyright 2005,2006 Nokia Corp.
 *   @author Rob Taylor <rob.taylor@collabora.co.uk>.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; 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 <string.h>

#include "farsight-plugin.h"


/**
 * SECTION:farsight-plugin
 * @short_description: A class for defining Farsight plugins
 */

#define FARSIGHT_PLUGIN_GET_PRIVATE(o)  \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), FARSIGHT_TYPE_PLUGIN, FarsightPluginPrivate))

static gboolean farsight_plugin_load (GTypeModule *module);
static void farsight_plugin_unload (GTypeModule *module);


static gchar **search_paths = NULL;

GList *plugins = NULL;

static GObjectClass *parent_class = NULL;

struct _FarsightPluginPrivate
{
  GModule *handle;
  gboolean disposed;
};


static void farsight_plugin_class_init (FarsightPluginClass * klass);
static void farsight_plugin_init (FarsightPlugin * plugin);
static void farsight_plugin_dispose (GObject * object);
static void farsight_plugin_finalize (GObject * object);


GType
farsight_plugin_get_type (void)
{
  static GType type = 0;

  if (type == 0) {
    static const GTypeInfo info = {
      sizeof (FarsightPluginClass),
      NULL,
      NULL,
      (GClassInitFunc) farsight_plugin_class_init,
      NULL,
      NULL,
      sizeof (FarsightPlugin),
      0,
      (GInstanceInitFunc) farsight_plugin_init
    };

    type = g_type_register_static (G_TYPE_TYPE_MODULE,
        "FarsightPlugin", &info, 0);
  }

  return type;
}

static void
farsight_plugin_search_path_init ()
{
  const gchar *env;

  if (search_paths)
    return;

  env = g_getenv ("FS_PLUGIN_PATH");

  if (env == NULL)
    {
      search_paths = g_new (gchar *, 2);
      search_paths[0] = g_strdup (LIBDIR);
      search_paths[1] = NULL;
      return;
    }
  else
    {
      gchar *path;

      path = g_strjoin (":", env, LIBDIR, NULL);
      search_paths = g_strsplit (path, ":", -1);
      g_free (path);
    }
}

static void
farsight_plugin_class_init (FarsightPluginClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
  GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);

  gobject_class->dispose = farsight_plugin_dispose;
  gobject_class->finalize = farsight_plugin_finalize;

  parent_class = g_type_class_peek_parent(klass);

  module_class->load = farsight_plugin_load;
  module_class->unload = farsight_plugin_unload;

  g_type_class_add_private (klass, sizeof (FarsightPluginPrivate));
  
  /* Calling from class initializer so it only gets init'ed once */
  farsight_plugin_search_path_init ();
}



static void
farsight_plugin_init (FarsightPlugin * plugin)
{
  /* member init */
  plugin->priv = FARSIGHT_PLUGIN_GET_PRIVATE (plugin);
  plugin->priv->handle = NULL;
  plugin->priv->disposed = FALSE;
  plugin->info = NULL;
}


static void
farsight_plugin_dispose (GObject * object)
{
  FarsightPlugin *plugin = FARSIGHT_PLUGIN (object);

  if (plugin->priv->disposed) {
    /* If dispose did already run, return. */
    return;
  }

  /* Make sure dispose does not run twice. */
  plugin->priv->disposed = TRUE;

  parent_class->dispose (object);
}

static void
farsight_plugin_finalize (GObject * object)
{
  parent_class->finalize (object);
}

static gboolean farsight_plugin_load (GTypeModule *module)
{
  FarsightPlugin *plugin = FARSIGHT_PLUGIN(module);
  gchar **search_path = NULL;
  gchar *path=NULL;

  gboolean (*farsight_init_plugin) (FarsightPlugin *);

  g_return_val_if_fail (plugin != NULL, FALSE);
  g_return_val_if_fail (plugin->name != NULL && plugin->name[0] != '\0', FALSE);

  for (search_path = search_paths; *search_path; search_path++) {
    g_message("looking for plugins in %s", *search_path);

    path = g_module_build_path(*search_path, plugin->name);

    
    
    plugin->priv->handle = g_module_open (path, G_MODULE_BIND_LOCAL);
    g_print ("opening module %s: %s\n", path,
             (plugin->priv->handle != NULL) ? "succeeded" : g_module_error ());
    g_free (path);

    if (!plugin->priv->handle) {
      continue;
    }

    else if (!g_module_symbol (plugin->priv->handle,
                          "farsight_init_plugin", 
                          (gpointer) & farsight_init_plugin)) {
      g_module_close (plugin->priv->handle);
      plugin->priv->handle = NULL;
      g_print ("could not find init function in plugin\n");
      continue;
    }

    else
      break;
  }
  
  if (!plugin->priv->handle) {
    return FALSE;
  }

  
  if (!farsight_init_plugin (plugin)) {
    /* TODO error handling (init error or no info defined) */
    g_print ("init error or no info defined");
    goto err_close_module;
  }

  if (plugin->info->major_version != FARSIGHT_MAJOR_VERSION ||
      plugin->info->minor_version > FARSIGHT_MINOR_VERSION) {
    /* TODO error handling (version mismatch) */
    g_print ("version mismatch");
    goto err_close_module;
  }


  return TRUE;

 err_close_module:
  g_module_close (plugin->priv->handle);
  return FALSE;

}

static void
farsight_plugin_unload (GTypeModule *module)
{
  FarsightPlugin *plugin = NULL;

  g_return_if_fail (module != NULL);

  plugin = FARSIGHT_PLUGIN (module);

  g_message("Unloading plugin %s", plugin->name);


  if (plugin->info->unload != NULL)
    plugin->info->unload (plugin);

  if (plugin->priv->handle != NULL)
    g_module_close (plugin->priv->handle);
}

static FarsightPlugin *
farsight_plugin_get_by_name (const gchar * name, const gchar * type_suffix)
{
  gchar *fullname;
  FarsightPlugin *plugin = NULL;
  GList *plugin_item;

  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (type_suffix != NULL, NULL);

  fullname = g_strdup_printf ("%s-%s",name,type_suffix);

  for (plugin_item = plugins;
       plugin_item;
       plugin_item = g_list_next(plugin_item))  {
    plugin = plugin_item->data;
    if (plugin->name == NULL || plugin->name[0] == 0)
      continue;
    if (!strcmp (plugin->name, fullname)) {
      break;
    }
    
  }
  g_free (fullname);

  if (plugin_item)
    return plugin;

  return NULL;
}


/**
 * farsight_plugin_create:
 * @name: The name of the plugin to load
 * @type_suffix: The type of plugin to load (normally "session" or
 * "transmitter"
 * @pluginptr: A pointer to the location where a pointer to the
 * #FarsightPlugin used can be stored 
 * 
 * Loads the appropriate plugin if necessary and creates a GObject of
 * the requested type
 *
 * Returns: the created GObject, or NULL if it fails
 **/
GObject *
farsight_plugin_create (const gchar * name, const gchar *type_suffix, FarsightPlugin **pluginptr)
{
  GObject *object;
  FarsightPlugin *plugin;
  
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (type_suffix != NULL, NULL);

  plugin = farsight_plugin_get_by_name (name, type_suffix);

  if (!plugin) {
    plugin = g_object_new (FARSIGHT_TYPE_PLUGIN, NULL);
    if (!plugin)
      return NULL;
    plugin->name = g_strdup_printf ("%s-%s",name,type_suffix);
    g_type_module_set_name (G_TYPE_MODULE (plugin), plugin->name);
    plugins = g_list_append(plugins, plugin);
  }

  if (!g_type_module_use (G_TYPE_MODULE (plugin)))
    return NULL;

  object = plugin->info->new_ ();

  g_type_module_unuse(G_TYPE_MODULE(plugin));

  if (pluginptr) {
    *pluginptr = plugin;
  }


  return object;
}


/**
 * farsight_plugin_get_name:
 * @plugin: a #FarsightPlugin to get it's name
 *
 * Returns the name of the given plugin plugin.
 *
 * Returns: a string to the name of the plugin, NULL if invalid.
 **/
G_CONST_RETURN gchar *
farsight_plugin_get_name (FarsightPlugin * plugin)
{
  g_return_val_if_fail (plugin != NULL, NULL);

  return plugin->name;
}

/**
 * farsight_plugin_get_description:
 * @plugin: a #FarsightPlugin to get it's description
 *
 * Returns the description of the given plugin plugin.
 *
 * Returns: a string containing the description, NULL if invalid.
 **/
G_CONST_RETURN gchar *
farsight_plugin_get_description (FarsightPlugin * plugin)
{
  g_return_val_if_fail (plugin != NULL, NULL);

  return plugin->info->description;
}

/**
 * farsight_plugin_get_version:
 * @plugin: a #FarsightPlugin to get it's version
 *
 * Returns the version of the given plugin plugin.
 *
 * Returns: a string containing the version, NULL if invalid.
 **/
G_CONST_RETURN gchar *
farsight_plugin_get_version (FarsightPlugin * plugin)
{
  g_return_val_if_fail (plugin != NULL, NULL);

  return plugin->info->version;
}

/**
 * farsight_plugin_get_author:
 * @plugin: a #FarsightPlugin to get it's author
 *
 * Returns the author of the given plugin plugin.
 *
 * Returns: a string containing the author, NULL if invalid.
 */
G_CONST_RETURN gchar *
farsight_plugin_get_author (FarsightPlugin * plugin)
{
  g_return_val_if_fail (plugin != NULL, NULL);

  return plugin->info->author;
}

/**
 * farsight_plugin_get_homepage:
 * @plugin: a #FarsightPlugin to get it's homepage 
 *
 * Returns the homepage of the given plugin plugin.
 *
 * Returns: a string containing the homepage, NULL if invalid.
 **/
G_CONST_RETURN gchar *
farsight_plugin_get_homepage (FarsightPlugin * plugin)
{
  g_return_val_if_fail (plugin != NULL, NULL);

  return plugin->info->homepage;
}

Generated by  Doxygen 1.6.0   Back to index