5 * Created by jan truetzschler v. falkenstein on Wed Apr 16 2003.
6 * Copyright (c) 2003 sampleAndHold.org. All rights reserved.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <Carbon/Carbon.h>
26 #include "InitAlloc.h"
29 #include "VMGlobals.h"
30 #include "PyrSymbolTable.h"
31 #include "PyrInterpreter.h"
32 #include "PyrKernel.h"
34 #include "PyrPrimitive.h"
35 #include "PyrObjectProto.h"
36 #include "PyrPrimitiveProto.h"
37 #include "PyrKernelProto.h"
38 #include "SC_InlineUnaryOp.h"
39 #include "SC_InlineBinaryOp.h"
46 const int kMaxSpeechChannels
= 32;
48 PyrSymbol
* s_speechwordAction
;
49 PyrSymbol
* s_speechdoneAction
;
50 SpeechChannel fCurSpeechChannel
[kMaxSpeechChannels
];
51 char *speechStrings
[kMaxSpeechChannels
];
53 pascal void OurSpeechDoneCallBackProc ( SpeechChannel inSpeechChannel
, long inRefCon
);
54 pascal void OurSpeechDoneCallBackProc ( SpeechChannel inSpeechChannel
, long inRefCon
)
58 pthread_mutex_lock (&gLangMutex
);
59 VMGlobals
*g
= gMainVMGlobals
;
61 ++g
->sp
; SetObject(g
->sp
, s_speech
->u
.classobj
); // Set the class
63 ++g
->sp
;SetInt(g
->sp
, (int) inRefCon
); //src
64 runInterpreter(g
, s_speechdoneAction
, 2);
65 if(speechStrings
[(int) inRefCon
] != NULL
){
66 free(speechStrings
[(int) inRefCon
]);
67 speechStrings
[(int) inRefCon
] = NULL
;
70 pthread_mutex_unlock (&gLangMutex
);
73 pascal void OurWordCallBackProc ( SpeechChannel inSpeechChannel
, long inRefCon
, long inWordPos
, short inWordLen
);
74 pascal void OurWordCallBackProc ( SpeechChannel inSpeechChannel
, long inRefCon
, long inWordPos
, short inWordLen
) {
76 pthread_mutex_lock (&gLangMutex
);
77 VMGlobals
*g
= gMainVMGlobals
;
79 ++g
->sp
; SetObject(g
->sp
, s_speech
->u
.classobj
);
81 ++g
->sp
; SetInt(g
->sp
, (int) inRefCon
); //src
82 runInterpreter(g
, s_speechwordAction
, 2);
85 pthread_mutex_unlock (&gLangMutex
);
88 int prInitSpeech(struct VMGlobals
*g
, int numArgsPushed
);
89 int prInitSpeech(struct VMGlobals
*g
, int numArgsPushed
){
92 //PyrSlot *a = g->sp-1;
96 if (chan
< 0 || chan
>= kMaxSpeechChannels
) return errIndexOutOfRange
;
98 for (int i
=0; i
<chan
; ++i
) {
99 if(fCurSpeechChannel
[i
]) DisposeSpeechChannel(fCurSpeechChannel
[i
]);
100 NewSpeechChannel( NULL
, fCurSpeechChannel
+i
);
101 theErr
= SetSpeechInfo (fCurSpeechChannel
[i
], soSpeechDoneCallBack
, (const void*)OurSpeechDoneCallBackProc
);
102 theErr
= SetSpeechInfo (fCurSpeechChannel
[i
], soWordCallBack
, (const void*)OurWordCallBackProc
);
103 theErr
= SetSpeechInfo (fCurSpeechChannel
[i
], soRefCon
, (void*) i
);
108 //NewSpeechDoneUPP(SpeechDoneProcPtr userRoutine);
109 //theErr = SetSpeechInfo (fCurSpeechChannel, soSpeechDoneCallBack, OurSpeechDoneCallBackProc);
111 int prSpeakText(struct VMGlobals
*g
, int numArgsPushed
);
112 int prSpeakText(struct VMGlobals
*g
, int numArgsPushed
){
114 OSErr theErr
= noErr
;
115 PyrSlot
*obj
= g
->sp
-2;
116 PyrSlot
*a
= g
->sp
-1;
117 PyrSlot
*str
= g
->sp
;
122 slotIntVal(a
, &chan
);
123 chan
= sc_clip(chan
, 0, kMaxSpeechChannels
);
124 if(speechStrings
[chan
] != NULL
) {
125 post("voice %i already speaking\n", chan
);
128 // speechStrings[chan] = (char*)pyr_pool_compile->Alloc((slotRawObject(a)->size + 1)* sizeof(char));
129 speechStrings
[chan
] = (char*) malloc((slotRawObject(str
)->size
+ 1)* sizeof(char));
131 MEMFAIL(speechStrings
[chan
]);
132 slotStrVal(str
, speechStrings
[chan
], slotRawObject(str
)->size
+1);
134 //if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel );
135 theErr
= SpeakText( fCurSpeechChannel
[chan
], speechStrings
[chan
], strlen(speechStrings
[chan
]));
136 //should be freed only after the text was spoken!
137 // todo move this bit to the callback!
138 // pyr_pool_compile->Free(theTextToSpeak);
143 int prSetSpeechRate(struct VMGlobals
*g
, int numArgsPushed
);
144 int prSetSpeechRate(struct VMGlobals
*g
, int numArgsPushed
){
146 OSErr theErr
= noErr
;
147 //PyrSlot *a = g->sp-2;
148 PyrSlot
*b
= g
->sp
-1;
152 slotIntVal(b
, &chan
);
153 slotDoubleVal(c
, &val
);
154 Fixed newRate
= (Fixed
)(val
* 65536.0);
155 // if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel );
156 theErr
= SetSpeechInfo (fCurSpeechChannel
[chan
], soRate
, &newRate
);
160 int prSetSpeechPitch(struct VMGlobals
*g
, int numArgsPushed
);
161 int prSetSpeechPitch(struct VMGlobals
*g
, int numArgsPushed
){
163 OSErr theErr
= noErr
;
164 //PyrSlot *a = g->sp-2;
165 PyrSlot
*b
= g
->sp
-1;
169 slotIntVal(b
, &chan
);
170 slotDoubleVal(c
, &val
);
171 Fixed newVal
= (Fixed
)(val
* 65536.0);
172 //if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel );
173 theErr
= SetSpeechPitch (fCurSpeechChannel
[chan
], newVal
);
177 int prSetSpeechPitchMod(struct VMGlobals
*g
, int numArgsPushed
);
178 int prSetSpeechPitchMod(struct VMGlobals
*g
, int numArgsPushed
){
180 OSErr theErr
= noErr
;
181 //PyrSlot *a = g->sp-2;
182 PyrSlot
*b
= g
->sp
-1;
186 slotIntVal(b
, &chan
);
187 slotDoubleVal(c
, &val
);
188 Fixed newVal
= (Fixed
)(val
* 65536.0);
189 // if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel );
190 theErr
= SetSpeechInfo (fCurSpeechChannel
[chan
], soPitchMod
, &newVal
);
194 int prSetSpeechVolume(struct VMGlobals
*g
, int numArgsPushed
);
195 int prSetSpeechVolume(struct VMGlobals
*g
, int numArgsPushed
) {
197 OSErr theErr
= noErr
;
198 //PyrSlot *a = g->sp-2;
199 PyrSlot
*b
= g
->sp
-1;
203 slotIntVal(b
, &chan
);
204 slotDoubleVal(c
, &val
);
205 Fixed newVal
= (Fixed
)(val
* 65536.0);
206 // if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel );
207 theErr
= SetSpeechInfo (fCurSpeechChannel
[chan
], soVolume
, &newVal
);
211 // theErr = PauseSpeechAt (fCurSpeechChannel, kImmediate);
212 // theErr = ContinueSpeech (fCurSpeechChannel);
213 int prSetSpeechPause(struct VMGlobals
*g
, int numArgsPushed
);
214 int prSetSpeechPause(struct VMGlobals
*g
, int numArgsPushed
){
216 OSErr theErr
= noErr
;
217 //PyrSlot *a = g->sp-2;
218 PyrSlot
*b
= g
->sp
-1;
222 slotIntVal(b
, &chan
);
224 //Fixed newVal = (Fixed)(val * 65536.0);
226 theErr
= ContinueSpeech(fCurSpeechChannel
[chan
] );
228 theErr
= PauseSpeechAt(fCurSpeechChannel
[chan
], kImmediate
);
233 int prSetSpeechStop(struct VMGlobals
*g
, int numArgsPushed
);
234 int prSetSpeechStop(struct VMGlobals
*g
, int numArgsPushed
){
236 OSErr theErr
= noErr
;
237 //PyrSlot *a = g->sp-2;
238 PyrSlot
*b
= g
->sp
-1;
240 int selector
[3] = {kImmediate
, kEndOfWord
, kEndOfWord
};
243 slotIntVal(b
, &chan
);
245 StopSpeechAt(fCurSpeechChannel
[chan
], selector
[val
]);
246 if(speechStrings
[chan
] != NULL
) {
247 free(speechStrings
[chan
]);
248 speechStrings
[chan
] = NULL
;
254 int prSetSpeechVoice(struct VMGlobals
*g
, int numArgsPushed
);
255 int prSetSpeechVoice(struct VMGlobals
*g
, int numArgsPushed
){
257 OSErr theErr
= noErr
;
258 //PyrSlot *a = g->sp-2;
259 PyrSlot
*b
= g
->sp
-1;
264 VoiceSpec theVoiceSpec
;
265 slotIntVal(b
, &chan
);
267 theErr
= GetIndVoice (val
, &theVoiceSpec
);
268 if (SetSpeechInfo (fCurSpeechChannel
[chan
], soCurrentVoice
, &theVoiceSpec
) == incompatibleVoice
) return (!errNone
);
273 int prSpeechVoiceIsSpeaking(struct VMGlobals
*g
, int numArgsPushed
);
274 int prSpeechVoiceIsSpeaking(struct VMGlobals
*g
, int numArgsPushed
){
275 PyrSlot
*out
= g
->sp
-1;
278 slotIntVal(b
, &chan
);
279 if(speechStrings
[chan
] != NULL
) SetTrue(out
);
285 void initSpeechPrimitives ()
289 base
= nextPrimitiveIndex();
292 s_speechwordAction
= getsym("doWordAction");
293 s_speechdoneAction
= getsym("doSpeechDoneAction");
294 s_speech
= getsym("Speech");
296 definePrimitive(base
, index
++, "_SpeakText", prSpeakText
, 3, 0);
297 definePrimitive(base
, index
++, "_InitSpeech", prInitSpeech
, 2, 0);
298 definePrimitive(base
, index
++, "_SetSpeechRate", prSetSpeechRate
, 3, 0);
299 definePrimitive(base
, index
++, "_SetSpeechPitch", prSetSpeechPitch
, 3, 0);
300 definePrimitive(base
, index
++, "_SetSpeechPitchMod", prSetSpeechPitchMod
, 3, 0);
301 definePrimitive(base
, index
++, "_SetSpeechVoice", prSetSpeechVoice
, 3, 0);
302 definePrimitive(base
, index
++, "_SetSpeechVolume", prSetSpeechVolume
, 3, 0);
303 definePrimitive(base
, index
++, "_SetSpeechPause", prSetSpeechPause
, 3, 0); //0 pause, 1 continue
304 definePrimitive(base
, index
++, "_SetSpeechStopAt", prSetSpeechStop
, 3, 0); //0 kImmediate, 1 kEndOfWord, 2 kEndOfSentence
305 definePrimitive(base
, index
++, "_SpeechVoiceIsSpeaking", prSpeechVoiceIsSpeaking
, 2, 0);
306 for(int i
=0; i
<kMaxSpeechChannels
; ++i
){
307 speechStrings
[i
] = NULL
;
308 if(fCurSpeechChannel
[i
]) DisposeSpeechChannel(fCurSpeechChannel
[i
]);
309 fCurSpeechChannel
[i
] = NULL
;