home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
120.lha
/
SpeechToy
/
SpToy.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-20
|
55KB
|
2,108 lines
/* SpeechToy.c Original by Dave Lucas, Enhancements by Rob Peck.
*
* o Can now read and write its own icon to get the defaults you set.
* o New menu item added to save current speech settings.
* o Can be started from WBENCH or CLI; if from CLI, can still
* read the icon file to get the default values.
*
* In the toolstrings, the data takes the form:
*
* SEX=1
* SEX=0
* for female (1) or male (0) voice.
*
* MODE=0
* MODE=1
* for expressive (0) or robotic (1) voice.
*
* FREQUENCY=20000
* numeric range from sampling frequency MIN to
* frequency MAX (see the audio.h file)
*
* RATE=150
* words per minute rate, see audio.h for range.
*
* VOLUME=64
* volume range from 0 to 64 (max).
*
* PITCH=224
* pitch value for speech, range see audio.h
*
* These values can be saved in the icon by using the save menu item
* --------------------------------------------------------------------
*
* WORDS=This is Amiga Speaking
* anything you want it to insert in the English Phrase area.
*
* TRANS=1
* means: Translate whatever words there are in the english.
*
* SPEAK=1
* means: Say it. When this is in the icon, it opens up talking.
*
* PHON=DHIHS IHZ AHMIY3GAH SPIY4KIHNX.
* This is the way you insert your own custom pronunciation.
* Note that it MUST be legal phonetics per the Speech docs.
*/
/* AREXX support:
*
* AREXX port is named SPEECHTOY, so that AREXX, which capitalizes
* things automatically, doesn't need quotes on the name to
* prevent it from capitalizing and not finding the port.
*
* To change any parameter, do EXACTLY as the toolstrings description
* shows... I use the SAME routines to parse the command that AREXX
* sends as are used to decode the icon's toolstrings.
*
* To send a command directly from a CLI interface, using AREXX
* support function, do this:
*
* rx "address speechtoy 'WORDS=Say this you turkey'"
* rx "address speechtoy 'TRANS=1'"
* rx "address speechtoy 'SPEAK=1'"
*/
/* CLI startup:
*
* To allow speechtoy to read its own icon, either CD to the
* directory where speechtoy is located, then: run speechtoy
* OR CD anywhere, then:
*
* run speechtoy <dir-where-icon-is-located>
*
* example:
*
* CD DF0:
* RUN df1:speechtoy df1:
*/
/* COMPILING: Lattice - compiles cleanly under Lattice 3.03 and 4.0
* if stack is set to 20000
*
* Manx 3.4b compiles cleanly, used for this object file.
*
* Original LUCAS comments (for most part) removed, see the FISH
* disk with original speechtoy to see what was there before.
* File got up over 65k source when I was through with it.
*
* Enhancements needed: Add capability to input PHONETIC strings.
* Strip it down into just a speech server
* with no windowing interface, but still read
* the icon file for the defaults.
*/
/* Written by David M Lucas. */
/* Enhanced by Rob Peck */
/* If you find somthing you don't like, fix it! Have fun! */
/* Send complaints to /dev/null. really. */
/* Thanks Amiga. */
#include "exec/types.h"
#include "exec/exec.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "devices/narrator.h"
#include "libraries/translator.h"
#include "exec/memory.h"
#include "libraries/dosextens.h"
#include "workbench/workbench.h"
#include "workbench/icon.h"
#include "workbench/startup.h"
#undef LIBRARY_VERSION
#undef LIBRARY_VERSION
#define LIBRARY_VERSION 0
/* forward declarations and external functions */
extern struct Library *OpenLibrary();
extern APTR AllocMem();
extern struct FileLock *CurrentDir();
extern struct DiskObject *GetDiskObject();
extern struct Task *FindTask();
extern struct Message *GetMsg();
extern long WriteIcon();
extern struct Window *OpenWindow();
extern void Delay();
char **toolsave; /* place to save the old pointer */
char *toolstrings[7]; /* a new set of toolstrings to use for writing */
struct MyDefaults {
int freq; int rate; int pitch;
int vol; int sex; int mode;
};
struct MyDefaults Defaults;
struct Library *IconBase;
extern struct DiskObject *ReadInfoFile();
void menumessage();
void gadgetmessage();
void DrawFace();
void freeimages();
/* #define DEBUG */
#define CONTWINDW 321
#define CONTWINDH 123
#define FACEWINDW 32
#define FACEWINDH 44
/* Pen numbers to draw gadget borders/images/text with */
#define REDP 3
#define BLKP 2
#define WHTP 1
#define BLUP 0
/* the length of the English and phonetic buffers */
#define ESTRINGSIZE 512
#define PSTRINGSIZE 768 /* phonemes are longer than english */
#define NUMPROPS 4
/* Ranges of proportional data */
#define RNGFREQ (MAXFREQ - MINFREQ) +1
#define RNGRATE (MAXRATE - MINRATE) +1
#define RNGPITCH (MAXPITCH - MINPITCH) +1
#define RNGVOL (MAXVOL - MINVOL) +1
#define DEFFREQ2 Defaults.freq
#define DEFRATE2 Defaults.rate
#define DEFPITCH2 Defaults.pitch
#define DEFVOL2 Defaults.vol
#define DEFSEX2 Defaults.sex
#define DEFMODE2 Defaults.mode
/* This section is part of the AREXX distribution disk,
* Copyright 1987, 1988 W. Hawes, reprinted by permission.
*/
/* This structure is used for passing arguments to external programs.
* It is usually passed as an "argstring", a pointer to the string buffer.
*/
struct RexxArg {
LONG ra_Size; /* total allocated length */
UWORD ra_Length; /* length of string */
UBYTE ra_Flags; /* attribute flags */
UBYTE ra_Hash; /* hash code */
BYTE ra_Buff[8]; /* buffer area */
}; /* size: 16 bytes (minimum) */
/* The RexxMsg structure is used for all communications with Rexx programs.
* It is an EXEC message with a parameter block appended.
*/
struct RexxMsg {
struct Message rm_Node; /* EXEC message structure */
APTR rm_TaskBlock; /* pointer to global structure */
APTR rm_LibBase; /* library base */
LONG rm_Action; /* command (action) code */
LONG rm_Result1; /* primary result (return code) */
LONG rm_Result2; /* secondary result */
STRPTR rm_Args[16]; /* argument block (ARG0-ARG15) */
struct MsgPort *rm_PassPort; /* forwarding port */
STRPTR rm_CommAddr; /* host address (port name) */
STRPTR rm_FileExt; /* file extension */
LONG rm_Stdin; /* input stream (filehandle) */
LONG rm_Stdout; /* output stream (filehandle) */
LONG rm_avail; /* future expansion */
}; /* size: 128 bytes */
/* end of selected portion of rexx/storage.h */
/* This is a dummy array, identical in form to the toolstrings array.
* Only one pointer (the first one) gets initialized to point to
* the argstring for the command that is transmitted by AREXX.
* The second pointer is NULL, ending what looks like a toolstrings
* array. This way we can use a single routine to obey both icon
* toolstring commands and AREXX commands.
*/
char *rexxstrings[2];
struct DiskObject *diskobj;
struct TextAttr TestFont = /* Needed for opening screen */
{
(STRPTR)"topaz.font",
TOPAZ_EIGHTY, 0, 0
};
/* Which audio channels to use */
UBYTE audio_chan[] = {3, 5, 10, 12};
/* Pointer to translator library vectors */
struct Library *TranslatorBase = 0;
struct MsgPort talk_port; /* Message port for the say's I/O */
struct MsgPort read_port; /* Message port for the say's I/O */
struct MsgPort *rexxport, *CreatePort(); /* added by RAP */
struct mouth_rb mouth_io; /* IO Request block, mouth flavor */
/* IO Request block, narrator flavor */
struct narrator_rb voice_io;
/* indicative of the Open return */
UBYTE NarratorOpenError = -1; /* not yet opened */
/* indicative of a Translations success */
UBYTE TranslatorError = 0;
USHORT i;
/* These are used to draw the eyes and mouth size relative */
USHORT MouthWMult;
USHORT EyesLeft;
USHORT MouthHMult;
USHORT EyesTop;
USHORT EyesBottom;
USHORT YMouthCenter; /* Pixels from top edge */
USHORT XMouthCenter; /* Pixels from left edge */
USHORT yaw;
USHORT LipWidth, LipHeight;
/* String Gadgets */
USHORT StrVectors[] = {
0, 0, 297, 0, 297, 14, 0, 14,
0, 1, 296, 1, 296, 13, 1, 13,
1, 1
};
struct Border StrBorder = {
-4, -3,
WHTP, BLUP, JAM1,
9,
StrVectors,
NULL
};
/* The same undo buffer is used for both string gadgets,
* this is sized to largest so that largest fits.
*/
UBYTE UndoBuffer[PSTRINGSIZE];
/* default text */
UBYTE EnglBuffer[ESTRINGSIZE] = "This is amiga speaking.";
struct StringInfo EnglInfo = {
EnglBuffer,
UndoBuffer,
0,
ESTRINGSIZE,
0, 0,
24,
0, 0, 0,
NULL,
0,
NULL
};
struct IntuiText EnglText = {
WHTP, BLUP,
JAM1,
0, -13,
&TestFont,
"English:",
NULL
};
struct Gadget EnglStrGadget = {
NULL,
11, 63, 290, 10,
GADGHCOMP,
RELVERIFY,
STRGADGET,
(APTR)&StrBorder,
NULL,
&EnglText,
0,
(APTR)&EnglInfo,
0,
NULL
};
/* Phonetic string gadget is where the program puts the
* translated string, necessating a call to RefreshGadgets(),
* and is where the user can type in Phonemes.
*/
UBYTE PhonBuffer[PSTRINGSIZE] =
"DHIHS IHZ AHMIY3GAH SPIY4KIHNX.";
struct StringInfo PhonInfo = {
PhonBuffer,
UndoBuffer,
0,
PSTRINGSIZE,
0, 0,
32,
0, 0, 0,
NULL,
NULL,
NULL
};
struct IntuiText PhonText = {
WHTP, BLUP,
JAM1,
0, -13,
&TestFont,
"Phonetics:",
NULL
};
struct Gadget PhonStrGadget = {
&EnglStrGadget,
11, 94, 290, 10,
GADGHCOMP,
RELVERIFY,
STRGADGET,
(APTR)&StrBorder,
NULL,
&PhonText,
0,
(APTR)&PhonInfo,
0,
NULL
};
/* Female Toggle (Highlight Image)
(Quasi mutual exclude with Male Toggle) */
struct Image FemaleImage = {
0, 0,
20, 10, 1,
NULL,
0x1, 0x0
};
struct Gadget FemaleGadget = {
&PhonStrGadget,
134, 34, 20, 10,
GADGIMAGE | GADGHCOMP,
/* Activation flags */
RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
BOOLGADGET,
(APTR)&FemaleImage,
NULL,
NULL,
0,
NULL,
0,
NULL
};
/* Male Toggle (Highlight Image)
(Quasi mutual Exclude with above) */
struct Image MaleImage = {
0, 0,
20, 10, 1,
NULL,
0x1, 0x0
};
struct Gadget MaleGadget = {
&FemaleGadget,
154, 34, 20, 10,
GADGIMAGE | GADGHCOMP | SELECTED,
/* Activation flags */
RELVERIFY | GADGIMMEDIATE | TOGGLESELECT | ACTIVATE,
BOOLGADGET,
(APTR)&MaleImage,
NULL,
NULL,
0,
NULL,
0,
NULL
};
/* This boolean toggle gadget has an
* alternate image that indicates
* selection. The image stays flipped
* until it gets another hit. (it toggles)
*/
/* Inflection Mode Toggle (AltImage) *************************/
struct Image HumanImage = {
0, 0,
40, 20, 1,
NULL,
0x1, 0x0
};
struct Image RobotImage = {
0, 0,
40, 20, 1,
NULL,
0x1, 0x0
};
struct Gadget ModeGadget = {
&MaleGadget,
134, 2, 40, 20,
GADGIMAGE | GADGHIMAGE,
RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
BOOLGADGET,
(APTR)&HumanImage,
(APTR)&RobotImage,
NULL,
0,
NULL,
0,
NULL
};
/* Face Toggle (image and text) */
struct IntuiText FaceIText = {
WHTP, BLUP,
JAM2,
4, 1,
&TestFont,
"Face",
NULL
};
struct Image FaceImage = {
0, 0,
40, 10, 1,
NULL,
0x1, 0x0
};
struct Gadget FaceGadget = {
&ModeGadget,
134, 23, 40, 10,
GADGIMAGE | GADGHCOMP,
RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
BOOLGADGET,
(APTR) &FaceImage,
NULL,
&FaceIText,
0,
NULL,
0,
NULL
};
/* Stop Hit (image and text) */
struct IntuiText StopIText = {
WHTP, BLUP,
JAM2,
4, 1,
&TestFont,
"Stop",
NULL
};
struct Image StopImage = {
0, 0,
40, 10, 1,
NULL,
0x1, 0x0
};
struct Gadget StopGadget = {
&FaceGadget,
134, 45, 40, 10,
GADGIMAGE | GADGHCOMP,
RELVERIFY | GADGIMMEDIATE,
BOOLGADGET,
(APTR) &StopImage,
NULL,
&StopIText,
0,
NULL,
0,
NULL
};
/* This is a hit (as opposed to toggle)
gadget that starts the translation.*/
/* Translate Hit (Highlight image) */
USHORT TransVectors[] = {
0, 0, 79, 0, 79, 13, 0, 13,
0, 1, 78, 1, 78, 12, 1, 12,
1, 1
};
struct Border TransBorder = {
-4, -3,
WHTP, BLUP, JAM1,
9,
TransVectors,
NULL
};
struct IntuiText TranslateIText = {
WHTP, BLUP,
JAM2,
0, 0,
&TestFont,
"Translate",
NULL
};
struct Gadget TranslateGadget = {
&StopGadget,
229, 48, 71, 8,
GADGHCOMP,
RELVERIFY | GADGIMMEDIATE,
BOOLGADGET,
(APTR)&TransBorder,
NULL,
&TranslateIText,
0,
NULL,
0,
NULL
};
/* This is a hit (as opposed to toggle) Starts the narration */
/* Speak Hit (Highlight Image) */
USHORT SpeakVectors[] = {
0, 0, 47, 0, 47, 13, 0, 13,
0, 1, 46, 1, 46, 12, 1, 12,
1, 1
};
struct Border SpeakBorder = {
-4, -3,
WHTP, BLUP, JAM1,
9,
SpeakVectors,
NULL
};
struct IntuiText SpeakIText = {
WHTP, BLUP,
JAM2,
0, 0,
&TestFont,
"Speak",
NULL
};
struct Gadget SpeakGadget = {
&TranslateGadget,
261, 79, 40, 8,
GADGHCOMP,
RELVERIFY | GADGIMMEDIATE,
BOOLGADGET,
(APTR)&SpeakBorder,
NULL,
&SpeakIText,
0,
NULL,
0,
NULL
};
/* Now the proportional gadgets. */
/* Proportional Gadgets **************************************/
/* The following variables are used to create proportional
* Gadgets. These variables will be filled in with copies of
* the generic Gadgetry below.
*/
SHORT PropCount = 0; /* index to next available Gadget */
struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
/* dummy AUTOKNOB Images are required */
struct Image PImages[NUMPROPS];
/* These get copies of TPropInfo */
struct PropInfo PInfos[NUMPROPS];
/* These get copies of TPropGadget */
struct Gadget Props[NUMPROPS];
struct IntuiText TPropText = {
WHTP, BLUP,
JAM1,
0, -10,
&TestFont,
NULL,
NULL
};
struct PropInfo TPropInfo = {
AUTOKNOB | FREEHORIZ,
0, 0,
0x1FFF, 0x1FFF,
0, 0, 0, 0, 0, 0
};
/* this is the template for the Gadget of a horizontal */
/* Proportional Gadget */
struct Gadget TPropGadget = {
&SpeakGadget,
7, 12, 115, 10,
GADGHCOMP | GADGIMAGE,
GADGIMMEDIATE | RELVERIFY,
PROPGADGET,
NULL,
NULL,
NULL,
0,
NULL,
0,
NULL
};
struct IntuitionBase *IntuitionBase = 0;
struct GfxBase *GfxBase = 0;
/* Only one menu. */
ULONG MenuNumber;
ULONG TheMenu;
ULONG TheItem;
struct IntuiText MenuItemText = {
BLUP,
WHTP,
JAM2,
0,
0,
&TestFont,
"About SpeechToy...",
NULL
};
struct IntuiText MenuItemText2 = {
BLUP,
WHTP,
JAM2,
0,
0,
&TestFont,
"Save Current Speech Settings",
NULL
};
struct MenuItem MyMenuItem2 = {
NULL,
0,
10,
250,
8,
ITEMTEXT | ITEMENABLED | HIGHCOMP,
0,
(APTR)&MenuItemText2,
NULL,
NULL,
NULL,
MENUNULL
};
struct MenuItem MyMenuItem = {
&MyMenuItem2,
0,
0,
250,
8,
ITEMTEXT | ITEMENABLED | HIGHCOMP,
0,
(APTR)&MenuItemText,
NULL,
NULL,
NULL,
MENUNULL
};
struct Menu MyMenu = {
NULL,
0,0,150,0,
MENUENABLED,
"SpeechToy Menu",
&MyMenuItem
};
struct IntuiText ReqText1 = {
BLUP,
WHTP,
JAM2,
5,
23,
&TestFont,
"Version 1.1 21 Dec, 1985",
NULL
};
struct IntuiText ReqText2 = {
BLUP,
WHTP,
JAM2,
5,
13,
&TestFont,
"Written by David M Lucas ",
&ReqText1
};
struct IntuiText ReqText3 = {
BLUP,
WHTP,
JAM2,
5,
3,
&TestFont,
"Enhancements by Rob Peck",
&ReqText2
};
struct IntuiText OKIText = {
BLUP, WHTP,
JAM2,
6, 3,
&TestFont,
"OK",
NULL
};
struct Requester *AboutRequester;
USHORT autoret;
struct Window *ControlWindow = NULL;
struct Window *FaceWindow = NULL;
struct IntuiMessage *MyIntuiMessage;
struct NewWindow NewControlWindow = {
00, 11,
CONTWINDW, CONTWINDH,
-1, -1,
GADGETUP | CLOSEWINDOW | MENUPICK,
WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
| GIMMEZEROZERO | ACTIVATE,
&Props[NUMPROPS-1],
NULL,
(UBYTE *)"SpeechToy",
NULL,
NULL,
20, 20,
CONTWINDW, CONTWINDH,
WBENCHSCREEN
};
struct NewWindow NewFaceWindow = {
CONTWINDW, 11,
FACEWINDW * 2, FACEWINDH,
-1, -1,
SIZEVERIFY | NEWSIZE | MENUPICK,
/* Flags (can be NULL) */
WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING
| SIZEBBOTTOM | GIMMEZEROZERO | ACTIVATE,
NULL,
NULL,
(UBYTE *)"Face",
NULL,
NULL,
FACEWINDW, FACEWINDH,
640, 200,
WBENCHSCREEN
};
USHORT FemaleIData[] = {
/* ---- - These nibbles matter to image. */
0x0000, 0x0000,
0x00F0, 0x0000,
0x0198, 0x0000,
0x030C, 0x0000,
0x0198, 0x0000,
0x00F0, 0x0000,
0x0060, 0x0000,
0x01F8, 0x0000,
0x0060, 0x0000,
0x0000, 0x0000
};
USHORT MaleIData[] = {
/* ---- - These nibbles matter to image. */
0x0000, 0x0000,
0x003E, 0x0000,
0x000E, 0x0000,
0x0036, 0x0000,
0x01E0, 0x0000,
0x0330, 0x0000,
0x0618, 0x0000,
0x0330, 0x0000,
0x01E0, 0x0000,
0x0000, 0x0000
};
USHORT HumanIData[] = {
/* ---- ---- -- These nibbles matter to image. */
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0007,0x9E00,0x0000,
0x0001,0x8600,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x2000,0x0000,
0x0000,0x1000,0x0000,
0x0000,0x0800,0x0000,
0x0000,0x7C00,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x7800,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000
};
USHORT RobotIData[] = {
/* ---- ---- -- These nibbles matter to image. */
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0007,0x9E00,0x0000,
0x0004,0x9200,0x0000,
0x0007,0x9E00,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0001,0xF800,0x0000,
0x0001,0x0800,0x0000,
0x0001,0xF800,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000
};
USHORT FaceIData[] = {
/* ---- ---- -- These nibbles matter to image. */
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000
};
USHORT StopIData[] = {
/* ---- ---- -- These nibbles matter to image. */
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000
};
USHORT *FemaleIData_chip = 0;
USHORT *MaleIData_chip = 0;
USHORT *HumanIData_chip = 0;
USHORT *RobotIData_chip = 0;
USHORT *FaceIData_chip = 0;
USHORT *StopIData_chip = 0;
LONG foundicon = FALSE; /* status variable */
LONG clistart = FALSE; /* status variable */
extern struct WBStartup *WBenchMsg;
char *iconname;
BPTR testlock, iconlock;
char namebuff[256]; /* where to store icon name if start from CLI */
char dirbuff[256]; /* store icon directory name if started from CLI */
ULONG parseresult; /* what happened when we parsed the strings */
ULONG ParseStrings();
void ParseRexxStrings();
void SetValues();
ULONG GetDefaults();
struct RexxMsg *myrexmsg;
/** start of code ***************************/
void
ModGadget(g)
struct Gadget *g;
{
USHORT i;
i = RemoveGadget(ControlWindow, g);
if(g == &ModeGadget)
ModeGadget.Flags ^= SELECTED;
if(g == &MaleGadget)
MaleGadget.Flags ^= SELECTED;
if(g == &FemaleGadget)
FemaleGadget.Flags ^= SELECTED;
AddGadget(ControlWindow, g, i);
RefreshGadgets(g, ControlWindow, NULL);
}
#define IssueTranslate() gadgetmessage(&TranslateGadget,ControlWindow)
#define IssueSpeak() gadgetmessage(&SpeakGadget,ControlWindow)
void
InitVoiceValues()
{
voice_io.sex = DEFSEX2;
voice_io.mode = DEFMODE2;
voice_io.rate = DEFRATE2;
voice_io.pitch = DEFPITCH2;
voice_io.volume = DEFVOL2;
voice_io.sampfreq = DEFFREQ2;
}
void
main(argc, argv)
int argc;
char **argv;
{
struct WBArg *wbarg;
USHORT i;
ULONG Signals; /* Wait() tells me which to look at */
ULONG MIClass; /* Save quickly, ReplyMsg() asap */
USHORT MICode; /* These hold my needed information */
APTR MIAddress;
iconlock = NULL;
iconname = NULL;
clistart = FALSE;
if(argc != 0) clistart = TRUE;
/* let MyCleanup know these signals not allocated yet */
talk_port.mp_SigBit = -1;
read_port.mp_SigBit = -1;
/* Open those libraries that the program uses directly */
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", LIBRARY_VERSION)) == 0) {
#ifdef DEBUG
if(clistart)
printf("Can't open the intuition library\n");
#endif
MyCleanup(1);
exit(FALSE);
}
if ((GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", LIBRARY_VERSION)) == 0) {
#ifdef DEBUG
if(clistart)
printf("Can't open the graphics library\n");
#endif
MyCleanup(2);
exit(FALSE);
}
if ((TranslatorBase = (struct Library *)
OpenLibrary("translator.library", LIBRARY_VERSION)) == 0) {
#ifdef DEBUG
if(clistart)
printf("Can't open the translator library\n");
#endif
MyCleanup(3);
exit(FALSE);
}
if ((IconBase = (struct Library *)
OpenLibrary("icon.library", 1)) == 0) {
#ifdef DEBUG
if(clistart)
printf("Can't open the icon library\n");
#endif
MyCleanup(4);
exit(FALSE);
}
/* Open the device */
if ((NarratorOpenError = OpenDevice("narrator.device", 0,
&voice_io, 0)) != 0) {
#ifdef DEBUG
if(clistart)
printf("Can't open the narrator device\n");
#endif
MyCleanup(5);
exit(FALSE);
}
/* **RAP */
if(argc == 0) /* opened from Workbench!!, Good! */
{
wbarg = WBenchMsg->sm_ArgList;
iconlock = wbarg->wa_Lock;
iconname = wbarg->wa_Name;
clistart = FALSE;
}
else /* open from CLI, see if currentdir has icon */
{
clistart = TRUE;
namebuff[0] = '\0';
strcat(namebuff, argv[0]);
strcat(namebuff, ".info");
/* Look in the CURRENT directory to see if file is there */
testlock = Lock(namebuff, ACCESS_READ);
/* To see if the icon file exists, we have to put .info
* onto the name of the file itself. BUT,
* when we read the icon, we do it without '.info' on it */
if(testlock == NULL)
{
/* the icon file is not in the CURRENT dir. */
iconlock = NULL;
iconname = NULL;
/* Now see if the user specified a directory
* in which the icon IS located; passed as argv[1] */
if(argc == 2)
{
dirbuff[0] = '\0';
strcat(dirbuff, argv[1]);
iconlock = Lock(dirbuff, ACCESS_READ);
/* If THAT directory exists, will pass it
* as a parameter IF we can also find that
* the icon is really there. More than one
* way to do this - could lock directory,
* go in there, then search for the file.
* Instead I chose to build directory path
* then try to lock the file. Same difference.
*/
if(iconlock != NULL) /* directory exists */
/* actually, this could be a
* file instead of a directory
* but who cares. */
{
namebuff[0] = '\0';
strcat(namebuff, argv[1]);
if(namebuff[strlen(argv[1])-1] != ':')
strcat(namebuff,"/");
strcat(namebuff, argv[0]);
/* This makes a complete path name to the icon */
/* WARNING - reusing variable named testlock here */
testlock = Lock(namebuff, ACCESS_READ);
if(testlock != NULL)
{
/* OK, the icon exists, lets hand it over
* (without the .info attached to it)
*/
namebuff[0] = '\0';
strcat(namebuff, argv[0]);
iconname = namebuff;
UnLock(testlock);
} /* end of if testlock (inner) */
} /* end of if iconlock */
} /* end of if argc == 2 */
} /* end of if testlock (outer) */
else /* else associated with if testlock (outer) */
{
/* testlock (first try) was non-NULL, icon IS in current dir */
/* OK, the icon exists in the current dir;
* lets hand it over
* (without the .info attached to it)
*/
namebuff[0] = '\0';
strcat(namebuff, argv[0]);
iconname = namebuff;
UnLock(testlock);
/* pass a lock on CURRENT dir. */
iconlock = Lock("",ACCESS_READ);
} /* end of else */
} /* end of else from test argc == 0 */
parseresult = GetDefaults(iconlock,iconname);
if(parseresult == FALSE)
/* added - read the icon toolstrings */
{
MyCleanup(6);
exit(FALSE);
}
#ifdef DEBUG
if(clistart)
printf("Got past getting the defaults\n");
#endif
/* This is where the proportional gadgets are set up, using
* the templates that were declared staticly.
*/
for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
PTexts[PropCount] = TPropText;
Props[PropCount] = TPropGadget;
PInfos[PropCount] = TPropInfo;
Props[PropCount].GadgetText = (struct IntuiText *)
&PTexts[PropCount];
Props[PropCount].GadgetRender = (APTR)
&PImages[PropCount];
Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
switch (PropCount) {
case 0:
PTexts[PropCount].IText = "Sample Freq:";
if (DEFFREQ2 == MAXFREQ)
PInfos[PropCount].HorizPot = 65535;
else
PInfos[PropCount].HorizPot = ((DEFFREQ2 - MINFREQ)
<< 16) / (MAXFREQ - MINFREQ);
break;
case 1:
PTexts[PropCount].IText = "Rate:";
Props[PropCount].TopEdge += 22;
Props[PropCount].NextGadget = &Props[PropCount-1];
if (DEFRATE2 == MAXRATE)
PInfos[PropCount].HorizPot = 65535;
else
PInfos[PropCount].HorizPot = ((DEFRATE2 - MINRATE)
<< 16) / (MAXRATE - MINRATE);
break;
case 2:
PTexts[PropCount].IText = "Pitch:";
Props[PropCount].LeftEdge += 183;
Props[PropCount].NextGadget = &Props[PropCount-1];
if (DEFPITCH2 == MAXPITCH)
PInfos[PropCount].HorizPot = 65535;
else
PInfos[PropCount].HorizPot = ((DEFPITCH2-MINPITCH)
<< 16) / (MAXPITCH - MINPITCH);
break;
case 3:
PTexts[PropCount].IText = "Volume:";
Props[PropCount].TopEdge += 22;
Props[PropCount].LeftEdge += 183;
Props[PropCount].NextGadget = &Props[PropCount-1];
if (DEFVOL2 == MAXVOL)
PInfos[PropCount].HorizPot = 65535;
else
PInfos[PropCount].HorizPot = ((DEFVOL2 - MINVOL)
<< 16) / (MAXVOL - MINVOL);
break;
}
}
/* Now allocate memory accessable by the chips for images */
if (InitImages() != TRUE) {
#ifdef DEBUG
if(clistart)
printf("Couldn't Allocate Images in chip memory.\n");
#endif
MyCleanup(7);
exit(FALSE);
}
/* Set up the write port, allocate the signal, */
/* and the message */
talk_port.mp_Node.ln_Type = NT_MSGPORT;
talk_port.mp_Flags = 0;
if ((talk_port.mp_SigBit = AllocSignal(-1)) == -1) {
#ifdef DEBUG
if(clistart)
printf("Couldn't Allocate talk Signal bit\n");
#endif
MyCleanup(8);
exit(FALSE);
}
talk_port.mp_SigTask = (struct Task *) FindTask((char *)
NULL);
NewList(&talk_port.mp_MsgList);
/* Set up the read port, allocate the signal, */
/* and the message */
read_port.mp_Node.ln_Type = NT_MSGPORT;
read_port.mp_Flags = 0;
if ((read_port.mp_SigBit = AllocSignal(-1)) == -1) {
#ifdef DEBUG
if(clistart)
printf("Couldn't Allocate read Signal bit\n");
#endif
MyCleanup(9);
exit(FALSE);
}
read_port.mp_SigTask = (struct Task *)
FindTask((char *) NULL);
NewList(&read_port.mp_MsgList);
/* Set up the write channel information */
/* **RAP */
rexxport = CreatePort("SPEECHTOY",0);
if(rexxport == NULL)
{
#ifdef DEBUG
if(clistart)
printf("Couldn't create rexxport\n");
#endif
MyCleanup(10);
exit(FALSE);
}
InitVoiceValues();
voice_io.ch_masks = (audio_chan);
voice_io.nm_masks = sizeof(audio_chan);
voice_io.mouths = 0;
voice_io.message.io_Message.mn_ReplyPort = &talk_port;
voice_io.message.io_Command = CMD_WRITE;
voice_io.message.io_Offset = 0;
voice_io.message.io_Data = (APTR)PhonBuffer;
voice_io.message.io_Message.mn_Length = sizeof(voice_io);
/* Set up the read channel information */
mouth_io.voice = voice_io;
mouth_io.width = 0;
mouth_io.height = 0;
mouth_io.voice.message.io_Message.mn_ReplyPort = &read_port;
mouth_io.voice.message.io_Command = CMD_READ;
mouth_io.voice.message.io_Error = 0;
if (FaceWindow == NULL) {
if ((ControlWindow = (struct Window *)OpenWindow
(&NewControlWindow)) == NULL) {
#ifdef DEBUG
if(clistart)
printf("Couldn't open the control window.\n");
#endif
MyCleanup(11);
exit(FALSE);
}
}
/* fill background of window */
SetAPen(ControlWindow->RPort, BLKP);
RectFill(ControlWindow->RPort,0,0,
ControlWindow->GZZWidth, ControlWindow->GZZHeight);
RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
SetMenuStrip(ControlWindow, &MyMenu);
SetValues();
/* !!! Ah, But what if FaceWindow's not been opened? */
for (;;) { /* ever wait for a signal and process it */
/* wait lets the rest of the system run, */
/* this program sleeps */
Signals = Wait((1 << ControlWindow->UserPort->mp_SigBit)
| (1 << FaceWindow->UserPort->mp_SigBit)
| (1 << voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)
| (1 << mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)
| (1 << rexxport->mp_SigBit));
/* now check to see to what we owe the intrusion */
if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
/* Process the Intuition message */
while (MyIntuiMessage=(struct IntuiMessage *)
GetMsg(ControlWindow->UserPort)) {
/* Get all the needed info and give message back */
MIClass = MyIntuiMessage->Class;
MICode = MyIntuiMessage->Code;
MIAddress = MyIntuiMessage->IAddress;
ReplyMsg(MyIntuiMessage);
/* Now, what was it you wanted? */
switch (MIClass) {
case MENUPICK:
menumessage(MICode, ControlWindow);
break;
case GADGETUP: /* reply, then process */
gadgetmessage(MIAddress, ControlWindow);
break;
case CLOSEWINDOW: /* bye! */
while (MyIntuiMessage = (struct
IntuiMessage *) GetMsg(
ControlWindow->UserPort))
ReplyMsg(MyIntuiMessage);
MyCleanup(12);
exit(TRUE);
break;
default:
#ifdef DEBUG
if(clistart)
printf("Unhandled Message Received.\n");
#endif
break;
} /* switch */
} /* while */
} /* if */
/* Woken by intuition for FaceWindow*/
if (Signals & (1<< FaceWindow->UserPort->mp_SigBit)) {
/* Process the Intuition message */
while (MyIntuiMessage=(struct IntuiMessage *)
GetMsg(FaceWindow->UserPort)) {
switch (MyIntuiMessage->Class) {
case SIZEVERIFY:
ReplyMsg(MyIntuiMessage);
break;
case MENUPICK:
menumessage(MyIntuiMessage->Code,FaceWindow);
ReplyMsg(MyIntuiMessage);
break;
case NEWSIZE: /* Don't reply until processed */
DrawFace();
ReplyMsg(MyIntuiMessage);
break;
default:
#ifdef DEBUG
if(clistart)
printf("Unhandled Message Received.\n");
#endif
ReplyMsg(MyIntuiMessage);
break;
} /* switch */
} /* while */
} /* if */
/* A voice SendIO (Write) has completed */
if (Signals & (1 <<
voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)) {
/* Was it Sucessful? filter out the abort error */
if (voice_io.message.io_Error == -2)
voice_io.message.io_Error = 0;
if (voice_io.message.io_Error != 0) {
#ifdef DEBUG
if(clistart)
printf("Narrator won't. (%ld)\n",
voice_io.message.io_Error);
#endif
/* flash this screen */
DisplayBeep(ControlWindow->WScreen);
/* let user see where phoneme string was bad. */
i = RemoveGadget(ControlWindow, &PhonStrGadget);
/* move the cursor to the error char */
PhonInfo.BufferPos = voice_io.message.io_Actual -1;
/* assure cursor (error point) is shown in gad. */
/* within 29 (number of chars shown) of front */
if (voice_io.message.io_Actual < 29)
PhonInfo.DispPos = 0;
/* within 29 of end */
else if ((voice_io.message.io_Length -
voice_io.message.io_Actual) < 29)
PhonInfo.DispPos = voice_io.message.io_Length
- 29;
else
PhonInfo.DispPos = voice_io.message.io_Actual
- 15;
AddGadget(ControlWindow, &PhonStrGadget, i);
RefreshGadgets(&PhonStrGadget, ControlWindow,
NULL);
voice_io.message.io_Error = 0;
}
/* SpeakGadget.Flags ^= GADGDISABLED;
FaceGadget.Flags ^= GADGDISABLED;
*/
OnGadget(&SpeakGadget, ControlWindow, NULL);
OnGadget(&FaceGadget, ControlWindow, NULL);
}
/* A mouth DoIO (Read) has completed */
if (Signals & (1 <<
mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)) {
WaitBOVP(&FaceWindow->WScreen->ViewPort);
SetAPen(FaceWindow->RPort, WHTP);
RectFill(FaceWindow->RPort, 0, EyesBottom,
FaceWindow->GZZWidth, FaceWindow->GZZHeight);
if (MouthWMult == 0)
LipWidth = mouth_io.width >> 1;
else
LipWidth = mouth_io.width * MouthWMult;
if (MouthHMult == 0)
LipHeight = mouth_io.height >> 1;
else
LipHeight = mouth_io.height * (MouthHMult);
SetAPen(FaceWindow->RPort, REDP);
Move(FaceWindow->RPort,
XMouthCenter - LipWidth, YMouthCenter);
Draw(FaceWindow->RPort,
XMouthCenter, YMouthCenter - LipHeight);
Draw(FaceWindow->RPort,
XMouthCenter + LipWidth, YMouthCenter);
Draw(FaceWindow->RPort,
XMouthCenter, YMouthCenter + LipHeight);
Draw(FaceWindow->RPort,
XMouthCenter - LipWidth, YMouthCenter);
/* the narrator will give an error when the */
/* write has completed and I've tried to read */
/* so I stop trying when that happens */
if (mouth_io.voice.message.io_Error == 0)
SendIO(&mouth_io);
}
/* a REXX message has arrived */
if(Signals & 1 << rexxport->mp_SigBit)
{
while(myrexmsg = (struct RexxMsg *)GetMsg(rexxport))
ParseRexxStrings(myrexmsg);
}
} /* for */
} /* main */
/* a MENUPICK has been received, this
* routine takes the appropriate action
*/
void
menumessage(code, w)
USHORT code;
struct Window *w;
{
int freq, rate, pitch, vol, sex, mode;
char toolbuff[560]; /* 20 characters times 7 strings (7th is null) */
int i,j;
int success;
j=0;
for(i=0; i<7; i++)
{
toolstrings[i] = &toolbuff[j];
j += 20;
}
switch (MENUNUM(code)) {
case 0:
switch (ITEMNUM(code)) {
case 0:
AutoRequest(w, &ReqText3, NULL,
&OKIText, 0, 0, 280, 47);
break;
case 1:
freq = voice_io.sampfreq;
sprintf(toolstrings[0],"FREQUENCY=%ld",freq);
rate = voice_io.rate;
sprintf(toolstrings[1],"RATE=%ld",rate);
pitch = voice_io.pitch;
sprintf(toolstrings[2],"PITCH=%ld",pitch);
vol = voice_io.volume;
sprintf(toolstrings[3],"VOLUME=%ld",vol);
mode = voice_io.mode;
sprintf(toolstrings[4],"MODE=%ld",mode);
sex = voice_io.sex;
sprintf(toolstrings[5],"SEX=%ld",sex);
toolstrings[6] = NULL;
/* NULL value terminates it */
toolsave = diskobj->do_ToolTypes; /* save pointer */
diskobj->do_ToolTypes = &toolstrings[0];
if(foundicon)
{
success = WriteIcon(iconlock, iconname, diskobj);
}
diskobj->do_ToolTypes = toolsave; /* restore it */
/* We restore it because the icon library routines
* have allocated a block of memory associated with
* this material and we have to give it all back at exit.
*/
break;
default:
break;
}
break;
}
}
/* Read the icon and if all of the tool strings are present, then
* use them to set the default values for the speechtoy. Return
* values are as follows: decimal 63 if all defaults are set, less
* than 63 if at least one default is messed up. Causes system to
* establish defaults on its own. ... Rob Peck
*/
extern struct DiskObject *ReadIcon();
ULONG
GetDefaults(idir, iname)
struct FileLock *idir;
char *iname;
{
char *FindToolType();
char **ts;
/* Establish all defaults on entry, then change them
* if new values are found in the toolstrings.
*/
DEFSEX2 = DEFSEX;
DEFMODE2 = DEFMODE;
DEFPITCH2 = DEFPITCH;
DEFVOL2 = DEFVOL;
DEFFREQ2 = DEFFREQ;
DEFRATE2 = DEFRATE;
if(iname == NULL)
{
/* Started from the CLI, and NO ICON FILE
* in the current directory. So this is IT! */
/* This is a successful initialization */
return(TRUE);
}
#ifdef DEBUG
if(clistart)
printf("Going to try to readicon now\n");
#endif
diskobj = ReadIcon(idir, iname); /* diskobj is a global */
#ifdef DEBUG
if(clistart)
printf("Returned from readicon with diskobj value: %lx\n",diskobj);
#endif
if(diskobj == NULL) return(FALSE);
foundicon = TRUE; /* another global */
ts = diskobj->do_ToolTypes; /* get ptr to tool strings */
return(ParseStrings(ts));
}
/* This routine is separated from the others to allow a command
* from the outside world to affect the defaults. Returns a mask
* with 1 bits in the position indicating which parameters it
* recognized and whose values it has set. That is, a 1 in bit
* position 0 means parameter 0 was recognized, a 1 in bit position
* 1 means it set parameter 1 and so on. ... Rob Peck
*
* Anything out of bounds results in setting things to their defaults.
*/
ULONG
ParseStrings(ts)
char **ts;
{
ULONG rtnval;
char *value;
int temp;
rtnval = 0;
value = FindToolType(ts, "FREQUENCY");
if(value)
{
DEFFREQ2 = atoi(value);
if(DEFFREQ2 < MINFREQ || DEFFREQ2 > MAXFREQ)
DEFFREQ2 = DEFFREQ;
rtnval |= 0x1;
}
value = FindToolType(ts, "RATE");
if(value)
{
DEFRATE2 = atoi(value);
if(DEFRATE2 < MINRATE || DEFRATE2 > MAXRATE)
DEFRATE2 = DEFRATE;
rtnval |=0x02;
}
value = FindToolType(ts, "PITCH");
if(value)
{
DEFPITCH2 = atoi(value);
if(DEFPITCH2 < MINPITCH || DEFPITCH2 > MAXPITCH)
DEFPITCH2 = DEFPITCH;
rtnval |=0x04;
}
value = FindToolType(ts, "VOLUME");
if(value)
{
DEFVOL2 = atoi(value);
if(DEFVOL2 < MINVOL || DEFVOL2 > MAXVOL)
DEFVOL2 = DEFVOL;
rtnval |=0x08;
}
value = FindToolType(ts, "MODE");
if(value)
{
temp = atoi(value);
if(DEFMODE2 < 0 || DEFMODE2 > 1)
DEFMODE2 = DEFMODE;
if(temp != DEFMODE2)
{
/* time for a change in the display */
rtnval |= 0x10;
DEFMODE2 = temp;
}
}
value = FindToolType(ts, "SEX");
if(value)
{
temp = atoi(value);
if(DEFSEX2 < 0 || DEFSEX2 > 1)
DEFSEX2 = DEFSEX;
if(temp != DEFSEX2)
{
/* time for a change in the display */
rtnval |= 0x20;
DEFSEX2 = temp;
}
}
/* for AREXX support, accept a string to be said */
value = FindToolType(ts, "WORDS");
if(value)
{
EnglBuffer[0] = '\0';
strncat(EnglBuffer, value, ESTRINGSIZE);
rtnval |= 0x40;
}
value = FindToolType(ts, "TRANS");
if(value)
{
rtnval |= 0x80;
}
value = FindToolType(ts, "SPEAK");
if(value)
{
rtnval |= 0x100;
}
value = FindToolType(ts, "PHON");
if(value)
{
PhonBuffer[0] = '\0';
strncat(PhonBuffer, value, PSTRINGSIZE);
rtnval |= 0x200;
}
return(rtnval);
}
/* Maximum total length of string passed from REXX is 1024 bytes,
* including the terminating null (my own arbitrary limit, from
* the declaration of rexxstrings[maxstringsize] in the global area.
*/
/* Only one argument, ARG0, is accepted by this program,
* passed with a command (RXCOMM) from AREXX.
*/
void
ParseRexxStrings(rxmsg)
struct RexxMsg *rxmsg;
{
/* parseresult is a global ULONG */
rexxstrings[0] = (char *)rxmsg->rm_Args[0];
rexxstrings[1] = NULL;
parseresult = ParseStrings(&rexxstrings[0]);
SetValues();
ReplyMsg(rxmsg);
}
/* a GADGETUP has been received, this
* routine takes the appropriate action
*/
void
gadgetmessage(address, w)
APTR address;
struct Window *w;
{
USHORT i;
long PropRange;
if (address == (APTR)&ModeGadget) {
if (ModeGadget.Flags & SELECTED)
DEFMODE2 = ROBOTICF0;
else
DEFMODE2 = NATURALF0;
}
else if (address == (APTR)&FaceGadget) {
/* tell the write that reads will be forthcomming */
if (FaceGadget.Flags & SELECTED) {
voice_io.mouths = 1;
if ((FaceWindow = (struct Window *)
OpenWindow(&NewFaceWindow)) == NULL) {
#ifdef DEBUG
if(clistart)
printf("Couldn't open the face window.\n");
#endif
MyCleanup(13);
exit(FALSE);
}
SetMenuStrip(FaceWindow, &MyMenu);
DrawFace();
}
else { /* FaceGadget de-SELECTed */
voice_io.mouths = 0;
NewFaceWindow.LeftEdge = FaceWindow->LeftEdge;
NewFaceWindow.TopEdge = FaceWindow->TopEdge;
NewFaceWindow.Width = FaceWindow->Width;
NewFaceWindow.Height = FaceWindow->Height;
CloseWindow(FaceWindow);
FaceWindow = NULL;
}
}
else if (address == (APTR)&StopGadget) {
AbortIO(&voice_io);
voice_io.message.io_Error = 0;
mouth_io.voice.message.io_Error = 0;
}
/* Since this program changes a flag that intuition expects
* only the user to change (SELECTED bit), this program has
* to remove, then change, then add this gadget. Then by
* passing the address of this gadget to RefreshGadgets(),
* only the gadgets from here to the start of the list will
* be refreshed, which minimizes the visible flash that
* RefreshGadgets() can introduce.
* If one of the two gadgets (female/male) is hit, toggle
* the selection of the other gadget (since the gadget hit
* was toggled by intuition when it was hit).
*/
else if (address == (APTR)&FemaleGadget) {
if (FemaleGadget.Flags & SELECTED)
DEFSEX2 = FEMALE;
else
DEFSEX2 = MALE;
ModGadget(&MaleGadget);
}
else if (address == (APTR)&MaleGadget) {
if (MaleGadget.Flags & SELECTED)
DEFSEX2 = MALE;
else
DEFSEX2 = FEMALE;
ModGadget(&FemaleGadget);
}
/* Since the program changes the contents of the string
* gadgets' buffer and it's size, which is something else
* intuition doesn't expect a program (as opposed to the
* user) to do. The program must remove, then change, then
* add this gadget, and then by passing the address of this
* gadget to RefreshGadgets(), only the gadgets from here
* to the start of the list will be refreshed, which
* minimizes the visible flash that RefreshGadgets() can
* introduce.
*/
else if (address == (APTR)&TranslateGadget) {
i = RemoveGadget(ControlWindow, &PhonStrGadget);
if ((TranslatorError = Translate((APTR)EnglBuffer,
EnglInfo.NumChars, (APTR)PhonBuffer, PhonInfo.MaxChars))
!= 0) {
#ifdef DEBUG
if(clistart)
printf("Translator won't. (%lx)\n",TranslatorError);
#endif
/* flash this screen */
DisplayBeep(ControlWindow->WScreen);
}
/* Hey! NumChars includes the terminating NULL. */
/* This must be done. */
PhonInfo.NumChars = voice_io.message.io_Length + 1;
if (PhonInfo.DispPos > voice_io.message.io_Length)
PhonInfo.DispPos = voice_io.message.io_Length;
AddGadget(ControlWindow, &PhonStrGadget, i);
RefreshGadgets(&PhonStrGadget, ControlWindow, NULL);
}
else if (address == (APTR)&SpeakGadget) {
/* SpeakGadget.Flags ^= GADGDISABLED;
FaceGadget.Flags ^= GADGDISABLED;
*/
OffGadget(&SpeakGadget, ControlWindow, NULL);
OffGadget(&FaceGadget, ControlWindow, NULL);
voice_io.message.io_Length = strlen(PhonBuffer);
InitVoiceValues(); /* Rob Peck - before any new
* speech output, copy the
* current values into the
* I/O request block
*/
SendIO(&voice_io);
if (voice_io.mouths == 1) {
mouth_io.voice.message.io_Error = 0;
SendIO(&mouth_io);
}
}
else if (address == (APTR)&EnglStrGadget); /* do nothing */
else if (address == (APTR)&PhonStrGadget); /* do nothing */
else if (address == (APTR)&Props[0]) {
PropRange = RNGFREQ;
DEFFREQ2 = (( (PInfos[0].HorizPot >> 1)
* PropRange) >> 15) + MINFREQ;
#ifdef DEBUG
if(clistart)
printf("Freq. = %ld\n", DEFFREQ2);
#endif
}
else if (address == (APTR)&Props[1]) {
PropRange = RNGRATE;
DEFRATE2 = (((PInfos[1].HorizPot >> 1)
* PropRange) >> 15) + MINRATE;
#ifdef DEBUG
if(clistart)
printf("Rate = %ld\n", DEFRATE2);
#endif
}
else if (address == (APTR)&Props[2]) {
PropRange = RNGPITCH;
DEFPITCH2 = (((PInfos[2].HorizPot >> 1)
* PropRange) >> 15) + MINPITCH;
#ifdef DEBUG
if(clistart)
printf("Pitch = %ld\n", DEFPITCH2);
#endif
}
else if (address == (APTR)&Props[3]) {
PropRange = RNGVOL;
DEFVOL2 = (((PInfos[3].HorizPot >> 1)
* PropRange) >> 15) + MINVOL;
#ifdef DEBUG
if(clistart)
printf("Vol. = %ld\n", DEFVOL2);
#endif
}
#ifdef DEBUG
else if (clistart) printf("Unhandled gadget up received!\n");
#endif
}
/* This calculates variables used to draw the mouth
* and eyes, as well as redrawing the face.
* Proportionality makes it very wierd, but it's
* wierder if you don't use a GimmeZeroZero window
* and GZZWidth/GZZHeight.
*/
void
DrawFace() {
XMouthCenter = FaceWindow->GZZWidth >> 1;
/* set left edge of left eye */
EyesLeft = FaceWindow->GZZWidth >> 2;
/* multiplier for mouth width */
MouthWMult = FaceWindow->GZZWidth >> 6;
EyesTop = (FaceWindow->GZZHeight >> 2)
- (FaceWindow->GZZHeight >> 4);
EyesBottom = EyesTop + (FaceWindow->GZZHeight >> 3) + 1;
yaw = FaceWindow->GZZHeight - EyesBottom;
YMouthCenter = ((yaw >> 1) + EyesBottom);
MouthHMult = yaw >> 5;
/* Set pen to White */
SetAPen(FaceWindow->RPort, WHTP);
RectFill(FaceWindow->RPort, 0, 0,
FaceWindow->GZZWidth, FaceWindow->GZZHeight);
/* Set pen to Blue */
SetAPen(FaceWindow->RPort, BLUP);
RectFill(FaceWindow->RPort,
EyesLeft, EyesTop,
EyesLeft + (FaceWindow->GZZWidth >> 3),
EyesTop + (FaceWindow->GZZHeight >> 3));
RectFill(FaceWindow->RPort,
(FaceWindow->GZZWidth >> 1)
+ (FaceWindow->GZZWidth >> 3),
EyesTop,
(FaceWindow->GZZWidth >> 1)
+ (FaceWindow->GZZWidth >> 3) /* two >> 3, not one >> 2 */
+ (FaceWindow->GZZWidth >> 3),/* so eyes are same width */
EyesTop + (FaceWindow->GZZHeight >> 3));
SetAPen(FaceWindow->RPort, REDP); /* Set pen to Red */
Move(FaceWindow->RPort,
XMouthCenter - (FaceWindow->GZZWidth >> 3), YMouthCenter);
Draw(FaceWindow->RPort,
XMouthCenter + (FaceWindow->GZZWidth >> 3), YMouthCenter);
}
/* Deallocate any memory, and close all of the
* windows/screens/devices/libraries in reverse order to
* make things work smoothly. And be sure to check
* that the open/allocation was successful before
* closing/deallocating.
*/
MyCleanup(n)
SHORT n;
{
#ifdef DEBUG
if(clistart)
printf("Exit reason = %ld\n",n);
#endif
if (clistart)
if(iconlock) UnLock(iconlock); /* Rob Peck */
if (rexxport)
DeletePort(rexxport); /* RAP */
if (diskobj != 0)
FreeDiskObject(diskobj);
if (read_port.mp_SigBit != -1)
FreeSignal(read_port.mp_SigBit);
if (talk_port.mp_SigBit != -1)
FreeSignal(talk_port.mp_SigBit);
if (FaceWindow != NULL)
CloseWindow(FaceWindow);
if (ControlWindow != NULL)
CloseWindow(ControlWindow);
/* freeimages makes sure image allocation was successful */
freeimages();
if (NarratorOpenError == 0)
CloseDevice(&voice_io);
if (TranslatorBase != 0)
CloseLibrary(TranslatorBase);
if (GfxBase != 0)
CloseLibrary(GfxBase);
if (IntuitionBase != 0)
CloseLibrary(IntuitionBase);
if (IconBase != 0)
CloseLibrary(IconBase);
return(0);
}
/* Allocate chip memory for gadget images, and set the
* pointers in the corresponding image structures to point
* to these images. This must be done because the program
* could be loaded into expansion memory (off the side of
* the box), which the custom chips cannot access.
* And images must be in chip ram (that's memory that the
* custom chips can access, the internal 512K).
*/
InitImages()
{
/* the images were staticly initialized above main */
extern USHORT *FemaleIData_chip;
extern USHORT *MaleIData_chip;
extern USHORT *HumanIData_chip;
extern USHORT *RobotIData_chip;
extern USHORT *FaceIData_chip;
extern USHORT *StopIData_chip;
int i;
/* Allocate them all, stop and return false on failure */
if ((FemaleIData_chip = (USHORT *)
AllocMem(sizeof(FemaleIData),MEMF_CHIP)) == 0)
return(FALSE);
if ((MaleIData_chip = (USHORT *)
AllocMem(sizeof(MaleIData),MEMF_CHIP)) == 0)
return(FALSE);
if ((HumanIData_chip = (USHORT *)
AllocMem(sizeof(HumanIData),MEMF_CHIP)) == 0)
return(FALSE);
if ((RobotIData_chip = (USHORT *)
AllocMem(sizeof(RobotIData),MEMF_CHIP)) == 0)
return(FALSE);
if ((FaceIData_chip = (USHORT *)
AllocMem(sizeof(FaceIData),MEMF_CHIP)) == 0)
return(FALSE);
if ((StopIData_chip = (USHORT *)
AllocMem(sizeof(StopIData),MEMF_CHIP)) == 0)
return(FALSE);
for (i=0; i<20; i++)
FemaleIData_chip[i] = FemaleIData[i];
for (i=0; i<20; i++)
MaleIData_chip[i] = MaleIData[i];
for (i=0; i<60; i++)
HumanIData_chip[i] = HumanIData[i];
for (i=0; i<60; i++)
RobotIData_chip[i] = RobotIData[i];
for (i=0; i<30; i++)
FaceIData_chip[i] = FaceIData[i];
for (i=0; i<30; i++)
StopIData_chip[i] = StopIData[i];
FemaleImage.ImageData = FemaleIData_chip;
MaleImage.ImageData = MaleIData_chip;
HumanImage.ImageData = HumanIData_chip;
RobotImage.ImageData = RobotIData_chip;
FaceImage.ImageData = FaceIData_chip;
StopImage.ImageData = StopIData_chip;
return(TRUE);
}
/* Deallocate the memory that was used for images,
* See initimages for more details.
*/
void
freeimages()
{
/* the images were staticly initialized above main */
extern USHORT *FemaleIData_chip;
extern USHORT *MaleIData_chip;
extern USHORT *HumanIData_chip;
extern USHORT *RobotIData_chip;
extern USHORT *FaceIData_chip;
extern USHORT *StopIData_chip;
/* Deallocate only if the pointer is really there. */
if (RobotIData_chip != 0)
FreeMem(RobotIData_chip, sizeof(RobotIData));
if (HumanIData_chip != 0)
FreeMem(HumanIData_chip, sizeof(HumanIData));
if (MaleIData_chip != 0)
FreeMem(MaleIData_chip, sizeof(MaleIData));
if (FemaleIData_chip != 0)
FreeMem(FemaleIData_chip, sizeof(FemaleIData));
if (FaceIData_chip != 0)
FreeMem(FaceIData_chip, sizeof(FaceIData));
if (StopIData_chip != 0)
FreeMem(StopIData_chip, sizeof(StopIData));
}
/* ReadIcon:
* input = lock on the directory where the icon resides
* (program only gets this if called from WBench)
* and name of the .info file to be read.
* returns a pointer to a DiskObject structure if success,
* or NULL if not.
*/
struct DiskObject *
ReadIcon(icondirlock, iconfilename)
struct FileLock *icondirlock; /* lock on dir where icon is located */
char *iconfilename; /* name of this icon */
{
struct FileLock *olddir;
struct DiskObject *dobj;
dobj = NULL; /* assume failure */
olddir = CurrentDir(icondirlock); /* Move where icon is */
dobj = GetDiskObject(iconfilename); /* Only then can read it */
CurrentDir(olddir); /* Return to original dir */
return(dobj); /* If successful, returns a pointer
* to a memory area allocated by
* the icon.library
*/
/* ... REMEMBER to FreeDiskObject when done with it. */
}
/* WriteIcon */
/* input = lock on the directory where to write and name of
* file to write, and a disk object pointer,
*
* output = nonzero if ok, but if value over 100, then error.
*/
long
WriteIcon(icondirlock, iconfilename, dobj)
struct FileLock *icondirlock;
char *iconfilename;
struct DiskObject *dobj;
{
struct FileLock *olddir;
long status;
status = -1; /* assume failure */
olddir = CurrentDir(icondirlock); /* move to target directory */
status = PutDiskObject(iconfilename, dobj);
if(status == 0)
{
status = IoErr(); /* let AmigaDOS say why if possible */
}
CurrentDir(olddir);
return(status);
}
void
SetValues()
{
USHORT i;
if(parseresult & 0x20)
{
if(
((DEFSEX2 == 1) && ((FemaleGadget.Flags & SELECTED) == 0)) ||
((DEFSEX2 == 0) && ((MaleGadget.Flags & SELECTED) == 0))
)
{
gadgetmessage(&FemaleGadget,ControlWindow);
gadgetmessage(&MaleGadget,ControlWindow);
}
}
if(parseresult & 0x10) ModGadget(&ModeGadget);
if(parseresult & 0x40) ModGadget(&EnglStrGadget);
if(parseresult & 0x80) IssueTranslate();
if(parseresult & 0x100) IssueSpeak();
if(parseresult & 0x200) ModGadget(&PhonStrGadget);
}