/* matos.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/
 *
 */

/* initialisation des devices */

#include "graveman.h"

GSList *Glistdrives = NULL;

Tdriveinfo *find_drive(gchar *Aident) {
  GSList *Lcur, *Lcurdev;
  Tdriveinfo *Ldrive;
 
  for (Lcur = Glistdrives; Lcur; Lcur = g_slist_next(Lcur)) { 
    Ldrive = (Tdriveinfo *)Lcur->data;

    for (Lcurdev = Ldrive->dev; Lcurdev; Lcurdev = g_slist_next(Lcurdev)) {

  _DEB("om compare [%s] et [%s]\n", Aident, (gchar *)Lcurdev->data);
      if (!strcmp(Aident, (gchar *)Lcurdev->data)) {
        _DEB("ici GL vitesse => %d\n", Ldrive->vitesse);
        return Ldrive;
      }
    }
  }

  return NULL;
}

/* ajout d'un lecteur a la liste des lecteurs */
void append_this_drive(Tdriveinfo *Adrive) {
  Glistdrives=g_slist_append(Glistdrives, Adrive);
}

/* liberation de la zone memoire occupe par une structure lecteur */
void free_this_drive(Tdriveinfo *Adrive) {
  GSList *Lcur;
  if (g_slist_length(Adrive->dev)) {
    for (Lcur = Adrive->dev; Lcur; Lcur = g_slist_next(Lcur)) {
      g_free((gchar *)Lcur->data);
    }
    g_slist_free(Adrive->dev);
  }
  if (g_slist_length(Adrive->bus)) {
    for (Lcur = Adrive->bus; Lcur; Lcur = g_slist_next(Lcur)) {
      g_free((gchar *)Lcur->data);
    }
    g_slist_free(Adrive->bus);
  }

  g_free(Adrive->name);
}

void free_drives(gboolean Aremovemanu)
{
  GSList *Ltmp = Glistdrives, *Lcurlist;
  gboolean Ldonotdel;
  Tdriveinfo *Lcur;

  while (Ltmp) {
    Lcurlist = Ltmp;
    Lcur = (Tdriveinfo *)Ltmp->data;

    Ldonotdel = (Lcur->manual == TRUE && Aremovemanu==FALSE);

    Ltmp = g_slist_next(Ltmp);

    if (Ldonotdel == FALSE) {
      free_this_drive((Tdriveinfo *)Lcurlist->data);
    
      Glistdrives = g_slist_delete_link(Glistdrives, Lcurlist);
    }
  }

  if (g_slist_length(Glistdrives)==0) Glistdrives = NULL;
}

void matos_get_current_matos(gboolean *Areadcd, gboolean *Awritecdr, gboolean *Awritecdrw, gboolean *Areaddvd, gboolean *Awritedvd)
{
  GSList *Lcur;
  Tdriveinfo *Ldrive;

  if (Areadcd) *Areadcd = FALSE;
  if (Awritecdr) *Awritecdr = FALSE;
  if (Awritecdrw) *Awritecdrw = FALSE;
  if (Areaddvd) *Areaddvd = FALSE;
  if (Awritedvd) *Awritedvd = FALSE;

  for (Lcur = Glistdrives; Lcur; Lcur = g_slist_next(Lcur)) { 
    Ldrive = (Tdriveinfo *)Lcur->data;

    if (DRIVE_READER(Ldrive) && Areadcd) *Areadcd = TRUE;
    if (DRIVE_WRITER(Ldrive) && Awritecdr) *Awritecdr = TRUE; 
    if (DRIVE_CDRW_WRITER(Ldrive) && Awritecdrw) *Awritecdrw = TRUE; 
    if (DRIVE_DVDREADER(Ldrive) && Areaddvd) *Areaddvd = TRUE;
    if (DRIVE_DVDWRITER(Ldrive) && Awritedvd) *Awritedvd = TRUE;
  }
}

void matos_insert_or_update_drive(gchar *Adev, gchar *Amarque, gchar *Amodel, gchar *Aquoi, Tsearchdrive *Adrivedesc)
{
  /* on commence par construire l'identifiant */
  gchar *Lident = g_strdup_printf("%s %s %s", Amarque, Amodel, Aquoi);
  GSList *Lcur = NULL;
  Tdriveinfo *Ldrive;

  for (Lcur = Glistdrives; Lcur; Lcur = g_slist_next(Lcur)) {
    Ldrive = (Tdriveinfo *)Lcur->data;

    if (!strcmp(Ldrive->name, Lident) && strcmp((gchar *)g_slist_last(Ldrive->bus)->data, Adrivedesc->bus)) {
_DEB("mise a jour du lecteur [%s]\n", Lident);      
      /* oui ce lecteur existe deja, c'est donc lui qui l'on va mettre a jour */
      break;
    }
  }

  if (!Lcur) {
    /* le lecteur n'existe pas encore, on l'ajoute a la liste */

    Ldrive = g_malloc0(sizeof(Tdriveinfo));
    Ldrive->name = Lident;

    Glistdrives = g_slist_append(Glistdrives, Ldrive);
_DEB("nouveau lecteur [%s]\n", Lident);      
  } else {
    g_free(Lident);
  }

_DEB("le bus en question [%s] = [%s]\n", Adrivedesc->bus, Adev);
  Ldrive->bus = g_slist_append(Ldrive->bus, g_strdup(Adrivedesc->bus));
  Ldrive->dev = g_slist_append(Ldrive->dev,
      g_strdup_printf("%s%s", Adrivedesc->useline,
        strcmp(Adrivedesc->bus, "IDE") && strncmp(Adrivedesc->bus, IDENT_SCSI, strlen(IDENT_SCSI)) ? 
          Adev : ""));
}

/* operation de copie */
gboolean burn_copy(Tgrave *Ag, GError **Aerror)
{
  Tdriveinfo *Lsource = matos_get_drive_info(Ag, "srccopycombo");
  Tdriveinfo *Lgraveur = matos_get_drive_info(Ag, "dstcopycombo");
  GtkEntry *Llecteuriso = GTK_ENTRY(sc_grave_get_widget(Ag, "srccopybtnvalue"));
  GtkEntry *Lgraveuriso = GTK_ENTRY(sc_grave_get_widget(Ag, "dstcopybtnvalue"));
  gchar *Ltxt;
  gboolean Lstatus;
  gboolean Loperationstatus = FALSE;
  gint Ltodo = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sc_grave_get_widget(Ag, "nbrcdcopy")));
  gint Ldone = 1;
  gchar Ltmpdir[MAXPATHLEN]="";
  gchar Liso[MAXPATHLEN]="";
  const gchar *Lptriso;
_DEB("DEBUT COPIE !!");

  if (!Lsource && !Lgraveur) {
    g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_MODE, 
      _("Cannot duplicate an iso image to an another iso image with graveman, just copy this file !"));
    return FALSE;
  }

  /* referecement variables */
  sc_grave_set_data(Ag, &Ltodo, "todo"); /* a faire */
  sc_grave_set_data(Ag, &Ldone, "done"); /* fais */
  sc_grave_set_data(Ag, &Loperationstatus, "operationstatus"); /* resultat de l'operation */
  sc_grave_set_data(Ag, &Ltmpdir, "tmpdir"); /* repertoire temporraire */
  sc_grave_set_data(Ag, Aerror, "gerror");  /* pointeur retour des erreurs */

  if (!Lsource) {
    /* copie d'une image vers un cd, on utilise cdrecord */
    Lptriso = gtk_entry_get_text(Llecteuriso);
    Ltxt = _FILENAME(Lptriso);
    g_strlcpy(Liso, Ltxt, MAXPATHLEN-1);
    g_free(Ltxt);

    /* on test si on a bien acces au fichier iso source */
    if (!*Liso) {
      g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_DATA, 
          _("A valid iso image location is required in the \"Duplicate from\" field."));
      Lstatus = FALSE;
    } else if (access(Liso, R_OK + F_OK)==-1) {
      g_set_error(Aerror, G_FILE_ERROR, g_file_error_from_errno(errno), "%s:%s\n%s",
          _("Cannot read iso image source file"),
          Liso, g_strerror(errno));
      Lstatus = FALSE;
    } else {
      sc_grave_set_data(Ag, &Liso, "iso"); /* image iso */

      Lstatus = burn_from_image("copy", Ag, Aerror);
      Lstatus = burn_iso2dvd(Ag, Aerror);
      sc_grave_del_data(Ag, "iso");
    }
  } else if (!Lgraveur) {
    /* copie d'un cd vers une image, on utilise readcd */
    struct stat Lfstat;
    Lptriso = gtk_entry_get_text(Lgraveuriso);
    Ltxt = _FILENAME(Lptriso);
    g_strlcpy(Liso, Ltxt, MAXPATHLEN-1);
    g_free(Ltxt);
    /* si le fichier existe deja on demande confirmatation avant de l'ecraser */
    Ltxt = NULL;
    if (!*Liso) {
      g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_DATA, 
            _("A valid iso image location is required the \"Duplicate to\" field."));
      Lstatus = FALSE;
    } else if (stat(Liso, &Lfstat) == -1) {
      if (errno != ENOENT) Ltxt = _("Cannot access file");
    } else if (access(Liso, W_OK)==-1) {
      Ltxt = _("Cannot overwrite file");
    }
    if (Ltxt) {
      g_set_error(Aerror, G_FILE_ERROR, g_file_error_from_errno(errno), "%s: %s\n%s",
          Ltxt, Liso, g_strerror(errno));
      Lstatus = FALSE;
    } else {
      Ltodo = 1;
      sc_grave_set_data(Ag, &Liso, "iso"); /* image iso */
      Lstatus = make_image(Ag, Aerror);
      sc_grave_del_data(Ag, "iso");
    }
  } else {  /* copie d'un cd a un autre, on utilise cdrdao */
    /* on ajoute une tache pour la lecture, 
     * si il y a simulation alors ajoute une tache a faire */
//    Ltodo = Ltodo + 1 + (Lsimul == TRUE ? 1 : 0);
    
      /* copie d'un cd vers un cd
       * on passe quand meme vers une image temporraire pour le moment,
       * c'est trop le bordel sinon ! */
_DEB("DEBUT COPIE !!");
    g_snprintf(Ltmpdir, MAXPATHLEN-1, "%s/%s", conf_get_string_def("tmpdir", "/tmp"), "gravemanXXXXXX");

    if (!mkdtemp(Ltmpdir)) {
      g_set_error(Aerror, G_FILE_ERROR, g_file_error_from_errno(errno), "%s %s: %s",
              _("Cannot create directory"), Ltmpdir, g_strerror(errno));    
      *Ltmpdir = 0;
      Lstatus = FALSE;
    } else {
      g_snprintf(Liso, MAXPATHLEN-1, "%s/tmpiso.bin", Ltmpdir);

      sc_grave_set_data(Ag, &Liso, "iso"); /* image iso */

      /* copie du cd avec monsieur cdrdao */
      Lstatus = copycd(Ag, Aerror);


      /* on copie donc vers l'iso 
      Lstatus = make_image(Ag, Aerror);
      if (Lstatus == TRUE && *Labort == FALSE) {
        * et maintenant dans le sens inverse si tout va toujours bien * 
        Ldone++;

        * si le lecteur et le graveur sont les meme alors on demande a l'utilisateur
         * de changer de CD.. ! *
        if (!strcmp(Lsrc, Ldst)) {
          gint Lrep;
          GtkWidget *Lconfirm = gtk_message_dialog_new(NULL,
                                              GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
                                              GTK_BUTTONS_YES_NO,
                 _("Reading is finished, now you should insert a CD-R, do you want to continue operation ?"));

          * on eject le CD *
          eject_cd(Lsrc, NULL);
          
          Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
          gtk_widget_destroy(Lconfirm);
          if (Lrep == GTK_RESPONSE_NO) {
            * si c'est non alors on arrete *
            *Labort = TRUE;
            Lstatus = TRUE;
          }
        }
       
        if (Lstatus == TRUE && *Labort == FALSE) { 
          Lstatus = burn_from_image("copy", Ag, Aerror);
        }
      } */
      sc_grave_del_data(Ag, "iso");

      deltempdir(Ltmpdir);
      *Ltmpdir = 0;
    }
  }

  sc_grave_del_data(Ag, "todo");
  sc_grave_del_data(Ag, "done");
  sc_grave_del_data(Ag, "operationstatus");
  sc_grave_del_data(Ag, "tmpdir");
  sc_grave_del_data(Ag, "gerror");

  return Lstatus;
}

/* operation gravure cd de donnee */
gboolean burn_data(Tgrave *Ag, GError **Aerror)
{
  gint Ltodo = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sc_grave_get_widget(Ag, "nbrcddata")));
  gboolean Lsimul = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "datasimul")));
  GtkEntry *Lgraveuriso = GTK_ENTRY(sc_grave_get_widget(Ag, "dstdatabtnvalue"));
  Tdriveinfo *Lgraveur = matos_get_drive_info(Ag, "dstdatacombo");
  gboolean *Labort = sc_grave_get_data(Ag, "gabort");
  gint Ldone = 1;
  gchar Ltmpdir[MAXPATHLEN] = "";
  gchar *Lextrapara = NULL;
  gchar Liso[MAXPATHLEN] = "";
  gchar *Ltmp;
  gboolean Loperationstatus = FALSE;
  gboolean Lstatus;

  sc_grave_set_data(Ag, &Ltodo, "todo"); /* a faire */
  sc_grave_set_data(Ag, &Ldone, "done"); /* fais */
  sc_grave_set_data(Ag, &Loperationstatus, "operationstatus"); /* resultat de l'operation */
  sc_grave_set_data(Ag, Aerror, "gerror");  /* pointeur retour des erreurs */
  sc_grave_set_data(Ag, &Ltmpdir, "tmpdir"); /* repertoire temporraire */

  /* on retourne dans ltmp le nom du repertoire temporraire utilise pour
   * l'operation */
  Lstatus = preparedata(Ag, Aerror);

  if (Lgraveur) {
    g_snprintf(Liso, MAXPATHLEN-1, "%s.iso", Ltmpdir);
    Ltodo+=(Lsimul ? 2 : 1); /* + 1 pour l'ecriture de l'image iso et 1 pour la simulation */
  } else {
    Ltmp = _FILENAME(gtk_entry_get_text(Lgraveuriso));
    g_strlcpy(Liso, Ltmp, MAXPATHLEN-1);
    g_free(Ltmp);
    Ltodo = 1;
  }

  sc_grave_set_data(Ag, &Liso, "iso"); /* image iso */
  if (Lstatus && *Labort==FALSE) {
    Lextrapara = make_image_getextrapara(Ag, "data");
    sc_grave_set_data(Ag, Lextrapara, "extrapara"); /* parametres supplementaires */
    Lstatus = make_iso(Ag, Aerror);
    sc_grave_del_data(Ag, "extrapara");
    g_free(Lextrapara);
    if (Lgraveur && Lstatus && *Labort==FALSE) {
      /* ici il faut appeler cdrecord ! */
      Lextrapara = burn_data_getextrapara(Ag);
      sc_grave_set_data(Ag, Lextrapara, "extrapara"); /* parametres supplementaires */
      Lstatus = burn_from_image("data", Ag, Aerror);
      sc_grave_del_data(Ag, "extrapara");
      g_free(Lextrapara);
    }
  }

  cleandata(Ag, NULL);
  
  if (Lgraveur && *Liso
      && g_file_test(Liso, G_FILE_TEST_EXISTS + G_FILE_TEST_IS_REGULAR)==TRUE) {
    unlink(Liso);
  }

  sc_grave_del_data(Ag, "todo");
  sc_grave_del_data(Ag, "done"); 
  sc_grave_del_data(Ag, "tmpdir");
  sc_grave_del_data(Ag, "operationstatus"); 
  sc_grave_del_data(Ag, "gerror");
  sc_grave_del_data(Ag, "iso");

  return Lstatus;
}

/* operation gravure cd audio */
gboolean burn_audio(Tgrave *Ag, GError **Aerror)
{
  GtkTreeModel *Ltreemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(sc_grave_get_widget(Ag, "LISTEAUDIO")));

  gint Ltodo = gtk_tree_model_iter_n_children(Ltreemodel, NULL);
  gint Ldone = 0;
  gchar Ltmpdir[MAXPATHLEN] = "";
  gboolean Lstatus, Loperationstatus = FALSE;

  sc_grave_set_data(Ag, &Ltodo, "todo"); /* a faire */
  sc_grave_set_data(Ag, &Ldone, "done"); /* fais */
  sc_grave_set_data(Ag, &Loperationstatus, "operationstatus"); /* resultat de l'operation */
  sc_grave_set_data(Ag, Aerror, "gerror");  /* pointeur retour des erreurs */
  sc_grave_set_data(Ag, &Ltmpdir, "tmpdir"); /* repertoire temporraire */

  Lstatus = preparetrack(Ag, Aerror);

  if (Lstatus == TRUE) {
    Ldone = 1;

    Lstatus = gravepiste(Ag, Aerror);
  }

  if (*Ltmpdir) {
    _DEB("on free tmpdir !");
    deltempdir(Ltmpdir);
  }

  sc_grave_del_data(Ag, "todo");
  sc_grave_del_data(Ag, "done"); 
  sc_grave_del_data(Ag, "tmpdir");
  sc_grave_del_data(Ag, "operationstatus"); 
  sc_grave_del_data(Ag, "gerror");

  return Lstatus ? TRUE : FALSE;
}

/* on efface le repertoire temporraire */
gboolean deltempdir(gchar *Ldirpath)
{
  gchar *Lfullname;
  GDir *Ldir;
  const gchar *Lunfic;

  if (!Ldirpath || !*Ldirpath) return TRUE;

  Ldir = g_dir_open(Ldirpath, 0, NULL);
  if (!Ldir) {
    g_warning("erreur lors de l'ouverture de [%s]: %s\n", Ldirpath, strerror(errno));
    return FALSE;
  }

  while ((Lunfic = g_dir_read_name(Ldir))) {
    if (!strcmp(Lunfic, ".") || !strcmp(Lunfic, "..")) continue;

    Lfullname = g_strdup_printf("%s/%s", Ldirpath, Lunfic);

    if (g_file_test(Lfullname, G_FILE_TEST_IS_DIR)) {
      /* on vide le repertoire avant */
      if (FALSE==deltempdir(Lfullname)) return FALSE;
    } else {
      if (unlink(Lfullname)==-1) {
        _WARN("erreur lors de la suppresion de [%s]\n", Lfullname);
      }
    }

    g_free(Lfullname);
  }

  g_dir_close(Ldir);

  _DEB("on efface => %s\n", Ldirpath);
  if (rmdir(Ldirpath)==-1) {
    _WARN("erreur lors de la suppresion du repertoire [%s]: %s\n", Ldirpath, strerror(errno));
    return FALSE;
  }
_DEB("ok fin efface");
  return TRUE;
}

/* retourne le type d'un peripherique */
void put_devicelabel(Tdriveinfo *Adrive, gchar *Abuf, gint Asizemax) {
  if (DRIVE_DVDWRITER(Adrive)) {
    g_strlcpy(Abuf, _("DVD Recorder"), Asizemax);
  } else if (DRIVE_WRITER(Adrive)) {
    g_strlcpy(Abuf, _("CD Recorder"), Asizemax);
  } else if (DRIVE_DVDREADER(Adrive)) {
    g_strlcpy(Abuf, _("DVD Reader"), Asizemax);
  } else if (DRIVE_READER(Adrive)) {
    g_strlcpy(Abuf, _("CD Reader"), Asizemax);
  } else {
    g_strlcpy(Abuf, _("Other device"), Asizemax);
  }
}

/*extern Tdriveinfo *get_drive_cmb(GtkComboBox *Acombo)
{
  GtkTreeModel *Lmodel = gtk_combo_box_get_model(GTK_COMBO_BOX(Acombo));
  GtkTreeIter Liter;
  gint Lvalue = -1;
  if (!gtk_combo_box_get_active_iter(Acombo, &Liter)) return NULL;

  gtk_tree_model_get(Lmodel, &Liter, 3, &Lvalue, -1);

  return (Tdriveinfo *) g_slist_nth_data(Glistdrives, Lvalue);
}*/

/* operation gravure dcd de donnee */
gboolean burn_dvddata(Tgrave *Ag, GError **Aerror)
{
  gint Ltodo = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sc_grave_get_widget(Ag, "nbrdvddata")));
  gboolean Lsimul = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "dvddatasimul")));
  GtkEntry *Lgraveuriso = GTK_ENTRY(sc_grave_get_widget(Ag, "dstdvddatabtnvalue"));
  Tdriveinfo *Lgraveur = matos_get_drive_info(Ag, "dstdvddatacombo");
  gint Ldone = 1;
  gchar Ltmpdir[MAXPATHLEN] = "";
  gchar *Lextrapara = NULL;
  gchar *Ltmp;
  gchar Liso[MAXPATHLEN] = "";
  gboolean Loperationstatus = FALSE;
  gboolean Lstatus;

  sc_grave_set_data(Ag, &Ltodo, "todo"); /* a faire */
  sc_grave_set_data(Ag, &Ldone, "done"); /* fais */
  sc_grave_set_data(Ag, &Loperationstatus, "operationstatus"); /* resultat de l'operation */
  sc_grave_set_data(Ag, Aerror, "gerror");  /* pointeur retour des erreurs */
  sc_grave_set_data(Ag, &Ltmpdir, "tmpdir"); /* repertoire temporraire */

  /* on retourne dans ltmp le nom du repertoire temporraire utilise pour
   * l'operation */
  Lstatus = preparedata(Ag, Aerror);

  Lextrapara = make_image_getextrapara(Ag, "dvddata");
  sc_grave_set_data(Ag, Lextrapara, "extrapara"); /* parametres supplementaires */

  if (Lgraveur) {
    if (Lsimul) Ltodo++; /* 1 pour la simulation */

    Lstatus = burn_data2dvd(Ag, Aerror);
  } else {
    Ltmp = _FILENAME(gtk_entry_get_text(Lgraveuriso));
    g_strlcpy(Liso, Ltmp, MAXPATHLEN-1);
    g_free(Ltmp);
    Ltodo = 1;
    sc_grave_set_data(Ag, &Liso, "iso"); /* image iso */
    Lstatus = make_iso(Ag, Aerror);
    sc_grave_del_data(Ag, "iso");
  }
  sc_grave_del_data(Ag, "extrapara");
  g_free(Lextrapara);

  cleandata(Ag, NULL);

  sc_grave_del_data(Ag, "todo");
  sc_grave_del_data(Ag, "done"); 
  sc_grave_del_data(Ag, "tmpdir");
  sc_grave_del_data(Ag, "operationstatus"); 
  sc_grave_del_data(Ag, "gerror");

  return Lstatus;
}

gchar* get_media_label(gint Atypecd, gchar *Abuf, gint Alen) {
  *Abuf = 0;

  if ((Atypecd & _MEDIA_TITLE_BLANKORAPPENDABLE) == _MEDIA_TITLE_BLANKORAPPENDABLE) {
    g_snprintf(Abuf, Alen, _("an empty or appendable CDR/RW"));
  } else if (((Atypecd & _MEDIA_DVDP_RW) == _MEDIA_DVDP_RW) || ((Atypecd & _MEDIA_DVDM_RW) == _MEDIA_DVDM_RW)) {
    g_snprintf(Abuf, Alen, _("a DVDRW"));
  } else if ((Atypecd & _MEDIA_TITLE_DVDRew) == _MEDIA_TITLE_DVDRew) {
    g_snprintf(Abuf, Alen, _("an empty or appendable DVDR/RW"));
  } else if (((Atypecd & _MEDIA_DVDR_P) == _MEDIA_DVDR_P) || ((Atypecd & _MEDIA_DVDR_M) == _MEDIA_DVDR_M)) {
    g_snprintf(Abuf, Alen, _("a DVDR"));
  } else if ((Atypecd & _MEDIA_DVD) == _MEDIA_DVD) {
    g_snprintf(Abuf, Alen, _("a DVD"));
  } else if ((Atypecd & _MEDIA_CDRW) == _MEDIA_CDRW) {
    g_snprintf(Abuf, Alen, _("a CDRW"));
  } else if ((Atypecd & _MEDIA_CDR) == _MEDIA_CDR) {
    g_snprintf(Abuf, Alen, _("a CDR"));
  } else if ((Atypecd & _MEDIA_CD) == _MEDIA_CD) {
    g_snprintf(Abuf, Alen, _("a CD"));
  } else if (Atypecd == _MEDIA_NONE) {
    g_snprintf(Abuf, Alen, _("no media"));
  }

  return Abuf;
}

void set_waitwindow_title(gboolean Ainsert, gint Atypecd, gint Acurrent, Tgrave *Awaitg)
{
  gchar Lcd[_BUF_SIZE];
  gchar Ltitle[_BUF_SIZE];
  Tdriveinfo *Ldevice = (Tdriveinfo *)sc_grave_get_data(Awaitg, "device1");
  GtkLabel *Llabel = GTK_LABEL(sc_grave_get_widget(Awaitg, "label1"));
  *Ltitle=0;

  get_media_label(Atypecd, Lcd, sizeof(Lcd)-1);

  if (Ainsert) {
    g_snprintf(Ltitle, sizeof(Ltitle)-1, _("Please insert %s in drive %s to continue..."), Lcd, Ldevice->name);
  } else {
    g_snprintf(Ltitle, sizeof(Ltitle)-1, _("Ok there is %s in drive %s."), Lcd, Ldevice->name);
  }
  gtk_label_set_text(Llabel, Ltitle);

  if (Ainsert) {
    Llabel = GTK_LABEL(sc_grave_get_widget(Awaitg, "label2"));
    g_snprintf(Ltitle, sizeof(Ltitle)-1, _("Currently: %s"),
        Acurrent > -1 ?  get_media_label(Acurrent, Lcd, sizeof(Lcd)-1) : _("Initialization..."));
    gtk_label_set_text(Llabel, Ltitle);
  }
}


/* attente que l'utilisateur ai inseré le/les cd qui va bien */
gboolean callback_waiting_for_user(gpointer Adata)
{
  Tgrave *Lg = (Tgrave *)Adata;
  gint *Lcont = (gint *)sc_grave_get_data(Lg, "cont");
  gint *Ldetect = NULL;
  GSList *Lrequis, *Lcur;
  Tdriveinfo *Ldrive = NULL;
  gint *Lmediatitle;
  gint Lmedialu = _MEDIA_NONE;
  gint Lmediatest;
  gboolean Lstatusmedia = TRUE;
  gboolean *Linitdisp = (gboolean *) sc_grave_get_data(Lg, "initdisp");
  
  Ldrive = sc_grave_get_data(Lg, "device1");
  if (!Ldrive) return TRUE;
  Lrequis = (GSList *) sc_grave_get_data(Lg, "devicerequis1");
  Ldetect = (gint *) sc_grave_get_data(Lg, "detect1");
  Lmediatitle = (gint *)sc_grave_get_data(Lg, "mediatitle1");

  if (Linitdisp && *Linitdisp) {
    set_waitwindow_title(Lstatusmedia, *Lmediatitle, -1, Lg);
    gtk_widget_show(GTK_WIDGET(sc_grave_get_data(Lg, "window")));
    gdk_flush ();
    *Linitdisp = FALSE;
  }
  matos_umount_device(Ldrive, NULL);
   
 _DEB("le premier avant le dvd [%d]", Lmedialu); 
  Lmedialu += get_dvdinfo(Lg, Ldrive, NULL);

 _DEB("le deuxieme avant le cd [%d]", Lmedialu); 
  if (Lmedialu == _MEDIA_NONE) {
    Lmedialu += get_cdinfo(Lg, Ldrive, NULL);
  }

 _DEB("[%d] la troisieme apres tout [%d]", Ldetect ? 1 : 0, Lmedialu); 
  if (Ldetect) *Ldetect = Lmedialu;

  for (Lcur = Lrequis; Lcur; Lcur = g_slist_next(Lcur)) {
    Lmediatest = (int ) Lcur->data;
    if ((Lmediatest & Lmedialu) == Lmediatest) {
      *Lcont  = 0;
      Lstatusmedia = FALSE;
      break;
    }
  }
  set_waitwindow_title(Lstatusmedia, *Lmediatitle, Lmedialu, Lg);
  gdk_flush ();


  return TRUE;
}

/* attente que l'utilisateur ai bien insere un cd */
gboolean waiting_for_user(gint Atitle, Tgrave *Ag, GSList *Arequiscd1, gint *Adetectcd1, Tdriveinfo *Ldriveident1)
{
  Tgrave *Lwaitg = sc_grave_load("window_waiting_cd.glade");
  GtkWidget *Lparent = sc_grave_get_widget(Ag, "topwindow");
  GtkWidget *Lwindow;
  gchar *Ldevicetitle1 = NULL;
  gchar *Ldevicetitle2 = NULL;
  gint Lcont = 2;
  gint Lpid = 0;
  gboolean Labort = FALSE;
  gboolean Linit = TRUE;
  guint Ltimeout = 0;

  if (Atitle == _MEDIA_NONE) return TRUE;
  
  g_assert(Lwaitg);
  
  gtk_image_set_from_pixbuf(GTK_IMAGE(sc_grave_get_widget(Lwaitg, "imgwaiting")), get_image("CDRWIcon"));
  Lwindow = GTK_WIDGET(sc_grave_get_widget(Lwaitg, "window_waiting_cd"));
  g_signal_connect(G_OBJECT(sc_grave_get_widget(Lwaitg, "cancelbutton")), "clicked", G_CALLBACK(abort_encours), Lwaitg);

  sc_grave_set_data(Lwaitg, Lwindow, "window");
  sc_grave_set_data(Lwaitg, &Lcont, "cont");
  sc_grave_set_data(Lwaitg, &Labort, "gabort");
  sc_grave_set_data(Lwaitg, &Lpid, "pid");
  
  if (Ldriveident1) {
    sc_grave_set_data(Lwaitg, Ldriveident1, "device1");
    sc_grave_set_data(Lwaitg, Adetectcd1, "detect1");
    sc_grave_set_data(Lwaitg, &Atitle, "mediatitle1");
    sc_grave_set_data(Lwaitg, Arequiscd1, "devicerequis1");

    set_waitwindow_title(TRUE, Atitle, -1, Lwaitg);
  }

  gtk_window_set_transient_for(GTK_WINDOW(Lwindow), GTK_WINDOW(Lparent));
  gtk_window_set_position(GTK_WINDOW(Lwindow), GTK_WIN_POS_CENTER_ALWAYS);


  /* on appele une fois le callback pour verifier que l'utilisateur n'ai pas
   * deja inseré le bon cd qui va bien */
  sc_grave_set_data(Lwaitg, &Linit, "initdisp");
  callback_waiting_for_user(Lwaitg);
  Linit = FALSE;

  if (Lcont == 2 && Labort == FALSE) {
    /* apparement non, on affiche la fenetre d'attente */
    Ltimeout = g_timeout_add(1500, callback_waiting_for_user, Lwaitg);
    do {
      gtk_main_iteration(); 
    } while (Lcont == 2 && Labort == FALSE);
  }
  sc_grave_del_data(Lwaitg, "initdisp");

  /* fin du timeout */ 
  if (Ltimeout) g_source_remove(Ltimeout);

  gtk_widget_destroy(Lwindow);

/*  g_free(Lident1); g_free(Lident2);*/
  g_free(Ldevicetitle1); g_free(Ldevicetitle2);

  sc_grave_destroy(Lwaitg);

  return (Lcont == 0 && Labort == FALSE);
}

Tdriveinfo *matos_get_drive_info(Tgrave *Ag, gchar *Aname)
{
  return get_combo_value(sc_grave_get_widget(Ag, Aname));
}

gchar *matos_get_device(Tdriveinfo *Adrive)
{
  GSList *Lcur;
  gchar *Lcurbus;
  gint i = 0;

  for (Lcur = Adrive->bus; Lcur; Lcur = g_slist_next(Lcur), i++) {
    Lcurbus = (gchar *) Lcur->data;

    if (!strcmp(Lcurbus, "IDE") || !strncmp(Lcurbus, IDENT_SCSI, strlen(IDENT_SCSI)) || !strcmp(Lcurbus, "MANU")) {
      return g_slist_nth_data(Adrive->dev, i);
    }
  }

  return NULL;
}

gboolean matos_is_an_iso(Tgrave *Ag, gchar *Aname)
{
  Tdriveinfo *Ldrive = get_combo_value(sc_grave_get_widget(Ag, Aname));

  return Ldrive ? TRUE : FALSE;
}

/* creation ou ajout de la liste des medias requis */
GSList *manage_mediarequis(GSList *Acurlist, ...)
{
  GSList *Lcurlist = Acurlist ? Acurlist : NULL;
  va_list Llist;
  gint Lt;

  va_start(Llist, Acurlist);
  while (1) {
    Lt = va_arg(Llist, gint);
    if (Lt == -1) break;

  Lcurlist = g_slist_append(Lcurlist, GINT_TO_POINTER(Lt));
  }
  va_end(Llist);

  return Lcurlist;
}

/* try to umount device when it's mounted
 * scan /etc/ftab file to do this */
gboolean matos_umount_device(Tdriveinfo *Adrive, GError **Aerror)
{
  gchar *Lcontent = NULL;
  gint i;
  gchar **Larrbuf, *Lcur, *s, *Lcurdev = NULL;
  gchar Lcommand[_BUF_SIZE];
  GSList *Llistdev;
  gboolean Lfind = FALSE, Lstatus = FALSE;

  if (!g_file_get_contents("/etc/mtab", &Lcontent, NULL, Aerror) || !Lcontent) return FALSE;
  Larrbuf = g_strsplit(Lcontent, "\n", 0);

  for (i=0; Larrbuf[i] && !Lfind; i++) {
    s = Lcur = Larrbuf[i];
    if (!*Lcur) continue;

  _DEB("deb => [%s]", Lcur);

    while (g_ascii_isalnum(*s) || *s=='/') s++;
    *s=0;
    if ((s=strchr(Lcur, '='))) Lcur=s+1;

    for (Llistdev = Adrive->dev; Llistdev; Llistdev = g_slist_next(Llistdev)) {
      Lcurdev = (gchar *) Llistdev->data;
_DEB("comp de [%s] et [%s]", Lcurdev,Lcur);
      if (!strcmp(Lcurdev, Lcur)) {
        Lfind = TRUE;
        break;
      }
    }
  }

  if (Lfind && Lcurdev) {
    g_snprintf(Lcommand, sizeof(Lcommand)-1, "/bin/umount %s", Lcurdev);

    _DEB("try to umount [%s]", Lcommand);

    Lstatus = g_spawn_command_line_async(Lcommand, Aerror);
  }

  g_strfreev(Larrbuf);
  g_free(Lcontent);

  return Lstatus;
}

gboolean matos_maj_drive_info(Tdriveinfo *Adrive, gchar *Adev, GError **Aerror)
{
  Adrive->type = 0;

  cdrecord_maj_drive_info(Adrive, Adev, Aerror);

  /* use /proc/sys/dev/cdrom/info with linux to detect DVD capability */
  proc_maj_drive_info(Adrive, Aerror);

  return TRUE;
}

/*
 * vim:et:ts=8:sts=2:sw=2
 */
