// file: $isip/class/sp/AudioFrontEnd/afnd_03.cc
// version: $Id: afnd_03.cc 9267 2003-07-15 19:34:50Z parihar $
//

// isip include files
//
#include "AudioFrontEnd.h"
#include <Sof.h>

//------------------------------------------------------------------
// these methods have to be in the same file so they can use the same
// static parser pointer
//------------------------------------------------------------------

// declare a static sof parser pointer
//
static SofParser* parser_d = (SofParser*)NULL;

// method: setParser
//
// arguments:
//  SofParser* parser: (input) sof file object
//
// return: a boolean value indicating status
//
// this method sets the parser from the parent object to be used in
// the next readData method
//
boolean AudioFrontEnd::setParser(SofParser* parser_a) {

  // set the parser
  //
  parser_d = parser_a;

  // exit gracefully
  //
  return true;
}

// method: read
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: a boolean value indicating status
//
// this method has the object read itself from an Sof file according
// to the specified name and tag
//
boolean AudioFrontEnd::read(Sof& sof_a, long tag_a, const String& name_a) {

  // get the instance of the object from the Sof file
  //
  if (!sof_a.find(name_a, tag_a)) {
    return false;
  }

  // read the actual data from the sof file
  //
  return readData(sof_a);
}

// method: readData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//  long size: (input) size in bytes of object (or FULL_OBJECT)
//  boolean param: (input) is the parameter name in the file?
//  boolean nested: (input) are we nested?
//
// return: a boolean value indicating status
//
// this method has the object read itself from an Sof file. it assumes
// that the Sof file is already positioned correctly
//
boolean AudioFrontEnd::readData(Sof& sof_a, const String& pname_a, long size_a,
				boolean param_a, boolean nested_a) {

  // implicit parameter is impossible with composite objects, but
  // nesting can be used
  //
  if (parser_d == (SofParser*)NULL) {

    parser_d = new SofParser;

    if (nested_a) {
      parser_d->setNest();
    }
    
    // load the parse
    //
    if (!parser_d->load(sof_a, size_a)) {

      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }           
  }
  
  // first clear the object to get rid of all components
  //
  clear();

  // read input data type
  //
  if (parser_d->isPresent(sof_a, PARAM_INPUT_DATA_TYPE)) {
    if (!FrontEndBase::
	DATA_TYPE_MAP.readElementData((long&)input_data_type_d,
				      sof_a, PARAM_INPUT_DATA_TYPE,
				      parser_d->getEntry(sof_a, PARAM_INPUT_DATA_TYPE))) {
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
                           __FILE__, __LINE__, Error::WARNING);
    }      
  }
  else {
    input_data_type_d = DEF_INPUT_DATA_TYPE;
  }
  
  // read the input file flag
  //  
  if (parser_d->isPresent(sof_a, PARAM_INPUT_FLAG)) {
    if (!input_flag_d.readData(sof_a, PARAM_INPUT_FLAG,
			       parser_d->getEntry(sof_a, PARAM_INPUT_FLAG)
			       )) {
      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }
  }
  else {
    input_flag_d.assign(DEF_INPUT_FLAG);
  }

  // read the data. note that we only read the header information
  // required to configure the audiofile object
  //
  if (parser_d->isPresent(sof_a, PARAM_AUDIO_INPUT)) {
    if (!audio_input_d.readSofStartData(sof_a, PARAM_AUDIO_INPUT,
					parser_d->getEntry(sof_a, PARAM_AUDIO_INPUT),
					true, true)) {

      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;

      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       
    
  }
  else {
    audio_input_d.clear();	// clear initializes to default
  }

  // read the data for features file
  //
  if (parser_d->isPresent(sof_a, PARAM_FEATURE_INPUT)) {
    if (!feature_input_d.readData(sof_a, PARAM_FEATURE_INPUT,
				  parser_d->getEntry(sof_a,
						     PARAM_FEATURE_INPUT),
				  true, true)) {
      
      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       
    
  }
  else {
    feature_input_d.clear();	// clear initializes to default
  }
  
  // read frame duration
  //
  if (parser_d->isPresent(sof_a, PARAM_FRAME_DURATION)) {
    if (!frame_duration_d.readData(sof_a,
				   PARAM_FRAME_DURATION,
				   parser_d->getEntry(sof_a,
						      PARAM_FRAME_DURATION))) {
      
      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       
  }
  else {
    frame_duration_d.assign(DEF_FRAME_DURATION);
  }
  
  // read signal duration 
  //
  if (parser_d->isPresent(sof_a, PARAM_SIGNAL_DURATION)) {
    if (!signal_duration_d.readData(sof_a, PARAM_SIGNAL_DURATION,
				    parser_d->getEntry(sof_a, PARAM_SIGNAL_DURATION))) {
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }	      
  }
  else {
    signal_duration_d.assign(DEF_SIGNAL_DURATION);
  }

  // read number of features 
  //
  if (parser_d->isPresent(sof_a, PARAM_NUMBER_OF_FEATURES)) {
    if (!number_of_features_d.readData(sof_a, PARAM_NUMBER_OF_FEATURES,
				       parser_d->
				       getEntry(sof_a,
						PARAM_NUMBER_OF_FEATURES))) {
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }	      
  }
  else {
    number_of_features_d.assign(DEF_NUMBER_OF_FEATURES);
  }
  
  if (parser_d->isPresent(sof_a, PARAM_START_TIME)) {
    if (!start_time_d.readData(sof_a, PARAM_START_TIME,
			       parser_d->getEntry(sof_a, PARAM_START_TIME))) {

      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }
  }
  else {
    start_time_d.assign(DEF_START_TIME);
  }

  if (parser_d->isPresent(sof_a, PARAM_END_TIME)) {
    if (!end_time_d.readData(sof_a, PARAM_END_TIME,
			     parser_d->getEntry(sof_a, PARAM_END_TIME))) {

      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       
  }
  else {
    end_time_d.assign(DEF_END_TIME);
  }

  if ((end_time_d > (float)0) && (start_time_d > end_time_d)) {

    debug(L"fe");
    // delete the parser
    //
    delete parser_d;
    parser_d = (SofParser*)NULL;
    
    // return a warning message
    //
    return Error::handle(name(), L"readData", ERR, __FILE__, __LINE__,
			 Error::WARNING);
  }
  
  if (parser_d->isPresent(sof_a, PARAM_CONTEXT_WINDOW)) {
    if (!context_window_d.readData(sof_a, PARAM_CONTEXT_WINDOW,
				   parser_d->getEntry(sof_a,
						      PARAM_CONTEXT_WINDOW))) {

      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       
    
  }
  else {
    context_window_d.assign(DEF_CONTEXT_WINDOW);
  }

  // get the channel index
  //
  if (parser_d->isPresent(sof_a, PARAM_CHANNEL_INDEX)) {
    if (!channel_index_d.readData(sof_a, PARAM_CHANNEL_INDEX,
				  parser_d->getEntry(sof_a,
						     PARAM_CHANNEL_INDEX),
				  false, false)) {
      
      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::IO,
			   __FILE__, __LINE__, Error::WARNING);
    }
  }
  else {
    channel_index_d.assign(DEF_CHANNEL_INDEX);
  }


  // read component list
  //
  if (parser_d->isPresent(sof_a, PARAM_COMPONENT_LIST)) {
    if (!component_list_d.readData(sof_a, PARAM_COMPONENT_LIST,
				   parser_d->getEntry(sof_a,
						      PARAM_COMPONENT_LIST))) {
      
      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       
  }
  else {
    component_list_d.assign(DEF_COMPONENT_LIST);
  }

  // the default file "value" is to read from the current file
  //
  if (component_list_d.eq(DEF_COMPONENT_LIST)) {
    component_list_d.assign(sof_a.getExpandedName());
  }
  
  if (parser_d->isPresent(sof_a, PARAM_COEF_NAME)) {
    String cname;
    if (!cname.readData(sof_a, PARAM_COEF_NAME,
			parser_d->getEntry(sof_a, PARAM_COEF_NAME))) {
      
      // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
			   __FILE__, __LINE__, Error::WARNING);
    }       

    setCoefName(cname);
  }
  else {
    setCoefName(DEF_COEF_NAME);
  }
  
  // get the data mode
  //
  if (parser_d->isPresent(sof_a, PARAM_DATA_MODE)) {
    if (!AlgorithmBase::DMODE_MAP.readElementData((long&)data_mode_d, sof_a,
						  PARAM_DATA_MODE,
						  parser_d->getEntry(sof_a,
						  PARAM_DATA_MODE))) {
      
       // delete the parser
      //
      delete parser_d;
      parser_d = (SofParser*)NULL;
      
      // return a warning message
      //
      return Error::handle(name(), L"readData", Error::READ,
                            __FILE__, __LINE__, Error::WARNING);
    }
  }
  else {
    data_mode_d = AlgorithmBase::DEF_DMODE;
  }

  // check that all parameters are accounted for
  //
  if (!parser_d->checkParams(sof_a)) {

    // delete the parser
    //
    delete parser_d;
    parser_d = (SofParser*)NULL;

    // return a warning message
    //
    return Error::handle(name(), L"readData", Error::IO, __FILE__, __LINE__,
			 Error::WARNING);
  }

  // delete the parser
  //
  delete parser_d;
  parser_d = (SofParser*)NULL;

  // parameters initialization for audio frontend
  //
  if (start_time_d != DEF_START_TIME ||
      end_time_d != DEF_END_TIME ||
      channel_index_d != DEF_CHANNEL_INDEX) {
    init(start_time_d, end_time_d, channel_index_d);
  }

  // exit gracefully
  //
  return true;
}

