1 # Pass this program the Holy Grail script on stdin.
5 from stdwinevents
import *
13 scrw
, scrh
= stdwin
.getscrsize()
14 if WINWIDTH
> 0.8*scrw
:
15 WINWIDTH
= int(0.8*scrw
)
16 BLACK
= stdwin
.fetchcolor('black')
17 RED
= stdwin
.fetchcolor('red')
18 BLUE
= stdwin
.fetchcolor('blue')
25 self
.nvoices
= macspeech
.CountVoices()
30 vd
= macspeech
.GetIndVoice(self
.curvoice
)
32 self
.curvoice
= self
.curvoice
+ 1
33 if self
.curvoice
> self
.nvoices
:
37 def newvoices(self
, n
):
40 self
.voices
.append(self
._newvoice
())
44 def setrate(self
, factor
):
45 self
.rate
= self
.rate
*factor
50 def speak(self
, i
, text
):
51 self
.voices
[i
-1].SpeakText(text
)
54 return macspeech
.Busy()
56 [NOTHING
, NEWSCENE
, ACT
, TEXT
, MORETEXT
] = range(5)
58 stripline
= string
.strip(line
)
61 if stripline
[:5] == 'Scene':
62 return NEWSCENE
, stripline
65 if line
[0] == ' ' and ':' in line
:
66 splitline
= string
.splitfields(stripline
, ':')
67 stripline
= string
.joinfields(splitline
[1:], ':')
68 return TEXT
, (splitline
[0], string
.strip(stripline
))
69 return MORETEXT
, stripline
72 lines
= file.readlines()
77 for i
in range(len(lines
)):
78 tp
, data
= parseline(lines
[i
])
80 acts
.append(actor_dict
.keys(), lines
[prev_act
:i
])
84 actor_dict
[data
[0]] = 1
91 self
.speaker
= MacSpeaker()
94 sys
.stdin
= open('SCRIPT', 'r')
95 self
.acts
= readscript(sys
.stdin
)
97 for actorlist
, actdata
in self
.acts
:
98 if len(actorlist
) > maxactor
:
99 maxactor
= len(actorlist
)
100 if not self
.loadnextact():
101 print 'No acts to play!'
103 self
.lh
= stdwin
.lineheight()
104 self
.winheight
= (maxactor
+2)*self
.lh
105 stdwin
.setdefwinsize(WINWIDTH
, self
.winheight
)
106 self
.win
= stdwin
.open('The Play')
107 self
.win
.setdocsize(WINWIDTH
, self
.winheight
)
108 self
.win
.change(((0,0),(WINWIDTH
, self
.winheight
)))
109 self
.menu
= self
.win
.menucreate('Play')
110 self
.menu
.additem('Faster', '+')
111 self
.menu
.additem('Slower', '-')
112 self
.menu
.additem('Quit', 'Q')
119 def loadnextact(self
):
120 if not self
.acts
: return 0
121 actors
, lines
= self
.acts
[0]
124 for i
in range(len(lines
)):
128 elif tp
in (NEWSCENE
, ACT
):
131 prevactor
= actors
.index(data
[0])
132 lines
[i
] = prevactor
+1, data
[1]
134 lines
[i
] = prevactor
+1, data
136 self
.actors
= [''] + actors
137 self
.actorlines
= [''] * len(self
.actors
)
139 self
.speaker
.newvoices(len(self
.actors
)-1)
142 for a
in self
.actors
:
143 w
= stdwin
.textwidth(a
)
144 if w
> self
.actwidth
:
148 def loadnextline(self
):
149 if not self
.lines
: return 0
150 self
.actorlines
[self
.prevline
] = ''
151 top
= self
.lh
*self
.prevline
152 self
.win
.change(((0, top
), (WINWIDTH
, top
+self
.lh
)))
153 line
, data
= self
.lines
[0]
155 self
.actorlines
[line
] = data
157 top
= self
.lh
*self
.prevline
158 self
.win
.change(((0, top
), (WINWIDTH
, top
+self
.lh
)))
160 self
.win
.settimer(5*self
.speed
)
163 self
.speaker
.speak(line
, data
)
166 nwords
= len(string
.split(data
))
167 tv
= self
.speed
*(nwords
+1)
168 self
.win
.settimer(tv
)
171 def timerevent(self
):
172 if self
.speaker
and self
.speaker
.busy():
176 if self
.loadnextline(): return
177 if not self
.loadnextact():
178 stdwin
.message('The END')
181 self
.win
.change(((0,0), (WINWIDTH
, self
.winheight
)))
183 def redraw(self
, top
, bottom
, draw
):
184 for i
in range(len(self
.actors
)):
186 bpos
= (i
+1)*self
.lh
-1
187 if tpos
< bottom
and bpos
> top
:
188 draw
.setfgcolor(BLUE
)
189 draw
.text((0, tpos
), self
.actors
[i
])
193 draw
.setfgcolor(BLACK
)
194 draw
.text((self
.actwidth
+5, tpos
), self
.actorlines
[i
])
197 self
.win
.settimer(10)
199 ev
, win
, arg
= stdwin
.getevent()
201 ((left
, top
), (right
, bot
)) = arg
202 self
.redraw(top
, bot
, self
.win
.begindrawing())
208 elif ev
== WE_MENU
and arg
[0] == self
.menu
:
211 self
.speed
= self
.speed
/2
213 self
.speaker
.setrate(1.4)
215 self
.speed
= self
.speed
* 2
217 self
.speaker
.setrate(0.7)