/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */

/* adin.c --- handle input source (select/start/stop) */

/* $Id: adin.c,v 1.6 2002/09/11 22:01:50 ri Exp $ */

/* when you add an input device as adin_*.c, you should register it as SP_* in
 * include/sent/speech.h, and add those function in adin_select() */

/*

===== Below describes how adin_* is called =====

adin_go() {
  adin_resume();
  for(;;)
    adin_read();
    if (no_segmentation || valid_segment) callback();
    if (error || end_of_stream || (!no_segmentation && end_of_segment)) break;
  }
  adin_pause();
  return(-1..error 0...EOST, 1...EOSEG);
}

main() {
  adin_standby(freq, arg);
  for(;;) {
	adin_begin();
	for(;;) {
		adin_go();
		error -> break;
		Process_2nd_Pass;
		EOS -> break;
	}
	adin_end();
  }
}

*/

#include <sent/stddefs.h>
#include <sent/speech.h>
#include <sent/adin.h>

static int input_source;
/* device handling functions */
static boolean (*ad_standby)(int, void *);/* standby (call once on startup) */
static boolean (*ad_begin)();	/* start recording */
static boolean (*ad_end)();	/* end recording */


/* assign specified adin_* functions and prepare for adin_go() */
static void
adin_register_func(boolean (*cad_standby)(int, void *),
		   boolean (*cad_begin)(),
		   int (*cad_read)(SP16 *, int),
		   boolean (*cad_end)(),
		   boolean (*cad_resume)(),
		   boolean (*cad_pause)(),
		   boolean segmentation_default,
		   boolean need_threaded)
{
  ad_standby = cad_standby;
  ad_begin = cad_begin;
  ad_end = cad_end;
  adin_setup_func(cad_read, cad_pause, cad_resume,
		  segmentation_default, 
		  need_threaded); /* inside adin_go */
}


/**********************************************************************/
/* select input source and setup device-specific functions */
boolean
adin_select(int source) /* input source */
{
  input_source = source;

  /* setup functions */
  switch(input_source) {
  case SP_RAWFILE:
#ifdef HAVE_LIBSNDFILE
    /* libsndfile interface */
    adin_register_func(adin_sndfile_standby, /* standby (called once on startup) */
		       adin_sndfile_begin, /* start (called for each stream) */
		       adin_sndfile_read, /* read (read sample) */
		       adin_sndfile_end, /* stop (called for each stream) */
		       NULL,	/* pause (called between each segment) */
		       NULL,	/* resume (called between each segment) */
		       FALSE,	/* default of pause segmentation */
		       FALSE);	/* TRUE if need threaded */
#else  /* ~HAVE_LIBSNDFILE */
    /* built-in RAW/WAV reader */
    adin_register_func(adin_file_standby, /* standby (called once on startup) */
		       adin_file_begin, /* start (called for each stream) */
		       adin_file_read, /* read (read sample) */
		       adin_file_end, /* stop (called for each stream) */
		       NULL,	/* pause (called between each segment) */
		       NULL,	/* resume (called between each segment) */
		       FALSE,	/* default of pause segmentation */
		       FALSE);	/* TRUE if need threaded */
#endif
    break;
#ifdef USE_MIC
  case SP_MIC:
    adin_register_func(adin_mic_standby,
		       NULL,
		       adin_mic_read,
		       NULL,
		       adin_mic_start,
		       adin_mic_stop,
		       TRUE,
		       TRUE);
    break;
#endif
#ifdef USE_NETAUDIO
  case SP_NETAUDIO:
    adin_register_func(adin_netaudio_standby,
		       NULL,
		       adin_netaudio_read,
		       NULL,
		       adin_netaudio_start,
		       adin_netaudio_stop,
		       TRUE,
		       TRUE);
    break;
#endif
  case SP_ADINNET:
    adin_register_func(adin_tcpip_standby,
		       adin_tcpip_begin,
		       adin_tcpip_read,
		       adin_tcpip_end,
		       NULL,
		       NULL,
		       FALSE,
		       FALSE);

    break;
  case SP_STDIN:
    adin_register_func(adin_stdin_standby,
		       adin_stdin_begin,
		       adin_stdin_read,
		       NULL,
		       NULL,
		       NULL,
		       FALSE,
		       FALSE);
    break;
  case SP_MFCFILE:
    /* MFC_FILE is not waveform, so special handling on main routine should be done */
    break;
  default:
    return FALSE;
  }
  return TRUE;
}

/* global functions: only call device-specific functions */
boolean
adin_standby(int freq, void *arg)
{
  if (ad_standby != NULL) return(ad_standby(freq, arg));
  else return TRUE;
}
boolean
adin_begin()
{
  if (ad_begin != NULL) return(ad_begin());
  else return TRUE;
}
boolean
adin_end()
{
  if (ad_end != NULL) return(ad_end());
  else return TRUE;
}
