1 /***********************************************************
2 Copyright 1991-1997 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 ******************************************************************/
34 #include <TextUtils.h>
43 #endif /* __MWERKS__ */
46 #include <CodeFragments.h>
50 /* Somehow the Apple Fix2X and X2Fix don't do what I expect */
51 #define fixed2double(x) (((double)(x))/32768.0)
52 #define double2fixed(x) ((Fixed)((x)*32768.0))
55 PyObject
*ms_error_object
;
64 lib_available
= ((ProcPtr
)SpeakString
!= (ProcPtr
)0);
66 err
= Gestalt(gestaltSpeechAttr
, &result
);
67 if ( err
== noErr
&& (result
& (1<<gestaltSpeechMgrPresent
)))
74 if ( !speech_available
) {
75 PyErr_SetString(ms_error_object
, "Speech Mgr not available");
79 if ( !lib_available
) {
80 PyErr_SetString(ms_error_object
, "Speech Mgr available, but shared lib missing");
89 ** Part one - the speech channel object
94 PyObject
*curtext
; /* If non-NULL current text being spoken */
97 staticforward PyTypeObject sctype
;
99 #define is_scobject(v) ((v)->ob_type == &sctype)
108 self
= PyObject_NEW(scobject
, &sctype
);
111 if ( (err
=NewSpeechChannel(arg
, &self
->chan
)) != 0) {
113 return (scobject
*)PyErr_Mac(ms_error_object
, err
);
115 self
->curtext
= NULL
;
125 DisposeSpeechChannel(self
->chan
);
136 if (!PyArg_NoArgs(args
))
138 if ((err
=StopSpeech(self
->chan
)) != 0) {
139 PyErr_Mac(ms_error_object
, err
);
142 if ( self
->curtext
) {
143 Py_DECREF(self
->curtext
);
144 self
->curtext
= NULL
;
151 sc_SpeakText(self
, args
)
159 if (!PyArg_Parse(args
, "s#", &str
, &len
))
161 if ( self
->curtext
) {
162 StopSpeech(self
->chan
);
163 Py_DECREF(self
->curtext
);
164 self
->curtext
= NULL
;
166 if ((err
=SpeakText(self
->chan
, (Ptr
)str
, (long)len
)) != 0) {
167 PyErr_Mac(ms_error_object
, err
);
170 (void)PyArg_Parse(args
, "O", &self
->curtext
); /* Or should I check this? */
171 Py_INCREF(self
->curtext
);
177 sc_GetRate(self
, args
)
184 if (!PyArg_NoArgs(args
))
186 if ((err
=GetSpeechRate(self
->chan
, &farg
)) != 0) {
187 PyErr_Mac(ms_error_object
, err
);
190 return PyFloat_FromDouble(fixed2double(farg
));
194 sc_GetPitch(self
, args
)
201 if (!PyArg_NoArgs(args
))
203 if ((err
=GetSpeechPitch(self
->chan
, &farg
)) != 0) {
204 PyErr_Mac(ms_error_object
, err
);
207 return PyFloat_FromDouble(fixed2double(farg
));
211 sc_SetRate(self
, args
)
218 if (!PyArg_Parse(args
, "d", &darg
))
220 if ((err
=SetSpeechRate(self
->chan
, double2fixed(darg
))) != 0) {
221 PyErr_Mac(ms_error_object
, err
);
229 sc_SetPitch(self
, args
)
236 if (!PyArg_Parse(args
, "d", &darg
))
238 if ((err
=SetSpeechPitch(self
->chan
, double2fixed(darg
))) != 0) {
239 PyErr_Mac(ms_error_object
, err
);
246 static struct PyMethodDef sc_methods
[] = {
247 {"Stop", (PyCFunction
)sc_Stop
},
248 {"SetRate", (PyCFunction
)sc_SetRate
},
249 {"GetRate", (PyCFunction
)sc_GetRate
},
250 {"SetPitch", (PyCFunction
)sc_SetPitch
},
251 {"GetPitch", (PyCFunction
)sc_GetPitch
},
252 {"SpeakText", (PyCFunction
)sc_SpeakText
},
253 {NULL
, NULL
} /* sentinel */
257 sc_getattr(self
, name
)
261 return Py_FindMethod(sc_methods
, (PyObject
*)self
, name
);
264 static PyTypeObject sctype
= {
265 PyObject_HEAD_INIT(&PyType_Type
)
267 "MacSpeechChannel", /*tp_name*/
268 sizeof(scobject
), /*tp_basicsize*/
271 (destructor
)sc_dealloc
, /*tp_dealloc*/
273 (getattrfunc
)sc_getattr
, /*tp_getattr*/
278 0, /*tp_as_sequence*/
285 ** Part two - the voice object
294 staticforward PyTypeObject mvtype
;
296 #define is_mvobject(v) ((v)->ob_type == &mvtype)
302 self
= PyObject_NEW(mvobject
, &mvtype
);
305 self
->initialized
= 0;
310 initmvobject(self
, ind
)
316 if ( (err
=GetIndVoice((short)ind
, &self
->vs
)) != 0 ) {
317 PyErr_Mac(ms_error_object
, err
);
320 if ( (err
=GetVoiceDescription(&self
->vs
, &self
->vd
, sizeof self
->vd
)) != 0) {
321 PyErr_Mac(ms_error_object
, err
);
324 self
->initialized
= 1;
337 mv_getgender(self
, args
)
343 if (!PyArg_NoArgs(args
))
345 if (!self
->initialized
) {
346 PyErr_SetString(ms_error_object
, "Uninitialized voice");
349 rv
= PyInt_FromLong(self
->vd
.gender
);
354 mv_newchannel(self
, args
)
358 if (!PyArg_NoArgs(args
))
360 if (!self
->initialized
) {
361 PyErr_SetString(ms_error_object
, "Uninitialized voice");
364 return (PyObject
*)newscobject(&self
->vs
);
367 static struct PyMethodDef mv_methods
[] = {
368 {"GetGender", (PyCFunction
)mv_getgender
},
369 {"NewChannel", (PyCFunction
)mv_newchannel
},
370 {NULL
, NULL
} /* sentinel */
374 mv_getattr(self
, name
)
378 return Py_FindMethod(mv_methods
, (PyObject
*)self
, name
);
381 static PyTypeObject mvtype
= {
382 PyObject_HEAD_INIT(&PyType_Type
)
384 "MacVoice", /*tp_name*/
385 sizeof(mvobject
), /*tp_basicsize*/
388 (destructor
)mv_dealloc
, /*tp_dealloc*/
390 (getattrfunc
)mv_getattr
, /*tp_getattr*/
395 0, /*tp_as_sequence*/
403 ** Part three - The module interface
406 /* See if Speech manager available */
409 ms_Available(self
, args
)
410 PyObject
*self
; /* Not used */
414 if (!PyArg_NoArgs(args
))
416 return PyInt_FromLong(speech_available
);
419 /* Count number of busy speeches */
423 PyObject
*self
; /* Not used */
428 if (!PyArg_NoArgs(args
))
430 if ( !check_available() )
432 result
= SpeechBusy();
433 return PyInt_FromLong(result
);
439 ms_SpeakString(self
, args
)
440 PyObject
*self
; /* Not used */
447 if (!PyArg_Parse(args
, "s", &str
))
449 if ( !check_available())
452 /* Free the old speech, after killing it off
453 ** (note that speach is async and c2pstr works inplace)
459 CurrentSpeech
= malloc(len
+1);
460 strcpy(CurrentSpeech
, str
);
461 err
= SpeakString(c2pstr(CurrentSpeech
));
463 PyErr_Mac(ms_error_object
, err
);
471 /* Count number of available voices */
474 ms_CountVoices(self
, args
)
475 PyObject
*self
; /* Not used */
480 if (!PyArg_NoArgs(args
))
482 if ( !check_available())
484 CountVoices(&result
);
485 return PyInt_FromLong(result
);
489 ms_GetIndVoice(self
, args
)
490 PyObject
*self
; /* Not used */
496 if( !PyArg_Parse(args
, "i", &ind
))
498 if ( !check_available() )
501 if ( !initmvobject(rv
, ind
) ) {
505 return (PyObject
*)rv
;
510 ms_Version(self
, args
)
511 PyObject
*self
; /* Not used */
516 if (!PyArg_NoArgs(args
))
518 if ( !check_available())
520 v
= SpeechManagerVersion();
521 return PyInt_FromLong(*(int *)&v
);
525 /* List of functions defined in the module */
527 static struct PyMethodDef ms_methods
[] = {
528 {"Available", ms_Available
},
529 {"CountVoices", ms_CountVoices
},
531 {"SpeakString", ms_SpeakString
},
532 {"GetIndVoice", ms_GetIndVoice
},
533 {"Version", ms_Version
},
534 {NULL
, NULL
} /* sentinel */
537 /* Initialization function for the module (*must* be called initmacspeech) */
544 speech_available
= init_available();
545 /* Create the module and add the functions */
546 m
= Py_InitModule("macspeech", ms_methods
);
548 /* Add some symbolic constants to the module */
549 d
= PyModule_GetDict(m
);
550 ms_error_object
= PyErr_NewException("macspeech.error", NULL
, NULL
);
551 PyDict_SetItemString(d
, "error", ms_error_object
);