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

Side by Side Diff: chrome/browser/extensions/extension_tts_api_mac.mm

Issue 9808024: Move TTS extension API to chrome/browser/speech/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix chromeos compile error, rebase Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <string>
6
7 #include "base/mac/cocoa_protocols.h"
8 #include "base/memory/scoped_nsobject.h"
9 #include "base/memory/singleton.h"
10 #include "base/sys_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/extension_function.h"
13 #include "chrome/browser/extensions/extension_tts_api_constants.h"
14 #include "chrome/browser/extensions/extension_tts_api_controller.h"
15 #include "chrome/browser/extensions/extension_tts_api_platform.h"
16
17 #import <Cocoa/Cocoa.h>
18
19 class ExtensionTtsPlatformImplMac;
20
21 @interface ChromeTtsDelegate : NSObject <NSSpeechSynthesizerDelegate> {
22 @private
23 ExtensionTtsPlatformImplMac* ttsImplMac_; // weak.
24 }
25
26 - (id)initWithPlatformImplMac:(ExtensionTtsPlatformImplMac*)ttsImplMac;
27
28 @end
29
30 class ExtensionTtsPlatformImplMac : public ExtensionTtsPlatformImpl {
31 public:
32 virtual bool PlatformImplAvailable() {
33 return true;
34 }
35
36 virtual bool Speak(
37 int utterance_id,
38 const std::string& utterance,
39 const std::string& lang,
40 const UtteranceContinuousParameters& params);
41
42 virtual bool StopSpeaking();
43
44 virtual bool IsSpeaking();
45
46 virtual bool SendsEvent(TtsEventType event_type);
47
48 // Called by ChromeTtsDelegate when we get a callback from the
49 // native speech engine.
50 void OnSpeechEvent(NSSpeechSynthesizer* sender,
51 TtsEventType event_type,
52 int char_index,
53 const std::string& error_message);
54
55 // Get the single instance of this class.
56 static ExtensionTtsPlatformImplMac* GetInstance();
57
58 private:
59 ExtensionTtsPlatformImplMac();
60 virtual ~ExtensionTtsPlatformImplMac();
61
62 scoped_nsobject<NSSpeechSynthesizer> speech_synthesizer_;
63 scoped_nsobject<ChromeTtsDelegate> delegate_;
64 int utterance_id_;
65 std::string utterance_;
66 bool sent_start_event_;
67
68 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplMac>;
69
70 DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplMac);
71 };
72
73 // static
74 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() {
75 return ExtensionTtsPlatformImplMac::GetInstance();
76 }
77
78 bool ExtensionTtsPlatformImplMac::Speak(
79 int utterance_id,
80 const std::string& utterance,
81 const std::string& lang,
82 const UtteranceContinuousParameters& params) {
83 // Deliberately construct a new speech synthesizer every time Speak is
84 // called, otherwise there's no way to know whether calls to the delegate
85 // apply to the current utterance or a previous utterance. In
86 // experimentation, the overhead of constructing and destructing a
87 // NSSpeechSynthesizer is minimal.
88 speech_synthesizer_.reset([[NSSpeechSynthesizer alloc] init]);
89 [speech_synthesizer_ setDelegate:delegate_];
90
91 utterance_id_ = utterance_id;
92 sent_start_event_ = false;
93
94 // TODO: convert SSML to SAPI xml. http://crbug.com/88072
95 utterance_ = utterance;
96
97 // TODO: support languages other than the default: crbug.com/88059
98
99 if (params.rate >= 0.0) {
100 // The TTS api defines rate via words per minute. Let 200 be the default.
101 [speech_synthesizer_
102 setObject:[NSNumber numberWithInt:params.rate * 200]
103 forProperty:NSSpeechRateProperty error:nil];
104 }
105
106 if (params.pitch >= 0.0) {
107 // The TTS api allows an approximate range of 30 to 65 for speech pitch.
108 [speech_synthesizer_
109 setObject: [NSNumber numberWithInt:(params.pitch * 17 + 30)]
110 forProperty:NSSpeechPitchBaseProperty error:nil];
111 }
112
113 if (params.volume >= 0.0) {
114 [speech_synthesizer_
115 setObject: [NSNumber numberWithFloat:params.volume]
116 forProperty:NSSpeechVolumeProperty error:nil];
117 }
118
119 return [speech_synthesizer_ startSpeakingString:
120 [NSString stringWithUTF8String: utterance.c_str()]];
121 }
122
123 bool ExtensionTtsPlatformImplMac::StopSpeaking() {
124 if (speech_synthesizer_.get()) {
125 [speech_synthesizer_ stopSpeaking];
126 speech_synthesizer_.reset(nil);
127 }
128 return true;
129 }
130
131 bool ExtensionTtsPlatformImplMac::IsSpeaking() {
132 // Note: this is OK even if speech_synthesizer_ is nil, it will return false.
133 return [speech_synthesizer_ isSpeaking];
134 }
135
136 bool ExtensionTtsPlatformImplMac::SendsEvent(TtsEventType event_type) {
137 return (event_type == TTS_EVENT_START ||
138 event_type == TTS_EVENT_END ||
139 event_type == TTS_EVENT_WORD ||
140 event_type == TTS_EVENT_ERROR);
141 }
142
143 void ExtensionTtsPlatformImplMac::OnSpeechEvent(
144 NSSpeechSynthesizer* sender,
145 TtsEventType event_type,
146 int char_index,
147 const std::string& error_message) {
148 // Don't send events from an utterance that's already completed.
149 // This depends on the fact that we construct a new NSSpeechSynthesizer
150 // each time we call Speak.
151 if (sender != speech_synthesizer_.get())
152 return;
153
154 if (event_type == TTS_EVENT_END)
155 char_index = utterance_.size();
156 ExtensionTtsController* controller = ExtensionTtsController::GetInstance();
157 if (event_type == TTS_EVENT_WORD && !sent_start_event_) {
158 controller->OnTtsEvent(
159 utterance_id_, TTS_EVENT_START, 0, "");
160 sent_start_event_ = true;
161 }
162 controller->OnTtsEvent(
163 utterance_id_, event_type, char_index, error_message);
164 }
165
166 ExtensionTtsPlatformImplMac::ExtensionTtsPlatformImplMac() {
167 utterance_id_ = -1;
168 sent_start_event_ = true;
169
170 delegate_.reset([[ChromeTtsDelegate alloc] initWithPlatformImplMac:this]);
171 }
172
173 ExtensionTtsPlatformImplMac::~ExtensionTtsPlatformImplMac() {
174 }
175
176 // static
177 ExtensionTtsPlatformImplMac* ExtensionTtsPlatformImplMac::GetInstance() {
178 return Singleton<ExtensionTtsPlatformImplMac>::get();
179 }
180
181 @implementation ChromeTtsDelegate
182
183 - (id)initWithPlatformImplMac:(ExtensionTtsPlatformImplMac*)ttsImplMac {
184 if ((self = [super init])) {
185 ttsImplMac_ = ttsImplMac;
186 }
187 return self;
188 }
189
190 - (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
191 didFinishSpeaking:(BOOL)finished_speaking {
192 ttsImplMac_->OnSpeechEvent(sender, TTS_EVENT_END, 0, "");
193 }
194
195 - (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
196 willSpeakWord:(NSRange)character_range
197 ofString:(NSString*)string {
198 ttsImplMac_->OnSpeechEvent(sender, TTS_EVENT_WORD,
199 character_range.location, "");
200 }
201
202 - (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
203 didEncounterErrorAtIndex:(NSUInteger)character_index
204 ofString:(NSString*)string
205 message:(NSString*)message {
206 std::string message_utf8 = base::SysNSStringToUTF8(message);
207 ttsImplMac_->OnSpeechEvent(sender, TTS_EVENT_ERROR, character_index,
208 message_utf8);
209 }
210
211 @end
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_tts_api_linux.cc ('k') | chrome/browser/extensions/extension_tts_api_platform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698