| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TTS_API_H_ |
| #define CHROME_BROWSER_EXTENSIONS_EXTENSION_TTS_API_H_ |
| |
| #include <queue> |
| #include <string> |
| |
| #include "base/singleton.h" |
| #include "base/task.h" |
| #include "chrome/browser/extensions/extension_function.h" |
| #include "chrome/browser/extensions/extension_tts_api_util.h" |
| |
| // Abstract class that defines the native platform TTS interface. |
| class ExtensionTtsPlatformImpl { |
| public: |
| static ExtensionTtsPlatformImpl* GetInstance(); |
| |
| // Speak the given utterance with the given parameters if possible, |
| // and return true on success. Utterance will always be nonempty. |
| // If the user does not specify the other values, then locale and gender |
| // will be empty strings, and rate, pitch, and volume will be -1.0. |
| // |
| // The ExtensionTtsController will only try to speak one utterance at |
| // a time. If it wants to intterupt speech, it will always call Stop |
| // before speaking again, otherwise it will wait until IsSpeaking |
| // returns false before calling Speak again. |
| virtual bool Speak( |
| const std::string& utterance, |
| const std::string& locale, |
| const std::string& gender, |
| double rate, |
| double pitch, |
| double volume) = 0; |
| |
| // Stop speaking immediately and return true on success. |
| virtual bool StopSpeaking() = 0; |
| |
| // Return true if the synthesis engine is currently speaking. |
| virtual bool IsSpeaking() = 0; |
| |
| virtual std::string error(); |
| virtual void clear_error(); |
| virtual void set_error(const std::string& error); |
| |
| protected: |
| ExtensionTtsPlatformImpl() {} |
| virtual ~ExtensionTtsPlatformImpl() {} |
| |
| std::string error_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImpl); |
| }; |
| |
| // One speech utterance. |
| class Utterance { |
| public: |
| // Construct an utterance given a profile, the text to speak, |
| // the options passed to tts.speak, and a completion task to call |
| // when the utterance is done speaking. |
| Utterance(Profile* profile, |
| const std::string& text, |
| DictionaryValue* options, |
| Task* completion_task); |
| ~Utterance(); |
| |
| // Calls the completion task and then destroys itself. |
| void FinishAndDestroy(); |
| |
| void set_error(const std::string& error) { error_ = error; } |
| void set_extension_id(const std::string& extension_id) { |
| extension_id_ = extension_id; |
| } |
| |
| // Accessors |
| Profile* profile() { return profile_; } |
| const std::string& extension_id() { return extension_id_; } |
| int id() { return id_; } |
| const std::string& text() { return text_; } |
| const Value* options() { return options_.get(); } |
| const std::string& voice_name() { return voice_name_; } |
| const std::string& locale() { return locale_; } |
| const std::string& gender() { return gender_; } |
| double rate() { return rate_; } |
| double pitch() { return pitch_; } |
| double volume() { return volume_; } |
| bool can_enqueue() { return can_enqueue_; } |
| const std::string& error() { return error_; } |
| |
| private: |
| // The profile that initiated this utterance. |
| Profile* profile_; |
| |
| // The extension ID of the extension providing TTS for this utterance, or |
| // empty if native TTS is being used. |
| std::string extension_id_; |
| |
| // The unique ID of this utterance, used to associate callback functions |
| // with utterances. |
| int id_; |
| |
| // The id of the next utterance, so we can associate requests with |
| // responses. |
| static int next_utterance_id_; |
| |
| // The text to speak. |
| std::string text_; |
| |
| // The full options arg passed to tts.speak, which may include fields |
| // other than the ones we explicitly parse, below. |
| scoped_ptr<Value> options_; |
| |
| // The parsed options. |
| std::string voice_name_; |
| std::string locale_; |
| std::string gender_; |
| double rate_; |
| double pitch_; |
| double volume_; |
| bool can_enqueue_; |
| |
| // The error string to pass to the completion task. Will be empty if |
| // no error occurred. |
| std::string error_; |
| |
| // The method to call when this utterance has completed speaking. |
| Task* completion_task_; |
| }; |
| |
| // Singleton class that manages text-to-speech. |
| class ExtensionTtsController { |
| public: |
| // Get the single instance of this class. |
| static ExtensionTtsController* GetInstance(); |
| |
| // Returns true if we're currently speaking an utterance. |
| bool IsSpeaking() const; |
| |
| // Speak the given utterance. If the utterance's can_enqueue flag is true |
| // and another utterance is in progress, adds it to the end of the queue. |
| // Otherwise, interrupts any current utterance and speaks this one |
| // immediately. |
| void SpeakOrEnqueue(Utterance* utterance); |
| |
| // Stop all utterances and flush the queue. |
| void Stop(); |
| |
| // Called when an extension finishes speaking an utterance. |
| void OnSpeechFinished(int request_id, std::string error_message); |
| |
| // For unit testing. |
| void SetPlatformImpl(ExtensionTtsPlatformImpl* platform_impl); |
| |
| private: |
| ExtensionTtsController(); |
| virtual ~ExtensionTtsController(); |
| |
| // Get the platform TTS implementation (or injected mock). |
| ExtensionTtsPlatformImpl* GetPlatformImpl(); |
| |
| // Start speaking the given utterance. Will either take ownership of |
| // |utterance| or delete it if there's an error. |
| void SpeakNow(Utterance* utterance); |
| |
| // Called periodically when speech is ongoing. Checks to see if the |
| // underlying platform speech system has finished the current utterance, |
| // and if so finishes it and pops the next utterance off the queue. |
| void CheckSpeechStatus(); |
| |
| // Clear the utterance queue. |
| void ClearUtteranceQueue(); |
| |
| // Finalize and delete the current utterance. |
| void FinishCurrentUtterance(); |
| |
| // Start speaking the next utterance in the queue. |
| void SpeakNextUtterance(); |
| |
| // Return the id string of the first extension with tts_voices in its |
| // manifest that matches the speech parameters of this utterance, |
| // or the empty string if none is found. |
| std::string GetMatchingExtensionId(Utterance* utterance); |
| |
| ScopedRunnableMethodFactory<ExtensionTtsController> method_factory_; |
| friend struct DefaultSingletonTraits<ExtensionTtsController>; |
| |
| // The current utterance being spoken. |
| Utterance* current_utterance_; |
| |
| // A queue of utterances to speak after the current one finishes. |
| std::queue<Utterance*> utterance_queue_; |
| |
| // A pointer to the platform implementation of text-to-speech, for |
| // dependency injection. |
| ExtensionTtsPlatformImpl* platform_impl_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ExtensionTtsController); |
| }; |
| |
| // |
| // Extension API function definitions |
| // |
| |
| class ExtensionTtsSpeakFunction : public AsyncExtensionFunction { |
| private: |
| ~ExtensionTtsSpeakFunction() {} |
| virtual bool RunImpl(); |
| void SpeechFinished(); |
| Utterance* utterance_; |
| DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.speak") |
| }; |
| |
| class ExtensionTtsStopSpeakingFunction : public SyncExtensionFunction { |
| private: |
| ~ExtensionTtsStopSpeakingFunction() {} |
| virtual bool RunImpl(); |
| DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.stop") |
| }; |
| |
| class ExtensionTtsIsSpeakingFunction : public SyncExtensionFunction { |
| private: |
| ~ExtensionTtsIsSpeakingFunction() {} |
| virtual bool RunImpl(); |
| DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.isSpeaking") |
| }; |
| |
| class ExtensionTtsSpeakCompletedFunction : public SyncExtensionFunction { |
| private: |
| ~ExtensionTtsSpeakCompletedFunction() {} |
| virtual bool RunImpl(); |
| DECLARE_EXTENSION_FUNCTION_NAME("experimental.tts.speakCompleted") |
| }; |
| |
| #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_TTS_API_H_ |