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 ******************************************************************/
32 #include <TextUtils.h>
37 #endif /* __MWERKS__ */
40 #include <CodeFragments.h>
44 /* Somehow the Apple Fix2X and X2Fix don't do what I expect */
45 #define fixed2double(x) (((double)(x))/32768.0)
46 #define double2fixed(x) ((Fixed)((x)*32768.0))
49 PyObject
*ms_error_object
;
58 lib_available
= ((ProcPtr
)SpeakString
!= (ProcPtr
)0);
60 err
= Gestalt(gestaltSpeechAttr
, &result
);
61 if ( err
== noErr
&& (result
& (1<<gestaltSpeechMgrPresent
)))
68 if ( !speech_available
) {
69 PyErr_SetString(ms_error_object
, "Speech Mgr not available");
73 if ( !lib_available
) {
74 PyErr_SetString(ms_error_object
, "Speech Mgr available, but shared lib missing");
83 ** Part one - the speech channel object
88 PyObject
*curtext
; /* If non-NULL current text being spoken */
91 staticforward PyTypeObject sctype
;
93 #define is_scobject(v) ((v)->ob_type == &sctype)
102 self
= PyObject_NEW(scobject
, &sctype
);
105 if ( (err
=NewSpeechChannel(arg
, &self
->chan
)) != 0) {
107 return (scobject
*)PyErr_Mac(ms_error_object
, err
);
109 self
->curtext
= NULL
;
119 DisposeSpeechChannel(self
->chan
);
130 if (!PyArg_NoArgs(args
))
132 if ((err
=StopSpeech(self
->chan
)) != 0) {
133 PyErr_Mac(ms_error_object
, err
);
136 if ( self
->curtext
) {
137 Py_DECREF(self
->curtext
);
138 self
->curtext
= NULL
;
145 sc_SpeakText(self
, args
)
153 if (!PyArg_Parse(args
, "s#", &str
, &len
))
155 if ( self
->curtext
) {
156 StopSpeech(self
->chan
);
157 Py_DECREF(self
->curtext
);
158 self
->curtext
= NULL
;
160 if ((err
=SpeakText(self
->chan
, (Ptr
)str
, (long)len
)) != 0) {
161 PyErr_Mac(ms_error_object
, err
);
164 (void)PyArg_Parse(args
, "O", &self
->curtext
); /* Or should I check this? */
165 Py_INCREF(self
->curtext
);
171 sc_GetRate(self
, args
)
178 if (!PyArg_NoArgs(args
))
180 if ((err
=GetSpeechRate(self
->chan
, &farg
)) != 0) {
181 PyErr_Mac(ms_error_object
, err
);
184 return PyFloat_FromDouble(fixed2double(farg
));
188 sc_GetPitch(self
, args
)
195 if (!PyArg_NoArgs(args
))
197 if ((err
=GetSpeechPitch(self
->chan
, &farg
)) != 0) {
198 PyErr_Mac(ms_error_object
, err
);
201 return PyFloat_FromDouble(fixed2double(farg
));
205 sc_SetRate(self
, args
)
212 if (!PyArg_Parse(args
, "d", &darg
))
214 if ((err
=SetSpeechRate(self
->chan
, double2fixed(darg
))) != 0) {
215 PyErr_Mac(ms_error_object
, err
);
223 sc_SetPitch(self
, args
)
230 if (!PyArg_Parse(args
, "d", &darg
))
232 if ((err
=SetSpeechPitch(self
->chan
, double2fixed(darg
))) != 0) {
233 PyErr_Mac(ms_error_object
, err
);
240 static struct PyMethodDef sc_methods
[] = {
241 {"Stop", (PyCFunction
)sc_Stop
},
242 {"SetRate", (PyCFunction
)sc_SetRate
},
243 {"GetRate", (PyCFunction
)sc_GetRate
},
244 {"SetPitch", (PyCFunction
)sc_SetPitch
},
245 {"GetPitch", (PyCFunction
)sc_GetPitch
},
246 {"SpeakText", (PyCFunction
)sc_SpeakText
},
247 {NULL
, NULL
} /* sentinel */
251 sc_getattr(self
, name
)
255 return Py_FindMethod(sc_methods
, (PyObject
*)self
, name
);
258 static PyTypeObject sctype
= {
259 PyObject_HEAD_INIT(&PyType_Type
)
261 "MacSpeechChannel", /*tp_name*/
262 sizeof(scobject
), /*tp_basicsize*/
265 (destructor
)sc_dealloc
, /*tp_dealloc*/
267 (getattrfunc
)sc_getattr
, /*tp_getattr*/
272 0, /*tp_as_sequence*/
279 ** Part two - the voice object
288 staticforward PyTypeObject mvtype
;
290 #define is_mvobject(v) ((v)->ob_type == &mvtype)
296 self
= PyObject_NEW(mvobject
, &mvtype
);
299 self
->initialized
= 0;
304 initmvobject(self
, ind
)
310 if ( (err
=GetIndVoice((short)ind
, &self
->vs
)) != 0 ) {
311 PyErr_Mac(ms_error_object
, err
);
314 if ( (err
=GetVoiceDescription(&self
->vs
, &self
->vd
, sizeof self
->vd
)) != 0) {
315 PyErr_Mac(ms_error_object
, err
);
318 self
->initialized
= 1;
331 mv_getgender(self
, args
)
337 if (!PyArg_NoArgs(args
))
339 if (!self
->initialized
) {
340 PyErr_SetString(ms_error_object
, "Uninitialized voice");
343 rv
= PyInt_FromLong(self
->vd
.gender
);
348 mv_newchannel(self
, args
)
352 if (!PyArg_NoArgs(args
))
354 if (!self
->initialized
) {
355 PyErr_SetString(ms_error_object
, "Uninitialized voice");
358 return (PyObject
*)newscobject(&self
->vs
);
361 static struct PyMethodDef mv_methods
[] = {
362 {"GetGender", (PyCFunction
)mv_getgender
},
363 {"NewChannel", (PyCFunction
)mv_newchannel
},
364 {NULL
, NULL
} /* sentinel */
368 mv_getattr(self
, name
)
372 return Py_FindMethod(mv_methods
, (PyObject
*)self
, name
);
375 static PyTypeObject mvtype
= {
376 PyObject_HEAD_INIT(&PyType_Type
)
378 "MacVoice", /*tp_name*/
379 sizeof(mvobject
), /*tp_basicsize*/
382 (destructor
)mv_dealloc
, /*tp_dealloc*/
384 (getattrfunc
)mv_getattr
, /*tp_getattr*/
389 0, /*tp_as_sequence*/
397 ** Part three - The module interface
400 /* See if Speech manager available */
403 ms_Available(self
, args
)
404 PyObject
*self
; /* Not used */
408 if (!PyArg_NoArgs(args
))
410 return PyInt_FromLong(speech_available
);
413 /* Count number of busy speeches */
417 PyObject
*self
; /* Not used */
422 if (!PyArg_NoArgs(args
))
424 if ( !check_available() )
426 result
= SpeechBusy();
427 return PyInt_FromLong(result
);
433 ms_SpeakString(self
, args
)
434 PyObject
*self
; /* Not used */
441 if (!PyArg_Parse(args
, "s", &str
))
443 if ( !check_available())
446 /* Free the old speech, after killing it off
447 ** (note that speach is async and c2pstr works inplace)
453 CurrentSpeech
= malloc(len
+1);
454 strcpy(CurrentSpeech
, str
);
455 err
= SpeakString(c2pstr(CurrentSpeech
));
457 PyErr_Mac(ms_error_object
, err
);
465 /* Count number of available voices */
468 ms_CountVoices(self
, args
)
469 PyObject
*self
; /* Not used */
474 if (!PyArg_NoArgs(args
))
476 if ( !check_available())
478 CountVoices(&result
);
479 return PyInt_FromLong(result
);
483 ms_GetIndVoice(self
, args
)
484 PyObject
*self
; /* Not used */
490 if( !PyArg_Parse(args
, "i", &ind
))
492 if ( !check_available() )
495 if ( !initmvobject(rv
, ind
) ) {
499 return (PyObject
*)rv
;
504 ms_Version(self
, args
)
505 PyObject
*self
; /* Not used */
510 if (!PyArg_NoArgs(args
))
512 if ( !check_available())
514 v
= SpeechManagerVersion();
515 return PyInt_FromLong(*(int *)&v
);
519 /* List of functions defined in the module */
521 static struct PyMethodDef ms_methods
[] = {
522 {"Available", ms_Available
},
523 {"CountVoices", ms_CountVoices
},
525 {"SpeakString", ms_SpeakString
},
526 {"GetIndVoice", ms_GetIndVoice
},
527 {"Version", ms_Version
},
528 {NULL
, NULL
} /* sentinel */
531 /* Initialization function for the module (*must* be called initmacspeech) */
538 speech_available
= init_available();
539 /* Create the module and add the functions */
540 m
= Py_InitModule("macspeech", ms_methods
);
542 /* Add some symbolic constants to the module */
543 d
= PyModule_GetDict(m
);
544 ms_error_object
= PyErr_NewException("macspeech.error", NULL
, NULL
);
545 PyDict_SetItemString(d
, "error", ms_error_object
);