• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeaccessibility API Reference
  • KDE Home
  • Contact Us
 

jovie

  • sources
  • kde-4.12
  • kdeaccessibility
  • jovie
  • jovie
ssmlconvert.cpp
Go to the documentation of this file.
1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2  SSMLConvert class
3 
4  This class is in charge of converting SSML text into a format that can
5  be handled by individual synths.
6  -------------------
7  Copyright:
8  (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
9  (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
10  -------------------
11  Original author: Paul Giannaros <ceruleanblaze@gmail.com>
12 ******************************************************************************/
13 
14 /***************************************************************************
15  * *
16  * This program is free software; you can redistribute it and/or modify *
17  * it under the terms of the GNU General Public License as published by *
18  * the Free Software Foundation; version 2 of the License or *
19  * (at your option) any later version. *
20  * *
21  ***************************************************************************/
22 
23 // SSMLConvert includes.
24 #include "ssmlconvert.h"
25 #include "ssmlconvert.moc"
26 
27 // Qt includes.
28 #include <QtXml/qdom.h>
29 #include <QtCore/QFile>
30 #include <QtCore/QTextStream>
31 
32 // KDE includes.
33 #include <kdeversion.h>
34 #include <kstandarddirs.h>
35 #include <QProcess>
36 #include <QStringList>
37 #include <ktemporaryfile.h>
38 #include <kdebug.h>
39 
41 SSMLConvert::SSMLConvert() {
42  m_talkers = QStringList();
43  m_xsltProc = 0;
44  m_state = tsIdle;
45 }
46 
48 SSMLConvert::SSMLConvert(const QStringList &talkers) {
49  m_talkers = talkers;
50  m_xsltProc = 0;
51  m_state = tsIdle;
52 }
53 
55 SSMLConvert::~SSMLConvert() {
56  delete m_xsltProc;
57  if (!m_inFilename.isEmpty()) QFile::remove(m_inFilename);
58  if (!m_outFilename.isEmpty()) QFile::remove(m_outFilename);
59 }
60 
62 void SSMLConvert::setTalkers(const QStringList &talkers) {
63  m_talkers = talkers;
64 }
65 
66 QString SSMLConvert::extractTalker(const QString &talkercode) {
67  QString t = talkercode.section(QLatin1String( "synthesizer=" ), 1, 1);
68  t = t.section(QLatin1Char( '"' ), 1, 1);
69  if(t.contains(QLatin1String( "flite" )))
70  return QLatin1String( "flite" );
71  else
72  return t.left(t.indexOf(QLatin1String( " " ))).toLower();
73 }
74 
106 QString SSMLConvert::appropriateTalker(const QString &text) const {
107  QDomDocument ssml;
108  ssml.setContent(text, false); // No namespace processing.
110  QStringList matches = m_talkers;
111 
113  QDomElement root = ssml.documentElement();
114  if(root.tagName() != QLatin1String( "speak" )) {
115  // Not SSML.
116  return QString();
117  }
118 
125  QString talklang, talkvoice, talkgender, talkvolume, talkrate, talkname;
126 
127  kDebug() << "SSMLConvert::appropriateTalker: BEFORE LANGUAGE SEARCH: " << matches.join(QLatin1String( " " ));;
131  if(root.hasAttribute(QLatin1String( "xml:lang" ))) {
132  QString lang = root.attribute(QLatin1String( "xml:lang" ));
133  kDebug() << "SSMLConvert::appropriateTalker: xml:lang found (" << lang << ")";
135  if(lang.contains(QLatin1String( "en-" ))) {
136  kDebug() << "SSMLConvert::appropriateTalker: English";
137  lang = QLatin1String( "en" );
138  }
141  matches = matches.filter(QLatin1String( "lang=\"" ) + lang);
142  }
143  else {
144  kDebug() << "SSMLConvert::appropriateTalker: no xml:lang found. Defaulting to en..";
145  matches = matches.filter(QLatin1String( "lang=\"en" ));
146  }
147 
148  kDebug() << "SSMLConvert::appropriateTalker: AFTER LANGUAGE SEARCH: " << matches.join(QLatin1String( " " ));;
149 
155  if(root.hasAttribute(QLatin1String( "gender" ))) {
156  QString gender = root.attribute(QLatin1String( "gender" ));
157  kDebug() << "SSMLConvert::appropriateTalker: gender found (" << gender << ")";
159  if(!(gender == QLatin1String( "male" ) || gender == QLatin1String( "female" ))) {
161  if(matches.filter(QLatin1String( "gender=\"" ) + gender).count() >= 1)
162  matches = matches.filter(QLatin1String( "gender=\"" ) + gender);
163  }
164  }
165  else {
166  kDebug() << "SSMLConvert::appropriateTalker: no gender found.";
167  }
168 
175  if(matches.filter(QLatin1String( "synthesizer=\"Festival Interactive" )).count() >= 1 ||
178  matches.filter(QLatin1String( "synthesizer=\"Hadifix" )).count() >= 1) {
179 
180  kDebug() << "SSMLConvert::appropriateTalker: Prosody allowed";
181  QStringList tmpmatches = matches.filter(QLatin1String( "synthesizer=\"Festival Interactive" ));
182  matches = matches.filter(QLatin1String( "synthesizer=\"Hadifix" ));
183  matches = tmpmatches + matches;
184  }
185  else
186  kDebug() << "SSMLConvert::appropriateTalker: No prosody-supporting talkers found";
187 
190  return matches[0];
191 }
192 
206 bool SSMLConvert::transform(const QString &text, const QString &xsltFilename) {
207  m_xsltFilename = xsltFilename;
209  KTemporaryFile inFile;
210  inFile.setPrefix(QLatin1String( "kttsd-" ));
211  inFile.setSuffix(QLatin1String( ".ssml" ));
212  inFile.setAutoRemove(false);
213  inFile.open();
214  m_inFilename = inFile.fileName();
215  QTextStream wstream (&inFile);
216  // TODO: Is encoding an issue here?
217  // TODO: It would be nice if we detected whether the XML is properly formed
218  // with the required xml processing instruction and encoding attribute. If
219  // not wrap it in such. But maybe this should be handled by SpeechData::setText()?
220  wstream << text;
221  inFile.flush();
222 
223  // Get a temporary output file name.
224  KTemporaryFile outFile;
225  outFile.setPrefix(QLatin1String( "kttsd-" ));
226  outFile.setSuffix(QLatin1String( ".output" ));
227  outFile.setAutoRemove(false);
228  outFile.open();
229  m_outFilename = outFile.fileName();
230 
232  QStringList args;
233  m_xsltProc = new QProcess;
234  args << QLatin1String( "-o" ) << m_outFilename << QLatin1String( "--novalid" )
235  << m_xsltFilename << m_inFilename;
236  // Warning: This won't compile under KDE 3.2. See FreeTTS::argsToStringList().
237  // kDebug() << "SSMLConvert::transform: executing command: " <<
238  // m_xsltProc->args() << endl;
239 
240  connect(m_xsltProc, SIGNAL(finished(int,QProcess::ExitStatus)),
241  this, SLOT(slotProcessExited()));
242  if (!m_xsltProc->execute(QLatin1String("xsltproc"), args))
243  {
244  kDebug() << "SSMLConvert::transform: Error starting xsltproc";
245  return false;
246  }
247  m_state = tsTransforming;
248  return true;
249 }
250 
251 void SSMLConvert::slotProcessExited()
252 {
253  m_xsltProc->deleteLater();
254  m_xsltProc = 0;
255  m_state = tsFinished;
256  emit transformFinished();
257 }
258 
262 int SSMLConvert::getState() { return m_state; }
263 
267 QString SSMLConvert::getOutput()
268 {
270  QFile readfile(m_outFilename);
271  if(!readfile.open(QIODevice::ReadOnly)) {
273  kDebug() << "SSMLConvert::slotProcessExited: Could not read file " << m_outFilename;
274  return QString();
275  }
276  QTextStream rstream(&readfile);
277  QString convertedData = rstream.readAll();
278  readfile.close();
279 
280  // kDebug() << "SSMLConvert::slotProcessExited: Read SSML file at " + m_inFilename + " and created " + m_outFilename + " based on the stylesheet at " << m_xsltFilename;
281 
282  // Clean up.
283  QFile::remove(m_inFilename);
284  m_inFilename.clear();
285  QFile::remove(m_outFilename);
286  m_outFilename.clear();
287 
288  // Ready for another transform.
289  m_state = tsIdle;
290 
291  return convertedData;
292 }
293 
SSMLConvert::SSMLConvert
SSMLConvert()
Constructors.
Definition: ssmlconvert.cpp:41
ssmlconvert.h
SSMLConvert::tsIdle
Definition: ssmlconvert.h:51
SSMLConvert::tsTransforming
Definition: ssmlconvert.h:52
SSMLConvert::transform
bool transform(const QString &text, const QString &xsltFilename)
Applies the spreadsheet for a talker to the SSML and returns the talker-native output.
Definition: ssmlconvert.cpp:206
SSMLConvert::getState
int getState()
Returns current processing state.
Definition: ssmlconvert.cpp:262
SSMLConvert::tsFinished
Definition: ssmlconvert.h:53
SSMLConvert::~SSMLConvert
virtual ~SSMLConvert()
Destructor.
Definition: ssmlconvert.cpp:55
SSMLConvert::appropriateTalker
QString appropriateTalker(const QString &text) const
Returns the most appropriate talker for the text to synth's talker code.
Definition: ssmlconvert.cpp:106
SSMLConvert::getOutput
QString getOutput()
Returns the output from call to transform.
Definition: ssmlconvert.cpp:267
SSMLConvert::setTalkers
void setTalkers(const QStringList &talkers)
Set the talker codes to be used.
Definition: ssmlconvert.cpp:62
SSMLConvert::transformFinished
void transformFinished()
Emitted whenever tranforming is completed.
SSMLConvert::extractTalker
QString extractTalker(const QString &talkercode)
Extract the synth name from a talker code (i.e festival, flite, freetts).
Definition: ssmlconvert.cpp:66
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:32:25 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

jovie

Skip menu "jovie"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeaccessibility API Reference

Skip menu "kdeaccessibility API Reference"
  • jovie

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal