| 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 <dlfcn.h> |
| 5 #include <math.h> | 6 #include <math.h> |
| 6 | 7 |
| 7 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
| 8 #include "chrome/browser/speech/extension_api/tts_extension_api_platform.h" | 9 #include "chrome/browser/speech/extension_api/tts_extension_api_platform.h" |
| 9 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
| 10 | 11 |
| 11 #include "library_loaders/libspeechd.h" | |
| 12 | |
| 13 using content::BrowserThread; | 12 using content::BrowserThread; |
| 14 | 13 |
| 15 namespace { | 14 namespace { |
| 16 | |
| 17 const char kNotSupportedError[] = | 15 const char kNotSupportedError[] = |
| 18 "Native speech synthesis not supported on this platform."; | 16 "Native speech synthesis not supported on this platform."; |
| 19 | 17 |
| 20 } // namespace | 18 // Speech dispatcher exports. |
| 19 // The following types come from the libspeechd-dev package/libspeechd.h. |
| 20 typedef enum { |
| 21 SPD_MODE_SINGLE = 0, |
| 22 SPD_MODE_THREADED = 1 |
| 23 } SPDConnectionMode; |
| 24 |
| 25 typedef enum { |
| 26 SPD_IMPORTANT = 1, |
| 27 SPD_MESSAGE = 2, |
| 28 SPD_TEXT = 3, |
| 29 SPD_NOTIFICATION = 4, |
| 30 SPD_PROGRESS = 5 |
| 31 } SPDPriority; |
| 32 |
| 33 typedef enum { |
| 34 SPD_EVENT_BEGIN, |
| 35 SPD_EVENT_END, |
| 36 SPD_EVENT_CANCEL, |
| 37 SPD_EVENT_PAUSE, |
| 38 SPD_EVENT_RESUME, |
| 39 SPD_EVENT_INDEX_MARK |
| 40 } SPDNotificationType; |
| 41 |
| 42 typedef enum { |
| 43 SPD_BEGIN = 1, |
| 44 SPD_END = 2, |
| 45 SPD_INDEX_MARKS = 4, |
| 46 SPD_CANCEL = 8, |
| 47 SPD_PAUSE = 16, |
| 48 SPD_RESUME = 32 |
| 49 } SPDNotification; |
| 50 |
| 51 typedef void (*SPDCallback)( |
| 52 size_t msg_id, size_t client_id, SPDNotificationType state); |
| 53 typedef void (*SPDCallbackIM)(size_t msg_id, |
| 54 size_t client_id, |
| 55 SPDNotificationType state, |
| 56 char* index_mark); |
| 57 |
| 58 typedef struct { |
| 59 /* PUBLIC */ |
| 60 SPDCallback callback_begin; |
| 61 SPDCallback callback_end; |
| 62 SPDCallback callback_cancel; |
| 63 SPDCallback callback_pause; |
| 64 SPDCallback callback_resume; |
| 65 SPDCallbackIM callback_im; |
| 66 |
| 67 /* PRIVATE */ |
| 68 int socket; |
| 69 FILE* stream; |
| 70 SPDConnectionMode mode; |
| 71 |
| 72 pthread_mutex_t* ssip_mutex; |
| 73 |
| 74 pthread_t* events_thread; |
| 75 pthread_mutex_t* comm_mutex; |
| 76 pthread_cond_t* cond_reply_ready; |
| 77 pthread_mutex_t* mutex_reply_ready; |
| 78 pthread_cond_t* cond_reply_ack; |
| 79 pthread_mutex_t* mutex_reply_ack; |
| 80 |
| 81 char* reply; |
| 82 } SPDConnection; |
| 83 |
| 84 typedef SPDConnection* (*spd_open_func)(const char* client_name, |
| 85 const char* connection_name, |
| 86 const char* user_name, |
| 87 SPDConnectionMode mode); |
| 88 typedef int (*spd_say_func)(SPDConnection* connection, |
| 89 SPDPriority priority, |
| 90 const char* text); |
| 91 typedef int (*spd_stop_func)(SPDConnection* connection); |
| 92 typedef void (*spd_close_func)(SPDConnection* connection); |
| 93 typedef int (*spd_set_notification_on_func)(SPDConnection* connection, |
| 94 SPDNotification notification); |
| 95 typedef int (*spd_set_voice_rate_func)(SPDConnection* connection, int rate); |
| 96 typedef int (*spd_set_voice_pitch_func)(SPDConnection* connection, int pitch); |
| 97 }; |
| 98 |
| 99 class SpeechDispatcherWrapper { |
| 100 public: |
| 101 static SPDNotificationType current_notification_; |
| 102 |
| 103 SpeechDispatcherWrapper(); |
| 104 ~SpeechDispatcherWrapper(); |
| 105 |
| 106 bool Speak(const char* text); |
| 107 bool IsSpeaking(); |
| 108 bool StopSpeaking(); |
| 109 void SetRate(int rate); |
| 110 void SetPitch(int pitch); |
| 111 |
| 112 // Resets the connection with speech dispatcher. |
| 113 void Reset(); |
| 114 |
| 115 // States whether Speech Dispatcher loaded successfully. |
| 116 bool loaded() { |
| 117 return loaded_; |
| 118 } |
| 119 |
| 120 private: |
| 121 static void NotificationCallback(size_t msg_id, |
| 122 size_t client_id, |
| 123 SPDNotificationType type); |
| 124 |
| 125 static void IndexMarkCallback(size_t msg_id, |
| 126 size_t client_id, |
| 127 SPDNotificationType state, |
| 128 char* index_mark); |
| 129 |
| 130 // Interface bindings. |
| 131 spd_open_func spd_open; |
| 132 spd_say_func spd_say; |
| 133 spd_stop_func spd_stop; |
| 134 spd_close_func spd_close; |
| 135 spd_set_notification_on_func spd_set_notification_on; |
| 136 spd_set_voice_rate_func spd_set_voice_rate; |
| 137 spd_set_voice_pitch_func spd_set_voice_pitch; |
| 138 |
| 139 bool loaded_; |
| 140 void* library_; |
| 141 SPDConnection* conn_; |
| 142 DISALLOW_COPY_AND_ASSIGN(SpeechDispatcherWrapper); |
| 143 }; |
| 144 |
| 145 // static |
| 146 SPDNotificationType SpeechDispatcherWrapper::current_notification_ = |
| 147 SPD_EVENT_END; |
| 21 | 148 |
| 22 class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl { | 149 class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl { |
| 23 public: | 150 public: |
| 24 virtual bool PlatformImplAvailable(); | 151 virtual bool PlatformImplAvailable(); |
| 25 virtual bool Speak( | 152 virtual bool Speak( |
| 26 int utterance_id, | 153 int utterance_id, |
| 27 const std::string& utterance, | 154 const std::string& utterance, |
| 28 const std::string& lang, | 155 const std::string& lang, |
| 29 const UtteranceContinuousParameters& params); | 156 const UtteranceContinuousParameters& params); |
| 30 virtual bool StopSpeaking(); | 157 virtual bool StopSpeaking(); |
| 31 virtual bool IsSpeaking(); | 158 virtual bool IsSpeaking(); |
| 32 virtual bool SendsEvent(TtsEventType event_type); | 159 virtual bool SendsEvent(TtsEventType event_type); |
| 33 void OnSpeechEvent(SPDNotificationType type); | 160 void OnSpeechEvent(SPDNotificationType type); |
| 34 | 161 |
| 35 // Get the single instance of this class. | 162 // Get the single instance of this class. |
| 36 static ExtensionTtsPlatformImplLinux* GetInstance(); | 163 static ExtensionTtsPlatformImplLinux* GetInstance(); |
| 37 | 164 |
| 38 private: | 165 private: |
| 39 ExtensionTtsPlatformImplLinux(); | 166 ExtensionTtsPlatformImplLinux(): utterance_id_(0) {} |
| 40 virtual ~ExtensionTtsPlatformImplLinux(); | 167 virtual ~ExtensionTtsPlatformImplLinux() {} |
| 41 | 168 |
| 42 // Resets the connection with speech dispatcher. | 169 SpeechDispatcherWrapper spd_; |
| 43 void Reset(); | |
| 44 | |
| 45 static void NotificationCallback(size_t msg_id, | |
| 46 size_t client_id, | |
| 47 SPDNotificationType type); | |
| 48 | |
| 49 static void IndexMarkCallback(size_t msg_id, | |
| 50 size_t client_id, | |
| 51 SPDNotificationType state, | |
| 52 char* index_mark); | |
| 53 | |
| 54 static SPDNotificationType current_notification_; | |
| 55 | |
| 56 LibSpeechdLoader libspeechd_loader_; | |
| 57 SPDConnection* conn_; | |
| 58 | 170 |
| 59 // These apply to the current utterance only. | 171 // These apply to the current utterance only. |
| 60 std::string utterance_; | 172 std::string utterance_; |
| 61 int utterance_id_; | 173 int utterance_id_; |
| 62 | 174 |
| 63 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplLinux>; | 175 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplLinux>; |
| 64 | 176 |
| 65 DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplLinux); | 177 DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplLinux); |
| 66 }; | 178 }; |
| 67 | 179 |
| 68 // static | 180 SpeechDispatcherWrapper::SpeechDispatcherWrapper() : loaded_(false) { |
| 69 SPDNotificationType ExtensionTtsPlatformImplLinux::current_notification_ = | 181 library_ = dlopen("libspeechd.so", RTLD_LAZY); |
| 70 SPD_EVENT_END; | 182 if (!library_) |
| 71 | |
| 72 ExtensionTtsPlatformImplLinux::ExtensionTtsPlatformImplLinux() | |
| 73 : utterance_id_(0) { | |
| 74 if (!libspeechd_loader_.Load("libspeechd.so.2")) | |
| 75 return; | 183 return; |
| 76 | 184 |
| 77 conn_ = libspeechd_loader_.spd_open( | 185 spd_open = reinterpret_cast<spd_open_func>(dlsym(library_, "spd_open")); |
| 78 "chrome", "extension_api", NULL, SPD_MODE_THREADED); | 186 if (!spd_open) |
| 187 return; |
| 188 |
| 189 spd_say = reinterpret_cast<spd_say_func>(dlsym(library_, "spd_say")); |
| 190 if (!spd_say) |
| 191 return; |
| 192 |
| 193 spd_stop = reinterpret_cast<spd_stop_func>(dlsym(library_, "spd_stop")); |
| 194 if (!spd_stop) |
| 195 return; |
| 196 |
| 197 spd_close = reinterpret_cast<spd_close_func>(dlsym(library_, "spd_close")); |
| 198 if (!spd_close) |
| 199 return; |
| 200 |
| 201 conn_ = spd_open("chrome", "extension_api", NULL, SPD_MODE_THREADED); |
| 79 if (!conn_) | 202 if (!conn_) |
| 80 return; | 203 return; |
| 81 | 204 |
| 205 spd_set_notification_on = reinterpret_cast<spd_set_notification_on_func>( |
| 206 dlsym(library_, "spd_set_notification_on")); |
| 207 if (!spd_set_notification_on) |
| 208 return; |
| 209 |
| 210 spd_set_voice_rate = reinterpret_cast<spd_set_voice_rate_func>( |
| 211 dlsym(library_, "spd_set_voice_rate")); |
| 212 if (!spd_set_voice_rate) |
| 213 return; |
| 214 |
| 215 spd_set_voice_pitch = reinterpret_cast<spd_set_voice_pitch_func>( |
| 216 dlsym(library_, "spd_set_voice_pitch")); |
| 217 if (!spd_set_voice_pitch) |
| 218 return; |
| 219 |
| 82 // Register callbacks for all events. | 220 // Register callbacks for all events. |
| 83 conn_->callback_begin = | 221 conn_->callback_begin = |
| 84 conn_->callback_end = | 222 conn_->callback_end = |
| 85 conn_->callback_cancel = | 223 conn_->callback_cancel = |
| 86 conn_->callback_pause = | 224 conn_->callback_pause = |
| 87 conn_->callback_resume = | 225 conn_->callback_resume = |
| 88 &NotificationCallback; | 226 &SpeechDispatcherWrapper::NotificationCallback; |
| 89 | 227 |
| 90 conn_->callback_im = &IndexMarkCallback; | 228 conn_->callback_im = &SpeechDispatcherWrapper::IndexMarkCallback; |
| 91 | 229 |
| 92 libspeechd_loader_.spd_set_notification_on(conn_, SPD_BEGIN); | 230 spd_set_notification_on(conn_, SPD_BEGIN); |
| 93 libspeechd_loader_.spd_set_notification_on(conn_, SPD_END); | 231 spd_set_notification_on(conn_, SPD_END); |
| 94 libspeechd_loader_.spd_set_notification_on(conn_, SPD_CANCEL); | 232 spd_set_notification_on(conn_, SPD_CANCEL); |
| 95 libspeechd_loader_.spd_set_notification_on(conn_, SPD_PAUSE); | 233 spd_set_notification_on(conn_, SPD_PAUSE); |
| 96 libspeechd_loader_.spd_set_notification_on(conn_, SPD_RESUME); | 234 spd_set_notification_on(conn_, SPD_RESUME); |
| 235 |
| 236 loaded_ = true; |
| 97 } | 237 } |
| 98 | 238 |
| 99 ExtensionTtsPlatformImplLinux::~ExtensionTtsPlatformImplLinux() { | 239 SpeechDispatcherWrapper::~SpeechDispatcherWrapper() { |
| 100 if (conn_) { | 240 if (conn_) { |
| 101 libspeechd_loader_.spd_close(conn_); | 241 spd_close(conn_); |
| 102 conn_ = NULL; | 242 conn_ = NULL; |
| 103 } | 243 } |
| 244 |
| 245 if (library_) { |
| 246 dlclose(library_); |
| 247 library_ = NULL; |
| 248 } |
| 249 } |
| 250 bool SpeechDispatcherWrapper::Speak(const char* text) { |
| 251 if (!loaded()) |
| 252 return false; |
| 253 if (spd_say(conn_, SPD_TEXT, text) == -1) { |
| 254 Reset(); |
| 255 return false; |
| 256 } |
| 257 return true; |
| 258 } |
| 259 |
| 260 bool SpeechDispatcherWrapper::IsSpeaking() { |
| 261 return SpeechDispatcherWrapper::current_notification_ == SPD_EVENT_BEGIN; |
| 262 } |
| 263 |
| 264 bool SpeechDispatcherWrapper::StopSpeaking() { |
| 265 if (!loaded()) |
| 266 return false; |
| 267 if (spd_stop(conn_) == -1) { |
| 268 Reset(); |
| 269 return false; |
| 270 } |
| 271 return true; |
| 272 } |
| 273 void SpeechDispatcherWrapper::SetRate(int rate) { |
| 274 spd_set_voice_rate(conn_, rate); |
| 275 } |
| 276 |
| 277 void SpeechDispatcherWrapper::SetPitch(int pitch) { |
| 278 spd_set_voice_pitch(conn_, pitch); |
| 279 } |
| 280 |
| 281 // Resets the connection with speech dispatcher. |
| 282 void SpeechDispatcherWrapper::Reset() { |
| 283 if (conn_) |
| 284 spd_close(conn_); |
| 285 conn_ = spd_open("chrome", "extension_api", NULL, SPD_MODE_THREADED); |
| 286 } |
| 287 |
| 288 // static |
| 289 void SpeechDispatcherWrapper::NotificationCallback( |
| 290 size_t msg_id, size_t client_id, SPDNotificationType type) { |
| 291 // We run Speech Dispatcher in threaded mode, so these callbacks should always |
| 292 // be in a separate thread. |
| 293 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 294 SpeechDispatcherWrapper::current_notification_ = type; |
| 295 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 296 base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, |
| 297 base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), |
| 298 type)); |
| 299 } |
| 104 } | 300 } |
| 105 | 301 |
| 106 void ExtensionTtsPlatformImplLinux::Reset() { | 302 // static |
| 107 if (conn_) | 303 void SpeechDispatcherWrapper::IndexMarkCallback(size_t msg_id, |
| 108 libspeechd_loader_.spd_close(conn_); | 304 size_t client_id, |
| 109 conn_ = libspeechd_loader_.spd_open( | 305 SPDNotificationType state, |
| 110 "chrome", "extension_api", NULL, SPD_MODE_THREADED); | 306 char* index_mark) { |
| 307 // TODO(dtseng): index_mark appears to specify an index type supplied by a |
| 308 // client. Need to explore how this is used before hooking it up with existing |
| 309 // word, sentence events. |
| 310 // We run Speech Dispatcher in threaded mode, so these callbacks should always |
| 311 // be in a separate thread. |
| 312 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 313 SpeechDispatcherWrapper::current_notification_ = state; |
| 314 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 315 base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, |
| 316 base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), |
| 317 state)); |
| 318 } |
| 111 } | 319 } |
| 112 | 320 |
| 113 bool ExtensionTtsPlatformImplLinux::PlatformImplAvailable() { | 321 bool ExtensionTtsPlatformImplLinux::PlatformImplAvailable() { |
| 114 return libspeechd_loader_.loaded() && (conn_ != NULL); | 322 return spd_.loaded(); |
| 115 } | 323 } |
| 116 | 324 |
| 117 bool ExtensionTtsPlatformImplLinux::Speak( | 325 bool ExtensionTtsPlatformImplLinux::Speak( |
| 118 int utterance_id, | 326 int utterance_id, |
| 119 const std::string& utterance, | 327 const std::string& utterance, |
| 120 const std::string& lang, | 328 const std::string& lang, |
| 121 const UtteranceContinuousParameters& params) { | 329 const UtteranceContinuousParameters& params) { |
| 122 if (!PlatformImplAvailable()) { | 330 if (!spd_.loaded()) { |
| 123 error_ = kNotSupportedError; | 331 error_ = kNotSupportedError; |
| 124 return false; | 332 return false; |
| 125 } | 333 } |
| 126 | 334 |
| 127 // Speech dispatcher's speech params are around 3x at either limit. | 335 // Speech dispatcher's speech params are around 3x at either limit. |
| 128 float rate = params.rate > 3 ? 3 : params.rate; | 336 float rate = params.rate > 3 ? 3 : params.rate; |
| 129 rate = params.rate < 0.334 ? 0.334 : rate; | 337 rate = params.rate < 0.334 ? 0.334 : rate; |
| 130 float pitch = params.pitch > 3 ? 3 : params.pitch; | 338 float pitch = params.pitch > 3 ? 3 : params.pitch; |
| 131 pitch = params.pitch < 0.334 ? 0.334 : pitch; | 339 pitch = params.pitch < 0.334 ? 0.334 : pitch; |
| 132 | 340 |
| 133 // Map our multiplicative range to Speech Dispatcher's linear range. | 341 // Map our multiplicative range to Speech Dispatcher's linear range. |
| 134 // .334 = -100. | 342 // .334 = -100. |
| 135 // 3 = 100. | 343 // 3 = 100. |
| 136 libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3)); | 344 spd_.SetRate(100 * log10(rate) / log10(3)); |
| 137 libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3)); | 345 spd_.SetPitch(100 * log10(pitch) / log10(3)); |
| 138 | 346 |
| 139 utterance_ = utterance; | 347 utterance_ = utterance; |
| 140 utterance_id_ = utterance_id; | 348 utterance_id_ = utterance_id; |
| 141 | 349 |
| 142 if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, utterance.c_str()) == -1) { | 350 spd_.Speak(utterance.c_str()); |
| 143 Reset(); | |
| 144 return false; | |
| 145 } | |
| 146 return true; | 351 return true; |
| 147 } | 352 } |
| 148 | 353 |
| 149 bool ExtensionTtsPlatformImplLinux::StopSpeaking() { | 354 bool ExtensionTtsPlatformImplLinux::StopSpeaking() { |
| 150 if (!PlatformImplAvailable()) | 355 return spd_.StopSpeaking(); |
| 151 return false; | |
| 152 if (libspeechd_loader_.spd_stop(conn_) == -1) { | |
| 153 Reset(); | |
| 154 return false; | |
| 155 } | |
| 156 return true; | |
| 157 } | 356 } |
| 158 | 357 |
| 159 bool ExtensionTtsPlatformImplLinux::IsSpeaking() { | 358 bool ExtensionTtsPlatformImplLinux::IsSpeaking() { |
| 160 return current_notification_ == SPD_EVENT_BEGIN; | 359 return spd_.IsSpeaking(); |
| 161 } | 360 } |
| 162 | 361 |
| 163 bool ExtensionTtsPlatformImplLinux::SendsEvent(TtsEventType event_type) { | 362 bool ExtensionTtsPlatformImplLinux::SendsEvent(TtsEventType event_type) { |
| 164 return (event_type == TTS_EVENT_START || | 363 return (event_type == TTS_EVENT_START || |
| 165 event_type == TTS_EVENT_END || | 364 event_type == TTS_EVENT_END || |
| 166 event_type == TTS_EVENT_CANCELLED || | 365 event_type == TTS_EVENT_CANCELLED || |
| 167 event_type == TTS_EVENT_MARKER); | 366 event_type == TTS_EVENT_MARKER); |
| 168 } | 367 } |
| 169 | 368 |
| 170 void ExtensionTtsPlatformImplLinux::OnSpeechEvent(SPDNotificationType type) { | 369 void ExtensionTtsPlatformImplLinux::OnSpeechEvent(SPDNotificationType type) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 183 controller->OnTtsEvent( | 382 controller->OnTtsEvent( |
| 184 utterance_id_, TTS_EVENT_CANCELLED, 0, std::string()); | 383 utterance_id_, TTS_EVENT_CANCELLED, 0, std::string()); |
| 185 break; | 384 break; |
| 186 case SPD_EVENT_INDEX_MARK: | 385 case SPD_EVENT_INDEX_MARK: |
| 187 controller->OnTtsEvent(utterance_id_, TTS_EVENT_MARKER, 0, std::string()); | 386 controller->OnTtsEvent(utterance_id_, TTS_EVENT_MARKER, 0, std::string()); |
| 188 break; | 387 break; |
| 189 } | 388 } |
| 190 } | 389 } |
| 191 | 390 |
| 192 // static | 391 // static |
| 193 void ExtensionTtsPlatformImplLinux::NotificationCallback( | |
| 194 size_t msg_id, size_t client_id, SPDNotificationType type) { | |
| 195 // We run Speech Dispatcher in threaded mode, so these callbacks should always | |
| 196 // be in a separate thread. | |
| 197 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 198 current_notification_ = type; | |
| 199 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 200 base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, | |
| 201 base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), | |
| 202 type)); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 // static | |
| 207 void ExtensionTtsPlatformImplLinux::IndexMarkCallback(size_t msg_id, | |
| 208 size_t client_id, | |
| 209 SPDNotificationType state, | |
| 210 char* index_mark) { | |
| 211 // TODO(dtseng): index_mark appears to specify an index type supplied by a | |
| 212 // client. Need to explore how this is used before hooking it up with existing | |
| 213 // word, sentence events. | |
| 214 // We run Speech Dispatcher in threaded mode, so these callbacks should always | |
| 215 // be in a separate thread. | |
| 216 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 217 current_notification_ = state; | |
| 218 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 219 base::Bind(&ExtensionTtsPlatformImplLinux::OnSpeechEvent, | |
| 220 base::Unretained(ExtensionTtsPlatformImplLinux::GetInstance()), | |
| 221 state)); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 // static | |
| 226 ExtensionTtsPlatformImplLinux* ExtensionTtsPlatformImplLinux::GetInstance() { | 392 ExtensionTtsPlatformImplLinux* ExtensionTtsPlatformImplLinux::GetInstance() { |
| 227 return Singleton<ExtensionTtsPlatformImplLinux, | 393 return Singleton<ExtensionTtsPlatformImplLinux, |
| 228 LeakySingletonTraits<ExtensionTtsPlatformImplLinux> >::get(); | 394 LeakySingletonTraits<ExtensionTtsPlatformImplLinux> >::get(); |
| 229 } | 395 } |
| 230 | 396 |
| 231 // static | 397 // static |
| 232 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() { | 398 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() { |
| 233 return ExtensionTtsPlatformImplLinux::GetInstance(); | 399 return ExtensionTtsPlatformImplLinux::GetInstance(); |
| 234 } | 400 } |
| OLD | NEW |