Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: chrome/browser/speech/extension_api/tts_extension_api_linux.cc

Issue 10915164: Initial support for native TTS on linux through tts extension API. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Initial patch. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
6 #include <libspeechd.h>
7 #include <math.h>
8
5 #include "base/memory/singleton.h" 9 #include "base/memory/singleton.h"
6 #include "chrome/browser/speech/extension_api/tts_extension_api_platform.h" 10 #include "chrome/browser/speech/extension_api/tts_extension_api_platform.h"
7 11
8 namespace { 12 namespace {
9 const char kNotSupportedError[] = 13 const char kNotSupportedError[] =
10 "Native speech synthesis not supported on this platform."; 14 "Native speech synthesis not supported on this platform.";
15
16 // Speech dispatcher exports.
17 typedef SPDConnection* (*spd_open_func)(const char* client_name,
dmazzoni 2012/09/09 21:40:18 Extra spaces
18 const char* connection_name,
19 const char* user_name,
20 SPDConnectionMode mode);
21 typedef int (*spd_say_func)(SPDConnection* connection,
22 SPDPriority priority,
23 const char* text);
24 typedef void (*spd_stop_func)(SPDConnection* connection);
25 typedef void (*spd_close_func)(SPDConnection* connection);
26 typedef int (*spd_set_notification_on_func)(SPDConnection* connection,
27 SPDNotification notification);
dmazzoni 2012/09/09 21:40:18 Fix indentation
28 typedef int (*spd_set_voice_rate_func)(SPDConnection* connection, int rate);
29 typedef int (*spd_set_voice_pitch_func)(SPDConnection* connection, int pitch);
11 }; 30 };
12 31
32 class SpeechDispatcherWrapper {
33 public:
34 static SPDNotificationType current_notification;
35
36 SpeechDispatcherWrapper() : loaded_(false) {
dmazzoni 2012/09/09 21:40:18 This is long, so move the implementation below rat
37 library_ = dlopen("libspeechd.so", RTLD_LAZY);
38 if (!library_)
39 return;
40
41 spd_open = reinterpret_cast<spd_open_func>(dlsym(library_, "spd_open"));
42 if (!spd_open)
43 return;
44
45 spd_say = reinterpret_cast<spd_say_func>(dlsym(library_, "spd_say"));
46 if (!spd_say)
47 return;
48
49 spd_stop = reinterpret_cast<spd_stop_func>(dlsym(library_, "spd_stop"));
50 if (!spd_stop)
51 return;
52
53 spd_close = reinterpret_cast<spd_close_func>(dlsym(library_, "spd_close"));
54 if (!spd_close)
55 return;
56
57 conn_ = spd_open("chrome", "extension_api", NULL, SPD_MODE_THREADED);
58 if (!conn_)
59 return;
60
61 spd_set_notification_on = reinterpret_cast<spd_set_notification_on_func>(
62 dlsym(library_, "spd_set_notification_on"));
63 if (!spd_set_notification_on)
64 return;
65
66 spd_set_voice_rate = reinterpret_cast<spd_set_voice_rate_func>(
67 dlsym(library_, "spd_set_voice_rate"));
68 if (!spd_set_voice_rate)
69 return;
70
71 spd_set_voice_pitch = reinterpret_cast<spd_set_voice_pitch_func>(
72 dlsym(library_, "spd_set_voice_pitch"));
73 if (!spd_set_voice_pitch)
74 return;
75
76 // Register callbacks for all events.
77 conn_->callback_begin =
78 conn_->callback_end =
79 conn_->callback_cancel =
80 conn_->callback_pause =
81 conn_->callback_resume =
82 &SpeechDispatcherWrapper::NotificationCallback;
83
84 spd_set_notification_on(conn_, SPD_BEGIN);
85 spd_set_notification_on(conn_, SPD_END);
86 spd_set_notification_on(conn_, SPD_CANCEL);
87 spd_set_notification_on(conn_, SPD_PAUSE);
88 spd_set_notification_on(conn_, SPD_RESUME);
89
90 loaded_ = true;
91 }
92
93 ~SpeechDispatcherWrapper() {
94 if (conn_) {
95 spd_close(conn_);
96 conn_ = NULL;
97 }
98
99 if (library_) {
100 dlclose(library_);
101 library_ = NULL;
102 }
103 }
104
105 bool Speak(const char* text) {
106 if (!loaded())
107 return false;
108
109 spd_say(conn_, SPD_TEXT, text);
110 return true;
111 }
112
113 bool IsSpeaking() {
114 return SpeechDispatcherWrapper::current_notification == SPD_EVENT_BEGIN;
115 }
116
117 bool StopSpeaking() {
118 if (!loaded())
119 return false;
120 spd_stop(conn_);
121 return true;
122 }
123
124 void SetRate(int rate) {
125 spd_set_voice_rate(conn_, rate);
126 }
127
128 void SetPitch(int pitch) {
129 spd_set_voice_pitch(conn_, pitch);
130 }
131
132 // States whether Speech Dispatcher loaded successfully.
133 bool loaded() {
134 return loaded_;
135 }
136
137 private:
138 static void NotificationCallback(size_t msg_id,
139 size_t client_id,
140 SPDNotificationType type);
141
142 // Interface bindings.
143 spd_open_func spd_open;
144 spd_say_func spd_say;
145 spd_stop_func spd_stop;
146 spd_close_func spd_close;
147 spd_set_notification_on_func spd_set_notification_on;
148 spd_set_voice_rate_func spd_set_voice_rate;
149 spd_set_voice_pitch_func spd_set_voice_pitch;
150
151 bool loaded_;
152 void* library_;
153 SPDConnection* conn_;
154 DISALLOW_COPY_AND_ASSIGN(SpeechDispatcherWrapper);
155 };
156 SPDNotificationType SpeechDispatcherWrapper::current_notification =
dmazzoni 2012/09/09 21:40:18 Add a newline before this, and add a comment that
157 SPD_EVENT_END;
158
13 class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl { 159 class ExtensionTtsPlatformImplLinux : public ExtensionTtsPlatformImpl {
14 public: 160 public:
15 virtual bool PlatformImplAvailable() { 161 virtual bool PlatformImplAvailable() {
16 return false; 162 return spd_.loaded();
17 } 163 }
18 164
19 virtual bool Speak( 165 virtual bool Speak(
20 int utterance_id, 166 int utterance_id,
21 const std::string& utterance, 167 const std::string& utterance,
22 const std::string& lang, 168 const std::string& lang,
23 const UtteranceContinuousParameters& params) { 169 const UtteranceContinuousParameters& params) {
24 error_ = kNotSupportedError; 170 if (!spd_.loaded()) {
25 return false; 171 error_ = kNotSupportedError;
172 return false;
173 }
174
175 if (params.rate >= 0.0 && params.rate <= 10.0)
176 spd_.SetRate(100 * log10(params.rate));
dmazzoni 2012/09/09 21:40:18 Documentation for how you came up with this mappin
177 if (params.pitch >= 0.0 && params.pitch <= 10.0)
178 spd_.SetPitch(100 * log10(params.pitch));
179
180 utterance_ = utterance;
181 utterance_id_ = utterance_id;
182
183 spd_.Speak(utterance.c_str());
184 return true;
26 } 185 }
27 186
28 virtual bool StopSpeaking() { 187 virtual bool StopSpeaking() {
29 error_ = kNotSupportedError; 188 return spd_.StopSpeaking();
30 return false;
31 } 189 }
32 190
33 virtual bool IsSpeaking() { 191 virtual bool IsSpeaking() {
34 error_ = kNotSupportedError; 192 return spd_.IsSpeaking();
35 return false;
36 } 193 }
37 194
38 virtual bool SendsEvent(TtsEventType event_type) { 195 virtual bool SendsEvent(TtsEventType event_type) {
39 return false; 196 return (event_type == TTS_EVENT_START || event_type == TTS_EVENT_END);
40 } 197 }
41 198
42 // Get the single instance of this class. 199 // Get the single instance of this class.
43 static ExtensionTtsPlatformImplLinux* GetInstance() { 200 static ExtensionTtsPlatformImplLinux* GetInstance() {
44 return Singleton<ExtensionTtsPlatformImplLinux>::get(); 201 return Singleton<ExtensionTtsPlatformImplLinux>::get();
45 } 202 }
46 203
204 void OnSpeechEvent(SPDNotificationType type) {
205 ExtensionTtsController* controller = ExtensionTtsController::GetInstance();
206 switch (type) {
207 case SPD_EVENT_BEGIN:
208 controller->OnTtsEvent(
209 utterance_id_, TTS_EVENT_START, 0, std::string());
210 break;
211 case SPD_EVENT_END:
212 controller->OnTtsEvent(
213 utterance_id_, TTS_EVENT_END, utterance_.size(), std::string());
214 break;
215 // TODO(dtseng): Unimplemented.
dmazzoni 2012/09/09 21:40:18 Can you implement these as part of this CL? They s
216 case SPD_EVENT_INDEX_MARK:
217 case SPD_EVENT_CANCEL:
218 case SPD_EVENT_PAUSE:
219 case SPD_EVENT_RESUME:
220 break;
221 }
222 }
223
47 private: 224 private:
48 ExtensionTtsPlatformImplLinux() {} 225 ExtensionTtsPlatformImplLinux(): utterance_id_(0) {}
49 virtual ~ExtensionTtsPlatformImplLinux() {} 226 virtual ~ExtensionTtsPlatformImplLinux() {}
50 227
228 SpeechDispatcherWrapper spd_;
229
230 // These apply to the current utterance only.
231 std::string utterance_;
232 int utterance_id_;
233
51 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplLinux>; 234 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplLinux>;
52 235
53 DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplLinux); 236 DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplLinux);
54 }; 237 };
55 238
56 // static 239 // static
57 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() { 240 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() {
58 return ExtensionTtsPlatformImplLinux::GetInstance(); 241 return ExtensionTtsPlatformImplLinux::GetInstance();
59 } 242 }
243
244 // static
245 void SpeechDispatcherWrapper::NotificationCallback(
246 size_t msg_id, size_t client_id, SPDNotificationType type) {
247 SpeechDispatcherWrapper::current_notification = type;
248 ExtensionTtsPlatformImplLinux::GetInstance()->OnSpeechEvent(type);
249 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698