Fawkes API  Fawkes Development Version
speechsynth_thread.cpp
00001 
00002 /***************************************************************************
00003  *  speechsynth_thread.cpp - Provide NaoQi speech synthesis to Fawkes
00004  *
00005  *  Created: Tue Jun 21 17:32:14 2011
00006  *  Copyright  2006-2011  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include "speechsynth_thread.h"
00024 
00025 #include <alcore/alerror.h>
00026 #include <alproxies/allauncherproxy.h>
00027 #include <alproxies/altexttospeechproxy.h>
00028 
00029 #include <interfaces/SpeechSynthInterface.h>
00030 
00031 using namespace fawkes;
00032 
00033 /** @class NaoQiSpeechSynthThread "motion_thread.h"
00034  * Thread to provide NaoQi motions to Fawkes.
00035  * This thread holds an ALMotion proxy and provides its capabilities via
00036  * the blackboard to other Fawkes threads.
00037  *
00038  * @author Tim Niemueller
00039  */
00040 
00041 /** Constructor. */
00042 NaoQiSpeechSynthThread::NaoQiSpeechSynthThread()
00043   : Thread("NaoQiSpeechSynthThread", Thread::OPMODE_WAITFORWAKEUP),
00044     BlockedTimingAspect(BlockedTimingAspect::WAKEUP_HOOK_ACT)
00045 {
00046 }
00047 
00048 
00049 /** Destructor. */
00050 NaoQiSpeechSynthThread::~NaoQiSpeechSynthThread()
00051 {
00052 }
00053 
00054 
00055 void
00056 NaoQiSpeechSynthThread::init()
00057 {
00058   __tts_task_id = -1;
00059 
00060   // Is ALTextToSpeech available?
00061   try {
00062     AL::ALPtr<AL::ALLauncherProxy> launcher(new AL::ALLauncherProxy(naoqi_broker));
00063     bool is_tts_available = launcher->isModulePresent("ALTextToSpeech");
00064 
00065     if (! is_tts_available) {
00066       throw Exception("NaoQi ALTextToSpeech is not available");
00067     }
00068   } catch (AL::ALError& e) {
00069     throw Exception("Checking ALTextToSpeech aliveness failed: %s",
00070                     e.toString().c_str());
00071   }
00072 
00073   __altts =
00074     AL::ALPtr<AL::ALTextToSpeechProxy>(new AL::ALTextToSpeechProxy(naoqi_broker));
00075 
00076   __speechsynth_if =
00077     blackboard->open_for_writing<SpeechSynthInterface>("NaoQi TTS");
00078 }
00079 
00080 
00081 void
00082 NaoQiSpeechSynthThread::finalize()
00083 {
00084   stop_speech();
00085 
00086   blackboard->close(__speechsynth_if);
00087   __speechsynth_if = NULL;
00088 
00089   __altts.reset();
00090 }
00091 
00092 
00093 /** Stop currently running speech synthesis. */
00094 void
00095 NaoQiSpeechSynthThread::stop_speech()
00096 {
00097   if (__tts_task_id != -1) {
00098     if (__altts->isRunning(__tts_task_id)) {
00099       __altts->stop(__tts_task_id);
00100     }
00101     __tts_task_id = -1;
00102   }
00103 }
00104 
00105 void
00106 NaoQiSpeechSynthThread::say(const char *text)
00107 {
00108   __tts_task_id = __altts->say(text);
00109 }
00110 
00111 void
00112 NaoQiSpeechSynthThread::loop()
00113 {
00114   bool working = (__tts_task_id != -1) && __altts->isRunning(__tts_task_id);
00115   if (! working) {
00116     process_messages();
00117   }
00118   __speechsynth_if->set_final( ! working );
00119   __speechsynth_if->write();
00120 }
00121 
00122 
00123 /** Process incoming BB messages. */
00124 void
00125 NaoQiSpeechSynthThread::process_messages()
00126 {
00127   // process bb messages
00128   if ( ! __speechsynth_if->msgq_empty() ) {
00129     if (SpeechSynthInterface::SayMessage *msg =
00130         __speechsynth_if->msgq_first_safe(msg))
00131     {
00132       say(msg->text());
00133       __speechsynth_if->set_msgid(msg->id());
00134     }
00135 
00136     __speechsynth_if->msgq_pop();
00137   }
00138 }