summaryrefslogtreecommitdiffstats
path: root/Mac/Demo/speech/grail.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1994-10-02 11:33:59 (GMT)
committerGuido van Rossum <guido@python.org>1994-10-02 11:33:59 (GMT)
commit3a80c8defe29ac7d169ad3d791f67bcaf7a9b3f2 (patch)
tree709905bc2fb0d0d218e9e115dc80758dced030aa /Mac/Demo/speech/grail.py
parent950d47fd6789c5c7d8aa4a0708659e713db17895 (diff)
downloadcpython-3a80c8defe29ac7d169ad3d791f67bcaf7a9b3f2.zip
cpython-3a80c8defe29ac7d169ad3d791f67bcaf7a9b3f2.tar.gz
cpython-3a80c8defe29ac7d169ad3d791f67bcaf7a9b3f2.tar.bz2
Add files by Jack
Diffstat (limited to 'Mac/Demo/speech/grail.py')
-rw-r--r--Mac/Demo/speech/grail.py228
1 files changed, 228 insertions, 0 deletions
diff --git a/Mac/Demo/speech/grail.py b/Mac/Demo/speech/grail.py
new file mode 100644
index 0000000..d926569
--- /dev/null
+++ b/Mac/Demo/speech/grail.py
@@ -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