/*
 * Copyright (c) 2002, 2003, 2004 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#include <gmodule.h>
#include <string.h>
#include "sg-util.h"
#include "st-plugin.h"
#include "st-plugins.h"
#include "st-dialog-api.h"
#include "st-settings.h"

/*** variable declarations ***************************************************/

GSList *st_plugins_list = NULL;

/*** function declarations ***************************************************/

static gboolean st_plugins_scan			(const char	*dirname,
						 GError		**err);
static gboolean st_plugins_scan_or_warn		(const char	*dirname);

/*** implementation **********************************************************/

void
st_plugins_load (void)
{
  char *private_pluginsdir;
  const char *plugins_path;
  
  if (! g_module_supported())
    {
      st_error_dialog(_("Unable to load plugins"),
		      _("Modules are not supported on this platform."));
      return;
    }
  
  if (g_file_test(PLUGINSDIR, G_FILE_TEST_IS_DIR))
    st_plugins_scan_or_warn(PLUGINSDIR);
      
  private_pluginsdir = g_build_filename(st_settings.private_dir, "plugins", NULL);
  if (g_file_test(private_pluginsdir, G_FILE_TEST_IS_DIR))
    st_plugins_scan_or_warn(private_pluginsdir);
  g_free(private_pluginsdir);

  plugins_path = g_getenv("STREAMTUNER_PLUGINS_PATH");
  if (plugins_path)
    {
      char **dirs;
      int i;

      dirs = g_strsplit(plugins_path, ":", 0);

      for (i = 0; dirs[i]; i++)
	st_plugins_scan_or_warn(dirs[i]);

      g_strfreev(dirs);
    }
}

static gboolean
st_plugins_scan (const char *dirname, GError **err)
{
  GDir *dir;
  const char *filename;
  
  g_return_val_if_fail(dirname != NULL, FALSE);

  if (! (dir = g_dir_open(dirname, 0, err)))
    return FALSE;
  
  while ((filename = g_dir_read_name(dir)))
    {
      char *extension;
      char *pathname;

      pathname = g_build_filename(dirname, filename, NULL);
      if (g_file_test(pathname, G_FILE_TEST_IS_REGULAR)
	  && (extension = strrchr(filename, '.'))
	  && (! strcmp(++extension, G_MODULE_SUFFIX) != 0))
	{
	  STPlugin *plugin;
	  const char *error;

	  plugin = st_plugin_new(pathname, sg_str_slist_contains(st_settings.disabled_plugins, pathname));

	  error = st_plugin_get_error(plugin);
	  if (error)
	    {
	      char *secondary;
	      char *normalized;

	      secondary = g_strdup_printf(_("Plugin %s could not be loaded: %s"), pathname, error);
	      normalized = st_dialog_normalize(secondary);

	      st_error_dialog(_("A plugin error has occurred"), "%s", normalized);
	  
	      g_free(secondary);
	      g_free(normalized);
	    }
	  
	  st_plugins_list = g_slist_append(st_plugins_list, plugin);
	}
      g_free(pathname);
    }

  g_dir_close(dir);

  return TRUE;
}

/*
 * Same as st_plugins_scan(), except that if it fails, it will warn
 * the user by itself instead of setting a GError.
 */
static gboolean
st_plugins_scan_or_warn (const char *dirname)
{
  GError *err = NULL;

  g_return_val_if_fail(dirname != NULL, FALSE);

  if (! st_plugins_scan(dirname, &err))
    {
      char *secondary;
      char *normalized;

      secondary = g_strdup_printf(_("Unable to scan plugins directory %s: %s"),
				  dirname, err->message);
      normalized = st_dialog_normalize(secondary);
      
      st_error_dialog(_("A plugin error has occurred"), "%s", normalized);

      g_free(secondary);
      g_free(normalized);

      g_error_free(err);

      return FALSE;
    }
  
  return TRUE;
}
