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

#define SOX_ERROR "sox:"
#define SOX_FILE_NOT_FOUND "No such file or directory"
#define SOX_FAILED_READING "Failed reading"

#define SOX_MP3 "mp3"
#define SOX_OGG "vorbis"

/* communication avec sox */

/* verification que sox ai bien le support ogg et mp3 */
gboolean check_sox()
{
  gchar *Lsox = conf_get_string("sox");
  gchar *Lcommandline, *Lerr = NULL;
  gboolean Lstatus;
  gint Lexit = 0;

  GsupportMp3 = FALSE;
  GsupportOgg = FALSE;

  if (!Lsox || !*Lsox) return FALSE;

  Lcommandline = g_strdup_printf("%s -help", conf_get_string("sox"));
  Lstatus = g_spawn_command_line_sync(Lcommandline, NULL, &Lerr, &Lexit, NULL);
  g_free(Lcommandline);

  GsupportMp3 = (Lstatus == TRUE && Lerr && ((strstr(Lerr, SOX_MP3))));
  GsupportOgg = (Lstatus == TRUE && Lerr && ((strstr(Lerr, SOX_OGG))));
  
  g_free(Lerr);

  return Lstatus;
}


/* transformation fichier son vers piste audio */

/* pour le moment on ne fais pas grand chose dans le callback ...
 * plus tard il y aura une meilleur gestion des erreurs ! */
gboolean sox_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
{
  GIOStatus Lstatus;
  Tgrave *Lg = (Tgrave *)Adata;
  gchar *Lbuffer = NULL;  
  gchar *s;
  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 */


  /* 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 = 1;
    return FALSE;
  }

  Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);
  _DEB("%s\n", Lbuffer);  
  if (Lbuffer) {
    if (( (strstr(Lbuffer, SOX_FILE_NOT_FOUND)) || (strstr(Lbuffer, SOX_FAILED_READING)) ) &&
          ((s=strstr(Lbuffer, SOX_ERROR)))) {
      g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_SOX, s+strlen(SOX_ERROR));
      g_free(Lbuffer);
      return FALSE;
    }
  }

  g_free(Lbuffer);

  return TRUE;
}

gboolean SoundToCdr(Tgrave *Ag, gchar *AFichier, gchar *AVers, GError **Aerror)
{
  gchar *Lcommandline;
  gchar **Lcmd;
  gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
  gboolean *Labort = (gboolean *)sc_grave_get_data(Ag, "gabort");
  gint *Lcont = (gint *) sc_grave_get_data(Ag, "cont");
  gint g_out, g_err, Lnbrarg;
  gchar *Lfic;
  gchar *Lvers;
  GIOChannel *Lcom, *Lcomerr;
  GIOStatus Lstatus;
  gboolean Lbolstatus;
  guint Lcomevent, Lcomerrevent;

  Lfic = sc_strescape(AFichier);
  Lvers = sc_strescape(AVers);
  Lcommandline = g_strdup_printf("%s %s \"%s\" \"%s\"", conf_get_string("sox"), conf_get_string("soxpara"), Lfic, Lvers);
  g_free(Lvers); g_free(Lfic);
  _DEB("execution [%s]\n", Lcommandline);

  Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
  g_free(Lcommandline);
  if (Lstatus == FALSE) {
    return FALSE;
  }

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

  if (Lbolstatus == FALSE) {
    g_warning("ERROR EXECUTION !\n");
    return FALSE;
  }
  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),
					     sox_callback,
					     Ag);
  
  Lcomerr = g_io_channel_unix_new( g_err );
  g_io_channel_set_encoding (Lcomerr, NULL, NULL);
  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),
					     sox_callback,
					     Ag);  

  while (*Lcont > 1 && *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;

  /* l'utilisateur a annule l'operation */
  if (*Labort==TRUE || *Aerror) return FALSE;

  return TRUE;
}

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