         	/*  Talker Hack Version 2.5 03-22-89  */

#define ERR 1L
#define SUCCESS 0L
#define REV 0L

#include "exec/types.h"
#include "exec/exec.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "devices/keymap.h"
#include "hardware/blit.h"
#include "devices/narrator.h"
#include "libraries/translator.h"
#include "stdio.h"
#include "clib/macros.h"
#include "face.h"
#include "eyes.h"
#include "mouthy.h"
#include "mouthx.h"
#include "stdio.h"

ULONG mclass,newmouth,neweyes;
UBYTE in_string[256], out_string[1024];

         /* select which audio channels to use */

BYTE audio_chan[] = {3, 5, 10, 12};

       struct Library *OpenLibrary();
       struct Library *TranslatorBase = NULL;
       struct MsgPort *voice_port; /* audio message port */
       struct MsgPort *mouth_port; /* video message port */
       struct mouth_rb *mouth_io;
       struct narrator_rb *voice_io;
       struct IntuitionBase *IntuitionBase = NULL;
       struct GfxBase   *GfxBase   = NULL;
       struct Screen *TalkerScreen = NULL;
       struct Window *TalkerWindow = NULL;
       struct ViewPort *Vprt       = NULL;
       struct RastPort *rast       = NULL;
       struct IntuiMessage *mesg   = NULL;
ULONG EyeArray[4] = { &eyes0_image,&eyes1_image,&eyes2_image,&eyes0_image };

ULONG *HArray[16] = {
                        &mouth0_image, &mouth0_image,
			&mouth1_image, &mouth3_image,
                        &mouth3_image, &mouth4_image,
                        &mouth5_image, &mouth6_image,
                        &mouth7_image, &mouth7_image,
                        &mouth8_image, &mouth9_image,
                        &mouth10_image, &mouthx11_image,
                        &mouthx11_image, &mouthx12_image 
                      };
ULONG *WArray[16] = {
                        &mouthx0_image, &mouthx0_image,
			&mouthx1_image, &mouthx2_image,
                        &mouthx3_image, &mouthx3_image,
                        &mouthx4_image, &mouthx5_image,
                        &mouthx6_image, &mouthx7_image,
                        &mouthx7_image, &mouthx8_image,
                        &mouthx9_image, &mouthx10_image,
                        &mouthx11_image, &mouthx12_image 
                      };
ULONG *BArray[16] = {
                        &mouth0_image, &mouthx1_image,
			&mouth2_image, &mouthx3_image,
                        &mouthx4_image, &mouthx5_image,
                        &mouthx6_image, &mouthx7_image,
                        &mouthx8_image, &mouthx8_image,
                        &mouthx9_image, &mouthx9_image,
                        &mouthx10_image, &mouthx11_image,
                        &mouthx12_image, &mouthx12_image 
                      };
static struct NewScreen NewScreenStructure = {
	0,0,	/* screen XY origin relative to View */
	640,200,	/* screen width and height */
	3,	/* screen depth (number of bitplanes) */
	0,1,	/* detail and block pens */
	HIRES,	/* display modes for this screen */
	CUSTOMSCREEN,	/* screen type */
	NULL,	/* pointer to default screen font */
	(UBYTE *)"© 1989 ",   /* screen title */
	NULL,	/* first in list of custom screen gadgets */
	NULL	/* pointer to custom BitMap structure */
};

#define NEWSCREENSTRUCTURE NewScreenStructure

USHORT Palette[] = {
   0x024C,   /* color #0 */
   0x0FFF,   /* color #1 */
   0x0000,   /* color #2 */
   0x0851,   /* color #3 */
   0x0FB9,   /* color #4 */
   0x0EA8,   /* color #5 */
   0x0C85,   /* color #6 */
   0x0730   /* color #7 */
#define PaletteColorCount 8
};

#define PALETTE Palette

static struct NewWindow NewWindowStructure1 = {
	400,0,	/* window XY origin relative to TopLeft of screen */
	160,86, /* window width and height */
	0,1,	/* detail and block pens */
	WINDOWCLOSE,	/* IDCMP flags */
	WINDOWDRAG+WINDOWCLOSE+SMART_REFRESH,/* window flags*/
	NULL,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	(UBYTE *)"Talker",	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	160,86, /* minimum width and height */
	-1,-1, /* maximum width and height  */
	CUSTOMSCREEN	/* destination screen type */
};


      /* end of PowerWindows source generation */

main(argc,argv)
 int argc;
 char *argv[];
 {
  OpenLibs();
  OpenWind();
  prep_to_talk();
   if( !argv[1] )
     enter_text();
   else
      {
       Delay(50);
       Blink(5L);
       say_file(argv[1]);
       Delay(25);
      };

  CloseWind(NULL);
 }

changestring(in,inlen,out,outlen)
 UBYTE *in,*out;
 SHORT inlen,outlen;
 {
  if(Translate(in,inlen,out,outlen))
    CloseWind("translation error");
  return;
 }

talk_to_me(speech)
 UBYTE *speech;
 {
  voice_io->message.io_Data=(APTR)speech;
  voice_io->message.io_Length=strlen(speech);
  voice_io->ch_masks=audio_chan;
  voice_io->nm_masks=sizeof(audio_chan);

  voice_io->mouths=1;
  voice_io->volume=64;
  voice_io->rate=150;
  voice_io->sex=MALE;
  voice_io->pitch=DEFPITCH;
  voice_io->sampfreq=23000;
  mouth_io->voice.message.io_Error = 0;

 SendIO(voice_io);

 while(mouth_io->voice.message.io_Error == 0)
     {
      DoIO(mouth_io);
      if(mouth_io->height >= mouth_io->width)
        newmouth = HArray[mouth_io->height];
      else
         newmouth = WArray[mouth_io->width];
         DrawImage(rast,newmouth,13L,15L);
 }
  WaitIO(voice_io);
  Closemouth(mouth_io->height,mouth_io->width);
  Blink(2L);

   return;
}

prep_to_talk()
{
if((voice_port=(struct MsgPort *)CreatePort(0,0))==NULL)
   return(ERR);

if((mouth_port=(struct MsgPort *)CreatePort(0L,0L))==NULL)
   return(ERR);

if((voice_io=(struct narrator_rb *)
      CreateExtIO(voice_port,sizeof(struct narrator_rb)))==NULL)
   return(ERR);

if((mouth_io=(struct mouth_rb *)
      CreateExtIO(mouth_port,sizeof(struct mouth_rb)))==NULL)
   return(ERR);

voice_io->message.io_Command=CMD_WRITE;

if(OpenDevice("narrator.device",0L,voice_io,0L)!=0L)
   return(ERR);

mouth_io->voice.message.io_Device=voice_io->message.io_Device;
mouth_io->voice.message.io_Unit=voice_io->message.io_Unit;
mouth_io->width = 0;
mouth_io->height = 0;
mouth_io->voice.message.io_Command = CMD_READ;
mouth_io->voice.message.io_Error = 0;

   return(SUCCESS);

}

OpenLibs()
 {
  TranslatorBase = (struct Library *)OpenLibrary("translator.library",REV); 
  if(TranslatorBase == NULL)
   {
    CloseWind("couldn't open translator library");
   }          
  IntuitionBase = (struct Library *)OpenLibrary("intuition.library",0);
  if(IntuitionBase == NULL)
   {
    CloseWind("couldn't open Intuition library");
   }
  GfxBase = (struct Library *)OpenLibrary("graphics.library",0); 
  if(GfxBase == NULL)
   {
    CloseWind("couldn't open Graphics library");
   }
  return;
 }

OpenWind()
 {
  if((TalkerScreen = (struct Screen *)OpenScreen(&NewScreenStructure)) == NULL)
   {
    CloseWind("Couldn't Open screen");
   }
  NewWindowStructure1.Screen = TalkerScreen;
  if((TalkerWindow = (struct Window *)OpenWindow(&NewWindowStructure1)) == NULL)
    CloseWind("Couldn't Open window");

  Vprt = (struct ViewPort *)ViewPortAddress(TalkerWindow);
  LoadRGB4(Vprt,&PALETTE,PaletteColorCount);
  rast = TalkerWindow->RPort;
  DrawImage(rast,&face0_image,13L,15L);

   return;
 }
CloseWind(errorstring)
 char *errorstring;
 {
  if(errorstring)
    puts(errorstring);
  if(voice_port)
    DeletePort(voice_port);
  if(mouth_port)
    DeletePort(mouth_port); 
  if(voice_io)
   {
    CloseDevice(voice_io); 
    DeleteExtIO(voice_io); 
   }
  if(mouth_io)
    DeleteExtIO(mouth_io); 
  if(TalkerWindow)
   {
    while( mesg = (struct IntuiMessage *)GetMsg(TalkerWindow->UserPort) )
         ReplyMsg(mesg);
    CloseWindow(TalkerWindow);
   }
  if(TalkerScreen)
    CloseScreen(TalkerScreen);
  exit(0);
 }

Blink(pauseme)
 ULONG pauseme;
 {
  int x;
  for(x = 0; x < 4; x++)
   {
    neweyes = EyeArray[x];
    DrawImage(rast,neweyes,13L,15L);
    Delay(pauseme);
    }
return;
 }

Closemouth(high,wide)
 UBYTE high,wide;
 {
  ULONG x;
  if(high > wide)
   {
    for(x = high; x > 0; x--)
       DrawImage(rast,HArray[x],13L,15L);
   }
  if(wide >= high)
   {
    for(x = wide; x > 0; x--)
     DrawImage(rast,WArray[x],13L,15L);
   }
  return;
 }

enter_text()
 { 
  Delay(25);
  ScreenToBack(TalkerScreen);
  printf("enter string: ");
  gets(in_string);
  ScreenToFront(TalkerScreen);
  Delay(10);
  Blink(10L);
  changestring(in_string,strlen(in_string),out_string,1024L);
  Delay(5);
  Blink(5L);
  talk_to_me(out_string);
  return;
 }

say_file(name)
 char *name;
 {
  FILE   *f;      /* file pointer */
  if ((f = fopen(name,"r")) == NULL)
   CloseWind("can't open file\n" );
  while(fgets(in_string,255,f) != 0L)
      {
       changestring(in_string,(long)strlen(in_string),out_string,1024L); 
       talk_to_me(&out_string);
      }
  return;
 }
