• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TTS_API_H_
6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_TTS_API_H_
7 
8 #include <queue>
9 #include <string>
10 
11 #include "base/memory/singleton.h"
12 #include "base/task.h"
13 #include "chrome/browser/extensions/extension_function.h"
14 #include "chrome/browser/extensions/extension_tts_api_util.h"
15 
16 // Abstract class that defines the native platform TTS interface.
17 class ExtensionTtsPlatformImpl {
18  public:
19   static ExtensionTtsPlatformImpl* GetInstance();
20 
21   // Speak the given utterance with the given parameters if possible,
22   // and return true on success. Utterance will always be nonempty.
23   // If the user does not specify the other values, then locale and gender
24   // will be empty strings, and rate, pitch, and volume will be -1.0.
25   //
26   // The ExtensionTtsController will only try to speak one utterance at
27   // a time. If it wants to interrupt speech, it will always call Stop
28   // before speaking again, otherwise it will wait until IsSpeaking
29   // returns false before calling Speak again.
30   virtual bool Speak(
31       const std::string& utterance,
32       const std::string& locale,
33       const std::string& gender,
34       double rate,
35       double pitch,
36       double volume) = 0;
37 
38   // Stop speaking immediately and return true on success.
39   virtual bool StopSpeaking() = 0;
40 
41   // Return true if the synthesis engine is currently speaking.
42   virtual bool IsSpeaking() = 0;
43 
44   virtual std::string error();
45   virtual void clear_error();
46   virtual void set_error(const std::string& error);
47 
48  protected:
ExtensionTtsPlatformImpl()49   ExtensionTtsPlatformImpl() {}
~ExtensionTtsPlatformImpl()50   virtual ~ExtensionTtsPlatformImpl() {}
51 
52   std::string error_;
53 
54   DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImpl);
55 };
56 
57 // One speech utterance.
58 class Utterance {
59  public:
60   // Construct an utterance given a profile, the text to speak,
61   // the options passed to tts.speak, and a completion task to call
62   // when the utterance is done speaking.
63   Utterance(Profile* profile,
64             const std::string& text,
65             DictionaryValue* options,
66             Task* completion_task);
67   ~Utterance();
68 
69   // Calls the completion task and then destroys itself.
70   void FinishAndDestroy();
71 
set_error(const std::string & error)72   void set_error(const std::string& error) { error_ = error; }
set_extension_id(const std::string & extension_id)73   void set_extension_id(const std::string& extension_id) {
74     extension_id_ = extension_id;
75   }
76 
77   // Accessors
profile()78   Profile* profile() { return profile_; }
extension_id()79   const std::string& extension_id() { return extension_id_; }
id()80   int id() { return id_; }
text()81   const std::string& text() { return text_; }
options()82   const Value* options() { return options_.get(); }
voice_name()83   const std::string& voice_name() { return voice_name_; }
locale()84   const std::string& locale() { return locale_; }
gender()85   const std::string& gender() { return gender_; }
rate()86   double rate() { return rate_; }
pitch()87   double pitch() { return pitch_; }
volume()88   double volume() { return volume_; }
can_enqueue()89   bool can_enqueue() { return can_enqueue_; }
error()90   const std::string& error() { return error_; }
91 
92  private:
93   // The profile that initiated this utterance.
94   Profile* profile_;
95 
96   // The extension ID of the extension providing TTS for this utterance, or
97   // empty if native TTS is being used.
98   std::string extension_id_;
99 
100   // The unique ID of this utterance, used to associate callback functions
101   // with utterances.
102   int id_;
103 
104   // The id of the next utterance, so we can associate requests with
105   // responses.
106   static int next_utterance_id_;
107 
108   // The text to speak.
109   std::string text_;
110 
111   // The full options arg passed to tts.speak, which may include fields
112   // other than the ones we explicitly parse, below.
113   scoped_ptr<Value> options_;
114 
115   // The parsed options.
116   std::string voice_name_;
117   std::string locale_;
118   std::string gender_;
119   double rate_;
120   double pitch_;
121   double volume_;
122   bool can_enqueue_;
123 
124   // The error string to pass to the completion task. Will be empty if
125   // no error occurred.
126   std::string error_;
127 
128   // The method to call when this utterance has completed speaking.
129   Task* completion_task_;
130 };
131 
132 // Singleton class that manages text-to-speech.
133 class ExtensionTtsController {
134  public:
135   // Get the single instance of this class.
136   static ExtensionTtsController* GetInstance();
137 
138   // Returns true if we're currently speaking an utterance.
139   bool IsSpeaking() const;
140 
141   // Speak the given utterance. If the utterance's can_enqueue flag is true
142   // and another utterance is in progress, adds it to the end of the queue.
143   // Otherwise, interrupts any current utterance and speaks this one
144   // immediately.
145   void SpeakOrEnqueue(Utterance* utterance);
146 
147   // Stop all utterances and flush the queue.
148   void Stop();
149 
150   // Called when an extension finishes speaking an utterance.
151   void OnSpeechFinished(int request_id, const std::string& error_message);
152 
153   // For unit testing.
154   void SetPlatformImpl(ExtensionTtsPlatformImpl* platform_impl);
155 
156  private:
157   ExtensionTtsController();
158   virtual ~ExtensionTtsController();
159 
160   // Get the platform TTS implementation (or injected mock).
161   ExtensionTtsPlatformImpl* GetPlatformImpl();
162 
163   // Start speaking the given utterance. Will either take ownership of
164   // |utterance| or delete it if there's an error.
165   void SpeakNow(Utterance* utterance);
166 
167   // Called periodically when speech is ongoing. Checks to see if the
168   // underlying platform speech system has finished the current utterance,
169   // and if so finishes it and pops the next utterance off the queue.
170   void CheckSpeechStatus();
171 
172   // Clear the utterance queue.
173   void ClearUtteranceQueue();
174 
175   // Finalize and delete the current utterance.
176   void FinishCurrentUtterance();
177 
178   // Start speaking the next utterance in the queue.
179   void SpeakNextUtterance();
180 
181   // Return the id string of the first extension with tts_voices in its
182   // manifest that matches the speech parameters of this utterance,
183   // or the empty string if none is found.
184   std::string GetMatchingExtensionId(Utterance* utterance);
185 
186   ScopedRunnableMethodFactory<ExtensionTtsController> method_factory_;
187   friend struct DefaultSingletonTraits<ExtensionTtsController>;
188 
189   // The current utterance being spoken.
190   Utterance* current_utterance_;
191 
192   // A queue of utterances to speak after the current one finishes.
193   std::queue<Utterance*> utterance_queue_;
194 
195   // A pointer to the platform implementation of text-to-speech, for
196   // dependency injection.
197   ExtensionTtsPlatformImpl* platform_impl_;
198 
199   DISALLOW_COPY_AND_ASSIGN(ExtensionTtsController);
200 };
201 
202 //
203 // Extension API function definitions
204 //
205 
206 class ExtensionTtsSpeakFunction : public AsyncExtensionFunction {
207  private:
208   ~ExtensionTtsSpeakFunction() {}
209   virtual bool RunImpl();
210   void SpeechFinished();
211   Utterance* utterance_;
212   DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.speak")
213 };
214 
215 class ExtensionTtsStopSpeakingFunction : public SyncExtensionFunction {
216  private:
217   ~ExtensionTtsStopSpeakingFunction() {}
218   virtual bool RunImpl();
219   DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.stop")
220 };
221 
222 class ExtensionTtsIsSpeakingFunction : public SyncExtensionFunction {
223  private:
224   ~ExtensionTtsIsSpeakingFunction() {}
225   virtual bool RunImpl();
226   DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.isSpeaking")
227 };
228 
229 class ExtensionTtsSpeakCompletedFunction : public SyncExtensionFunction {
230  private:
231   ~ExtensionTtsSpeakCompletedFunction() {}
232   virtual bool RunImpl();
233   DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.speakCompleted")
234 };
235 
236 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TTS_API_H_
237