home *** CD-ROM | disk | FTP | other *** search
-
- /*--------------------------*|
- | TalkerII.c 10/01/90 |
- |*--------------------------*/
- /*=====================================================================*/
- /* Talker II Display Hack -- */
- /* VERSION 1 REVISION 0 */
- /*---------------------------------------------------------------------*/
- /* This is the primary file for Talker II. */
- /* It encompasses all major routines, including those dealing with */
- /* Message retrieval. */
- /*---------------------------------------------------------------------*/
- /* Talker II is based around the example routines for using the */
- /* narrator/translator devices from "Inside The Amiga". Because of */
- /* this, even though I made changes to the original code (to make it */
- /* work), I don't feel I can retain a copyright on it. Special thanks */
- /* to Keith Young (Access!) for his help with dealing with command */
- /* line arguments, along with much other assistance. */
- /*=====================================================================*/
-
- /* Auto: cc -su TalkerII.c
-
- */
-
- #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 "graphics/view.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "clib/macros.h"
- #include "faceII.h"
- #include "eyesII.h"
- #include "mouthyII.h"
- #include "mouthxII.h"
- #include "browsII.h"
- #include "stdio.h"
-
- ULONG mclass;
- struct Image *newmouth,*neweyes;
- char in_string[256], out_string[1024];
-
- /* select which audio channels to use */
-
- UBYTE 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;
-
-
- /*====================================================*/
- /* LookArray[][] is for determining which eye image */
- /* to show. The first 6 elements look left, the 2nd */
- /* 6 elements look right. */
- /*====================================================*/
-
- struct Image *LookArray[2][6] = {
- &eyes0_Image,&eyes3_Image,&eyes4_Image,
- &eyes4_Image,&eyes3_Image,&eyes0_Image,
- &eyes0_Image,&eyes5_Image,&eyes6_Image,
- &eyes6_Image,&eyes5_Image,&eyes0_Image
- };
-
- /*=================================================*/
- /* EyeArray[] is for determining which eye image */
- /* to show as the Talker blinks. Note that the */
- /* sequence is open, mid, closed, open. There is */
- /* NOT an element for mid as the eye reopens. */
- /* This appears more realistic, to me. */
- /*=================================================*/
-
- struct Image *EyeArray[4] = {
- &eyes0_Image,
- &eyes1_Image,
- &eyes2_Image,
- &eyes0_Image
- };
-
- /*===============================================*/
- /* HArray[] is used to determine which mouth */
- /* image to show. It is used for the sequences */
- /* where the height value is greater than the */
- /* width value. */
- /*===============================================*/
-
- struct Image *HArray[16] = {
- &mouthx0_Image, &mouthx0_Image,
- &mouthx1_Image, &mouthx3_Image,
- &mouthx3_Image, &mouthx4_Image,
- &mouthx5_Image, &mouthx6_Image,
- &mouthx7_Image, &mouthx7_Image,
- &mouthx8_Image, &mouthx9_Image,
- &mouthx10_Image, &mouthy11_Image,
- &mouthy11_Image, &mouthy12_Image
- };
-
-
- /*===============================================*/
- /* WArray[] is used to determine which mouth */
- /* image to show. It is used for the sequences */
- /* where the width value is greater than the */
- /* height value. */
- /*===============================================*/
-
- struct Image *WArray[16] = {
- &mouthy0_Image, &mouthy0_Image,
- &mouthy1_Image, &mouthy2_Image,
- &mouthy3_Image, &mouthy3_Image,
- &mouthy4_Image, &mouthy5_Image,
- &mouthy6_Image, &mouthy7_Image,
- &mouthy7_Image, &mouthy8_Image,
- &mouthy9_Image, &mouthy10_Image,
- &mouthy11_Image, &mouthy12_Image
- };
-
- /*===============================================*/
- /* BArray[] is used to determine which mouth */
- /* image to show. It is used for the sequences */
- /* where the height value is equal to the */
- /* width value. */
- /*===============================================*/
-
- struct Image *BArray[16] = {
- &mouthx0_Image, &mouthx1_Image,
- &mouthx2_Image, &mouthy3_Image,
- &mouthy4_Image, &mouthy5_Image,
- &mouthy6_Image, &mouthy7_Image,
- &mouthy8_Image, &mouthy8_Image,
- &mouthy9_Image, &mouthy9_Image,
- &mouthy10_Image, &mouthy11_Image,
- &mouthy12_Image, &mouthy12_Image
- };
-
- /*===================================*/
- /* old_palette is a pointer to the */
- /* allocated memory for palette[] */
- /* and colourarray[] */
- /*===================================*/
-
- UWORD *old_palette = NULL;
-
- /*======================================*/
- /* Palette[] (note the capital P) is */
- /* used to hold the values of my 5 */
- /* palette colours for Talker's face. */
- /*======================================*/
-
- USHORT Palette[] = {
- 0x0620, /* color #8 */
- 0x0c85, /* color #9 */
- 0x0ea8, /* color #10 */
- 0x0fb9, /* color #11 */
- 0x0841, /* color #12 */
- #define PaletteColorCount 5
- };
-
- #define PALETTE Palette
-
- static struct NewWindow NewWindowStructure1 = {
- 400,100, /* window XY origin relative to TopLeft of screen */
- 100,86, /* window width and height */
- 0,1, /* detail and block pens */
- CLOSEWINDOW+DISKINSERTED+DISKREMOVED+INTUITICKS+ACTIVEWINDOW, /* IDCMP */
- WINDOWDRAG+WINDOWCLOSE+WINDOWDEPTH+
- WINDOWACTIVE+ACTIVATE+SMART_REFRESH, /* window flags */
- NULL, /* first gadget in gadget list */
- NULL, /* custom CHECKMARK imagery */
- (UBYTE *)"][", /* window title */
- NULL, /* custom screen pointer */
- NULL, /* custom bitmap */
- 100,86, /* minimum width and height */
- -1,-1, /* maximum width and height */
- WBENCHSCREEN /* destination screen type */
- };
- /* end of PowerWindows source generation */
-
-
- /*===========================================*/
- /* CloseWind() -- */
- /*-------------------------------------------*/
- /* This routine is the program's final */
- /* exit point. This shuts down all opened */
- /* windows, ports, and deallocates all */
- /* allocated memory. */
- /*===========================================*/
-
- VOID
- 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)
- {
- if(old_palette != NULL)
- {
- restore_screen(old_palette);
- FreeMem(old_palette,(long)(16 * sizeof(UWORD)));
- };
-
- while( mesg = (struct IntuiMessage *)GetMsg(TalkerWindow->UserPort) )
- ReplyMsg(mesg);
- CloseWindow(TalkerWindow);
- };
-
- exit(0);
- }
-
-
- /*===================================================*/
- /* changestring() -- */
- /*---------------------------------------------------*/
- /* This routine translates the string */
- /* passed to it into something the narrator.device */
- /* can handle. "in" points to the incoming string, */
- /* "out" points to the outgoing string. "inlen" */
- /* is the length of the incoming string, "outlen" */
- /* is the length of the outgoing string. */
- /*===================================================*/
-
- VOID
- changestring(in,inlen,out,outlen)
- UBYTE *in,*out;
- SHORT inlen,outlen;
- {
- if(Translate(in,inlen,out,outlen))
- {
- CloseWind("translation error");
- };
-
- }
-
-
- /*================================================*/
- /* Blink() -- */
- /*------------------------------------------------*/
- /* This routine handles the blinking of the */
- /* eyes and controls the speed of the blink. */
- /*================================================*/
-
- VOID
- Blink(pauseme)
- ULONG pauseme;
- {
- int x;
- for(x = 0; x < 4; x++)
- {
- neweyes = EyeArray[x];
- WaitTOF();
- DrawImage(rast,neweyes,7,15);
- Delay(pauseme);
- };
-
- }
-
-
- /*=======================================*/
- /* Closemouth() -- */
- /*---------------------------------------*/
- /* This routine closes the mouth */
- /* after a 'sentence' has been spoken. */
- /* It determines which array to use, */
- /* based upon height vs width. */
- /*=======================================*/
-
- VOID
- Closemouth(high,wide)
- UBYTE high,wide;
- {
- ULONG x;
- if(high > wide)
- {
- for(x = high; x > 0; x--)
- {
- WaitTOF();
- DrawImage(rast,HArray[x],7,15);
- };
- };
-
- if(wide >= high)
- {
- for(x = wide; x > 0; x--)
- {
- WaitTOF();
- DrawImage(rast,WArray[x],7,15);
- };
- };
-
- }
-
-
- /*==================================================*/
- /* NewPalette() -- */
- /*--------------------------------------------------*/
- /* This routine sets up the 5 color registers */
- /* used to make the colors of the face. Note that */
- /* colors 1 and 2 are used as as well as colors */
- /* 8-12. Color 1 must be black, color 2 must be */
- /* white or it'll look weird. */
- /*==================================================*/
-
- VOID
- NewPalette()
- {
- long x;
- UWORD discolour;
- for(x = 0;x < 5;x++)
- {
- discolour = Palette[x];
- SetRGB4(Vprt,x + 8,((discolour&0xf00)>>8),(discolour&0xf0)>>4,
- (discolour&0x0f));
- };
-
- }
-
-
- /*===========================================*/
- /* HandleEvent() -- */
- /*-------------------------------------------*/
- /* This routine deals with all events that */
- /* are captured with GetEvents(). It first */
- /* copies the message into variables, and */
- /* then calls ReplyMsg() to free up the msg */
- /* port. It is called from GetEvents(), */
- /* and returns nothing. */
- /*===========================================*/
-
- VOID
- HandleEvent(EventMessage)
- struct IntuiMessage *EventMessage;
- {
- ULONG class;
- USHORT code, qual;
- struct Gadget *address;
- SHORT MooseX,MooseY;
- struct Window *disone;
-
- class = EventMessage->Class;
- code = EventMessage->Code;
- qual = EventMessage->Qualifier;
- disone = EventMessage->IDCMPWindow;
- address = (struct Gadget *)EventMessage->IAddress;
- MooseX = EventMessage->MouseX;
- MooseY = EventMessage->MouseY;
-
- ReplyMsg((struct Message *)EventMessage);
-
- if(class == DISKINSERTED)
- {
- restore_screen(old_palette);
- NewPalette();
- };
-
- if(class == DISKREMOVED)
- {
- blank_screen();
- };
-
- if(class == CLOSEWINDOW)
- {
- CloseWind("We're outta here.\n");
- };
-
- }
-
-
- /*=============================================*/
- /* GetEvents() */
- /*---------------------------------------------*/
- /* This routine is the loop for getting */
- /* and processing Window IDCMP events. It is */
- /* affected by clicking on the close gadget, */
- /* and by inserting or removing a diskette. */
- /* It is called by, and therefore is only */
- /* effective through, LookAround(), restore_ */
- /* screen() and blank_screen. */
- /*=============================================*/
-
- VOID
- GetEvents()
- {
- struct IntuiMessage *EventMsg;
- WaitPort(TalkerWindow->UserPort);
- while(EventMsg = (struct IntuiMessage *)GetMsg(TalkerWindow->UserPort))
- HandleEvent(EventMsg);
- }
-
-
- /*==================================================================*/
- /* LookAround() -- */
- /*------------------------------------------------------------------*/
- /* This routine makes the Talker look around awhile. You pass */
- /* a value for how long you want it to look around, it uses that */
- /* as a seed for the random number generator, and then generates */
- /* a random number to determine which way the Talker will look. */
- /* The random value will be either 0 or 1 because of the modulo */
- /* performed on it. This value is plugged in as the first */
- /* dimension of the array LookArray[][], and then a for loop */
- /* determines the 2nd dimension This walks you halfway through the */
- /* array, either to the left (number equals zero) or to the right */
- /* (number equals 1). It also calls GetEvents() in the middle of */
- /* this loop, to determine if the user wishes to blank the screen */
- /* (or restore it). */
- /*==================================================================*/
-
- VOID
- LookAround(waiter)
- int waiter;
- {
- int iterations,disimage,whichway;
- struct Image *newlook;
- srand(waiter);
- for(iterations = 0;iterations < waiter;iterations++)
- {
- whichway = rand() % 2;
- for(disimage = 0;disimage < 6;disimage++)
- {
- newlook = LookArray[whichway][disimage];
- WaitTOF();
- DrawImage(rast,newlook,7,15);
- if(disimage == 3)
- {
- Delay(((rand() % 50) + 1) * 2);
- };
-
- GetEvents();
- };
-
- if(!(rand() % 10))
- {
- Blink(2);
- };
-
- Delay(((rand() % 100) + 1) * 2);
- };
-
- }
-
-
- /*==============================================*/
- /* talk_to_me() -- */
- /*----------------------------------------------*/
- /* This routine does the actual output of */
- /* speech. It sets up the parameters of the */
- /* narrator_rb and mouth_rb structures to */
- /* output a 'sentence' of speech, as well as */
- /* the 'format' of that speech. It then gets */
- /* the data for the shape of the Talker's */
- /* mouth. That data is a value from 0 to 15 */
- /* for width, and a value from 0 to 15 for */
- /* height. */
- /*==============================================*/
-
- VOID
- talk_to_me(speech)
- char *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];
- };
-
- WaitTOF();
- DrawImage(rast,newmouth,7,15);
- }
-
- WaitIO(voice_io);
- Closemouth(mouth_io->height,mouth_io->width);
- if(!(rand() % 100))
- {
- LookAround(rand());
- };
-
- if(!(rand() % 10))
- {
- Blink(2);
- };
-
- }
-
- /*===============================================*/
- /* prep_to_talk() -- */
- /*-----------------------------------------------*/
- /* This routine initializes the system to */
- /* speak. It creates and initializes the audio */
- /* message port, and the 'video' message port, */
- /* the port we use to get the mouth shapes. */
- /*===============================================*/
-
- int
- 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() -- */
- /*------------------------------------------------------*/
- /* This routine opens all the libraries accessed */
- /* by the program. It bails out with an error message */
- /* if it cannot open any of the libraries. */
- /*======================================================*/
-
- VOID
- OpenLibs()
- {
- TranslatorBase = OpenLibrary("translator.library",REV);
- if(TranslatorBase == NULL)
- {
- CloseWind("couldn't open translator library");
- };
-
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
- if(IntuitionBase == NULL)
- {
- CloseWind("couldn't open Intuition library");
- };
-
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
- if(GfxBase == NULL)
- {
- CloseWind("couldn't open Graphics library");
- };
-
- }
-
-
-
- int
- Preserve_Colours(colourarray)
- UWORD colourarray[16];
- {
- long x;
- for(x = 0;x < 16; x++)
- {
- if((colourarray[x] = GetRGB4(Vprt->ColorMap,x)) < 0)
- {
- CloseWind("couldn't save old palette, sorry");
- };
- };
-
- return(1);
- }
-
- /*=========================================================*/
- /* restore_screen() -- */
- /*---------------------------------------------------------*/
- /* This routine restores the workbench's _original_ */
- /* palette in its entirety. Which means that the colors */
- /* used to draw the Talker will revert to their original */
- /* values. It does the restore by incrementing the value */
- /* of 16 color registers until each is equal to its */
- /* original value, preserved (via PreserveColours()) by */
- /* the array pointed at by old_palette. */
- /*=========================================================*/
-
- restore_screen(palette)
- UWORD palette[16];
- {
- long discolour,x,y;
- for(x = 0;x < 16;x++)
- {
- for(y = 0;y < 16;y++)
- {
- discolour = GetRGB4(Vprt->ColorMap,y);
- discolour += 273;
-
- if(discolour > (long)palette[y])
- {
- discolour = (long)palette[y];
- };
-
- SetRGB4(Vprt,y,((discolour&0xf00)>>8),(discolour&0xf0)>>4,
- (discolour&0x0f));
- };
-
- Delay(x);
- };
- }
-
- /*=================================================*/
- /* blank_screen() -- */
- /*-------------------------------------------------*/
- /* This routine fades the screen colours */
- /* to black. Note that this does not affect the */
- /* pointer, because the colour registers */
- /* themselves are unaffected (I think that's */
- /* why :). It works the opposite of restore_ */
- /* screen(), in that colors are decremented */
- /* til they reach zero. Note the majick number: */
- /* 273, which is 0x0111 hex, or 0000000100010001 */
- /* in binary. Since the r-g-b values are stored */
- /* with r having a value of 0-15 times 2^8th, g */
- /* having a value of 0-15 times 2^4th, and then */
- /* b having a value of 0-15 times 2^0th, in a */
- /* long value (top 4 bits are ignored), the */
- /* majick number will subtract 1 from each r-g-b */
- /* value. Subtracting one would only change the */
- /* b value, which will mess things up once you */
- /* do the shift (in SetRGB4()). */
- /*=================================================*/
-
- blank_screen()
- {
- long discolour,x,y;
- for(x = 0;x < 16;x++)
- {
- for(y = 0;y < 16;y++)
- {
- discolour = GetRGB4(Vprt->ColorMap,y);
- discolour -= (long)273;
-
- if(discolour < (long)0)
- {
- discolour = (long)0;
- };
-
- SetRGB4(Vprt,y,((discolour&0xf00)>>8),(discolour&0xf0)>>4,
- (discolour&0x0f));
- };
-
- Delay(x);
- };
- }
-
-
- /*====================================================*/
- /* OpenWind() -- */
- /*----------------------------------------------------*/
- /* This routine opens the window which contains */
- /* the Talker imagery. It also allocates the memory */
- /* for the array of values for the old palette, and */
- /* points old_palette at it. It then saves the old */
- /* colours (via Preserve_Colours()), and sets up a */
- /* new palette using the 5 colours in Palette[]. It */
- /* then draws the initial facial image. */
- /*====================================================*/
-
- VOID
- OpenWind()
- {
- if((TalkerWindow = (struct Window *)OpenWindow(&NewWindowStructure1)) == NULL)
- {
- CloseWind("Couldn't Open window");
- };
-
- Vprt = (struct ViewPort *)ViewPortAddress(TalkerWindow);
- if((old_palette = (UWORD *)AllocMem(sizeof(UWORD) * 16,MEMF_CLEAR)) != NULL)
- {
- if(Preserve_Colours(old_palette) == NULL)
- {
- CloseWind("Can't restore old palette");
- };
-
- NewPalette();
- };
- rast = TalkerWindow->RPort;
- WaitTOF();
- DrawImage(rast,&face0_Image,7,15);
-
- }
-
-
-
-
- /*===================================*/
- /* enter_text() -- */
- /*-----------------------------------*/
- /* This routine is called when */
- /* TalkerII is invoked without any */
- /* command line arguments. It */
- /* prompts the user for text to be */
- /* spoken, then speaks that text. */
- /*===================================*/
-
- VOID
- enter_text()
- {
- Delay(25);
- printf("enter string: ");
- gets(in_string);
- Delay(10);
- Blink(10L);
- changestring(in_string,strlen(in_string),out_string,1024L);
- Delay(5);
- Blink(5L);
- talk_to_me(out_string);
-
- }
-
-
- /*=========================================*/
- /* say_file() -- */
- /*-----------------------------------------*/
- /* This routine speaks the text in a */
- /* file. It opens the file given in the */
- /* command line argument(s), translates */
- /* the text, and outputs it. */
- /*=========================================*/
-
- VOID
- 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);
- };
-
- }
-
-
- /*========================================*/
- /* Howlong() -- */
- /*----------------------------------------*/
- /* This routine determines how long */
- /* the Talker should look around before */
- /* speaking the file. */
- /*========================================*/
-
- int
- Howlong(timerstring)
- char *timerstring;
- {
- int i;
- i = atoi((timerstring + 2));
- return(i);
- }
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- OpenLibs();
- OpenWind();
- prep_to_talk();
-
- if(!argv[1])
- {
- enter_text();
- }
- else if(strncmp(argv[1],"-l",2) == NULL)
- {
- LookAround(Howlong(argv[1]));
- Blink(5);
- if(argv[2])
- {
- say_file(argv[2]);
- };
- }
- else
- {
- Blink(5);
- say_file(argv[1]);
- };
-
- Delay(25);
- CloseWind(NULL);
- }
-