home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
- Amsterdam, The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior permission.
-
- STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
- /* xx module */
-
- #include "allobjects.h"
- #include "modsupport.h"
-
- #include <GestaltEqu.h>
- #include "pascal.h"
- #include "Speech.h"
-
- /* Somehow the Apple Fix2X and X2Fix don't do what I expect */
- #define fixed2double(x) (((double)(x))/32768.0)
- #define double2fixed(x) ((Fixed)((x)*32768.0))
-
- char *CurrentSpeech;
- object *ms_error_object;
-
- /* General error handler */
- static object *
- ms_error(num)
- OSErr num;
- {
- char buf[40];
-
- sprintf(buf, "Mac Speech Mgr error #%d", num);
- err_setstr(ms_error_object, buf);
- return (object *)NULL;
- }
-
- /* -------------
- **
- ** Part one - the speech channel object
- */
- typedef struct {
- OB_HEAD
- object *x_attr; /* Attributes dictionary */
- SpeechChannel chan;
- object *curtext; /* If non-NULL current text being spoken */
- } scobject;
-
- staticforward typeobject sctype;
-
- #define is_scobject(v) ((v)->ob_type == &sctype)
-
- static scobject *
- newscobject(arg)
- VoiceSpec *arg;
- {
- scobject *xp;
- OSErr err;
-
- xp = NEWOBJ(scobject, &sctype);
- if (xp == NULL)
- return NULL;
- xp->x_attr = NULL;
- if ( (err=NewSpeechChannel(arg, &xp->chan)) != 0) {
- DECREF(xp);
- return (scobject *)ms_error(err);
- }
- xp->curtext = NULL;
- return xp;
- }
-
- /* sc methods */
-
- static void
- sc_dealloc(xp)
- scobject *xp;
- {
- DisposeSpeechChannel(xp->chan);
- XDECREF(xp->x_attr);
- DEL(xp);
- }
-
- static object *
- sc_Stop(self, args)
- scobject *self;
- object *args;
- {
- OSErr err;
-
- if (!getnoarg(args))
- return NULL;
- if ((err=StopSpeech(self->chan)) != 0)
- return ms_error(err);
- if ( self->curtext ) {
- DECREF(self->curtext);
- self->curtext = NULL;
- }
- INCREF(None);
- return None;
- }
-
- static object *
- sc_SpeakText(self, args)
- scobject *self;
- object *args;
- {
- OSErr err;
- char *str;
- int len;
-
- if (!getargs(args, "s#", &str, &len))
- return NULL;
- if ( self->curtext ) {
- StopSpeech(self->chan);
- DECREF(self->curtext);
- self->curtext = NULL;
- }
- if ((err=SpeakText(self->chan, (Ptr)str, (long)len)) != 0)
- return ms_error(err);
- (void)getargs(args, "O", &self->curtext); /* Or should I check this? */
- INCREF(self->curtext);
- INCREF(None);
- return None;
- }
-
- static object *
- sc_GetRate(self, args)
- scobject *self;
- object *args;
- {
- OSErr err;
- Fixed farg;
-
- if (!getnoarg(args))
- return NULL;
- if ((err=GetSpeechRate(self->chan, &farg)) != 0)
- return ms_error(err);
- return newfloatobject(fixed2double(farg));
- }
-
- static object *
- sc_GetPitch(self, args)
- scobject *self;
- object *args;
- {
- OSErr err;
- Fixed farg;
-
- if (!getnoarg(args))
- return NULL;
- if ((err=GetSpeechPitch(self->chan, &farg)) != 0)
- return ms_error(err);
- return newfloatobject(fixed2double(farg));
- }
-
- static object *
- sc_SetRate(self, args)
- scobject *self;
- object *args;
- {
- OSErr err;
- double darg;
-
- if (!getargs(args, "d", &darg))
- return NULL;
- if ((err=SetSpeechRate(self->chan, double2fixed(darg))) != 0)
- return ms_error(err);
- INCREF(None);
- return None;
- }
-
- static object *
- sc_SetPitch(self, args)
- scobject *self;
- object *args;
- {
- OSErr err;
- double darg;
-
- if (!getargs(args, "d", &darg))
- return NULL;
- if ((err=SetSpeechPitch(self->chan, double2fixed(darg))) != 0)
- return ms_error(err);
- INCREF(None);
- return None;
- }
-
- static struct methodlist sc_methods[] = {
- {"Stop", (method)sc_Stop},
- {"SetRate", (method)sc_SetRate},
- {"GetRate", (method)sc_GetRate},
- {"SetPitch", (method)sc_SetPitch},
- {"GetPitch", (method)sc_GetPitch},
- {"SpeakText", (method)sc_SpeakText},
- {NULL, NULL} /* sentinel */
- };
-
- static object *
- sc_getattr(xp, name)
- scobject *xp;
- char *name;
- {
- if (xp->x_attr != NULL) {
- object *v = dictlookup(xp->x_attr, name);
- if (v != NULL) {
- INCREF(v);
- return v;
- }
- }
- return findmethod(sc_methods, (object *)xp, name);
- }
-
- static int
- sc_setattr(xp, name, v)
- scobject *xp;
- char *name;
- object *v;
- {
- if (xp->x_attr == NULL) {
- xp->x_attr = newdictobject();
- if (xp->x_attr == NULL)
- return -1;
- }
- if (v == NULL) {
- int rv = dictremove(xp->x_attr, name);
- if (rv < 0)
- err_setstr(AttributeError,
- "delete non-existing sc attribute");
- return rv;
- }
- else
- return dictinsert(xp->x_attr, name, v);
- }
-
- static typeobject sctype = {
- OB_HEAD_INIT(&Typetype)
- 0, /*ob_size*/
- "MacSpeechChannel", /*tp_name*/
- sizeof(scobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)sc_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)sc_getattr, /*tp_getattr*/
- (setattrfunc)sc_setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- };
-
- /* -------------
- **
- ** Part two - the voice object
- */
- typedef struct {
- OB_HEAD
- object *x_attr; /* Attributes dictionary */
- int initialized;
- VoiceSpec vs;
- VoiceDescription vd;
- } mvobject;
-
- staticforward typeobject mvtype;
-
- #define is_mvobject(v) ((v)->ob_type == &mvtype)
-
- static mvobject *
- newmvobject()
- {
- mvobject *xp;
- xp = NEWOBJ(mvobject, &mvtype);
- if (xp == NULL)
- return NULL;
- xp->x_attr = NULL;
- xp->initialized = 0;
- return xp;
- }
-
- static int
- initmvobject(self, ind)
- mvobject *self;
- int ind;
- {
- OSErr err;
-
- if ( (err=GetIndVoice((short)ind, &self->vs)) != 0 ) {
- ms_error(err);
- return 0;
- }
- if ( (err=GetVoiceDescription(&self->vs, &self->vd, sizeof self->vd)) != 0) {
- ms_error(err);
- return 0;
- }
- self->initialized = 1;
- return 1;
- }
- /* mv methods */
-
- static void
- mv_dealloc(xp)
- mvobject *xp;
- {
- XDECREF(xp->x_attr);
- DEL(xp);
- }
-
- static object *
- mv_getgender(self, args)
- mvobject *self;
- object *args;
- {
- object *rv;
-
- if (!getnoarg(args))
- return NULL;
- if (!self->initialized) {
- err_setstr(ms_error_object, "Uninitialized voice");
- return NULL;
- }
- rv = newintobject(self->vd.gender);
- return rv;
- }
-
- static object *
- mv_newchannel(self, args)
- mvobject *self;
- object *args;
- {
- if (!getnoarg(args))
- return NULL;
- if (!self->initialized) {
- err_setstr(ms_error_object, "Uninitialized voice");
- return NULL;
- }
- return (object *)newscobject(&self->vs);
- }
-
- static struct methodlist mv_methods[] = {
- {"GetGender", (method)mv_getgender},
- {"NewChannel", (method)mv_newchannel},
- {NULL, NULL} /* sentinel */
- };
-
- static object *
- mv_getattr(xp, name)
- mvobject *xp;
- char *name;
- {
- if (xp->x_attr != NULL) {
- object *v = dictlookup(xp->x_attr, name);
- if (v != NULL) {
- INCREF(v);
- return v;
- }
- }
- return findmethod(mv_methods, (object *)xp, name);
- }
-
- static int
- mv_setattr(xp, name, v)
- mvobject *xp;
- char *name;
- object *v;
- {
- if (xp->x_attr == NULL) {
- xp->x_attr = newdictobject();
- if (xp->x_attr == NULL)
- return -1;
- }
- if (v == NULL) {
- int rv = dictremove(xp->x_attr, name);
- if (rv < 0)
- err_setstr(AttributeError,
- "delete non-existing MacVoice attribute");
- return rv;
- }
- else
- return dictinsert(xp->x_attr, name, v);
- }
-
- static typeobject mvtype = {
- OB_HEAD_INIT(&Typetype)
- 0, /*ob_size*/
- "MacVoice", /*tp_name*/
- sizeof(mvobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)mv_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)mv_getattr, /*tp_getattr*/
- (setattrfunc)mv_setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- };
-
-
- /* -------------
- **
- ** Part three - The module interface
- */
-
- /* See if Speech manager available */
-
- static object *
- ms_Available(self, args)
- object *self; /* Not used */
- object *args;
- {
- OSErr err;
- long result;
-
- if (!getnoarg(args))
- return NULL;
- err = Gestalt(gestaltSpeechAttr, &result);
- if ( err == noErr && (result & (1<<gestaltSpeechMgrPresent)))
- result = 1;
- else
- result = 0;
- return newintobject(result);
- }
-
- /* Count number of busy speeches */
-
- static object *
- ms_Busy(self, args)
- object *self; /* Not used */
- object *args;
- {
- OSErr err;
- short result;
-
- if (!getnoarg(args))
- return NULL;
- result = SpeechBusy();
- return newintobject(result);
- }
-
- /* Say something */
-
- static object *
- ms_SpeakString(self, args)
- object *self; /* Not used */
- object *args;
- {
- OSErr err;
- short result;
- char *str;
- int len;
-
- if (!getstrarg(args, &str))
- return NULL;
- if (CurrentSpeech) {
- /* Free the old speech, after killing it off
- ** (note that speach is async and c2pstr works inplace)
- */
- SpeakString("\p");
- free(CurrentSpeech);
- }
- len = strlen(str);
- CurrentSpeech = malloc(len+1);
- strcpy(CurrentSpeech, str);
- err = SpeakString(c2pstr(CurrentSpeech));
- if ( err )
- return ms_error(err);
- INCREF(None);
- return None;
- }
-
-
- /* Count number of available voices */
-
- static object *
- ms_CountVoices(self, args)
- object *self; /* Not used */
- object *args;
- {
- OSErr err;
- short result;
-
- if (!getnoarg(args))
- return NULL;
- CountVoices(&result);
- return newintobject(result);
- }
-
- static object *
- ms_GetIndVoice(self, args)
- object *self; /* Not used */
- object *args;
- {
- OSErr err;
- mvobject *rv;
- long ind;
-
- if( !getargs(args, "i", &ind))
- return 0;
- rv = newmvobject();
- if ( !initmvobject(rv, ind) ) {
- DECREF(rv);
- return NULL;
- }
- return (object *)rv;
- }
-
-
-
- /* List of functions defined in the module */
-
- static struct methodlist ms_methods[] = {
- {"Available", ms_Available},
- {"CountVoices", ms_CountVoices},
- {"Busy", ms_Busy},
- {"SpeakString", ms_SpeakString},
- {"GetIndVoice", ms_GetIndVoice},
- {NULL, NULL} /* sentinel */
- };
-
-
- /* Initialization function for the module (*must* be called initmacspeech) */
-
- void
- initmacspeech()
- {
- object *m, *d;
-
- /* Create the module and add the functions */
- m = initmodule("macspeech", ms_methods);
-
- /* Add some symbolic constants to the module */
- d = getmoduledict(m);
- ms_error_object = newstringobject("macspeech.error");
- dictinsert(d, "error", ms_error_object);
-
- /* Check for errors */
- if (err_occurred())
- fatal("can't initialize module macspeech");
- }
-