#include <stdio.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <festival.h>

#include <sstream>
#include <string>

#include <termios.h>
#include <fcntl.h>

#include <dirent.h>

void ListarCarpeta(), InicializarControlador(), ComprobarVoces(), RefinarTexto(), Decir(string), VaciarBufferTeclado();
void SeleccionarDocumento(string), LeerDocumento(FILE*,int,char*);
bool ProxCaracteres(FILE*,string), AntCaracteres(FILE*,string), EncontrarSustitucion(FILE*,FILE*,FILE*,char);
int ComprobarSigNumeros(FILE*);
char BuscaControlador(), UltimaTeclaPulsada(), ComprobarTeclado();
string ObtenerArchivo(int);

int heap_size = 210000;
int load_init_files = 1;

int main(int argc, char **argv)
{
    bool salir = false, haleido = false;
    char opcionchar;
    int opcionint;

    festival_initialize(load_init_files,heap_size);	//se inicializa Festival

    InicializarControlador();				//se busca el controlador de sonido adecuado

    ComprobarVoces();					//se comprueba si están instaladas las voces utilizadas

    ListarCarpeta();					//se da a elegir el fichero para leer de entre los disponibles en le carpeta 'Textos'
}

//-----------------------------------------------------------------
//Función para mostrar y elegir los textos disponibles para lectura.
//-----------------------------------------------------------------
void ListarCarpeta()
{
    struct dirent *d;
    const char *direccion = "./Textos";
    char *nomdocu;
    string docu;
    int numtextos = -2;

    DIR *directorio = opendir(direccion);
    while ((d=readdir(directorio)) != NULL)		//contamos cuántos ficheros hay en la carpeta 'Textos'
	numtextos++;

    closedir(directorio);

    if (numtextos == 0)					//Si no hay ningún texto, se cierra la aplicación.
    {
	printf("No hay archivos disponibles en la carpeta 'Textos'.\nSaliendo de la aplicación...\n");
	fflush(stdout);
	Decir("no hay archivos disponibles en la carpeta textos. Saliendo de la aplicación");
	exit(1);
    }
    if (numtextos == 1)					//Si sólo hay uno, se selecciona automáticamente
    {
	docu = ObtenerArchivo(0);
	SeleccionarDocumento(docu);
    }
    else
    {
	while(true)					//Si hay más de uno, se elige el deseado mediante un menú visual y sonoro
	{
	    system("clear");
	    cout << "\n    PULSE ESPACIO TRAS ESCUCHAR EL DOCUMENTO DESEADO, O ESCAPE PARA SALIR";
	    cout << "\n    ---------------------------------------------------------------------\n\n";
	    Decir("pulse espacio tras escuchar el documento deseado, o escape para salir");
	    festival_say_text(" ");
	    sleep(1);
	    ComprobarTeclado();
	    VaciarBufferTeclado();


	    for (int conta = 0; conta <= numtextos-1; conta ++)
	    {
		docu = ObtenerArchivo(conta);
		nomdocu = strdup(docu.c_str());
		printf("%s\n",nomdocu);
		Decir(docu);
		sleep(1);
		if (ComprobarTeclado() == ' ')
		{
		    SeleccionarDocumento(docu);
		    break;
		}
	    }
	}
    }
}

//----------------------------------------------------------------------------------------
//Función para obtener el nombre de un archivo a partir del lugar que ocupa en la carpeta.
//----------------------------------------------------------------------------------------
string ObtenerArchivo(int numarch)
{
    struct dirent *d;
    const char *direccion = "./Textos";
    int numtextos = -1;

    DIR *directorio = opendir(direccion);
    while ((d=readdir(directorio)) != NULL)
    {
	if (strcmp("..",d->d_name)!=0 && strcmp(".",d->d_name)!=0)
	    numtextos++;
	if (numtextos == numarch)
	    return d->d_name;
    }
    closedir(directorio);
}

//----------------------------------------------------------------------------------------------------------------
//Función para preparar el documento escogido para su lectura, eligiendo lectura completa o desde el último punto.
//----------------------------------------------------------------------------------------------------------------
void SeleccionarDocumento(string elnombredoc)
{
    char *nombredoc = strdup(elnombredoc.c_str());
    FILE * eldocumento;
    FILE * laguia;
    char direcdoc[512] = "./Textos/";
    char direcguia[512]= "./Guias/";
    char frasechar[512] = "Procesando el documento ";
    int opcion=0, linea=0;
    char charlinea[5];

    strcat(frasechar,nombredoc);
    strcat(direcdoc,nombredoc);
    strcat(direcguia,nombredoc);
    strcat(direcguia,".guia");

    printf("\n%s\n",frasechar);
    fflush(stdout);
    Decir(frasechar);

    laguia = fopen(direcguia,"r");
    if (laguia != NULL)
    {
	printf("Pulse ESPACIO para continuar por donde lo dejó, o INTRO para leer desde el principio...");
	fflush(stdout);
	Decir("Pulse espacio para continuar por donde lo dejó, o intro para leer desde el principio");
	VaciarBufferTeclado();
	while(opcion==0)
	{
	    sleep(1);
	    if (ComprobarTeclado() == ' ')
		opcion = 1;
	    if (ComprobarTeclado() == '\n')
		opcion = 2;
	    VaciarBufferTeclado();
	}
	if (opcion == 1)
	{
	    fgets(charlinea,5,laguia);
	    linea = atoi(charlinea);
	}
    }
    
    eldocumento = fopen(direcdoc,"r");
    LeerDocumento(eldocumento,linea, direcguia);
}

//------------------------------------------------------------------------------------------------------------------
//Función que lee el documento seleccionado, desde la línea indicada y previa conversión a la codificación adecuada.
//------------------------------------------------------------------------------------------------------------------
void LeerDocumento(FILE * eldoc, int lalinea, char archiguia[512])
{
    FILE* fichdest;
    FILE* fichref;
    FILE* fichguia;
    char charslinea[4096];
    bool finfich = false;
    int lineactual = lalinea;

    fichdest = fopen("./Archiaux/leyendo.txt","w");

    for (int contalin = 0; contalin < lineactual; contalin++)
	fgets(charslinea,4096,eldoc);

    do{
	if (fgets(charslinea,4096,eldoc) == NULL)
	    finfich = true;
	else
	    fputs(charslinea,fichdest);	
    } while(!finfich);

    fflush(fichdest);
    fclose(fichdest);

    RefinarTexto();

    system ("iconv --from-code=UTF-8 --to-code=ISO-8859-1 ./Archiaux/leyendoRef.txt > ./Archiaux/leyendoISO8859.txt -c -s");

    printf("\nIniciando lectura. (Pulse ESCAPE en cualquier momento para finalizar tras el párrafo en curso y guardar la posición)");
    fflush(stdout);
    Decir("Iniciando lectura. Pulse ESCAPE en cualquier momento para finalizar tras el párrafo en curso y guardar la posición");
    sleep(1);

    fichref = fopen("./Archiaux/leyendoISO8859.txt","r");
    finfich = false;
    festival_eval_command("(voice_JuntaDeAndalucia_es_pa_diphone)");
    do{
	VaciarBufferTeclado();
	ComprobarTeclado();
	if (fgets(charslinea,4096,fichref) == NULL)
	{
	    finfich = true;

	    remove(archiguia);
	}
	else
	{
	    festival_say_text(charslinea);
	    lineactual++;
	    fichguia = fopen(archiguia,"w");
	    fprintf(fichguia,"%d",lineactual);
	    fclose(fichguia);
	}
    }while(!finfich);
    fclose(fichref);
}

//-------------------------------------------------------------------------------------------------------------
//Función que comprueba si en las siguientes posiciones al puntero del fichero indicado se encuentra la cadena.
//-------------------------------------------------------------------------------------------------------------
bool ProxCaracteres(FILE * fdesc, string laetiqueta)
{
    char proxcaracter;
    char *etiqueta = strdup(laetiqueta.c_str());
    int posCursorInicial = ftell(fdesc);
 
    fseek(fdesc,-1,SEEK_CUR);
    for (int i=0; i <= strlen(etiqueta)-1; i++)
    {
	proxcaracter = fgetc(fdesc);
	if (proxcaracter != etiqueta[i])
	{
	    fseek(fdesc,posCursorInicial,SEEK_SET);
	    return false;
	}
    }

    return true;
}

//-------------------------------------------------------------------------------------------------------------
//Función que comprueba si en las anteriores posiciones al puntero del fichero indicado se encuentra la cadena.
//-------------------------------------------------------------------------------------------------------------
bool AntCaracteres(FILE * fdesc, string laetiqueta)
{
    char proxcaracter;
    char *etiqueta = strdup(laetiqueta.c_str());
    int posCursorInicial = ftell(fdesc);
 
    fseek(fdesc,-(strlen(etiqueta)+1),SEEK_CUR);
    for (int i=0; i <= strlen(etiqueta)-1; i++)
    {
	proxcaracter = fgetc(fdesc);
	if (proxcaracter != etiqueta[i])
	{
	    fseek(fdesc,posCursorInicial,SEEK_SET);
	    return false;
	}
    }
    fseek(fdesc,posCursorInicial,SEEK_SET);
    return true;
}

//--------------------------------------------------------------------------------------------------------
//Función que devuelve el número de cifras que aparecen seguidas en las siguientes posiciones del fichero.
//--------------------------------------------------------------------------------------------------------
int ComprobarSigNumeros(FILE * fdesc)
{
    char proxcaracter;
    int posCursorInicial = ftell(fdesc);
    int numCifras = 0;
    bool haycifras = true;
 
    do
    {
	proxcaracter = fgetc(fdesc);
	if (proxcaracter >= 48 && proxcaracter <= 57)
	{
	    numCifras++;
	}
	else
	    haycifras = false;
    } while(haycifras);

    fseek(fdesc,posCursorInicial,SEEK_SET);
    return numCifras;
}

//--------------------------------------------------------
//Función que adecúa el texto para la lectura en Festival.
//--------------------------------------------------------
void RefinarTexto()
{
    FILE * forigen;
    FILE * fdestino;
    FILE * fdiccionario;

    char caracteractual, ultimoescrito, caracteraux;

    forigen = fopen("./Archiaux/leyendo.txt","r");
    fdestino = fopen("./Archiaux/leyendoRef.txt","w");
    fdiccionario = fopen("./sustituciones","r");

    do{
	caracteractual = fgetc(forigen);
	if (!ProxCaracteres(forigen," ") && !ProxCaracteres(forigen,"«") && !ProxCaracteres(forigen,"»")) // (Aunque lo primero parece un espacio, es un multicaracter que no se procesa correctamente y se debe omitir).
	{
	    switch(caracteractual)
	    {
		case ' ':	// Tratamos aparte los espacios.
		    if (ultimoescrito != ' ' && ultimoescrito != '\n') // Los espacios se omiten si van precedidos de otro espacio o un salto de linea
		    {
			if (ProxCaracteres(forigen," .") && ultimoescrito != '.') //o si después de ellos viene un punto.
			{
			    fputc('.',fdestino);
			    ultimoescrito = '.';
			}
			else if (ProxCaracteres(forigen," (")) // Si después de ellos viene un paréntesis abierto.
			{
			    fputc(',',fdestino); // Se pone un punto.
			    ultimoescrito = ',';
			}
			else if (ProxCaracteres(forigen," - ")) // Si después de ellos viene un guión y un espacio.
			{
			    fputc(',',fdestino); // Se pone un punto.
			    ultimoescrito = ',';
			}
			else
			{
			    fputc(' ',fdestino);	// En otro caso se mantiene el espacio.
			    ultimoescrito = ' ';
			}
		    }
		    break;
		case '.':	// Tratamos aparte los puntos.
		    if (ultimoescrito >= 48 && ultimoescrito <= 57)	// Si el caracter anterior al punto era un número:
		    {
			switch(ComprobarSigNumeros(forigen)) //comprobamos si lo que sigue al punto es una cifra,
			{
			    case 2: fputc('.',fdestino); //Si la cifra es de 2 dígitos, ponemos el punto y la siguiente cifra sin espacio, pues
				fputc(fgetc(forigen),fdestino);	//probablemente es una hora.
				break;
			    case 3: break;	//Y si es una cifra de 3 dígitos quitamos el punto porque festival no lo reconoce como separador.
			    default: fputc('.',fdestino);	// En otro caso lo mantenemos.
				ultimoescrito = '.';
			}
		    }
		    else if (ultimoescrito != '.' && ultimoescrito != ' ' && ultimoescrito != ',' && ultimoescrito != '\n')
		    {	// Si el caracter anterior al punto no es ni una cifra, ni un punto, ni un espacio, ni una coma, ni un salto de linea,
			fputc('.',fdestino);	//lo mantenemos.
			ultimoescrito = '.';
		    }
		    break;
		case ',':	// Tratamos aparte las comas.
		    if (ultimoescrito >= 48 && ultimoescrito <= 57 && ComprobarSigNumeros(forigen) > 0) //si la coma está precedida y seguida de cifras...
		    {	//sustituimos el signo ',' por la palabra 'coma' para que la pronuncie en lugar de hacer una pausa.
			fputc(' ',fdestino); fputc('c',fdestino); fputc('o',fdestino); fputc('m',fdestino); fputc('a',fdestino); fputc(' ',fdestino);
			ultimoescrito = ' ';
		    }
		    else if (ultimoescrito != ',' && ultimoescrito != ' ')
		    {
			fputc(',',fdestino);
			ultimoescrito = ',';
		    }
		    break;
		case '(':	// Los paréntesis los cambiamos por comas para que haga una pausa
		    {
			if (ultimoescrito != ',' && ultimoescrito != '.')
			{
			    fputc(',',fdestino);
			    ultimoescrito = ',';			    
			}
		    }
		    break;
		case ')':
		    {
			if (ProxCaracteres(forigen,")."))
			{
			    fputc('.',fdestino);
			    ultimoescrito = '.';
			}
			else
			{
			    fputc(',',fdestino);
			    ultimoescrito = ',';
			}
		    }
		    break;
		default: //Cualquier otro caracter no tratado especialmente lo mostramos sin más,
		    if (ultimoescrito == '.' || ultimoescrito == ',') //poniendo antes un espacio si va justo después de un punto o una coma.
			fputc(' ',fdestino);
		    if (!EncontrarSustitucion(forigen,fdestino,fdiccionario,ultimoescrito))	//Si no se encuentra una sustitución,
		    {
			fputc(caracteractual,fdestino);		//escribe el caracter de manera habitual.
			ultimoescrito = caracteractual;
		    }
		    else
			ultimoescrito = '_'; // (cualquier carácter no interceptado en posteriores iteraciones)
	    }
	}
    } while(caracteractual != EOF);

    fflush(fdestino);
    fclose(forigen);
    fclose(fdestino);
    fclose(fdiccionario);
}

//---------------------------------------------------------------------------------------------------------------
//Función que busca si para la próxima palabra hay una pronunciación más adecuada en el fichero de sustituciones.
//---------------------------------------------------------------------------------------------------------------
bool EncontrarSustitucion(FILE * orig, FILE * dest, FILE * dicci, char ultchar) // Comprueba si la siguiente palabra encontrada es sustituble por alguna de las recogidas en el fichero "sustituciones"
{
    if (!(ultchar ==' ' || ultchar =='.' || ultchar ==',' || ultchar =='(' || ultchar ==')' || ultchar ==':' || ultchar =='\n'))
	return false;
    char pal_dicci[1440];
    char ultimochar;
    int posEncontrada = 0;
    char palabra[1440];
    int posCursorInicial = ftell(orig);
    bool quedan = true;

    fseek(orig,-1,SEEK_CUR);
    fgets(palabra,1440,orig);

    fseek(orig,posCursorInicial,SEEK_SET);
    fseek(dicci,0,SEEK_SET);

    while(quedan)
    {
	if (fgets(pal_dicci,1440,dicci)) // Vamos comprobando linea a linea del fichero.
	{
	    if (tolower(pal_dicci[0]) == tolower(palabra[0])) // Si las palabras empiezan igual
	    {
		for (int i=1; i <= strlen(pal_dicci)-1; i++)
		{
		    if (pal_dicci[i] == '>' && (palabra[i]==' ' || palabra[i]=='.' || palabra[i]==',' || palabra[i]==')' || palabra[i]=='\n'))
		    { //si han coincidido todas las letras hasta encontrar '>' significa que la palabra está contemplada
			for (int j=i+1; j <= strlen(pal_dicci)-2; j++)
			{
			    fputc(pal_dicci[j],dest);	//así que se escribe lo que haya en la parte derecha del '>'
			}
			fseek(orig,i-1,SEEK_CUR);	//y se actualiza el puntero del fichero de lectura a la posición justo despúes de la palabra.
			return true;
		    }
		    else
		    {
			if (tolower(palabra[i]) != tolower(pal_dicci[i])) //Cuando una letra no coincide entre las cadenas, se acaba con esa linea
			    break;
		    }
		}
	    }
	}
	else
	{
	    quedan = false;
	}
    }

    return false;
}

//--------------------------------------------------------------------------
//Función que lee el texto indicado previa conversión al charset ISO-8859-1.
//--------------------------------------------------------------------------
void Decir(string eltexto) // Función para leer con la codificación adecuada la cadena de texto suministrada.
{
    char *texto = strdup(eltexto.c_str());
    FILE * archiaux;

    archiaux = fopen("./Archiaux/archiaux","w");
    fputs(texto,archiaux);
    fflush(archiaux);
    fclose(archiaux);
    system ("iconv --from-code=UTF-8 --to-code=ISO-8859-1 ./Archiaux/archiaux > ./Archiaux/archiauxISO8859 -c -s");
    archiaux = fopen("./Archiaux/archiauxISO8859","r");
    remove("./Archiaux/archiaux");
    fgets(texto,1440,archiaux);
    festival_eval_command("(voice_el_diphone)");
    festival_say_text(texto);
    fclose(archiaux);
    remove("./Archiaux/archiauxISO8859");
    festival_wait_for_spooler();
}

//-----------------------------------------------------------------------------------
//Función que devuelve la última tecla pulsada o fuerza la salida si ésta era Escape.
//-----------------------------------------------------------------------------------
char ComprobarTeclado()
{
    char tecla = UltimaTeclaPulsada();
    if (tecla == 27)
    {
	cout << "\n\nGracias por usar nuestro programa. Vuelva pronto.\n\n";
	Decir("Gracias por usar nuestro programa. Vuelva pronto");
	exit(1);
    }
    return tecla;
}

//---------------------------------------------
//Función que devuelve la última tecla pulsada.
//---------------------------------------------
char UltimaTeclaPulsada() // Esta es una versión modificada del Kbhit para linux, para que devuvelva la última tecla pulsada
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

    if(ch != EOF)
    {
	ungetc(ch, stdin);
	return ch;
    }

  return NULL;
}

//-----------------------------------------
//Función para vaciar el buffer de entrada.
//-----------------------------------------
void VaciarBufferTeclado()
{
    setvbuf(stdin, NULL, _IONBF,0); // Al deshabilitar la entrada estandar se vacía el buffer,
    setvbuf(stdin, NULL, _IOFBF,0); //tras lo cual volvemos a habilitarla.
}

//-----------------------------------------------------------------------------------------
//Función que comprueba si las voces a utilizar están instaladas y avisa en caso contrario.
//-----------------------------------------------------------------------------------------
void ComprobarVoces()
{
    DIR* directorio;
    bool estavoz1 = false, estavoz2 = false;
    char dirvoz1[72] = "/usr/share/festival/voices/spanish/JuntaDeAndalucia_es_pa_diphone"; //voz masculina de la Junta de Andalucía
    char dirvoz2[48] = "/usr/share/festival/voices/spanish/el_diphone";	//voz masculina estándar
    char carpetavoz1[32] = "JuntaDeAndalucia_es_pa_diphone";
    char carpetavoz2[12] = "el_diphone";

    if ((directorio = opendir(dirvoz1)) != NULL)
	estavoz1 = true;

    if ((directorio = opendir(dirvoz2)) != NULL)
	estavoz2 = true;

    if (!estavoz1 || !estavoz2)
    {
	printf("Algunas voces utilizadas no están instaladas. Esto puede afectar sensiblemente la calidad de la experiencia:\n");
	if (!estavoz1)
	    printf("%s\n",carpetavoz1);
	if (!estavoz2)
	    printf("%s\n",carpetavoz2);
	fflush(stdout);
	Decir("algunas voces utilizadas no están instaladas. Esto puede afectar sensiblemente la calidad de la experiencia");
    }
}

//-----------------------------------------------------------------------------------------------------------------
//Función que carga el controlador de sonido indicado en el fichero configaudio, que en caso de no existir lo crea.
//-----------------------------------------------------------------------------------------------------------------
void InicializarControlador()
{
    FILE * archiconfig;
    char codigodriver;

    archiconfig = fopen("configaudio","r");
    if (archiconfig == NULL)
    {
	codigodriver = BuscaControlador();
	sleep(1);
	if (codigodriver == '0')
	{
	    cout << "\n¡No se encuentra un controlador de sonido adecuado!\nSaliendo de la aplicación...\n\n";
	    exit(1);
	}
	archiconfig = fopen("configaudio","w");
	fputc(codigodriver,archiconfig);
	fclose(archiconfig);
    }
    else
    {
	codigodriver = fgetc(archiconfig);
	fclose(archiconfig);
	switch (codigodriver)
	{
	    case '1': festival_eval_command("(Parameter.set 'Audio_Command \"aplay -D plug:dmix -q -c 1 -t raw -f S16_BE -r $SR $FILE\")"); break;
	    case '2': festival_eval_command("(Parameter.set 'Audio_Command \"esdaudio $FILE\")"); break;
	    case '3': festival_eval_command("(Parameter.set 'Audio_Command \"sun16audio $FILE\")"); break;
	    case '4': festival_eval_command("(Parameter.set 'Audio_Command \"sunaudio $FILE\")"); break;
	    case '5': festival_eval_command("(Parameter.set 'Audio_Command \"freebsd16audio $FILE\")"); break;
	    case '6': festival_eval_command("(Parameter.set 'Audio_Command \"linux16audio $FILE\")"); break;
	}
	festival_eval_command("(Parameter.set 'Audio_Method 'Audio_Command)");
	festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");	
    }
    system("clear");
}

//-------------------------------------------------------------------------------------------------------------
//Función que se encarga de ir probando los controladores uno a uno hasta que encuentra uno válido y lo guarda.
//-------------------------------------------------------------------------------------------------------------
char BuscaControlador()
{
    time_t Tantes, Tdespues;

    system("clear");
    cout << "Detectada primera ejecución. Buscando controlador de audio adecuado...";
    fflush(stdout);
    sleep(3);

    festival_eval_command("(Parameter.set 'Audio_Command \"aplay -D plug:dmix -q -c 1 -t raw -f S16_BE -r $SR $FILE\")");
    festival_eval_command("(Parameter.set 'Audio_Method 'Audio_Command)");
    festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");
    time(&Tantes);
    Decir("detectado el controlador ALSA");
    system("clear");
    time(&Tdespues);
    if (difftime(Tdespues,Tantes) >= 2)
	return '1';

    festival_eval_command("(Parameter.set 'Audio_Method 'esdaudio)");
    festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");
    time(&Tantes);
    Decir("detectado el controlador E S D.");
    system("clear");
    time(&Tdespues);
    if (difftime(Tdespues,Tantes) >= 2)
	return '2';

    festival_eval_command("(Parameter.set 'Audio_Method 'sun16audio)");
    festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");
    time(&Tantes);
    Decir("detectado el controlador san audio 16 bits");
    system("clear");
    time(&Tdespues);
    if (difftime(Tdespues,Tantes) >= 2)
	return '3';

    festival_eval_command("(Parameter.set 'Audio_Method 'sunaudio)");
    festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");
    time(&Tantes);
    Decir("detectado el controlador san audio");
    system("clear");
    time(&Tdespues);
    if (difftime(Tdespues,Tantes) >= 2)
	return '4';

    festival_eval_command("(Parameter.set 'Audio_Method 'freebsd16audio)");
    festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");
    time(&Tantes);
    Decir("detectado el controlador frii B S D audio 16 bits");
    system("clear");
    time(&Tdespues);
    if (difftime(Tdespues,Tantes) >= 2)
	return '5';

    festival_eval_command("(Parameter.set 'Audio_Method 'linux16audio)");
    festival_eval_command("(Parameter.set 'Audio_Required_Format 'snd)");
    time(&Tantes);
    Decir("detectado el controlador Linux audio 16 bits");
    system("clear");
    time(&Tdespues);
    if (difftime(Tdespues,Tantes) >= 2)
	return '6';

    return '0';
}



