• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/browser/extensions/extension_tts_api.h"
6 
7 #include <atlbase.h>
8 #include <atlcom.h>
9 #include <sapi.h>
10 
11 #include "base/memory/singleton.h"
12 #include "base/string_number_conversions.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "base/win/scoped_comptr.h"
16 
17 namespace util = extension_tts_api_util;
18 
19 class ExtensionTtsPlatformImplWin : public ExtensionTtsPlatformImpl {
20  public:
21   virtual bool Speak(
22       const std::string& utterance,
23       const std::string& language,
24       const std::string& gender,
25       double rate,
26       double pitch,
27       double volume);
28 
29   virtual bool StopSpeaking();
30 
31   virtual bool IsSpeaking();
32 
33   // Get the single instance of this class.
34   static ExtensionTtsPlatformImplWin* GetInstance();
35 
36  private:
37   ExtensionTtsPlatformImplWin();
~ExtensionTtsPlatformImplWin()38   virtual ~ExtensionTtsPlatformImplWin() {}
39 
40   base::win::ScopedComPtr<ISpVoice> speech_synthesizer_;
41   bool paused_;
42 
43   friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplWin>;
44 
45   DISALLOW_COPY_AND_ASSIGN(ExtensionTtsPlatformImplWin);
46 };
47 
48 // static
GetInstance()49 ExtensionTtsPlatformImpl* ExtensionTtsPlatformImpl::GetInstance() {
50   return ExtensionTtsPlatformImplWin::GetInstance();
51 }
52 
Speak(const std::string & src_utterance,const std::string & language,const std::string & gender,double rate,double pitch,double volume)53 bool ExtensionTtsPlatformImplWin::Speak(
54     const std::string& src_utterance,
55     const std::string& language,
56     const std::string& gender,
57     double rate,
58     double pitch,
59     double volume) {
60   std::wstring utterance = UTF8ToUTF16(src_utterance);
61 
62   if (!speech_synthesizer_)
63     return false;
64 
65   // Speech API equivalents for kGenderKey and kLanguageNameKey do not
66   // exist and thus are not supported.
67 
68   if (rate >= 0.0) {
69     // The TTS api allows a range of -10 to 10 for speech rate.
70     speech_synthesizer_->SetRate(static_cast<int32>(rate * 20 - 10));
71   }
72 
73   if (pitch >= 0.0) {
74     // The TTS api allows a range of -10 to 10 for speech pitch.
75     // TODO(dtseng): cleanup if we ever use any other properties that
76     // require xml.
77     std::wstring pitch_value =
78         base::IntToString16(static_cast<int>(pitch * 20 - 10));
79     utterance = L"<pitch absmiddle=\"" + pitch_value + L"\">" +
80         utterance + L"</pitch>";
81   }
82 
83   if (volume >= 0.0) {
84     // The TTS api allows a range of 0 to 100 for speech volume.
85     speech_synthesizer_->SetVolume(static_cast<uint16>(volume * 100));
86   }
87 
88   if (paused_) {
89     speech_synthesizer_->Resume();
90     paused_ = false;
91   }
92   speech_synthesizer_->Speak(
93       utterance.c_str(), SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL);
94 
95   return true;
96 }
97 
StopSpeaking()98 bool ExtensionTtsPlatformImplWin::StopSpeaking() {
99   if (speech_synthesizer_ && !paused_) {
100     speech_synthesizer_->Pause();
101     paused_ = true;
102   }
103   return true;
104 }
105 
IsSpeaking()106 bool ExtensionTtsPlatformImplWin::IsSpeaking() {
107   if (speech_synthesizer_ && !paused_) {
108     SPVOICESTATUS status;
109     HRESULT result = speech_synthesizer_->GetStatus(&status, NULL);
110     if (result == S_OK) {
111       if (status.dwRunningState == 0 ||  // 0 == waiting to speak
112           status.dwRunningState == SPRS_IS_SPEAKING) {
113         return true;
114       }
115     }
116   }
117   return false;
118 }
119 
ExtensionTtsPlatformImplWin()120 ExtensionTtsPlatformImplWin::ExtensionTtsPlatformImplWin()
121   : speech_synthesizer_(NULL),
122     paused_(false) {
123   CoCreateInstance(
124       CLSID_SpVoice,
125       NULL,
126       CLSCTX_SERVER,
127       IID_ISpVoice,
128       reinterpret_cast<void**>(&speech_synthesizer_));
129 }
130 
131 // static
GetInstance()132 ExtensionTtsPlatformImplWin* ExtensionTtsPlatformImplWin::GetInstance() {
133   return Singleton<ExtensionTtsPlatformImplWin>::get();
134 }
135