97 #include <yarp/os/all.h>
100 using namespace yarp::os;
104 class MouthHandler :
public PeriodicThread
107 RpcClient emotions,r1;
109 double t0, duration, equalize_time;
115 if (emotions.getOutputCount()>0)
118 cmd.addVocab32(
"set");
119 cmd.addVocab32(
"mou");
120 cmd.addVocab32(state);
121 emotions.write(cmd,reply);
130 if (equalize_time>0.)
131 Time::delay(equalize_time);
147 if (Time::now()-t0>=duration)
155 if (r1.getOutputCount()>0)
158 cmd.addVocab32(
"tstart");
169 emotions.interrupt();
177 MouthHandler() : PeriodicThread(1.0), duration(-1.0), equalize(false) { }
180 void configure(ResourceFinder &rf)
182 string name=rf.find(
"name").asString();
183 equalize_time=rf.check(
"equalize_time",Value(0.)).asFloat64();
184 equalize_time=std::max(0.,equalize_time);
185 emotions.open(
"/"+name+
"/emotions:o");
186 r1.open(
"/"+name+
"/r1:rpc");
189 setPeriod((
double)rf.check(
"period",Value(200)).asInt32()/1000.0);
193 void setAutoSuspend(
const double duration)
195 this->duration=duration;
202 if (r1.getOutputCount()>0)
205 cmd.addVocab32(
"tstart");
210 PeriodicThread::resume();
219 PeriodicThread::suspend();
221 lock_guard<mutex> lg(mtx);
225 if (r1.getOutputCount()>0)
228 cmd.addVocab32(
"tstop");
236 class iSpeak :
protected BufferedPort<Bottle>,
237 public PeriodicThread,
242 string package_options;
243 deque<Bottle> buffer;
252 void report(
const PortInfo &info)
254 if (info.created && !info.incoming)
259 void onRead(Bottle &request)
261 lock_guard<mutex> lg(mtx);
262 buffer.push_back(request);
278 if (speechdev.asPort().isOpen())
285 void execSpeechDevOptions()
287 lock_guard<mutex> lg(mtx);
288 if (speechdev.getOutputCount()>0)
290 Bottle options(package_options);
291 for (
int i=0; i<options.size(); i++)
293 if (Bottle *opt=options.get(i).asList())
297 yInfo(
"Setting option: %s",cmd.toString().c_str());
298 speechdev.write(cmd,rep);
299 yInfo(
"Received reply: %s",rep.toString().c_str());
306 void speak(
const string &phrase)
308 lock_guard<mutex> lg(mtx);
309 if (speechdev.asPort().isOpen())
311 if (speechdev.getOutputCount()>0)
314 cmd.addString(
"say");
315 cmd.addString(phrase);
316 speechdev.write(cmd,rep);
321 string command(
"echo \"");
327 if (package==
"festival")
330 command+=package_options;
331 int ret=system(command.c_str());
340 bool onlyMouth=
false;
341 int rate=(int)(1000.0*mouth.getPeriod());
342 bool resetRate=
false;
343 double duration=-1.0;
348 Bottle request=buffer.front();
351 if (request.size()>0)
353 if (request.get(0).isString())
354 phrase=request.get(0).asString();
355 else if (request.get(0).isFloat64() || request.get(0).isInt32())
357 time=request.get(0).asFloat64();
361 if (request.size()>1)
363 if (request.get(1).isInt32())
365 int newRate=request.get(1).asInt32();
368 mouth.setPeriod((
double)newRate/1000.0);
373 if ((request.size()>2) && request.get(0).isString())
374 if (request.get(2).isFloat64() || request.get(2).isInt32())
375 duration=request.get(2).asFloat64();
383 mouth.setAutoSuspend(duration);
384 if (mouth.isSuspended())
396 mouth.setPeriod((
double)rate/1000.0);
398 lock_guard<mutex> lg(mtx);
399 if (buffer.size()==0)
405 yInfo(
"Setting options at connection time");
406 execSpeechDevOptions();
413 iSpeak() : PeriodicThread(0.2)
420 void configure(ResourceFinder &rf)
422 name=rf.find(
"name").asString();
423 package=rf.find(
"package").asString();
424 package_options=rf.find(
"package_options").asString();
428 if (package==
"speech-dev")
430 speechdev.open(
"/"+name+
"/speech-dev/rpc");
431 speechdev.setReporter(*
this);
434 yInfo(
"iSpeak wraps around \"%s\" speech synthesizer",package.c_str());
435 yInfo(
"starting command-line options: \"%s\"",package_options.c_str());
441 lock_guard<mutex> lg(mtx);
446 string get_package_options()
const
448 return package_options;
452 void set_package_options(
const string &package_options)
454 this->package_options=package_options;
455 if (speechdev.asPort().isOpen())
456 execSpeechDevOptions();
462 class Launcher:
public RFModule
470 bool configure(ResourceFinder &rf)
472 speaker.configure(rf);
473 if (!speaker.start())
476 string name=rf.find(
"name").asString();
477 rpc.open(
"/"+name+
"/rpc");
492 bool respond(
const Bottle &command, Bottle &reply)
494 int cmd0=command.get(0).asVocab32();
495 if (cmd0==Vocab32::encode(
"stat"))
497 reply.addString(speaker.isSpeaking()?
"speaking":
"quiet");
501 if (command.size()>1)
503 int cmd1=command.get(1).asVocab32();
504 if (cmd1==Vocab32::encode(
"opt"))
506 if (cmd0==Vocab32::encode(
"set"))
508 if (command.size()>2)
510 string cmd2=command.get(2).asString();
511 speaker.set_package_options(cmd2);
512 reply.addString(
"ack");
516 else if (cmd0==Vocab32::encode(
"get"))
518 reply.addString(speaker.get_package_options());
524 return RFModule::respond(command,reply);
542 int main(
int argc,
char *argv[])
545 if (!yarp.checkNetwork())
547 yError(
"YARP server not available!");
552 rf.setDefault(
"name",
"iSpeak");
553 rf.setDefault(
"package",
"speech-dev");
554 rf.setDefault(
"package_options",
"");
555 rf.configure(argc,argv);
558 return launcher.runModule(rf);