OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <string> | 5 #include <string> |
6 | 6 |
7 #include "base/memory/scoped_nsobject.h" | 7 #include "base/memory/scoped_nsobject.h" |
8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 virtual bool Speak( | 57 virtual bool Speak( |
58 int utterance_id, | 58 int utterance_id, |
59 const std::string& utterance, | 59 const std::string& utterance, |
60 const std::string& lang, | 60 const std::string& lang, |
61 const VoiceData& voice, | 61 const VoiceData& voice, |
62 const UtteranceContinuousParameters& params) OVERRIDE; | 62 const UtteranceContinuousParameters& params) OVERRIDE; |
63 | 63 |
64 virtual bool StopSpeaking() OVERRIDE; | 64 virtual bool StopSpeaking() OVERRIDE; |
65 | 65 |
| 66 virtual void Pause() OVERRIDE; |
| 67 |
| 68 virtual void Resume() OVERRIDE; |
| 69 |
66 virtual bool IsSpeaking() OVERRIDE; | 70 virtual bool IsSpeaking() OVERRIDE; |
67 | 71 |
68 virtual void GetVoices(std::vector<VoiceData>* out_voices) OVERRIDE; | 72 virtual void GetVoices(std::vector<VoiceData>* out_voices) OVERRIDE; |
69 | 73 |
70 // Called by ChromeTtsDelegate when we get a callback from the | 74 // Called by ChromeTtsDelegate when we get a callback from the |
71 // native speech engine. | 75 // native speech engine. |
72 void OnSpeechEvent(NSSpeechSynthesizer* sender, | 76 void OnSpeechEvent(NSSpeechSynthesizer* sender, |
73 TtsEventType event_type, | 77 TtsEventType event_type, |
74 int char_index, | 78 int char_index, |
75 const std::string& error_message); | 79 const std::string& error_message); |
76 | 80 |
77 // Get the single instance of this class. | 81 // Get the single instance of this class. |
78 static TtsPlatformImplMac* GetInstance(); | 82 static TtsPlatformImplMac* GetInstance(); |
79 | 83 |
80 private: | 84 private: |
81 TtsPlatformImplMac(); | 85 TtsPlatformImplMac(); |
82 virtual ~TtsPlatformImplMac(); | 86 virtual ~TtsPlatformImplMac(); |
83 | 87 |
84 scoped_nsobject<SingleUseSpeechSynthesizer> speech_synthesizer_; | 88 scoped_nsobject<SingleUseSpeechSynthesizer> speech_synthesizer_; |
85 scoped_nsobject<ChromeTtsDelegate> delegate_; | 89 scoped_nsobject<ChromeTtsDelegate> delegate_; |
86 int utterance_id_; | 90 int utterance_id_; |
87 std::string utterance_; | 91 std::string utterance_; |
88 bool sent_start_event_; | 92 bool sent_start_event_; |
| 93 int last_char_index_; |
| 94 bool paused_; |
89 | 95 |
90 friend struct DefaultSingletonTraits<TtsPlatformImplMac>; | 96 friend struct DefaultSingletonTraits<TtsPlatformImplMac>; |
91 | 97 |
92 DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplMac); | 98 DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplMac); |
93 }; | 99 }; |
94 | 100 |
95 // static | 101 // static |
96 TtsPlatformImpl* TtsPlatformImpl::GetInstance() { | 102 TtsPlatformImpl* TtsPlatformImpl::GetInstance() { |
97 return TtsPlatformImplMac::GetInstance(); | 103 return TtsPlatformImplMac::GetInstance(); |
98 } | 104 } |
99 | 105 |
100 bool TtsPlatformImplMac::Speak( | 106 bool TtsPlatformImplMac::Speak( |
101 int utterance_id, | 107 int utterance_id, |
102 const std::string& utterance, | 108 const std::string& utterance, |
103 const std::string& lang, | 109 const std::string& lang, |
104 const VoiceData& voice, | 110 const VoiceData& voice, |
105 const UtteranceContinuousParameters& params) { | 111 const UtteranceContinuousParameters& params) { |
106 // TODO: convert SSML to SAPI xml. http://crbug.com/88072 | 112 // TODO: convert SSML to SAPI xml. http://crbug.com/88072 |
107 utterance_ = utterance; | 113 utterance_ = utterance; |
| 114 paused_ = false; |
108 | 115 |
109 NSString* utterance_nsstring = | 116 NSString* utterance_nsstring = |
110 [NSString stringWithUTF8String:utterance_.c_str()]; | 117 [NSString stringWithUTF8String:utterance_.c_str()]; |
111 | 118 |
112 // Deliberately construct a new speech synthesizer every time Speak is | 119 // Deliberately construct a new speech synthesizer every time Speak is |
113 // called, otherwise there's no way to know whether calls to the delegate | 120 // called, otherwise there's no way to know whether calls to the delegate |
114 // apply to the current utterance or a previous utterance. In | 121 // apply to the current utterance or a previous utterance. In |
115 // experimentation, the overhead of constructing and destructing a | 122 // experimentation, the overhead of constructing and destructing a |
116 // NSSpeechSynthesizer is minimal. | 123 // NSSpeechSynthesizer is minimal. |
117 speech_synthesizer_.reset( | 124 speech_synthesizer_.reset( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 } | 165 } |
159 | 166 |
160 return [speech_synthesizer_ startSpeakingRetainedUtterance]; | 167 return [speech_synthesizer_ startSpeakingRetainedUtterance]; |
161 } | 168 } |
162 | 169 |
163 bool TtsPlatformImplMac::StopSpeaking() { | 170 bool TtsPlatformImplMac::StopSpeaking() { |
164 if (speech_synthesizer_.get()) { | 171 if (speech_synthesizer_.get()) { |
165 [speech_synthesizer_ stopSpeaking]; | 172 [speech_synthesizer_ stopSpeaking]; |
166 speech_synthesizer_.reset(nil); | 173 speech_synthesizer_.reset(nil); |
167 } | 174 } |
| 175 paused_ = false; |
168 return true; | 176 return true; |
169 } | 177 } |
170 | 178 |
| 179 void TtsPlatformImplMac::Pause() { |
| 180 if (speech_synthesizer_.get() && utterance_id_ && !paused_) { |
| 181 [speech_synthesizer_ pauseSpeakingAtBoundary:NSSpeechImmediateBoundary]; |
| 182 paused_ = true; |
| 183 TtsController::GetInstance()->OnTtsEvent( |
| 184 utterance_id_, TTS_EVENT_PAUSE, last_char_index_, ""); |
| 185 } |
| 186 } |
| 187 |
| 188 void TtsPlatformImplMac::Resume() { |
| 189 if (speech_synthesizer_.get() && utterance_id_ && paused_) { |
| 190 [speech_synthesizer_ continueSpeaking]; |
| 191 paused_ = false; |
| 192 TtsController::GetInstance()->OnTtsEvent( |
| 193 utterance_id_, TTS_EVENT_RESUME, last_char_index_, ""); |
| 194 } |
| 195 } |
| 196 |
171 bool TtsPlatformImplMac::IsSpeaking() { | 197 bool TtsPlatformImplMac::IsSpeaking() { |
172 return [NSSpeechSynthesizer isAnyApplicationSpeaking]; | 198 return [NSSpeechSynthesizer isAnyApplicationSpeaking]; |
173 } | 199 } |
174 | 200 |
175 void TtsPlatformImplMac::GetVoices(std::vector<VoiceData>* outVoices) { | 201 void TtsPlatformImplMac::GetVoices(std::vector<VoiceData>* outVoices) { |
176 NSArray* voices = [NSSpeechSynthesizer availableVoices]; | 202 NSArray* voices = [NSSpeechSynthesizer availableVoices]; |
177 | 203 |
178 // Create a new temporary array of the available voices with | 204 // Create a new temporary array of the available voices with |
179 // the default voice first. | 205 // the default voice first. |
180 NSMutableArray* orderedVoices = | 206 NSMutableArray* orderedVoices = |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 else if ([gender isEqualToString:NSVoiceGenderFemale]) | 242 else if ([gender isEqualToString:NSVoiceGenderFemale]) |
217 data.gender = TTS_GENDER_FEMALE; | 243 data.gender = TTS_GENDER_FEMALE; |
218 else | 244 else |
219 data.gender = TTS_GENDER_NONE; | 245 data.gender = TTS_GENDER_NONE; |
220 data.events.insert(TTS_EVENT_START); | 246 data.events.insert(TTS_EVENT_START); |
221 data.events.insert(TTS_EVENT_END); | 247 data.events.insert(TTS_EVENT_END); |
222 data.events.insert(TTS_EVENT_WORD); | 248 data.events.insert(TTS_EVENT_WORD); |
223 data.events.insert(TTS_EVENT_ERROR); | 249 data.events.insert(TTS_EVENT_ERROR); |
224 data.events.insert(TTS_EVENT_CANCELLED); | 250 data.events.insert(TTS_EVENT_CANCELLED); |
225 data.events.insert(TTS_EVENT_INTERRUPTED); | 251 data.events.insert(TTS_EVENT_INTERRUPTED); |
| 252 data.events.insert(TTS_EVENT_PAUSE); |
| 253 data.events.insert(TTS_EVENT_RESUME); |
226 } | 254 } |
227 } | 255 } |
228 | 256 |
229 void TtsPlatformImplMac::OnSpeechEvent( | 257 void TtsPlatformImplMac::OnSpeechEvent( |
230 NSSpeechSynthesizer* sender, | 258 NSSpeechSynthesizer* sender, |
231 TtsEventType event_type, | 259 TtsEventType event_type, |
232 int char_index, | 260 int char_index, |
233 const std::string& error_message) { | 261 const std::string& error_message) { |
234 // Don't send events from an utterance that's already completed. | 262 // Don't send events from an utterance that's already completed. |
235 // This depends on the fact that we construct a new NSSpeechSynthesizer | 263 // This depends on the fact that we construct a new NSSpeechSynthesizer |
236 // each time we call Speak. | 264 // each time we call Speak. |
237 if (sender != speech_synthesizer_.get()) | 265 if (sender != speech_synthesizer_.get()) |
238 return; | 266 return; |
239 | 267 |
240 if (event_type == TTS_EVENT_END) | 268 if (event_type == TTS_EVENT_END) |
241 char_index = utterance_.size(); | 269 char_index = utterance_.size(); |
242 TtsController* controller = TtsController::GetInstance(); | 270 TtsController* controller = TtsController::GetInstance(); |
243 if (event_type == TTS_EVENT_WORD && !sent_start_event_) { | 271 if (event_type == TTS_EVENT_WORD && !sent_start_event_) { |
244 controller->OnTtsEvent( | 272 controller->OnTtsEvent( |
245 utterance_id_, TTS_EVENT_START, 0, ""); | 273 utterance_id_, TTS_EVENT_START, 0, ""); |
246 sent_start_event_ = true; | 274 sent_start_event_ = true; |
247 } | 275 } |
248 controller->OnTtsEvent( | 276 controller->OnTtsEvent( |
249 utterance_id_, event_type, char_index, error_message); | 277 utterance_id_, event_type, char_index, error_message); |
| 278 last_char_index_ = char_index; |
250 } | 279 } |
251 | 280 |
252 TtsPlatformImplMac::TtsPlatformImplMac() { | 281 TtsPlatformImplMac::TtsPlatformImplMac() { |
253 utterance_id_ = -1; | 282 utterance_id_ = -1; |
254 sent_start_event_ = true; | 283 sent_start_event_ = true; |
| 284 paused_ = false; |
255 | 285 |
256 delegate_.reset([[ChromeTtsDelegate alloc] initWithPlatformImplMac:this]); | 286 delegate_.reset([[ChromeTtsDelegate alloc] initWithPlatformImplMac:this]); |
257 } | 287 } |
258 | 288 |
259 TtsPlatformImplMac::~TtsPlatformImplMac() { | 289 TtsPlatformImplMac::~TtsPlatformImplMac() { |
260 } | 290 } |
261 | 291 |
262 // static | 292 // static |
263 TtsPlatformImplMac* TtsPlatformImplMac::GetInstance() { | 293 TtsPlatformImplMac* TtsPlatformImplMac::GetInstance() { |
264 return Singleton<TtsPlatformImplMac>::get(); | 294 return Singleton<TtsPlatformImplMac>::get(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 didSpeak_ = true; | 343 didSpeak_ = true; |
314 return [super startSpeakingString:utterance_]; | 344 return [super startSpeakingString:utterance_]; |
315 } | 345 } |
316 | 346 |
317 - (bool)startSpeakingString:(NSString*)utterance { | 347 - (bool)startSpeakingString:(NSString*)utterance { |
318 CHECK(false); | 348 CHECK(false); |
319 return false; | 349 return false; |
320 } | 350 } |
321 | 351 |
322 @end | 352 @end |
OLD | NEW |