/* config.c
 * Copyright (C) 2004, 2005 Sylvain Cresto <scresto@gmail.com>
 *
 * This file is part of graveman!
 *
 * graveman! is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or
 * (at your option) any later version.
 * 
 * graveman! 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 General Public License
 * along with program; see the file COPYING. If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA. 
 * 
 * URL: http://www.nongnu.org/graveman/
 *
 */

#include "graveman.h"

gchar Gfileconf[1024];
GHashTable *Gconfigprog = NULL;
GError *Gerror = NULL;
gint Gfifosize = 6; /* taille fifo en MO */

/* liste des directives utilisees dans le fichier de configuration
 * TYPE, clef, requis ou non, valeur par defaut */
TProgRequis Glisteprogrequis[] = {
  { CONF_PROG, "cdrecord", "", CONF_SAVEALWAYS },
  { CONF_STRING, "cdrecordpara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "mkisofs", "", CONF_SAVEALWAYS },
  { CONF_STRING, "mkisofspara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "readcd", "", CONF_SAVEALWAYS },
  { CONF_STRING, "readcdpara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "sox", "", CONF_SAVEALWAYS },
  { CONF_STRING, "soxpara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "dvd+rw-mediainfo", "", CONF_SAVEALWAYS },
  { CONF_STRING, "dvd+rw-mediainfopara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "dvd+rw-format", "", CONF_SAVEALWAYS },
  { CONF_STRING, "dvd+rw-formatpara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "growisofs", "", CONF_SAVEALWAYS },
  { CONF_STRING, "growisofspara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "cdrdao", "", CONF_SAVEALWAYS },
  { CONF_STRING, "cdrdaopara", "", CONF_SAVEALWAYS },
  { CONF_PROG, "flac", "", CONF_SAVEALWAYS },
  { CONF_STRING, "flacpara", "", CONF_SAVEALWAYS },
  { CONF_DIR, "tmpdir", "/tmp", CONF_SAVEALWAYS },
  { CONF_STRING, "overburn", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "autoblank", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "fastblank", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "charsetdata", "DEFAULT", CONF_SAVEALWAYS },
  { CONF_STRING, "eject", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "iconsize", "48", CONF_SAVEALWAYS },
  { CONF_STRING, "statusbar", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "tooltips", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "saveconfig", "1", CONF_SAVEALWAYS },

  /* onglet audio */
  { CONF_STRING, "dstaudiocombo", "", CONF_SAVEONEXIT + CONF_DEVICE },
  { CONF_STRING, "dstaudiospeed", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "audiodao", "1", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "audionotfix", "", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "audiosimul", "", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "nbrcdaudio", "1", CONF_SAVEONEXIT + CONF_SPIN },
  
  /* onglet data */
  { CONF_STRING, "dstdatacombo", "", CONF_SAVEONEXIT + CONF_DEVICE },
  { CONF_STRING, "dstdataspeed", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "nbrcddata", "1", CONF_SAVEONEXIT + CONF_SPIN },
  { CONF_STRING, "dataformat", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "datamodburn", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "dataisolevel", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "datarockridge", "1", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "datajoliet", "1", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "datamulti", "", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "datanotfix", "", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "datasimul", "", CONF_SAVEONEXIT + CONF_CHECK },

  /* onglet dvd data */
  { CONF_STRING, "dstdvddatacombo", "", CONF_SAVEONEXIT + CONF_DEVICE },
  { CONF_STRING, "dstdvddataspeed", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "nbrdvddata", "1", CONF_SAVEONEXIT + CONF_SPIN },
  { CONF_STRING, "dvddatanotfix", "", CONF_SAVEONEXIT + CONF_CHECK },
  { CONF_STRING, "dvddatasimul", "", CONF_SAVEONEXIT + CONF_CHECK },


 /* onglet copier */
  { CONF_STRING, "srccopycombo", "", CONF_SAVEONEXIT + CONF_DEVICE },
  { CONF_STRING, "dstcopycombo", "", CONF_SAVEONEXIT + CONF_DEVICE },
  { CONF_STRING, "dstcopyspeed", "", CONF_SAVEONEXIT + CONF_COMBO },
  { CONF_STRING, "nbrcdcopy", "1", CONF_SAVEONEXIT + CONF_SPIN },
  { CONF_STRING, "copysimul", "", CONF_SAVEONEXIT + CONF_CHECK },

  /* onglet autres */
  { CONF_STRING, "dstothercombo", "", CONF_SAVEONEXIT + CONF_DEVICE },
  
#if 0
  { CONF_STRING, "extended", FALSE, "1" },
#endif
  { CONF_STRING, "version", "1", CONF_SAVEALWAYS },
  { CONF_STRING, "scan_drives", "0", CONF_SAVEALWAYS + CONF_PERSIST },
  { CONF_STRING, "theme", "default", CONF_SAVEALWAYS },
  { CONF_IGNORE, NULL, NULL, 0 },
};

TProgRequis *getentrydef(gchar *Aentry)
{
  TProgRequis *Lcurentry;
  for (Lcurentry = Glisteprogrequis; Lcurentry->entry; Lcurentry++) {
    if (!strcmp(Lcurentry->entry, Aentry)) return Lcurentry;
  }
  g_assert(0);
  return NULL;
}

/* callback ecriture fichier de conf */
void foreachconfig(gpointer Akey, gpointer Avalue, gpointer Adata)
{
  FILE *Lfic = (FILE *) Adata;

  fprintf(Lfic, "%s=%s\n", (gchar *)Akey, (gchar *)Avalue);
}

/* callback ecriture type de media dans le fichier de conf */
void foreachmedia(gpointer Amedia, gpointer Adata)
{
  FILE *Lfic = (FILE *) Adata;
  Tmediaentry *Amediaentry = (Tmediaentry *) Amedia;

  fprintf(Lfic, "[media]\n");
  fprintf(Lfic, "length=%ld\n", Amediaentry->size);
  fprintf(Lfic, "datalabel=%s\n", Amediaentry->labeldata);
  fprintf(Lfic, "audiolabel=%s\n", Amediaentry->labelaudio);
}

/* callback ecriture d'un charset */
void foreachcharsets(gpointer Acharset, gpointer Adata)
{
  FILE *Lfic = (FILE *) Adata;
  Tdata *Lcharset = (Tdata *) Acharset;

  fprintf(Lfic, "[charsets]\n");
  fprintf(Lfic, "code=%s\n", Lcharset->data);
  fprintf(Lfic, "label=%s\n", Lcharset->label);
}

/* callback ecriture d'un lecteur */
void foreachdrives(gpointer Adrive, gpointer Adata)
{
  FILE *Lfic = (FILE *) Adata;
  Tdriveinfo *Ldrive = (Tdriveinfo *) Adrive; 
  gint i;

  fprintf(Lfic, "[lecteur]\n");
  for (i=0; i < g_slist_length(Ldrive->bus); i++) {
    fprintf(Lfic, "dev=%s|%s\n", (gchar *)g_slist_nth_data(Ldrive->bus, i),(gchar *)g_slist_nth_data(Ldrive->dev, i));
  }
  fprintf(Lfic, "actu=%d\n", Ldrive->actuperiph);  /* numero du dev utilise */
  fprintf(Lfic, "name=%s\n", Ldrive->name);  
  fprintf(Lfic, "type=%d\n", Ldrive->type);
  fprintf(Lfic, "vitesse=%d\n", Ldrive->vitesse);
  fprintf(Lfic, "vitessedvd=%d\n", Ldrive->vitessedvd);
  fprintf(Lfic, "manual=%d\n", Ldrive->manual == TRUE ? 1 : 0);
}

gchar *dump_file_list(char *Abuf, gint Asize)
{
  GSList *Llistconfig = get_config_path();
  GSList *Lcurlist;

  memset(Abuf, 0, Asize);

  for (Lcurlist = Llistconfig; Lcurlist; Lcurlist = g_slist_next(Lcurlist)) {
    if (*Abuf) strncat(Abuf, "\n", Asize-strlen(Abuf)-5);
    strncat(Abuf, Lcurlist->data, Asize-strlen(Abuf)-5);
  }

  g_slist_free(Llistconfig);

  return Abuf;
}

/* ecriture du fichier de configuration */
gboolean write_conf(GError **Aerror)
{
  FILE *Lfic;
  gchar *Ltmp;
  
  if (!get_config_file(W_OK)) return FALSE;

  if (!(Lfic=fopen(Gfileconf, "w"))) {
    Ltmp = g_strdup_printf(_("Cannot create %s: %s"), Gfileconf, g_strerror(errno));
    g_set_error(Aerror, G_FILE_ERROR, g_file_error_from_errno(errno), Ltmp, g_strerror(errno)); 
    g_warning("%s", Ltmp);
    g_free(Ltmp);
    
    return FALSE;
  }

  fprintf(Lfic, "[general]\n");
  fprintf(Lfic, "confversion=%s\n", VERSION);
  g_hash_table_foreach(Gconfigprog, foreachconfig, (gpointer *)(Lfic));
  
  /* ecriture des lecteurs */
  g_slist_foreach(Glistdrives, foreachdrives, (gpointer *)(Lfic));

  /* ecriture des charsets */
  g_slist_foreach(Gcharsetlist, foreachcharsets, (gpointer *)(Lfic));

  fclose(Lfic);

  return TRUE;
}

/* initialisation de la configuration et des valeurs par default */
void config_init()
{
  const gchar *s = g_getenv("CDR_FIFOSIZE");
  Gconfigprog = _hash();
  Gmedialist = NULL;

  conf_store_value("fastblank", "1");
  conf_store_value("tmpdir", "/tmp");
  conf_store_value("lastdir", "");
  conf_store_value("iconsize", "48");
  conf_store_value("statusbar", "1");
  conf_store_value("saveconfig", "1");
  conf_store_value("tooltips", "1");
  conf_store_value("theme", "default");
  if (s) {
    Gfifosize = atoi(s);
    if (Gfifosize<=0) Gfifosize=6;
  }
}

/* on regarde si un fichier de configuration existe 
 * tel que definie par http://standards.freedesktop.org/basedir-spec/latest/ */

/* construction de la liste des PATH dans lequel on va chercher la configuration */
GSList *get_config_path()
{
  GSList *Lnewlist = NULL;
  const gchar *Lenv;
  gchar *Lpath;
  gchar **Llistpath;
  gint i;

  /* parametre -c sur la ligne de commande */
  if ((Lpath = param_get_string("config_file"))) {
    Llistpath = g_strsplit(Lpath, ":", 0);

    for (i=0; Llistpath[i]; i++) {
      if (!*Llistpath[i]) continue; /* on ignore les entrees vides */
      Lnewlist = g_slist_append(Lnewlist, g_strdup_printf(Llistpath[i]));
    }

    g_strfreev(Llistpath);
  }
  
  if ((Lenv=g_getenv("XDG_CONFIG_HOME"))) {
    Lpath = g_strdup_printf("%s/%s/%s.conf", Lenv, PACKAGE, PACKAGE);
    Lnewlist = g_slist_append(Lnewlist, Lpath);
  } else if ((Lenv=g_getenv("HOME"))) {
    Lpath = g_strdup_printf("%s/.config/%s/%s.conf", Lenv, PACKAGE, PACKAGE);
    Lnewlist = g_slist_append(Lnewlist, Lpath);
  }

  if ((Lenv = g_getenv("XDG_CONFIG_DIRS"))) {
    Llistpath = g_strsplit(Lenv, ":", 0);

    for (i=0; Llistpath[i]; i++) {
      if (!*Llistpath[i]) continue; /* on ignore les entrees vides */
      Lpath = g_strdup_printf("%s/%s/%s.conf", Llistpath[i], PACKAGE, PACKAGE);
      Lnewlist = g_slist_append(Lnewlist, Lpath);
    }

    g_strfreev(Llistpath);

  } else {
    Lpath = g_strdup_printf("/etc/xdg/%s/%s.conf", PACKAGE, PACKAGE);
    Lnewlist = g_slist_append(Lnewlist, Lpath);
  }

  return Lnewlist;
}

/* on regarde si un repertoire de donnée existe
 * tel que definie par http://standards.freedesktop.org/basedir-spec/latest/
 * on regarde de + en dernier dans le DATADIR definie a la compilation
 */

/* construction de la liste des PATH dans lequel on va chercher la configuration */
GSList *get_data_path()
{
  GSList *Lnewlist = NULL;
  const gchar *Lenv;
  gchar *Lpath;
  gchar **Llistpath;
  gint i;

  /* parametre -c sur la ligne de commande */
  if ((Lpath = param_get_string("data_file"))) {
    Llistpath = g_strsplit(Lpath, ":", 0);

    for (i=0; Llistpath[i]; i++) {
      if (!*Llistpath[i]) continue; /* on ignore les entrees vides */
      Lnewlist = g_slist_append(Lnewlist, g_strdup_printf(Llistpath[i]));
    }

    g_strfreev(Llistpath);
  }

  if ((Lenv=g_getenv("XDG_DATA_HOME"))) {
    Lpath = g_strdup_printf("%s/%s", Lenv, PACKAGE);
    Lnewlist = g_slist_append(Lnewlist, Lpath);
  } else if ((Lenv=g_getenv("HOME"))) {
    Lpath = g_strdup_printf("%s/.local/share/%s", Lenv, PACKAGE);
    Lnewlist = g_slist_append(Lnewlist, Lpath);
  }

  if ((Lenv = g_getenv("XDG_DATA_DIRS"))) {
    Llistpath = g_strsplit(Lenv, ":", 0);

    for (i=0; Llistpath[i]; i++) {
      Lpath = g_strdup_printf("%s/%s", Llistpath[i], PACKAGE);
      Lnewlist = g_slist_append(Lnewlist, Lpath);
    }

    g_strfreev(Llistpath);
  }

  Lpath = g_strdup_printf("/usr/local/share/%s", PACKAGE);
  Lnewlist = g_slist_append(Lnewlist, Lpath);
  Lpath = g_strdup_printf("/usr/share/%s", PACKAGE);
  Lnewlist = g_slist_append(Lnewlist, Lpath);
  Lpath = g_strdup_printf("%s/%s", DATA_DIR, PACKAGE);
  Lnewlist = g_slist_append(Lnewlist, Lpath);

  return Lnewlist;
}

gboolean get_config_file(gint Lmode)
{
  GSList *Llistconfig = get_config_path();
  GSList *Lcurlist;
  gboolean Ltrouve = FALSE;
  gchar Lonlyname[1024];
  gchar *s;
  
  *Gfileconf = 0; 

  for (Lcurlist = Llistconfig; Lcurlist; Lcurlist = g_slist_next(Lcurlist)) {
    if (W_OK == Lmode) {
      g_strlcpy(Lonlyname, (gchar *)Lcurlist->data, sizeof(Lonlyname)-1);      
      if (!(s=strrchr(Lonlyname, '/'))) continue;
      *s=0;
      if (FALSE == sc_mkdir(Lonlyname, 00750)) continue;

      Ltrouve = TRUE;
    } else if (access((gchar *)Lcurlist->data, F_OK)==0) {
      Ltrouve = TRUE;
    }
    if (Ltrouve) {
      g_strlcpy(Gfileconf, (gchar *) Lcurlist->data, sizeof(Gfileconf)-1);
      break;
    }
  }

#ifdef DEBUG
  if (*Gfileconf) {
    g_message("une conf [%s] valide trouve !\n", Gfileconf);
  } else {
    g_message("pas de conf valide de trouve!\n");
  }
#endif

  if (!Ltrouve)
    g_strlcpy(Gfileconf, (gchar *) g_slist_nth_data(Llistconfig, 0), sizeof(Gfileconf)-1);

  g_slist_free(Llistconfig);

  return Ltrouve;
}

/* sauve une cle dans le hash de configuration */
void conf_store_value(gchar *Aentry, gchar *Avalue)
{
  gpointer Loldkey, Loldval;
  /* on commence par supprimer l'eventuelle ancienne cle */
  if (g_hash_table_lookup_extended(Gconfigprog, Aentry, &Loldkey, &Loldval) == TRUE) {
    g_hash_table_remove(Gconfigprog, Aentry);
    g_free(Loldkey);
    g_free(Loldval);
  }

  g_hash_table_insert(Gconfigprog, g_strdup(Aentry), g_strdup(Avalue ? Avalue : ""));
}

void conf_store_int(gchar *Aentry, gint Avalue)
{
  gchar Lstrvalue[7];
  g_snprintf(Lstrvalue, sizeof(Lstrvalue)-1, "%d", Avalue);

  conf_store_value(Aentry, Lstrvalue);
}


#if 0
void config_init_default_media()
{
  Tmediaentry *Lcurmedia;
  Tmediaentry *Lnewmedia;
  for (Lcurmedia = Gdefaultmedia; Lcurmedia->size; Lcurmedia++) {
    Lnewmedia = g_malloc0(sizeof(Tmediaentry));
    Lnewmedia->labeldata = g_strdup(Lcurmedia->labeldata);
    Lnewmedia->labelaudio = g_strdup(Lcurmedia->labelaudio);
    Lnewmedia->size = Lcurmedia->size;
//printf("1 de +\n");
    Gmedialist = g_slist_append(Gmedialist, Lnewmedia);
  }
//  printf("fin\n");
}
#endif

/* callback appele lors de la comparasion de 2 medias */
gint config_find_media_callback(gconstpointer Acompsize, gconstpointer Acompvers)
{
  gulong *Lsize = (gulong *)Acompsize;
  Tmediaentry *LB = (Tmediaentry *)Acompvers;

  if (*Lsize == LB->size) return 0;
  if (*Lsize > LB->size) return 1;
  return -1;
}

/* ajout d'un charset a  la liste des charsets */
gboolean config_append_charset(gchar *Acode, gchar *Alabel)
{
  Tdata *Lnewcharset = g_malloc(sizeof(Tdata));

  Lnewcharset->data = g_strdup(Acode);
  Lnewcharset->label = g_strdup(Alabel && *Alabel ? Alabel : Acode);

  Gcharsetlist = g_slist_append(Gcharsetlist, Lnewcharset);

  return TRUE;
}

/* ajout d'un media a la liste des media */
gboolean config_append_media(gulong Alen, gchar *Alabeldata, gchar *Alabelaudio)
{
  Tmediaentry *Lnewmedia = g_malloc(sizeof(Tmediaentry));

  /* on commence par verifier qu'un media de cette taille n'existe pas deja */
  if (!Alen || g_slist_find_custom(Gmedialist, &Alen, config_find_media_callback)) {
    g_free(Lnewmedia);
    return FALSE;
  }
  Lnewmedia->size = Alen;
  Lnewmedia->labeldata = g_strdup(Alabeldata);
  Lnewmedia->labelaudio = g_strdup(Alabelaudio);

  Gmedialist = g_slist_append(Gmedialist, Lnewmedia);

  return TRUE;
}

/* savegarde de la valeur de certains champs du formulaire lorsque
 * l'option "save on exit" est active */
void manage_saveonexit_value(Tgrave *Ag)
{
  TProgRequis *Lcurentry;
  GtkWidget *Lwidget;

  for (Lcurentry = Glisteprogrequis; Lcurentry->entry; Lcurentry++) {
    if (!(Lcurentry->level & CONF_SAVEONEXIT)) continue;
    Lwidget = sc_grave_get_widget(Ag, Lcurentry->entry);

    if (!GTK_IS_WIDGET(Lwidget)) {
      g_warning("Error %s is missing!", Lcurentry->entry);
      continue;
    }
    _DEB("on sauve '%s'\n", Lcurentry->entry);
        
    if (Lcurentry->level & CONF_COMBO) {
      conf_store_value(Lcurentry->entry, get_combo_value(Lwidget));
    } else if (Lcurentry->level & CONF_DEVICE) {
      Tdriveinfo *Ldevice = get_combo_value(Lwidget);
      if (Ldevice != NULL)
        conf_store_value(Lcurentry->entry, DRIVE_DEV(Ldevice));
    } else if (Lcurentry->level & CONF_SPIN) {
      conf_store_int(Lcurentry->entry, gtk_spin_button_get_value(GTK_SPIN_BUTTON(Lwidget)));
    } else if (Lcurentry->level & CONF_CHECK) {
      conf_store_value(Lcurentry->entry, _BOOLEAN_CONF(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Lwidget))));
    }
  }
}

/* gestion de la configuration (creation/chargement/sauvegarde...) */
gboolean manage_config(Tgrave *Ag, gshort Aop, GError **Aerror)
{
  TProgRequis *Lcurprog;
  gchar *Lprog;
  gboolean Lstatus = TRUE;
  GtkWidget *Lwindow1 = sc_grave_get_widget(Ag, "topwindow");

  if (Aop & UPDATE_SAVEONEXIT_VALUE) {
    /* mise a jour des valeurs a sauvegarder lorsque l'on quitte */
    manage_saveonexit_value(Ag);
  }

  if (Aop & CONF_INIT_DEFAULT) {
    /* initialsiation des valeurs par defaut */
    for (Lcurprog = Glisteprogrequis; Lcurprog->entry; Lcurprog++) {
      if (Lcurprog->defaultvalue && *Lcurprog->defaultvalue) {
        Lprog = g_strdup(Lcurprog->defaultvalue);

        conf_store_value(Lcurprog->entry, Lprog);
      }
    }
  }

  if (Aop & SEARCH_PROG) {
    /* on recherche les programmes externes */
    for (Lcurprog = Glisteprogrequis; Lcurprog->entry; Lcurprog++) {
      if (Lcurprog->type &~ CONF_PROG) continue;

      Lprog = g_find_program_in_path(Lcurprog->entry);

      conf_store_value(Lcurprog->entry, Lprog);
#ifdef DEBUG
      if (! Lprog || !*Lprog) g_warning("ERREUR LE PROG [%s] EST INDISPENSABLE ET NON TROUVE !\n", Lcurprog->entry);
#endif
    }
    
    /* pour mkisofs on regarde qu'il y ai bien le support iso version 2 */
    conf_store_value("mkisofs_support_isov2", _BOOLEAN_CONF(check_mkisofs()));

    /* pour sox on regarde si il a bien le support ogg / mp3 */
    check_sox();
    conf_store_value("sox_support_mp3", _BOOLEAN_CONF(GsupportMp3));
    conf_store_value("sox_support_ogg", _BOOLEAN_CONF(GsupportOgg));
    
    GsupportFlac = *conf_get_string("flac");
  }

  if (Aop & SEARCH_LECTEUR) {
    /* maintenant scan des lecteurs */
    cherchelecteur(NULL, Ag);
  }

  if (Aop & SEARCH_CHARSETS) {
    /* scan des charsets definie dans mkisofs */
    cherchecharset(NULL, Ag);
  }

  if (Aop & UPDATE_SIZE && GTK_IS_WIDGET(Lwindow1)) {
    gint Lx = 0, Ly = 0, Lwidth = 0, Lheight = 0;
    /* mise a jour position et taille de la fenetre */
    gtk_window_get_position(GTK_WINDOW(Lwindow1), &Lx, &Ly);
    gtk_window_get_size(GTK_WINDOW(Lwindow1), &Lwidth, &Lheight);
    conf_store_int("x", Lx);
    conf_store_int("y", Ly);
    conf_store_int("width", Lwidth);
    conf_store_int("height", Lheight);
  }

  if (Aop & WRITE_CONFIG) {    
    Lstatus = write_conf(Aerror);
    if (!Lstatus) {
      gchar Lbuf[_BUF_SIZE];
      gchar *Lfullmsg = g_strdup_printf(_("Cannot save configuration file !\nI have tried on those files:\n%s"),
          dump_file_list(Lbuf, sizeof(Lbuf)-1));
      GtkWidget *Ldialog = gtk_message_dialog_new(GTK_IS_WIDGET(Lwindow1) ? GTK_WINDOW(Lwindow1) : NULL,
         GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
         Lfullmsg);
      
      g_warning("%s", Lfullmsg);

      gtk_dialog_run(GTK_DIALOG(Ldialog));
      gtk_widget_destroy(Ldialog);
      g_free(Lfullmsg);
    }
  }

  return Lstatus;
}

/* renvoi une valeur du fichier de configuration */
gchar *conf_get_string(gchar *Anom)
{
  return (gchar *)g_hash_table_lookup(Gconfigprog, Anom);
}

/* renvoi une valeur du fichier de configuration si elle est presente ou une valeur
 * par defaut */
gchar *conf_get_string_def(gchar *Anom, gchar *Adefault)
{
  gchar *Lreturn = (gchar *)g_hash_table_lookup(Gconfigprog, Anom);
  if (!Lreturn || *Lreturn==0) return Adefault;

  return Lreturn;
}

/* renvoi un nombre du fichier de configuration */
gint conf_get_int(gchar *Anom)
{
  gchar *Lvalue = (gchar *)g_hash_table_lookup(Gconfigprog, Anom);
  if (!Lvalue) return -1;
  return atoi(Lvalue);
}

/* renvoi un boolean du fichier de configuration */
gboolean conf_get_boolean(gchar *Anom)
{
  gchar *Lvalue = (gchar *)g_hash_table_lookup(Gconfigprog, Anom);
  return (Lvalue && *Lvalue == '1' ? TRUE : FALSE);
}

void clean_config()
{
  TProgRequis *Lcurprog;
  gchar *Luneligne;
  
  /* pour etre sur on fixe toutes les directives requises a au moins "chaine vide" */
  for (Lcurprog = Glisteprogrequis; Lcurprog->entry; Lcurprog++) {
    Luneligne = (gchar *)g_hash_table_lookup(Gconfigprog, Lcurprog->entry);
    if (!Luneligne) g_hash_table_insert(Gconfigprog, g_strdup(Lcurprog->entry), g_strdup(""));
  }
  
#if 0
  /* si aucune description de media on insere celles par default */
  if (g_slist_length(Gmedialist)==0) {
  //printf("alors la len => %d\n", g_slist_length(Gmedialist));
    config_init_default_media();
  }
  //printf("TOTAL => %d\n", g_slist_length(Gmedialist));
#endif
}


/* lecture d'un fichier de configuration */
gboolean read_config(GError **Aerror)
{
  gchar *Lcontents = NULL;
  gchar *Lkey, *Lvalue;
  gchar **Llignes;
  gchar *Luneligne;
  gchar Lemplacement[_BUF_SIZE] = "";
  gint i;
  gulong Lmedialen = 0;
  gchar Lmedialabeldata[_BUF_SIZE] = "", Lcharsetcode[_BUF_SIZE] = "";
  gchar Lmedialabelaudio[_BUF_SIZE] = "", Lcharsetlabel[_BUF_SIZE] = "";
  Tdriveinfo *Ldriveinfo = NULL;

  if (!g_file_get_contents(Gfileconf, &Lcontents, NULL, Aerror)) {
    g_warning("%s", (*Aerror)->message);
    return FALSE;
  }
    
  Llignes = g_strsplit((const gchar *) Lcontents, "\n", 200);

  for (i=0; Llignes[i]; i++) {
    Luneligne = (gchar *)Llignes[i];
    g_strstrip(Luneligne);

    if (!*Luneligne || *Luneligne == ';' || *Luneligne == '#') continue;

    if (*Luneligne == '[') {
      if (Ldriveinfo) { /* ajout d'un lecteur si un en cours */
        append_this_drive(Ldriveinfo);
        Ldriveinfo = NULL;
      }
      
      g_strlcpy(Lemplacement, Luneligne, sizeof(Lemplacement));
      
      if (!strcmp(Lemplacement, "[media]")) { /* init media */
        Lmedialen = 0; *Lmedialabeldata = *Lmedialabelaudio = 0;
      } else if (!strcmp(Lemplacement, "[lecteur]")) {  /* init lecteur */
        Ldriveinfo = g_malloc0(sizeof(Tdriveinfo));
      }
    } else if (!strcmp(Lemplacement, "[general]")) {
      /* section general */
      Lvalue = strchr(Luneligne, '=');
      if (Lvalue) { *(Lvalue++)=0; } else { continue; }
      Lkey = Luneligne;

      g_hash_table_insert(Gconfigprog, g_strdup(Lkey), g_strdup(Lvalue));
    } else if (!strcmp(Lemplacement, "[charsets]")) {
      /* section charsets */
      Lvalue = strchr(Luneligne, '=');
      if (Lvalue) { *(Lvalue++)=0; } else { continue; }
      Lkey = Luneligne;

      if (!strcmp(Lkey, "code")) {
        g_strlcpy(Lcharsetcode, Lvalue, sizeof(Lcharsetcode)-1);
      } else if (!strcmp(Lkey, "label")) {
        g_strlcpy(Lcharsetlabel, Lvalue, sizeof(Lcharsetlabel)-1);
      }

      if (*Lcharsetcode && *Lcharsetlabel) {
        config_append_charset(Lcharsetcode, Lcharsetlabel);

        *Lcharsetcode = *Lcharsetlabel = 0;
      }
    } else if (!strcmp(Lemplacement, "[media]")) {
      /* section liste des medias */
      Lvalue = strchr(Luneligne, '=');
      if (Lvalue) { *(Lvalue++)=0; } else { continue; }
      Lkey = Luneligne;

      if (!strcmp(Lkey, "length")) {
        Lmedialen = strtoul(Lvalue, NULL, 10);
      } else if (!strcmp(Lkey, "datalabel")) {
        g_strlcpy(Lmedialabeldata, Lvalue, sizeof(Lmedialabeldata)-1);
      } else if (!strcmp(Lkey, "audiolabel")) {
        g_strlcpy(Lmedialabelaudio, Lvalue, sizeof(Lmedialabelaudio)-1);
      }

      if (Lmedialen && *Lmedialabeldata && *Lmedialabelaudio) {
        config_append_media(Lmedialen, Lmedialabeldata, Lmedialabelaudio);
        Lmedialen = 0;
      }
    } else if (!strcmp(Lemplacement, "[lecteur]")) {
      /* section lecteur */
      Lvalue = strchr(Luneligne, '=');
      if (Lvalue) { *(Lvalue++)=0; } else { continue; }
      Lkey = Luneligne;
     
      if (!strcmp(Lkey, "type")) {
        Ldriveinfo->type = atoi(Lvalue);
      } else if (!strcmp(Lkey, "name")) {
        if (Ldriveinfo->name) g_free(Ldriveinfo->name);
        Ldriveinfo->name = g_strdup(Lvalue);
      } else if (!strcmp(Lkey, "dev")) {
        gchar *Lvalue2 = strchr(Lvalue, '|');
        if (Lvalue2) *(Lvalue2++)=0;
        Ldriveinfo->bus = g_slist_append(Ldriveinfo->bus, Lvalue2 ? g_strdup(Lvalue) : "OLD");
        Ldriveinfo->dev = g_slist_append(Ldriveinfo->dev, g_strdup(Lvalue2 ? Lvalue2 : Lvalue));
      } else if (!strcmp(Lkey, "actu")) {
        Ldriveinfo->actuperiph = atoi(Lvalue);
      } else if (!strcmp(Lkey, "vitesse")) {
        Ldriveinfo->vitesse = atoi(Lvalue);
      } else if (!strcmp(Lkey, "manual")) {
        Ldriveinfo->manual = *Lvalue == '1' ? TRUE : FALSE;
      }
    }
  }

  if (Ldriveinfo) {
    if (g_slist_length(Ldriveinfo->dev) && Ldriveinfo->name && Ldriveinfo->vitesse) {
      append_this_drive(Ldriveinfo);
    } else {
      free_this_drive(Ldriveinfo);
    }
  }

  g_strfreev(Llignes);
  g_free(Lcontents);
  clean_config();

  GsupportMp3 = conf_get_boolean("sox_support_mp3");
  GsupportOgg = conf_get_boolean("sox_support_ogg");
  GsupportFlac = *conf_get_string("flac");

  if (!test_version()) return FALSE;  
  
  return TRUE;
}

void maj_foreach_prog(gpointer Akey, gpointer Avalue, gpointer Adata)
{
  Tgrave *Lg = (Tgrave *) Adata;
  GtkWidget *Lobj = sc_grave_get_widget(Lg, Akey);
  gchar *Lname, *Lconfvalue;
  GtkEntry *Lobjentry;
  GtkWidget *Lobjlbl;
  GtkWidget *Lobjtips;
  gchar Ltipstxt[_BUF_SIZE];
  
  if (!GTK_IS_WIDGET(Lobj)) return;

  Lname = g_strdup_printf("%s%s", gtk_widget_get_name(Lobj), "para");
  Lobjentry = GTK_ENTRY(sc_grave_get_widget(Lg, Lname));

  Lconfvalue = conf_get_string(Lname);
  gtk_entry_set_text(Lobjentry, Lconfvalue ? Lconfvalue : "");
  g_free(Lname);

  Lobjlbl = sc_grave_get_widgetv(Lg, "%s%s", gtk_widget_get_name(Lobj), "lbl");
  Lobjtips = sc_grave_get_widgetv(Lg, "%s%s", gtk_widget_get_name(Lobj), "tips");
      
  if (*(gchar *)Avalue) {
    gtk_widget_set_sensitive(GTK_WIDGET(Lobjentry), TRUE);
    gtk_label_set_text(GTK_LABEL(Lobjlbl), (gchar *)Avalue);

    if (!strcmp((gchar *)Akey, "mkisofs") && FALSE == conf_get_boolean("mkisofs_support_isov2")) {
      /* mkisofs est bien la, mais pas de support ISO v2 */
      gtk_image_set_from_pixbuf(GTK_IMAGE(Lobj), get_image("WARNIcon"));
      g_snprintf(Ltipstxt, sizeof(Ltipstxt)-1, _("%s was found but does not support ISO 9660 version 2, this function will be disabled."), (gchar *)Akey);
    } else if (!strcmp((gchar *)Akey, "sox") &&
        (FALSE == conf_get_boolean("sox_support_mp3") || FALSE == conf_get_boolean("sox_support_ogg"))) {
      /* sox est bien la, mais pas de support MP3 ou/et OGG */
      gtk_image_set_from_pixbuf(GTK_IMAGE(Lobj), get_image("WARNIcon"));
      
      if (FALSE == conf_get_boolean("sox_support_mp3") && FALSE == conf_get_boolean("sox_support_ogg")) {
        g_snprintf(Ltipstxt, sizeof(Ltipstxt)-1, _("%s was found but does not support neither OGG or MP3 file format, those functions will be disabled."), (gchar *)Akey);
      } else if (FALSE == conf_get_boolean("sox_support_mp3")) {
        g_snprintf(Ltipstxt, sizeof(Ltipstxt)-1, _("%s was found but does not support MP3 file format, this function will be disabled."), (gchar *)Akey);
      } else {
        g_snprintf(Ltipstxt, sizeof(Ltipstxt)-1, _("%s was found but does not support OGG file format, this function will be disabled."), (gchar *)Akey);
      }
    } else {
      gtk_image_set_from_pixbuf(GTK_IMAGE(Lobj), get_image("OKIcon"));
      g_snprintf(Ltipstxt, sizeof(Ltipstxt)-1, _("%s was found."), (gchar *)Akey);
    }
    gtk_tooltips_set_tip(sc_grave_get_data(Lg, "_tooltips"), Lobjtips, Ltipstxt, Ltipstxt);
  } else {
    gtk_image_set_from_pixbuf(GTK_IMAGE(Lobj), get_image("BADIcon"));
    gtk_widget_set_sensitive(GTK_WIDGET(Lobjentry), FALSE);
    gtk_label_set_text(GTK_LABEL(Lobjlbl), (gchar *)Akey);
    g_snprintf(Ltipstxt, sizeof(Ltipstxt)-1, _("%s was not found, some features of graveman will be disabled."), (gchar *)Akey);
    gtk_tooltips_set_tip(sc_grave_get_data(Lg, "_tooltips"), Lobjtips, Ltipstxt, Ltipstxt);

  }
}

/* mise a jour de la page "programme externe" */
void maj_proprietes_prog(Tgrave *Ag)
{
  TProgRequis *Lcurentry;
  gchar *Lvalue;
  
  for (Lcurentry = Glisteprogrequis; Lcurentry->entry; Lcurentry++) {
    if (Lcurentry->type == CONF_PROG) {
      Lvalue = conf_get_string(Lcurentry->entry);
      maj_foreach_prog(Lcurentry->entry, Lvalue, Ag);
    }
  }
}

/* on restaure la derniere position et taille de la fenetre */
void restore_main_window_pos(GtkWidget *Awindow1)
{
  gint Lx = conf_get_int("x");
  gint Ly = conf_get_int("y");
  gint Lwidth = conf_get_int("width");
  gint Lheight = conf_get_int("height");

  if (Lx > -1 && Ly > -1 && Lwidth > 0 && Lheight > 0) {
    gtk_window_resize(GTK_WINDOW(Awindow1), Lwidth, Lheight);
    gtk_window_move(GTK_WINDOW(Awindow1), Lx, Ly);
  }
}

/* on restaure les dernieres valeurs utilisees pour certains champs */
void restore_last_used_values(Tgrave *Ag)
{
  TProgRequis *Lcurentry;
  GtkWidget *Lwidget;

  for (Lcurentry = Glisteprogrequis; Lcurentry->entry; Lcurentry++) {
    if (!(Lcurentry->level & CONF_SAVEONEXIT)) continue;

    if ((Lcurentry->level & CONF_SPIN) || (Lcurentry->level & CONF_CHECK)) {
      Lwidget = sc_grave_get_widget(Ag, Lcurentry->entry);
      if (!GTK_IS_WIDGET(Lwidget)) {
        g_warning("Error %s is missing!", Lcurentry->entry);
        continue;
      }

      if (Lcurentry->level & CONF_SPIN) {
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(Lwidget), conf_get_int(Lcurentry->entry));
      } else {
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Lwidget), conf_get_boolean(Lcurentry->entry));
      }
    }
  }
}

/* utilisation du dernier repertoire visite */
void use_last_dir(GtkFileChooser *Awidget)
{
  gchar *Llastdir = conf_get_string("lastdir");

  if (Llastdir) gtk_file_chooser_set_current_folder_uri(Awidget, Llastdir);
}

/* sauvegarde du dernier repertoire visite */
void save_last_dir(GtkFileChooser *Awidget)
{
  gchar *Llastdir = gtk_file_chooser_get_current_folder_uri(Awidget);

  if (Llastdir) conf_store_value("lastdir", Llastdir);
}

/* test sur la version du fichier de configuration .. */
gboolean test_version()
{
  char *Lver = conf_get_string("confversion");
  if (!Lver || ((strcmp(Lver, VERSION)) && (strncmp(Lver, "0.3.12", 6)))) {
    gchar *Lerrmsg = g_strdup_printf(_("graveman update !\n\nYou must remove your old configuration file '%s'.\nThen you can restart graveman..\n\nThanks ! :-)"), Gfileconf);
    GtkWidget *Lerr = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
                          GTK_BUTTONS_OK, Lerrmsg);
    gtk_dialog_run(GTK_DIALOG(Lerr));
    gtk_widget_destroy(Lerr);
   
    return FALSE;
  }

  return TRUE;
}
/*
 * vim:et:ts=8:sts=2:sw=2
 */
