| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 #include "chrome/browser/extensions/extension_tts_api_chromeos.h" | |
| 6 | |
| 7 #include <list> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/memory/singleton.h" | |
| 11 #include "base/memory/weak_ptr.h" | |
| 12 #include "base/message_loop.h" | |
| 13 #include "base/stl_util.h" | |
| 14 #include "base/string_number_conversions.h" | |
| 15 #include "chrome/browser/chromeos/dbus/dbus_thread_manager.h" | |
| 16 #include "chrome/browser/chromeos/dbus/speech_synthesizer_client.h" | |
| 17 #include "chrome/browser/extensions/extension_tts_api_controller.h" | |
| 18 #include "chrome/browser/extensions/extension_tts_api_platform.h" | |
| 19 | |
| 20 using base::DoubleToString; | |
| 21 | |
| 22 namespace { | |
| 23 const int kSpeechCheckDelayIntervalMs = 100; | |
| 24 }; | |
| 25 | |
| 26 // Very simple queue of utterances that can't be spoken because audio | |
| 27 // isn't initialized yet. | |
| 28 struct QueuedUtterance { | |
| 29 int utterance_id; | |
| 30 std::string utterance; | |
| 31 std::string lang; | |
| 32 UtteranceContinuousParameters params; | |
| 33 }; | |
| 34 | |
| 35 class ExtensionTtsPlatformImplChromeOs | |
| 36 : public ExtensionTtsPlatformImpl { | |
| 37 public: | |
| 38 virtual bool PlatformImplAvailable() { | |
| 39 return true; | |
| 40 } | |
| 41 | |
| 42 virtual bool Speak( | |
| 43 int utterance_id, | |
| 44 const std::string& utterance, | |
| 45 const std::string& lang, | |
| 46 const UtteranceContinuousParameters& params); | |
| 47 | |
| 48 virtual bool StopSpeaking(); | |
| 49 | |
| 50 virtual bool SendsEvent(TtsEventType event_type); | |
| 51 | |
| 52 // Get the single instance of this class. | |
| 53 static ExtensionTtsPlatformImplChromeOs* GetInstance(); | |
| 54 | |
| 55 // TTS won't begin until this is called. | |
| 56 void Enable(); | |
| 57 | |
| 58 private: | |
| 59 ExtensionTtsPlatformImplChromeOs(); | |
| 60 virtual ~ExtensionTtsPlatformImplChromeOs() {} | |
| 61 | |
| 62 void PollUntilSpeechFinishes(int utterance_id); | |
| 63 void ContinuePollingIfSpeechIsNotFinished(int utterance_id, bool result); | |
| 64 | |
| 65 void AppendSpeakOption(std::string key, | |
| 66 std::string value, | |
| 67 std::string* options); | |
| 68 | |
| 69 int utterance_id_; | |
| 70 int utterance_length_; | |
| 71 std::list<QueuedUtterance*> queued_utterances_; | |
| 72 bool enabled_; | |
| 73 base::WeakPtrFactory<ExtensionTtsPlatformImplChromeOs> weak_ptr_factory_; | |
| 74 | |
| 75 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplChromeOs>; | |
| 76 | |
| 77 DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplChromeOs); | |
| 78 }; | |
| 79 | |
| 80 // static | |
| 81 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() { | |
| 82 return ExtensionTtsPlatformImplChromeOs::GetInstance(); | |
| 83 } | |
| 84 | |
| 85 ExtensionTtsPlatformImplChromeOs::ExtensionTtsPlatformImplChromeOs() | |
| 86 : enabled_(false), | |
| 87 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
| 88 } | |
| 89 | |
| 90 bool ExtensionTtsPlatformImplChromeOs::Speak( | |
| 91 int utterance_id, | |
| 92 const std::string& utterance, | |
| 93 const std::string& lang, | |
| 94 const UtteranceContinuousParameters& params) { | |
| 95 if (!enabled_) { | |
| 96 QueuedUtterance *queued = new QueuedUtterance(); | |
| 97 queued->utterance_id = utterance_id; | |
| 98 queued->utterance = utterance; | |
| 99 queued->lang = lang; | |
| 100 queued->params = params; | |
| 101 queued_utterances_.push_back(queued); | |
| 102 return true; | |
| 103 } | |
| 104 | |
| 105 utterance_id_ = utterance_id; | |
| 106 utterance_length_ = utterance.size(); | |
| 107 | |
| 108 std::string options; | |
| 109 | |
| 110 if (!lang.empty()) { | |
| 111 AppendSpeakOption( | |
| 112 chromeos::SpeechSynthesizerClient::kSpeechPropertyLocale, | |
| 113 lang, | |
| 114 &options); | |
| 115 } | |
| 116 | |
| 117 if (params.rate >= 0.0) { | |
| 118 AppendSpeakOption( | |
| 119 chromeos::SpeechSynthesizerClient::kSpeechPropertyRate, | |
| 120 DoubleToString(params.rate), | |
| 121 &options); | |
| 122 } | |
| 123 | |
| 124 if (params.pitch >= 0.0) { | |
| 125 // The TTS service allows a range of 0 to 2 for speech pitch. | |
| 126 AppendSpeakOption( | |
| 127 chromeos::SpeechSynthesizerClient::kSpeechPropertyPitch, | |
| 128 DoubleToString(params.pitch), | |
| 129 &options); | |
| 130 } | |
| 131 | |
| 132 if (params.volume >= 0.0) { | |
| 133 // The Chrome OS TTS service allows a range of 0 to 5 for speech volume, | |
| 134 // but 5 clips, so map to a range of 0...4. | |
| 135 AppendSpeakOption( | |
| 136 chromeos::SpeechSynthesizerClient::kSpeechPropertyVolume, | |
| 137 DoubleToString(params.volume * 4), | |
| 138 &options); | |
| 139 } | |
| 140 | |
| 141 chromeos::SpeechSynthesizerClient* speech_synthesizer_client = | |
| 142 chromeos::DBusThreadManager::Get()->GetSpeechSynthesizerClient(); | |
| 143 | |
| 144 speech_synthesizer_client->Speak(utterance, options); | |
| 145 if (utterance_id_ >= 0) { | |
| 146 ExtensionTtsController* controller = ExtensionTtsController::GetInstance(); | |
| 147 controller->OnTtsEvent(utterance_id_, TTS_EVENT_START, 0, std::string()); | |
| 148 PollUntilSpeechFinishes(utterance_id_); | |
| 149 } | |
| 150 | |
| 151 return true; | |
| 152 } | |
| 153 | |
| 154 bool ExtensionTtsPlatformImplChromeOs::StopSpeaking() { | |
| 155 // If we haven't been enabled yet, clear the internal queue. | |
| 156 if (!enabled_) { | |
| 157 STLDeleteElements(&queued_utterances_); | |
| 158 return true; | |
| 159 } | |
| 160 | |
| 161 chromeos::DBusThreadManager::Get()->GetSpeechSynthesizerClient()-> | |
| 162 StopSpeaking(); | |
| 163 return true; | |
| 164 } | |
| 165 | |
| 166 bool ExtensionTtsPlatformImplChromeOs::SendsEvent(TtsEventType event_type) { | |
| 167 return (event_type == TTS_EVENT_START || | |
| 168 event_type == TTS_EVENT_END || | |
| 169 event_type == TTS_EVENT_ERROR); | |
| 170 } | |
| 171 | |
| 172 void ExtensionTtsPlatformImplChromeOs::Enable() { | |
| 173 enabled_ = true; | |
| 174 while (!queued_utterances_.empty()) { | |
| 175 QueuedUtterance* queued = queued_utterances_.front(); | |
| 176 Speak(queued->utterance_id, | |
| 177 queued->utterance, | |
| 178 queued->lang, | |
| 179 queued->params); | |
| 180 delete queued; | |
| 181 queued_utterances_.pop_front(); | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 void ExtensionTtsPlatformImplChromeOs::PollUntilSpeechFinishes( | |
| 186 int utterance_id) { | |
| 187 if (utterance_id != utterance_id_) { | |
| 188 // This utterance must have been interrupted or cancelled. | |
| 189 return; | |
| 190 } | |
| 191 chromeos::SpeechSynthesizerClient* speech_synthesizer_client = | |
| 192 chromeos::DBusThreadManager::Get()->GetSpeechSynthesizerClient(); | |
| 193 speech_synthesizer_client->IsSpeaking(base::Bind( | |
| 194 &ExtensionTtsPlatformImplChromeOs::ContinuePollingIfSpeechIsNotFinished, | |
| 195 weak_ptr_factory_.GetWeakPtr(), utterance_id)); | |
| 196 } | |
| 197 | |
| 198 void ExtensionTtsPlatformImplChromeOs::ContinuePollingIfSpeechIsNotFinished( | |
| 199 int utterance_id, bool is_speaking) { | |
| 200 if (utterance_id != utterance_id_) { | |
| 201 // This utterance must have been interrupted or cancelled. | |
| 202 return; | |
| 203 } | |
| 204 if (!is_speaking) { | |
| 205 ExtensionTtsController* controller = ExtensionTtsController::GetInstance(); | |
| 206 controller->OnTtsEvent( | |
| 207 utterance_id_, TTS_EVENT_END, utterance_length_, std::string()); | |
| 208 return; | |
| 209 } | |
| 210 // Continue polling. | |
| 211 MessageLoop::current()->PostDelayedTask( | |
| 212 FROM_HERE, base::Bind( | |
| 213 &ExtensionTtsPlatformImplChromeOs::PollUntilSpeechFinishes, | |
| 214 weak_ptr_factory_.GetWeakPtr(), | |
| 215 utterance_id), | |
| 216 kSpeechCheckDelayIntervalMs); | |
| 217 } | |
| 218 | |
| 219 void ExtensionTtsPlatformImplChromeOs::AppendSpeakOption( | |
| 220 std::string key, | |
| 221 std::string value, | |
| 222 std::string* options) { | |
| 223 *options += | |
| 224 key + | |
| 225 chromeos::SpeechSynthesizerClient::kSpeechPropertyEquals + | |
| 226 value + | |
| 227 chromeos::SpeechSynthesizerClient::kSpeechPropertyDelimiter; | |
| 228 } | |
| 229 | |
| 230 // static | |
| 231 ExtensionTtsPlatformImplChromeOs* | |
| 232 ExtensionTtsPlatformImplChromeOs::GetInstance() { | |
| 233 return Singleton<ExtensionTtsPlatformImplChromeOs>::get(); | |
| 234 } | |
| 235 | |
| 236 // global | |
| 237 void EnableChromeOsTts() { | |
| 238 ExtensionTtsPlatformImplChromeOs::GetInstance()->Enable(); | |
| 239 } | |
| OLD | NEW |