mirror of
https://github.com/python/cpython.git
synced 2024-11-24 18:34:43 +08:00
Add files by Jack
This commit is contained in:
parent
950d47fd67
commit
3a80c8defe
1204
Mac/Demo/speech/SCRIPT
Normal file
1204
Mac/Demo/speech/SCRIPT
Normal file
File diff suppressed because it is too large
Load Diff
228
Mac/Demo/speech/grail.py
Normal file
228
Mac/Demo/speech/grail.py
Normal file
@ -0,0 +1,228 @@
|
||||
# Pass this program the Holy Grail script on stdin.
|
||||
import sys
|
||||
import string
|
||||
import stdwin
|
||||
from stdwinevents import *
|
||||
|
||||
try:
|
||||
import macspeech
|
||||
except ImportError:
|
||||
macspeech = None
|
||||
|
||||
WINWIDTH = 1000
|
||||
scrw, scrh = stdwin.getscrsize()
|
||||
if WINWIDTH > 0.8*scrw:
|
||||
WINWIDTH = int(0.8*scrw)
|
||||
BLACK = stdwin.fetchcolor('black')
|
||||
RED = stdwin.fetchcolor('red')
|
||||
BLUE = stdwin.fetchcolor('blue')
|
||||
|
||||
done='done'
|
||||
|
||||
class MacSpeaker:
|
||||
def __init__(self):
|
||||
self.voices = []
|
||||
self.nvoices = macspeech.CountVoices()
|
||||
self.curvoice = 1
|
||||
self.rate = 1.0
|
||||
|
||||
def _newvoice(self):
|
||||
vd = macspeech.GetIndVoice(self.curvoice)
|
||||
sc = vd.NewChannel()
|
||||
self.curvoice = self.curvoice + 1
|
||||
if self.curvoice > self.nvoices:
|
||||
self.curvoice = 1
|
||||
return sc
|
||||
|
||||
def newvoices(self, n):
|
||||
self.voices = []
|
||||
for i in range(n):
|
||||
self.voices.append(self._newvoice())
|
||||
if self.rate <> 1.0:
|
||||
self.setrate(1.0)
|
||||
|
||||
def setrate(self, factor):
|
||||
self.rate = self.rate*factor
|
||||
for v in self.voices:
|
||||
r = v.GetRate()
|
||||
v.SetRate(r*factor)
|
||||
|
||||
def speak(self, i, text):
|
||||
self.voices[i-1].SpeakText(text)
|
||||
|
||||
def busy(self):
|
||||
return macspeech.Busy()
|
||||
|
||||
[NOTHING, NEWSCENE, ACT, TEXT, MORETEXT] = range(5)
|
||||
def parseline(line):
|
||||
stripline = string.strip(line)
|
||||
if not stripline:
|
||||
return NOTHING, ''
|
||||
if stripline[:5] == 'Scene':
|
||||
return NEWSCENE, stripline
|
||||
if line[0] == '[':
|
||||
return ACT, stripline
|
||||
if line[0] == ' ' and ':' in line:
|
||||
splitline = string.splitfields(stripline, ':')
|
||||
stripline = string.joinfields(splitline[1:], ':')
|
||||
return TEXT, (splitline[0], string.strip(stripline))
|
||||
return MORETEXT, stripline
|
||||
|
||||
def readscript(file):
|
||||
lines = file.readlines()
|
||||
acts = []
|
||||
actor_dict = {}
|
||||
longest = 0
|
||||
prev_act = 0
|
||||
for i in range(len(lines)):
|
||||
tp, data = parseline(lines[i])
|
||||
if tp == NEWSCENE:
|
||||
acts.append(actor_dict.keys(), lines[prev_act:i])
|
||||
prev_act = i
|
||||
actor_dict = {}
|
||||
elif tp == TEXT:
|
||||
actor_dict[data[0]] = 1
|
||||
lines[i] = tp, data
|
||||
return acts[1:]
|
||||
|
||||
class Main:
|
||||
def __init__(self):
|
||||
if macspeech:
|
||||
self.speaker = MacSpeaker()
|
||||
else:
|
||||
self.speaker = None
|
||||
sys.stdin = open('SCRIPT', 'r')
|
||||
self.acts = readscript(sys.stdin)
|
||||
maxactor = 0
|
||||
for actorlist, actdata in self.acts:
|
||||
if len(actorlist) > maxactor:
|
||||
maxactor = len(actorlist)
|
||||
if not self.loadnextact():
|
||||
print 'No acts to play!'
|
||||
raise done
|
||||
self.lh = stdwin.lineheight()
|
||||
self.winheight = (maxactor+2)*self.lh
|
||||
stdwin.setdefwinsize(WINWIDTH, self.winheight)
|
||||
self.win = stdwin.open('The Play')
|
||||
self.win.setdocsize(WINWIDTH, self.winheight)
|
||||
self.win.change(((0,0),(WINWIDTH, self.winheight)))
|
||||
self.menu = self.win.menucreate('Play')
|
||||
self.menu.additem('Faster', '+')
|
||||
self.menu.additem('Slower', '-')
|
||||
self.menu.additem('Quit', 'Q')
|
||||
self.speed = 4
|
||||
|
||||
def done(self):
|
||||
del self.win
|
||||
del self.menu
|
||||
|
||||
def loadnextact(self):
|
||||
if not self.acts: return 0
|
||||
actors, lines = self.acts[0]
|
||||
del self.acts[0]
|
||||
prevactor = 0
|
||||
for i in range(len(lines)):
|
||||
tp, data = lines[i]
|
||||
if tp == NOTHING:
|
||||
continue
|
||||
elif tp in (NEWSCENE, ACT):
|
||||
lines[i] = 0, data
|
||||
elif tp == TEXT:
|
||||
prevactor = actors.index(data[0])
|
||||
lines[i] = prevactor+1, data[1]
|
||||
else:
|
||||
lines[i] = prevactor+1, data
|
||||
self.lines = lines
|
||||
self.actors = [''] + actors
|
||||
self.actorlines = [''] * len(self.actors)
|
||||
if self.speaker:
|
||||
self.speaker.newvoices(len(self.actors)-1)
|
||||
self.prevline = 0
|
||||
self.actwidth = 0
|
||||
for a in self.actors:
|
||||
w = stdwin.textwidth(a)
|
||||
if w > self.actwidth:
|
||||
self.actwidth = w
|
||||
return 1
|
||||
|
||||
def loadnextline(self):
|
||||
if not self.lines: return 0
|
||||
self.actorlines[self.prevline] = ''
|
||||
top = self.lh*self.prevline
|
||||
self.win.change(((0, top), (WINWIDTH, top+self.lh)))
|
||||
line, data = self.lines[0]
|
||||
del self.lines[0]
|
||||
self.actorlines[line] = data
|
||||
self.prevline = line
|
||||
top = self.lh*self.prevline
|
||||
self.win.change(((0, top), (WINWIDTH, top+self.lh)))
|
||||
if line == 0:
|
||||
self.win.settimer(5*self.speed)
|
||||
else:
|
||||
if self.speaker:
|
||||
self.speaker.speak(line, data)
|
||||
tv = 1
|
||||
else:
|
||||
nwords = len(string.split(data))
|
||||
tv = self.speed*(nwords+1)
|
||||
self.win.settimer(tv)
|
||||
return 1
|
||||
|
||||
def timerevent(self):
|
||||
if self.speaker and self.speaker.busy():
|
||||
self.win.settimer(1)
|
||||
return
|
||||
while 1:
|
||||
if self.loadnextline(): return
|
||||
if not self.loadnextact():
|
||||
stdwin.message('The END')
|
||||
self.win.close()
|
||||
raise done
|
||||
self.win.change(((0,0), (WINWIDTH, self.winheight)))
|
||||
|
||||
def redraw(self, top, bottom, draw):
|
||||
for i in range(len(self.actors)):
|
||||
tpos = i*self.lh
|
||||
bpos = (i+1)*self.lh-1
|
||||
if tpos < bottom and bpos > top:
|
||||
draw.setfgcolor(BLUE)
|
||||
draw.text((0, tpos), self.actors[i])
|
||||
if i == 0:
|
||||
draw.setfgcolor(RED)
|
||||
else:
|
||||
draw.setfgcolor(BLACK)
|
||||
draw.text((self.actwidth+5, tpos), self.actorlines[i])
|
||||
|
||||
def run(self):
|
||||
self.win.settimer(10)
|
||||
while 1:
|
||||
ev, win, arg = stdwin.getevent()
|
||||
if ev == WE_DRAW:
|
||||
((left, top), (right, bot)) = arg
|
||||
self.redraw(top, bot, self.win.begindrawing())
|
||||
elif ev == WE_TIMER:
|
||||
self.timerevent()
|
||||
elif ev == WE_CLOSE:
|
||||
self.win.close()
|
||||
raise done
|
||||
elif ev == WE_MENU and arg[0] == self.menu:
|
||||
if arg[1] == 0:
|
||||
if self.speed > 1:
|
||||
self.speed = self.speed/2
|
||||
if self.speaker:
|
||||
self.speaker.setrate(1.4)
|
||||
elif arg[1] == 1:
|
||||
self.speed = self.speed * 2
|
||||
if self.speaker:
|
||||
self.speaker.setrate(0.7)
|
||||
elif arg[1] == 2:
|
||||
self.win.close()
|
||||
raise done
|
||||
|
||||
if 1:
|
||||
main = Main()
|
||||
try:
|
||||
main.run()
|
||||
except done:
|
||||
pass
|
||||
del main
|
31
Mac/Demo/speech/hum.py
Normal file
31
Mac/Demo/speech/hum.py
Normal file
@ -0,0 +1,31 @@
|
||||
#
|
||||
# Hum - The singing macintosh
|
||||
#
|
||||
import macspeech
|
||||
import sys
|
||||
import string
|
||||
|
||||
dict = { 'A':57, 'A#':58, 'B':59, 'C':60, 'C#':61, 'D':62, 'D#':63,
|
||||
'E':64, 'F':65, 'F#':66, 'G':67, 'G#':68}
|
||||
|
||||
vd = macspeech.GetIndVoice(2)
|
||||
vc = vd.NewChannel()
|
||||
print 'Input strings of notes, as in A B C C# D'
|
||||
while 1:
|
||||
print 'S(tr)ing-',
|
||||
str = sys.stdin.readline()
|
||||
if not str:
|
||||
break
|
||||
str = string.split(str[:-1])
|
||||
data = []
|
||||
for s in str:
|
||||
if not dict.has_key(s):
|
||||
print 'No such note:', s
|
||||
else:
|
||||
data.append(dict[s])
|
||||
print data
|
||||
for d in data:
|
||||
vc.SetPitch(float(d))
|
||||
vc.SpeakText('la')
|
||||
while macspeech.Busy():
|
||||
pass
|
18
Mac/Modules/macspeech/README
Normal file
18
Mac/Modules/macspeech/README
Normal file
@ -0,0 +1,18 @@
|
||||
To add this stuff to Macintosh python (and have some use for it):
|
||||
|
||||
1. Obtain a copy of the Speech Manager. It can be found on
|
||||
ftp.apple.com.
|
||||
2. Put the Speech.h file from the Speech Manager distribution and
|
||||
macspeechmodule.c in your python Modules directory.
|
||||
3. Add the new module to python and build a new python.
|
||||
4. Install the Speech Manager (under sys7 the extension goes in the
|
||||
Extensions folder, the data file in the System folder) and reboot.
|
||||
5. Try it.
|
||||
|
||||
The test program 'hum' does that, you type notes and it hums them
|
||||
(badly, addmitted, but that isn't my fault really).
|
||||
|
||||
The test program 'grail' is more fun, but you need stdwin support for
|
||||
it. It reads the script for the Holy Grail film from the file SCRIPT
|
||||
and both animates it (text only:-) on the screen and reads it out the
|
||||
speaker. It will use all voices available in the system.
|
559
Mac/Modules/macspeechmodule.c
Normal file
559
Mac/Modules/macspeechmodule.c
Normal file
@ -0,0 +1,559 @@
|
||||
/***********************************************************
|
||||
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");
|
||||
}
|
Loading…
Reference in New Issue
Block a user