mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Add files by Jack
This commit is contained in:
parent
950d47fd67
commit
3a80c8defe
5 changed files with 2040 additions and 0 deletions
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…
Add table
Add a link
Reference in a new issue