/* cdrecord.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"

/* communication avec cdrdao */

#define SCANDEVICE "scsibus"
#define CDRECORD_NOSUCHFILE "No read access for"
#define CDRECORD_FIFO "fifo"
#define CDRECORD_BUF "buf"
#define CDRECORD_STATUS "fifo was "
#define CDRECORD_ERRORDISK "No disk / Wrong disk"
#define CDRECORD_INAPPROPRIATE "Inappropriate audio coding"
#define CDRECORD_INPUTOUTPUT_ERROR "Input/output error."
#define CDRECORD_FIXATING "Fixating..."
#define CDRECORD_BLANKING "Blanking "
#define CDRECORD_BAD_RECORDER "Sorry, no CD/DVD-Recorder or unsupported CD/DVD-Recorder found"

#define CDRDAO_TRACK "Track "
#define CDRDAO_ATSPEED "at speed "
#define CDRDAO_ANALYZING "Analyzing track "
#define CDRDAO_NOSPACELEFT "No space left on device"
#define CDRDAO_LENGTH "length "
#define CDRDAO_WRITING_TRACK "Writing track "
#define CDRDAO_COPYING_TRACK "Copying data track "
#define CDRDAO_WROTE "Wrote "
#define CDRDAO_BLOCKS " blocks. Buffer fill"
#define CDRDAO_FLUSHING "Flushing cache..."
#define CDRDAO_SUCCESSFULLY "successfully."
#define CDRDAO_OF "of "
#define CDRDAO_BUFFERS "Buffers "
#define CDRDAO_INCOMPATIBLE_MEDIUM "Medium in recorder device is not empty and not appendable"
#define CDRDAO_SESSIONS "Sessions "

/* detection des media */
#define CDRDAO_CDRW "CD-RW"
#define CDRDAO_YES ": yes"
#define CDRDAO_NO ": no"
#define CDRDAO_CDR "CD-R medium"
#define CDRDAO_EMPTY "CD-R empty"
#define CDRDAO_TOCTYPE "Toc Type"
#define CDRDAO_APPENDABLE "Appendable"
#define CDRDAO_NA ": n/a"
#define CDRDAO_CD "CD"
#define SESSION_ZERO ": 0"

/* callback appele lorsque cdrdao grave les pistes */
gboolean cdrdao_grave_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
{
  GIOStatus Lstatus;
  Tgrave *Lg = (Tgrave *)Adata;
  gchar Lbuffer[_BUF_SIZE];
  gint *Lcont = (gint *) sc_grave_get_data(Lg, "cont"); /* on traite encore des donnees ? */
  GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
  gint *Ltodo = (gint *) sc_grave_get_data(Lg, "todo"); /* nombre de piste a traiter */
  gint *Ldone = (gint *) sc_grave_get_data(Lg, "done"); /* nombre de piste deja traite */
  gchar *Llasttrack = (gchar *) sc_grave_get_data(Lg, "lasttrack"); /* precedente piste traite */
  gchar *Latspeed = (gchar *) sc_grave_get_data(Lg, "atspeed"); /* vitesse reel operation */
  glong *Llength = (glong *) sc_grave_get_data(Lg, "length"); /* longueur total */
  gchar *f, *e;
  gchar Lsbuf[_BUF_SIZE];
  gdouble Lpct, Ltava;
  gsize Llu = 0;

  GtkLabel *Ltitle = GTK_LABEL(sc_grave_get_data(Lg, "gravetitle"));
  GtkProgressBar *Lprogressbar = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_total"));
  GtkProgressBar *Lprogressbar2 = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_step"));
  GtkProgressBar *LprogressbarFifo = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_fifo"));
  GtkProgressBar *LprogressbarBuffer = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_buffer"));
  
  /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
  if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
    (*Lcont) = 0;
    return FALSE;
  }
  
  *Lbuffer = 0;
  Lstatus = g_io_channel_read_chars(Astd, Lbuffer, _BUF_SIZE-1, &Llu, NULL);  
  if (!*Lbuffer || Lstatus == G_IO_STATUS_ERROR || Lstatus == G_IO_STATUS_AGAIN) {
    return TRUE;
  }
  Lbuffer[Llu]=0;
_DEB("===>%s", Lbuffer);
  if ((f=strstr(Lbuffer, CDRDAO_LENGTH))) {
    /* longueur total du cd */
    f=f+strlen(CDRDAO_LENGTH);
    *Llength = get_2time(f);
    if (*Llength < 0) *Llength = 0;
  }

  if ((f=strstr(Lbuffer, CDRDAO_WROTE))) {
     /* copie en cours */

    if (strstr(f, CDRDAO_BLOCKS)) {
      /* fin de l'operation */      
      gtk_label_set_text(Ltitle, _("Finishing operation..."));
    } else {
      gdouble Lgbuf = 0, Lfifo = 0;
      gdouble Lde = 0, La = 0;
      gboolean Lok = FALSE;
      
      /* champ deja grave */
      f=f+strlen(CDRDAO_WROTE);
      Lde = atof(f);
      if ((f=tools_next_no_numeric(f))) {
        *(f++)=0;
        if ((f=strstr(f, CDRDAO_OF))) {
          f=f+strlen(CDRDAO_OF);

          La = atof(f);

          if ((f=tools_next_no_numeric(f))) {
            *(f++)=0;

            if ((f=strstr(f, CDRDAO_BUFFERS))) {
              f=f+strlen(CDRDAO_BUFFERS);
              e=ltrim(f);
              Lgbuf = atof(e);
              if ((f=tools_next_putzero(e, '%'))) {
                e=ltrim(f);
                Lfifo = atof(e);
                if (tools_next_putzero(e, '%')) Lok = TRUE;
              }
            }
          }
        }
      }

      if (Lok) {
        g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("Writing track %s - %.0f MB of %.0f MB at %s"),
            Llasttrack, Lde, La, Latspeed);
        gtk_label_set_text(Ltitle, Lsbuf);

        Lpct = POURCENT(La, Lde);
        maj_progress(Lprogressbar2, Lpct);

        /* avancement total */
        Ltava = (1.0/ (*Ltodo)) * ((*Ldone)+Lpct);
        maj_progress(Lprogressbar, Ltava);

        /* barre fifo */
        g_snprintf(Lsbuf, sizeof(Lsbuf)-1, "%.0f%%", Lfifo);
        gtk_progress_bar_set_fraction(LprogressbarFifo, Lfifo * 0.01);
        gtk_progress_bar_set_text(LprogressbarFifo, Lsbuf);

        /* barre buffer */
        g_snprintf(Lsbuf, sizeof(Lsbuf)-1, "%.0f%%", Lgbuf);
        gtk_progress_bar_set_fraction(LprogressbarBuffer, Lgbuf * 0.01);
        gtk_progress_bar_set_text(LprogressbarBuffer, Lsbuf);
      }

    }      
  } else if ((f=strstr(Lbuffer, CDRDAO_TRACK))) {
    /* debut lecture d'une piste */
    f=f+strlen(CDRDAO_TRACK);
    e=f;
    for (e=f; isdigit(*e); e++) ;
    *e=0;
    if (*f) {
      g_snprintf(Llasttrack, _BUF_SIZE-1, "%s", f);
      g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("Reading track %s at %s..."), f, Latspeed);
      gtk_label_set_text(Ltitle, Lsbuf);
    }
  } else if ((f=strstr(Lbuffer, CDRDAO_ATSPEED))) {
    /* vitesse reel operation */
    f=f+strlen(CDRDAO_ATSPEED);
    e=f;
    for (e=f; isdigit(*e); e++) ;
    *e=0;
    if (*f) {
      g_snprintf(Latspeed, _BUF_SIZE-1, "%sx", f);
    }
  } else if ((strchr(Lbuffer, 13))) {
    /* operation lecture d'une piste en cours */
    glong Lcur = get_2time(Lbuffer);
    if (Lcur > 0) {
      /* avancement operation */
      Lpct = POURCENT(*Llength, Lcur);
      maj_progress(Lprogressbar2, Lpct);

      /* avancement total */
      Ltava = (1.0/ (*Ltodo)) * ((*Ldone)-1+Lpct);
      maj_progress(Lprogressbar, Ltava);
    }
  } else if ((f=strstr(Lbuffer, CDRDAO_ANALYZING))) {
    /* mise a jour du titre analyse de la piste en cours */
    f=f+strlen(CDRDAO_ANALYZING);
    if ((e=tools_next_no_numeric(f))) {
      *e=0;
      g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("Analyzing track %s at %s..."), f, Latspeed);
      gtk_label_set_text(Ltitle, Lsbuf);
    }
  } else if ((f=strstr(Lbuffer, CDRDAO_WRITING_TRACK))) {
    /* mise a jour du titre ecriture de la piste en cours */
    f=f+strlen(CDRDAO_WRITING_TRACK);
    if ((e=tools_next_no_numeric(f))) {
      gboolean *Lsimul = (gboolean *) sc_grave_get_data(Lg, "simul"); /* simulation */
      
      *e=0;
      if (atoi(f)==1) {
        (*Ldone)++;
      }
      g_snprintf(Llasttrack, _BUF_SIZE-1, "%s", f);
      g_snprintf(Lsbuf, sizeof(Lsbuf)-1,
          *Lsimul ? _("Simulated writing track %s as %s...") : _("Writing track %s at %s..."),
          f, Latspeed);
      gtk_label_set_text(Ltitle, Lsbuf);
    }
  } else if ((f=strstr(Lbuffer, CDRDAO_COPYING_TRACK))) {
    /* mise a jour du titre ecriture de la piste en cours */
    f=f+strlen(CDRDAO_COPYING_TRACK);
    if ((e=tools_next_no_numeric(f))) {
      *e=0;
      g_snprintf(Llasttrack, _BUF_SIZE-1, "%s", f);
      g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("Reading track %s at %s..."), f, Latspeed);
      gtk_label_set_text(Ltitle, Lsbuf);
    }
  } else if (strstr(Lbuffer, CDRDAO_FLUSHING)) {
    /* blanking disk */
    gtk_label_set_text(Ltitle, _("Flushing cache..."));
  } else if ((f=strstr(Lbuffer, CDRDAO_SUCCESSFULLY))) {
    gboolean *Lstatus = (gboolean *) sc_grave_get_data(Lg, "operationstatus");

    /* ok tout s'est bien passe ! */
    *Lstatus = TRUE;
  } else if ((strstr(Lbuffer, CDRDAO_INCOMPATIBLE_MEDIUM))) {
    /* erreur pas de cd vierge */
    g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_NO_CD, _("Error, a blank CD-R/CD-RW is required in the cd recorder !"));
    (*Lcont) = 0;
    return FALSE;
  } else if ((f=strstr(Lbuffer, CDRDAO_NOSPACELEFT))) {
    /* erreur pas assez d'espace disque disponnible ! */
    g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("No space left on device !"));
    g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_NO_SPACE_LEFT, Lsbuf);
    (*Lcont) = 0;
    return FALSE;

  } 

  return TRUE;
}

/* operation de copie d'un cd */
gboolean copycd(Tgrave *Ag, GError **Aerror) {
  GtkWindow *Lwindow = GTK_WINDOW(sc_grave_get_data(Ag, "window_burn"));
  GtkWidget *Lvitesse = sc_grave_get_widget(Ag, "dstcopyspeed");
  Tdriveinfo *Lsource = matos_get_drive_info(Ag, "srccopycombo");
  Tdriveinfo *Lgraveur = matos_get_drive_info(Ag, "dstcopycombo");
  gchar *Lrepertoire = (gchar *)sc_grave_get_data(Ag, "tmpdir");
  gchar *Liso = (gchar *)sc_grave_get_data(Ag, "iso");
  gboolean *Loperationstatus = (gboolean *)sc_grave_get_data(Ag, "operationstatus");
  gboolean *Labort = (gboolean *) sc_grave_get_data(Ag, "gabort");
  gchar **Lcmd;
  gchar *Lcommandline;
  GIOChannel *Lcom, *Lcomerr;
  guint Lcomevent, Lcomerrevent;
  gint *Lcont = (gint *) sc_grave_get_data(Ag, "cont"); /* on traite encore des donnees ? */
  /* nombre d'element total */
  gint *Ldone = (gint *)sc_grave_get_data(Ag, "done"); /* fais */
  gint *Ltodo = (gint *) sc_grave_get_data(Ag, "todo");
  gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
  
  gint g_out, g_err, Lnbrarg;
  gboolean Lstatus = FALSE;
  gchar *Lbufvitesse;
  gboolean Lsimul = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "copysimul")));
  gboolean Lonfly = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "copyonfly")));
  gint Lnbrgravure = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sc_grave_get_widget(Ag, "nbrcdcopy")));
  gboolean Lwanteject = conf_get_boolean("eject");
  gint Lcurcd;
  gboolean Ldosimul;
  gint Lnbrpass=1;
  gboolean Leject = FALSE;
  gchar Latspeed[_BUF_SIZE]; /* vitesse reel de l'operation */
  gchar Llasttrack[_BUF_SIZE]; /* derniere piste traite */
  glong Llength; /* longueur total du cd */

  Lbufvitesse = get_combo_value(Lvitesse);

  *Ltodo = ((Lnbrgravure * 2 ) + (Lsimul ? 2 : 0) + (Lonfly ? Lnbrgravure : 0));

  sc_grave_set_data(Ag, &Latspeed, "atspeed");
  sc_grave_set_data(Ag, &Llasttrack, "lasttrack");
  sc_grave_set_data(Ag, &Llength, "length");
  sc_grave_set_data(Ag, &Ldosimul, "simul");
  
  for (Lcurcd=1; Lcurcd<= Lnbrgravure;
      ((Lsimul && Lnbrpass>1) || (!Lsimul)) ? ( Lcurcd++, Lnbrpass=1 ) : ( Lnbrpass++ )) { 
    *Loperationstatus = FALSE;
    Ldosimul = (Lsimul && Lnbrpass==1);
    g_strlcpy(Latspeed, "-", sizeof(Latspeed)-1);
    *Llasttrack = 0;
    Llength = 0;

    if (Lcurcd > 1 && !Ldosimul) {
      /* copie sur un nouveau cd, on demande a l'utilisateur d'inserer le
       * nouveau cd vierge */

      GSList *Llmediarequis2 = sc_grave_get_data(Ag, "mediarequis2");
      gint *Lmediatitle2 = sc_grave_get_data(Ag, "mediatitle2");
      gchar *Ltxt = sc_grave_get_data(Ag, "medialabel");
      gboolean Lstatus;
      Tgrave *Ldialoghash;
      GtkWidget *Lconfirm;
      gint Lrep;

      /*
       * TODO : FAIRE UNE BELLE FONCTION DE CODE DUPLIQUE UN BON PAQUET DE FOIS #@!!
       */ 
      eject_cd(DRIVE_DEV(Lgraveur), NULL);
      Lstatus = waiting_for_user(*Lmediatitle2, Ag, Llmediarequis2 , NULL, Lgraveur);
          
      if (Lstatus==FALSE) {
        /* si c'est non alors on arrete */
        *Labort = TRUE; Lstatus = TRUE; break;
      } 
      
      Ldialoghash = create_dialog_confirm_operation(GTK_WIDGET(Lwindow), Ltxt, NULL, FALSE);

      Lconfirm = sc_grave_get_data(Ldialoghash, "window");
      Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
      gtk_widget_destroy(Lconfirm);

      if (Lrep != GTK_RESPONSE_YES) {
        /* si c'est non alors on arrete */
        *Labort = TRUE; Lstatus = TRUE;
        break;
      }
    }

    /* faut il ejecter le CD-R apres l'operation ?
     * oui si l'utilisateur a cocher la case "ejecter le cd" ou
     * si il faut realiser d'autre gravure sur d'autres CD-R */
    Leject = ((Lcurcd > 1 && (Lwanteject || Lcurcd<Lnbrgravure)) || (Lcurcd == 1 && !Ldosimul && Lwanteject));

      /* try to umount devices before access */
      matos_umount_device(Lsource, NULL);
      matos_umount_device(Lgraveur, NULL);

/*    if (Lonfly || Ldosimul || Lcurcd == 1) {
      * copie a la volé, ou simulation, ou cd numero 1, on n'utilise pas l'image sauvé
       * lors de la precedente operation */
      Lcommandline = g_strdup_printf("%s copy -n -v 2 %s %s %s %s%s --source-device %s --device %s --datafile %s %s %s",
        conf_get_string("cdrdao"), 
        Ldosimul ? " --simulate" : "",
        Lonfly ? " --on-the-fly" : "",
        Leject ? "--eject" : "",
        *Lbufvitesse == '0' ? "" : "--speed", *Lbufvitesse == '0' ? "" : Lbufvitesse,
        DRIVE_DEV(Lsource), DRIVE_DEV(Lgraveur), Liso,
        conf_get_boolean("overburn") ? "--overburn" : "",
        conf_get_string("cdrdaopara"));
/*    } else {*/
      /* sinon on l'utilise oui ! */
/*    } */

_DEB("execution [%s]\n", Lcommandline);
    Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
    g_free(Lcommandline);
    if (Lstatus == FALSE) {
      break;
    }

    Lstatus = g_spawn_async_with_pipes(Lrepertoire, Lcmd, NULL, /* env argument */
        (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
        NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
    g_strfreev(Lcmd);

    if (Lstatus == FALSE) {
      g_warning("ERROR EXECUTION !\n");
      break;
    }

    *Lcont = 1;
    Lcom = g_io_channel_unix_new( g_out );
    g_io_channel_set_encoding (Lcom, NULL, NULL);
    g_io_channel_set_buffered(Lcom, FALSE);
    g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
    Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
                                        cdrdao_grave_callback, Ag);
  
    Lcomerr = g_io_channel_unix_new( g_err );
    g_io_channel_set_encoding (Lcomerr, NULL, NULL);
    g_io_channel_set_buffered(Lcomerr, FALSE);
    g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
    Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
                                        cdrdao_grave_callback, Ag);  
    
    while (*Lcont>0 && *Labort == FALSE) {
      gtk_main_iteration(); 
    }

    exit_prog(*Lpid, *Labort, Aerror, NULL);

    g_source_remove(Lcomerrevent);
    g_source_remove(Lcomevent);

    g_io_channel_shutdown(Lcomerr, FALSE, NULL);
    g_io_channel_unref(Lcomerr);  
    g_io_channel_shutdown(Lcom, FALSE, NULL);
    g_io_channel_unref(Lcom);
    g_spawn_close_pid(*Lpid);
    *Lpid = 0;

    if (*Aerror) {
      Lstatus = FALSE;
      break;
    }
    if (*Loperationstatus == FALSE) {
      /* cdrdao n'a pas reussi a grave le cd mais on n'a intercepte aucune erreur ! argh!
       * dans tous les cas ce n'est pas normal, on genere une erreur */
      g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_UNKNOWN_ERROR, 
          _("Communication error with cdrdao !"));
      Lstatus = FALSE;
      break;
    }

    if (Ldosimul) {
      /* fin de la simulation, tout s'est apparement bien passe
       * on demande confirmation avent de commencer la vrai gravure */
      gint Lrep;
      GtkWidget *Lconfirm = gtk_message_dialog_new(Lwindow,
                                            GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
                                            GTK_BUTTONS_YES_NO, 
                      _("Simulation successful. Do you want to write the CD for real?"));
      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;
        break;
      }
    }
    (*Ldone)++;
  }

  g_free(Lbufvitesse);

  sc_grave_del_data(Ag, "simul");
  sc_grave_del_data(Ag, "length");
  sc_grave_del_data(Ag, "lasttrack");
  sc_grave_del_data(Ag, "atspeed");

  return Lstatus;
}


/* retourne les infos sur le media inseré dans le lecteur */
gint get_cdinfo(Tgrave *Ag, Tdriveinfo *Adevice, GError **Aerror)
{
  gchar Lcommandline[_BUF_SIZE];
  gboolean Lstatus;
  gchar **Larrbuf;
  gchar **Lcmd;
  gint i;
  gint Llu = _MEDIA_NONE;
  gint g_err, g_out, Lnbrarg;
  GIOChannel *Lcom;
  guint Lcomevent;
  gint Lloccont = 2;
  gint *Lpid = (gint *)sc_grave_get_data(Ag, "pid");
  GString *Loutput;
  gchar *Lcdprg = conf_get_string("cdrdao");
  gboolean Lskipnocd = FALSE;

  if (!Lcdprg || !*Lcdprg) return 0;

  g_snprintf(Lcommandline, sizeof(Lcommandline)-1, "%s disk-info --device %s", Lcdprg, DRIVE_DEV(Adevice));
_DEB("execution de [%s]", Lcommandline);
  if (!g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror)) return 0;


  Lstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, (GSpawnFlags) (G_SPAWN_DO_NOT_REAP_CHILD), NULL, NULL,
      Lpid, NULL, &g_out, &g_err, Aerror);
  g_strfreev(Lcmd);

  if (Lstatus == FALSE) {
    return 0;
  }

  Loutput = g_string_new("");
  sc_grave_set_data(Ag, Loutput, "buffer");
  sc_grave_set_data(Ag, &Lloccont, "loccont");
  
  Lcom = g_io_channel_unix_new( g_out );
  g_io_channel_set_encoding (Lcom, NULL, NULL);
  g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
  Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
                                      read_all_output_callback, Ag);

  while (Lloccont > 0) {
    gtk_main_iteration();
  }
  exit_prog(*Lpid, FALSE, Aerror, NULL);

  g_source_remove(Lcomevent);

  g_io_channel_shutdown(Lcom, FALSE, NULL);
  g_io_channel_unref(Lcom);
  g_spawn_close_pid(*Lpid);

  Larrbuf = g_strsplit(Loutput->str, "\n", 0);

  g_string_free(Loutput, TRUE);

  sc_grave_del_data(Ag, "loccount");
  sc_grave_del_data(Ag, "buffer");


  for (i=0; Larrbuf[i]; i++) {
    if (!*Larrbuf[i]) continue;
    if (!strncmp(Larrbuf[i], CDRDAO_CDRW, strlen(CDRDAO_CDRW))) {
_DEB("cdrdao1 => '%s'", Larrbuf[i]);
      if (strstr(Larrbuf[i], CDRDAO_YES)) {
        Llu += _MEDIA_CDRW;
      }
    } else if (!strncmp(Larrbuf[i], CDRDAO_TOCTYPE, strlen(CDRDAO_TOCTYPE))) {
_DEB("cdrdao2 => '%s'", Larrbuf[i]);
      if (strstr(Larrbuf[i], CDRDAO_CD)) {
        Llu += _MEDIA_CD;
      }
    } else if (!strncmp(Larrbuf[i], CDRDAO_CDR, strlen(CDRDAO_CDR))) {
_DEB("cdrdao3 => '%s'", Larrbuf[i]);
      if (!strstr(Larrbuf[i], CDRDAO_NA)) {
        Llu += _MEDIA_CDR;
      } else {
        Lskipnocd = TRUE;
      }
    } else if (!strncmp(Larrbuf[i], CDRDAO_EMPTY, strlen(CDRDAO_EMPTY))) {
_DEB("cdrdao4 => '%s'", Larrbuf[i]);
      if (strstr(Larrbuf[i], CDRDAO_YES)) {
        Llu += _MEDIA_BLANK;
      } else {
        Llu += _MEDIA_NOBLANK;
      }
    } else if (!strncmp(Larrbuf[i], CDRDAO_APPENDABLE, strlen(CDRDAO_APPENDABLE))) {
_DEB("cdrdao5 => '%s'", Larrbuf[i]);
      if (!strstr(Larrbuf[i], CDRDAO_NO)) {
        Llu += _MEDIA_APPENDABLE;
      }
    } else if (!strncmp(Larrbuf[i], CDRDAO_SESSIONS, strlen(CDRDAO_SESSIONS))) {
_DEB("cdrdao6 => '%s'", Larrbuf[i]);
      if (!strstr(Larrbuf[i], SESSION_ZERO)) {
        Lskipnocd = FALSE;
      }
    }
  }
  
  g_strfreev(Larrbuf);

  return Lskipnocd ? _MEDIA_NONE : Llu;
}


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