speechclient.cpp
00001 /* 00002 This file is part of Akregator. 00003 00004 Copyright (C) 2005 Frank Osterfeld <frank.osterfeld at kdemail.net> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 00020 As a special exception, permission is given to link this program 00021 with any edition of TQt, and distribute the resulting executable, 00022 without including the source code for TQt in the source distribution. 00023 */ 00024 00025 #include "article.h" 00026 #include "speechclient.h" 00027 #include "utils.h" 00028 00029 #include <dcopclient.h> 00030 #include <kapplication.h> 00031 #include <kcharsets.h> 00032 #include <klocale.h> 00033 #include <kdebug.h> 00034 #include <kstaticdeleter.h> 00035 #include <ktrader.h> 00036 00037 #include <tqstring.h> 00038 #include <tqvaluelist.h> 00039 00040 namespace Akregator 00041 { 00042 00043 class SpeechClient::SpeechClientPrivate 00044 { 00045 public: 00046 00047 bool isTextSpeechInstalled; 00048 TQValueList<uint> pendingJobs; 00049 }; 00050 00051 SpeechClient* SpeechClient::m_self = 0; 00052 00053 static KStaticDeleter<SpeechClient> speechclsd; 00054 00055 SpeechClient* SpeechClient::self() 00056 { 00057 if (!m_self) 00058 m_self = speechclsd.setObject(m_self, new SpeechClient); 00059 return m_self; 00060 } 00061 00062 00063 SpeechClient::SpeechClient() : DCOPStub("kttsd", "KSpeech"), DCOPObject("akregatorpart_kspeechsink"), TQObject(), d(new SpeechClientPrivate) 00064 { 00065 d->isTextSpeechInstalled = false; 00066 setupSpeechSystem(); 00067 } 00068 00069 SpeechClient::~SpeechClient() 00070 { 00071 delete d; 00072 d = 0; 00073 } 00074 00075 void SpeechClient::slotSpeak(const TQString& text, const TQString& language) 00076 { 00077 if (!isTextToSpeechInstalled() || text.isEmpty()) 00078 return; 00079 uint jobNum = setText(text, language); 00080 startText(jobNum); 00081 d->pendingJobs.append(jobNum); 00082 if (d->pendingJobs.count() == 1) 00083 { 00084 emit signalJobsStarted(); 00085 emit signalActivated(true); 00086 } 00087 } 00088 00089 void SpeechClient::slotSpeak(const Article& article) 00090 { 00091 if (!isTextToSpeechInstalled() || article.isNull()) 00092 return; 00093 00094 TQString speakMe; 00095 speakMe += KCharsets::resolveEntities(Utils::stripTags((article).title())) 00096 + ". . . . " 00097 + KCharsets::resolveEntities(Utils::stripTags((article).description())); 00098 slotSpeak(speakMe, "en"); 00099 } 00100 00101 void SpeechClient::slotSpeak(const TQValueList<Article>& articles) 00102 { 00103 if (!isTextToSpeechInstalled() || articles.isEmpty()) 00104 return; 00105 00106 TQString speakMe; 00107 00108 for (TQValueList<Article>::ConstIterator it = articles.begin(); it != articles.end(); ++it) 00109 { 00110 if (!speakMe.isEmpty()) 00111 speakMe += ". . . . . . " + i18n("Next Article: "); 00112 speakMe += KCharsets::resolveEntities(Utils::stripTags((*it).title())) 00113 + ". . . . " 00114 + KCharsets::resolveEntities(Utils::stripTags((*it).description())); 00115 } 00116 00117 SpeechClient::self()->slotSpeak(speakMe, "en"); 00118 } 00119 00120 void SpeechClient::slotAbortJobs() 00121 { 00122 if (!d->pendingJobs.isEmpty()) 00123 { 00124 for (TQValueList<uint>::ConstIterator it = d->pendingJobs.begin(); it != d->pendingJobs.end(); ++it) 00125 { 00126 removeText(*it); 00127 } 00128 00129 d->pendingJobs.clear(); 00130 emit signalJobsDone(); 00131 emit signalActivated(false); 00132 } 00133 } 00134 00135 ASYNC SpeechClient::textRemoved(const TQCString& /*appId*/, uint jobNum) 00136 { 00137 kdDebug() << "SpeechClient::textRemoved() called" << endl; 00138 if (d->pendingJobs.contains(jobNum)) 00139 { 00140 d->pendingJobs.remove(jobNum); 00141 if (d->pendingJobs.isEmpty()) 00142 { 00143 emit signalJobsDone(); 00144 emit signalActivated(false); 00145 } 00146 } 00147 } 00148 00149 bool SpeechClient::isTextToSpeechInstalled() const 00150 { 00151 return d->isTextSpeechInstalled; 00152 } 00153 00154 void SpeechClient::setupSpeechSystem() 00155 { 00156 KTrader::OfferList offers = KTrader::self()->query("DCOP/Text-to-Speech", "Name == 'KTTSD'"); 00157 if (offers.count() == 0) 00158 { 00159 kdDebug() << "KTTSD not installed, disable support" << endl; 00160 d->isTextSpeechInstalled = false; 00161 } 00162 else 00163 { 00164 DCOPClient* client = dcopClient(); 00165 //client->attach(); 00166 if (client->isApplicationRegistered("kttsd")) 00167 { 00168 d->isTextSpeechInstalled = true; 00169 } 00170 else 00171 { 00172 TQString error; 00173 if (KApplication::startServiceByDesktopName("kttsd", TQStringList(), &error)) 00174 { 00175 kdDebug() << "Starting KTTSD failed with message " << error << endl; 00176 d->isTextSpeechInstalled = false; 00177 } 00178 else 00179 { 00180 d->isTextSpeechInstalled = true; 00181 } 00182 } 00183 } 00184 if (d->isTextSpeechInstalled) 00185 { 00186 00187 bool c = connectDCOPSignal("kttsd", "KSpeech", 00188 "textRemoved(TQCString, uint)", 00189 "textRemoved(TQCString, uint)", 00190 false); 00191 if (!c) 00192 kdDebug() << "SpeechClient::setupSpeechSystem(): connecting signals failed" << endl; 00193 c = connectDCOPSignal("kttsd", "KSpeech", 00194 "textFinished(TQCString, uint)", 00195 "textRemoved(TQCString, uint)", 00196 false); 00197 } 00198 } 00199 00200 00201 } // namespace Akregator 00202 00203 #include "speechclient.moc"