1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
27 #include "allobjects.h"
28 #include "modsupport.h"
30 #include <GestaltEqu.h>
39 #endif /* __MWERKS__ */
46 /* Somehow the Apple Fix2X and X2Fix don't do what I expect */
47 #define fixed2double(x) (((double)(x))/32768.0)
48 #define double2fixed(x) ((Fixed)((x)*32768.0))
51 object
*ms_error_object
;
60 lib_available
= ((ProcPtr
)SpeakString
!= (ProcPtr
)0);
62 err
= Gestalt(gestaltSpeechAttr
, &result
);
63 if ( err
== noErr
&& (result
& (1<<gestaltSpeechMgrPresent
)))
70 if ( !speech_available
) {
71 err_setstr(ms_error_object
, "Speech Mgr not available");
75 if ( !lib_available
) {
76 err_setstr(ms_error_object
, "Speech Mgr available, but shared lib missing");
85 ** Part one - the speech channel object
90 object
*curtext
; /* If non-NULL current text being spoken */
93 staticforward typeobject sctype
;
95 #define is_scobject(v) ((v)->ob_type == &sctype)
104 self
= NEWOBJ(scobject
, &sctype
);
107 if ( (err
=NewSpeechChannel(arg
, &self
->chan
)) != 0) {
109 return (scobject
*)PyErr_Mac(ms_error_object
, err
);
111 self
->curtext
= NULL
;
121 DisposeSpeechChannel(self
->chan
);
134 if ((err
=StopSpeech(self
->chan
)) != 0) {
135 PyErr_Mac(ms_error_object
, err
);
138 if ( self
->curtext
) {
139 DECREF(self
->curtext
);
140 self
->curtext
= NULL
;
147 sc_SpeakText(self
, args
)
155 if (!getargs(args
, "s#", &str
, &len
))
157 if ( self
->curtext
) {
158 StopSpeech(self
->chan
);
159 DECREF(self
->curtext
);
160 self
->curtext
= NULL
;
162 if ((err
=SpeakText(self
->chan
, (Ptr
)str
, (long)len
)) != 0) {
163 PyErr_Mac(ms_error_object
, err
);
166 (void)getargs(args
, "O", &self
->curtext
); /* Or should I check this? */
167 INCREF(self
->curtext
);
173 sc_GetRate(self
, args
)
182 if ((err
=GetSpeechRate(self
->chan
, &farg
)) != 0) {
183 PyErr_Mac(ms_error_object
, err
);
186 return newfloatobject(fixed2double(farg
));
190 sc_GetPitch(self
, args
)
199 if ((err
=GetSpeechPitch(self
->chan
, &farg
)) != 0) {
200 PyErr_Mac(ms_error_object
, err
);
203 return newfloatobject(fixed2double(farg
));
207 sc_SetRate(self
, args
)
214 if (!getargs(args
, "d", &darg
))
216 if ((err
=SetSpeechRate(self
->chan
, double2fixed(darg
))) != 0) {
217 PyErr_Mac(ms_error_object
, err
);
225 sc_SetPitch(self
, args
)
232 if (!getargs(args
, "d", &darg
))
234 if ((err
=SetSpeechPitch(self
->chan
, double2fixed(darg
))) != 0) {
235 PyErr_Mac(ms_error_object
, err
);
242 static struct methodlist sc_methods
[] = {
243 {"Stop", (method
)sc_Stop
},
244 {"SetRate", (method
)sc_SetRate
},
245 {"GetRate", (method
)sc_GetRate
},
246 {"SetPitch", (method
)sc_SetPitch
},
247 {"GetPitch", (method
)sc_GetPitch
},
248 {"SpeakText", (method
)sc_SpeakText
},
249 {NULL
, NULL
} /* sentinel */
253 sc_getattr(self
, name
)
257 return findmethod(sc_methods
, (object
*)self
, name
);
260 static typeobject sctype
= {
261 OB_HEAD_INIT(&Typetype
)
263 "MacSpeechChannel", /*tp_name*/
264 sizeof(scobject
), /*tp_basicsize*/
267 (destructor
)sc_dealloc
, /*tp_dealloc*/
269 (getattrfunc
)sc_getattr
, /*tp_getattr*/
274 0, /*tp_as_sequence*/
281 ** Part two - the voice object
290 staticforward typeobject mvtype
;
292 #define is_mvobject(v) ((v)->ob_type == &mvtype)
298 self
= NEWOBJ(mvobject
, &mvtype
);
301 self
->initialized
= 0;
306 initmvobject(self
, ind
)
312 if ( (err
=GetIndVoice((short)ind
, &self
->vs
)) != 0 ) {
313 PyErr_Mac(ms_error_object
, err
);
316 if ( (err
=GetVoiceDescription(&self
->vs
, &self
->vd
, sizeof self
->vd
)) != 0) {
317 PyErr_Mac(ms_error_object
, err
);
320 self
->initialized
= 1;
333 mv_getgender(self
, args
)
341 if (!self
->initialized
) {
342 err_setstr(ms_error_object
, "Uninitialized voice");
345 rv
= newintobject(self
->vd
.gender
);
350 mv_newchannel(self
, args
)
356 if (!self
->initialized
) {
357 err_setstr(ms_error_object
, "Uninitialized voice");
360 return (object
*)newscobject(&self
->vs
);
363 static struct methodlist mv_methods
[] = {
364 {"GetGender", (method
)mv_getgender
},
365 {"NewChannel", (method
)mv_newchannel
},
366 {NULL
, NULL
} /* sentinel */
370 mv_getattr(self
, name
)
374 return findmethod(mv_methods
, (object
*)self
, name
);
377 static typeobject mvtype
= {
378 OB_HEAD_INIT(&Typetype
)
380 "MacVoice", /*tp_name*/
381 sizeof(mvobject
), /*tp_basicsize*/
384 (destructor
)mv_dealloc
, /*tp_dealloc*/
386 (getattrfunc
)mv_getattr
, /*tp_getattr*/
391 0, /*tp_as_sequence*/
399 ** Part three - The module interface
402 /* See if Speech manager available */
405 ms_Available(self
, args
)
406 object
*self
; /* Not used */
412 return newintobject(speech_available
);
415 /* Count number of busy speeches */
419 object
*self
; /* Not used */
426 if ( !check_available() )
428 result
= SpeechBusy();
429 return newintobject(result
);
435 ms_SpeakString(self
, args
)
436 object
*self
; /* Not used */
443 if (!getstrarg(args
, &str
))
445 if ( !check_available())
448 /* Free the old speech, after killing it off
449 ** (note that speach is async and c2pstr works inplace)
455 CurrentSpeech
= malloc(len
+1);
456 strcpy(CurrentSpeech
, str
);
457 err
= SpeakString(c2pstr(CurrentSpeech
));
459 PyErr_Mac(ms_error_object
, err
);
467 /* Count number of available voices */
470 ms_CountVoices(self
, args
)
471 object
*self
; /* Not used */
478 if ( !check_available())
480 CountVoices(&result
);
481 return newintobject(result
);
485 ms_GetIndVoice(self
, args
)
486 object
*self
; /* Not used */
492 if( !getargs(args
, "i", &ind
))
494 if ( !check_available() )
497 if ( !initmvobject(rv
, ind
) ) {
506 ms_Version(self
, args
)
507 object
*self
; /* Not used */
514 if ( !check_available())
516 v
= SpeechManagerVersion();
517 return newintobject(*(int *)&v
);
521 /* List of functions defined in the module */
523 static struct methodlist ms_methods
[] = {
524 {"Available", ms_Available
},
525 {"CountVoices", ms_CountVoices
},
527 {"SpeakString", ms_SpeakString
},
528 {"GetIndVoice", ms_GetIndVoice
},
529 {"Version", ms_Version
},
530 {NULL
, NULL
} /* sentinel */
533 /* Initialization function for the module (*must* be called initmacspeech) */
540 speech_available
= init_available();
541 /* Create the module and add the functions */
542 m
= initmodule("macspeech", ms_methods
);
544 /* Add some symbolic constants to the module */
545 d
= getmoduledict(m
);
546 ms_error_object
= newstringobject("macspeech.error");
547 dictinsert(d
, "error", ms_error_object
);
549 /* Check for errors */
551 fatal("can't initialize module macspeech");