/* $Id: saol_main.cpp,v 1.2 1997/11/20 18:37:28 eds Exp $ */
/* $Log: saol_main.cpp,v $
// Revision 1.2  1997/11/20  18:37:28  eds
// SASBF integration.
//
 * Revision 1.2  1997/11/15 00:43:25  luked
 * This is the result of the manual merge from the vendor branch for the
 * release tagged Fribourg_after_integration. I (brian) have probably lost
 * some history, but oh well.
 *
 * This contains the integration work by Eric Scheirer (MIT).
 *
 * Revision 1.3  1997/11/10  23:00:50  eds
 * Interfaced with new decoder.
 * Made it into C++ file.
 *
 * Revision 1.2  1997/09/17  14:14:07  eds
 * Documented '-verbose' switch.
 * */
/*********************************************************************

This software module was originally developed by

Eric D. Scheirer (MIT Media Laboratory)

in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
as specified by the MPEG-2 NBC/MPEG-4 Audio standard.  ISO/IEC gives
users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
software module or modifications thereof for use in hardware or
software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
standards. Those intending to use this software module in hardware or
software products are advised that this use may infringe existing
patents. The original developer of this software module and his/her
company, the subsequent editors and their companies, and ISO/IEC have
no liability for use of this software module or modifications thereof
in an implementation.

This software module is hereby released into the public domain.

***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#ifdef _WIN32
#include <string.h>
void srand48(long x) {
  srand((int)x);
}
#else
#include <strings.h>
#endif

#include <time.h>

extern "C" {
#include "saol.h"
#ifdef _SASBF
#include "sf_wave_def.h"
#endif
#include "y.tab.h"
#include "saol_interp.h"
#include "saol_sched.h"
#include "aifif.h"
#include <malloc.h>
extern int yyparse(void);
extern void open_inputs(sa_decoder *sa);
int yywrap(void) {
  return 1;
}
struct cmdinfo cmd;
extern int yydebug;  
extern FILE *yyin;
sa_decoder *cur_sa; /* only needed at startup for yyparse() and MIDIfiles */
}


void help(void);
void saol_startup(sa_decoder *,struct cmdinfo *);
void help(void);
extern void process_bitstream();

main(int argc, char *argv[]) {
  sa_decoder *sa;
  int text = 0;

#ifdef _WIN32
  _fmode = O_BINARY;
#endif 

  cmd.sco = cmd.orc = cmd.out = cmd.bit = NULL;
  cmd.temp = ".";
  cmd.text = 0;
  cmd.verbose = 0;
  cmd.inct = 0;
  cmd.midi = 0;
  cmd.sfbank0 = 0;
  cmd.sfbank1 = 0;

  yydebug = 0; 
  sa = (sa_decoder *)malloc(sizeof(sa_decoder));
  if (!sa) {
    printf("Fatal: couldn't create SA decoder.\n");
    exit(1);
  }


  srand48((long)time(NULL));
  while (++argv,--argc) {
    if (!strncmp(*argv,"-bit",4)) {cmd.bit = *(++argv); argc--;}
    else if (!strncmp(*argv,"-v",2)) {cmd.verbose = 1;}
    else if (!strcmp(*argv,"-temp")) {cmd.temp = *(++argv); argc--;}
    else if (!strncmp(*argv,"-sc",3)) {cmd.sco = *(++argv); argc--;}
    else if (!strncmp(*argv,"-or",3)) {cmd.orc = *(++argv); argc--;}
    else if (!strncmp(*argv,"-out",4)) {cmd.out = *(++argv); argc--; }
    else if (!strcmp(*argv,"-midi")) {cmd.midi = *(++argv); argc--; }
    else if (!strncmp(*argv,"-in",3)) {
      cmd.in[cmd.inct] = *(++argv); argc--;
      cmd.delay[cmd.inct++] = atof(*(++argv)); argc--;
    }
    else if (!strncmp(*argv,"-help",5)) help();
    else if (!strncmp(*argv,"-text",5)) { cmd.text = 1;}
    else if (!strcmp(*argv,"-sbank0")) { cmd.sfbank0 = *(++argv); argc--; }
    else if (!strcmp(*argv,"-sbank1")) { cmd.sfbank1 = *(++argv); argc--; }
    else { printf("Unknown option '%s'.\n",*argv); exit(1); }
  }

  if (cmd.midi) {
    printf("MIDI support not done yet.\n");
    exit(1);
  }
  
  if ((!cmd.orc && (!cmd.midi || !cmd.sco)) && !cmd.bit)
    help();

  saol_startup(sa,&cmd);

  while (sa->sched->running) {
    sched_run_kcycle(sa);
  }

  finish_output(sa);
  printf("\n");
  return(0);
}


void saol_startup(sa_decoder *sa,struct cmdinfo *cmd) {
  FILE *fp;
  char s[800];
  int i;

  sa->audioout = 0;

  sa->textout = cmd->text; 
  sa->audioout = 0;
  sa->synerror = 0;
  sa->verbose = cmd->verbose;
  sa->audioout = 0;
  sa->global_cx = NULL;
  sa->ksmps = 0;
  sa->outfile = cmd->out;
  sa->all_ptrs = NULL;
  sa->bufsize = 0;
  sa->replace_count = 0;
  sa->sched = NULL;
  sa->aifout = NULL;
  sa->outbuf = NULL;
  sa->outbuf_ct = 0;
  sa->ended = 0;
  sa->all = NULL;
  sa->inct = cmd->inct;
  sa->in = (inputfile *)calloc(cmd->inct,sizeof(inputfile));
  for (i=0;i!=sa->inct;i++) {
    sa->in[i].fn = strdup(cmd->in[i]);
    sa->in[i].delay = cmd->delay[i];
    sa->in[i].aif_in = NULL;
  }
  sa->inbuf = NULL;
  sa->inbus = NULL;
  sa->inchan = 0;
  sa->MIDICCINIT = 0;
  
  for (i = 0; i < NUM_MIDI_CHANS; i++)
  {
	  /* Contiuous Controller Initializations go here */
		sa->midicc[i][128] = 8192;	/* Pitch bend set to none */
		sa->midicc[i][7] = 64;
		sa->midicc[i][11] = 127;
		sa->midicc[i][10] = 56;		/* Pan set to center */
  }/* LSD midiCC add: for now PitchBend is CC#128 */

  if (cmd->bit) {
    /* write temp files */
    sprintf(s,"%s%ctemp.sao",cmd->temp,DIRSEP);
    cmd->orc = strdup(s);
    sprintf(s,"%s%ctemp.sas",cmd->temp,DIRSEP);
    cmd->sco = strdup(s);
    process_bitstream();
    if (cmd->has_sbf) {
      sprintf(s,"%s%ctemp.sbf",cmd->temp,DIRSEP);
      cmd->sfbank0 = strdup(s);
    }
    
  }


  if (cmd->sfbank0)
  {
#ifdef _SASBF
	  sf_bank_load(sa, cmd->sfbank0, 0);
	  printf("sfbank0 loaded\n");
#else
	  printf("No SASBF support in this executable.\n");
#endif
  }

  /* LSD sfbank command add */
  if (cmd->sfbank1)
  {
#ifdef _SASBF
	  sf_bank_load(sa, cmd->sfbank1, 1);
	  printf("sfbank1 loaded\n");
#else
	  printf("No SASBF support in this executable.\n");
#endif
	  
  }


  if (!(fp = fopen(cmd->orc,"r"))) {
    printf("Fatal: couldn't open orchestra file '%s'.\n",cmd->orc);
    exit(1);
  }
	
  yyin = fp;

  sa->all = new_orc();
  cur_sa = sa;
  open_inputs(sa); /* do first so get #input channels */
  yyparse();
  if (!sa->all->g)
    sa->all->g = new_orc_global();
  build_sym_table(sa);
  rate_checking(sa);
  macro_expand(sa);

  if (sa->synerror) exit(1);
  make_global_context(sa);
  start_scheduler(sa);
  if (cmd->sco) parse_score(sa,cmd->sco);
}

void runtime(char *s) {
  printf("Runtime error: %s\n",s);
  *(int *)0 = 1;		/* dump core */
  exit(1);
}


void help() {
  printf("Usage: saolc -orc [orcfile] [options]\n");
  printf("          -or-\n");
  printf("       saolc -bitstream [bitfile] [options]\n");
  printf("\n");
  printf("Options:\n");
  printf("   -sco         : score file in SASL format\n");
  printf("   -midi        : format 0/1 MIDI file\n");
  printf("   -sfbank0     : SA sample bank file #0 \n");
  printf("   -sfbank1     : SA sample bank file #1 \n");
  printf("   -text        : dump text sample values to stdout.                    \n");
  printf("   -temp        : directory for temp files for bitstream processing [.] \n");
  printf("   -in [fn] [t] : input sound file beginning at time t.\n");
  printf("   -out [file]  : write output as AIFF file.\n");
  printf("   -verbose     : dump out orch info and de-macroized orchestra.\n\n");
  printf("At least one of -sco, -midi, -bitstream must be specified.\n");
  printf("\n");
  exit(1);
}

