Separate out the TtsController interface from it's impl

Create TtsControllerImpl so that TtsController can serve
as TTS interface once it is moved to content in future.
The approach is similar to SpeechRecognitionManager.
This is part of an effort to move TTS to content.

BUG=347045

Review URL: https://codereview.chromium.org/412783002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285169 0039d316-1c4b-4281-b951-d872f2087c98
parent d60ec3e0
...@@ -274,109 +274,63 @@ class TtsController { ...@@ -274,109 +274,63 @@ class TtsController {
static TtsController* GetInstance(); static TtsController* GetInstance();
// Returns true if we're currently speaking an utterance. // Returns true if we're currently speaking an utterance.
bool IsSpeaking(); virtual bool IsSpeaking() = 0;
// Speak the given utterance. If the utterance's can_enqueue flag is true // Speak the given utterance. If the utterance's can_enqueue flag is true
// and another utterance is in progress, adds it to the end of the queue. // and another utterance is in progress, adds it to the end of the queue.
// Otherwise, interrupts any current utterance and speaks this one // Otherwise, interrupts any current utterance and speaks this one
// immediately. // immediately.
void SpeakOrEnqueue(Utterance* utterance); virtual void SpeakOrEnqueue(Utterance* utterance) = 0;
// Stop all utterances and flush the queue. Implies leaving pause mode // Stop all utterances and flush the queue. Implies leaving pause mode
// as well. // as well.
void Stop(); virtual void Stop() = 0;
// Pause the speech queue. Some engines may support pausing in the middle // Pause the speech queue. Some engines may support pausing in the middle
// of an utterance. // of an utterance.
void Pause(); virtual void Pause() = 0;
// Resume speaking. // Resume speaking.
void Resume(); virtual void Resume() = 0;
// Handle events received from the speech engine. Events are forwarded to // Handle events received from the speech engine. Events are forwarded to
// the callback function, and in addition, completion and error events // the callback function, and in addition, completion and error events
// trigger finishing the current utterance and starting the next one, if // trigger finishing the current utterance and starting the next one, if
// any. // any.
void OnTtsEvent(int utterance_id, virtual void OnTtsEvent(int utterance_id,
TtsEventType event_type, TtsEventType event_type,
int char_index, int char_index,
const std::string& error_message); const std::string& error_message) = 0;
// Return a list of all available voices, including the native voice, // Return a list of all available voices, including the native voice,
// if supported, and all voices registered by extensions. // if supported, and all voices registered by extensions.
void GetVoices(Profile* profile, std::vector<VoiceData>* out_voices); virtual void GetVoices(Profile* profile,
std::vector<VoiceData>* out_voices) = 0;
// Called by TtsExtensionLoaderChromeOs::LoadTtsExtension when it // Called by TtsExtensionLoaderChromeOs::LoadTtsExtension when it
// finishes loading the built-in TTS component extension. // finishes loading the built-in TTS component extension.
void RetrySpeakingQueuedUtterances(); virtual void RetrySpeakingQueuedUtterances() = 0;
// Called by the extension system or platform implementation when the // Called by the extension system or platform implementation when the
// list of voices may have changed and should be re-queried. // list of voices may have changed and should be re-queried.
void VoicesChanged(); virtual void VoicesChanged() = 0;
// Add a delegate that wants to be notified when the set of voices changes. // Add a delegate that wants to be notified when the set of voices changes.
void AddVoicesChangedDelegate(VoicesChangedDelegate* delegate); virtual void AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) = 0;
// Remove delegate that wants to be notified when the set of voices changes. // Remove delegate that wants to be notified when the set of voices changes.
void RemoveVoicesChangedDelegate(VoicesChangedDelegate* delegate); virtual void RemoveVoicesChangedDelegate(VoicesChangedDelegate* delegate) = 0;
// Set the delegate that processes TTS requests with user-installed // Set the delegate that processes TTS requests with user-installed
// extensions. // extensions.
void SetTtsEngineDelegate(TtsEngineDelegate* delegate); virtual void SetTtsEngineDelegate(TtsEngineDelegate* delegate) = 0;
// For unit testing. // For unit testing.
void SetPlatformImpl(TtsPlatformImpl* platform_impl); virtual void SetPlatformImpl(TtsPlatformImpl* platform_impl) = 0;
int QueueSize(); virtual int QueueSize() = 0;
protected: protected:
TtsController(); virtual ~TtsController() {}
virtual ~TtsController();
private:
// Get the platform TTS implementation (or injected mock).
TtsPlatformImpl* GetPlatformImpl();
// Start speaking the given utterance. Will either take ownership of
// |utterance| or delete it if there's an error. Returns true on success.
void SpeakNow(Utterance* utterance);
// Clear the utterance queue. If send_events is true, will send
// TTS_EVENT_CANCELLED events on each one.
void ClearUtteranceQueue(bool send_events);
// Finalize and delete the current utterance.
void FinishCurrentUtterance();
// Start speaking the next utterance in the queue.
void SpeakNextUtterance();
// Given an utterance and a vector of voices, return the
// index of the voice that best matches the utterance.
int GetMatchingVoice(const Utterance* utterance,
std::vector<VoiceData>& voices);
friend struct DefaultSingletonTraits<TtsController>;
// The current utterance being spoken.
Utterance* current_utterance_;
// Whether the queue is paused or not.
bool paused_;
// A queue of utterances to speak after the current one finishes.
std::queue<Utterance*> utterance_queue_;
// A set of delegates that want to be notified when the voices change.
std::set<VoicesChangedDelegate*> voices_changed_delegates_;
// A pointer to the platform implementation of text-to-speech, for
// dependency injection.
TtsPlatformImpl* platform_impl_;
// The delegate that processes TTS requests with user-installed extensions.
TtsEngineDelegate* tts_engine_delegate_;
DISALLOW_COPY_AND_ASSIGN(TtsController);
}; };
#endif // CHROME_BROWSER_SPEECH_TTS_CONTROLLER_H_ #endif // CHROME_BROWSER_SPEECH_TTS_CONTROLLER_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/speech/tts_controller.h" #include "chrome/browser/speech/tts_controller_impl.h"
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -102,23 +102,27 @@ void Utterance::set_options(const base::Value* options) { ...@@ -102,23 +102,27 @@ void Utterance::set_options(const base::Value* options) {
options_.reset(options->DeepCopy()); options_.reset(options->DeepCopy());
} }
TtsController* TtsController::GetInstance() {
return TtsControllerImpl::GetInstance();
}
// //
// TtsController // TtsControllerImpl
// //
// static // static
TtsController* TtsController::GetInstance() { TtsControllerImpl* TtsControllerImpl::GetInstance() {
return Singleton<TtsController>::get(); return Singleton<TtsControllerImpl>::get();
} }
TtsController::TtsController() TtsControllerImpl::TtsControllerImpl()
: current_utterance_(NULL), : current_utterance_(NULL),
paused_(false), paused_(false),
platform_impl_(NULL), platform_impl_(NULL),
tts_engine_delegate_(NULL) { tts_engine_delegate_(NULL) {
} }
TtsController::~TtsController() { TtsControllerImpl::~TtsControllerImpl() {
if (current_utterance_) { if (current_utterance_) {
current_utterance_->Finish(); current_utterance_->Finish();
delete current_utterance_; delete current_utterance_;
...@@ -128,7 +132,7 @@ TtsController::~TtsController() { ...@@ -128,7 +132,7 @@ TtsController::~TtsController() {
ClearUtteranceQueue(false); // Don't sent events. ClearUtteranceQueue(false); // Don't sent events.
} }
void TtsController::SpeakOrEnqueue(Utterance* utterance) { void TtsControllerImpl::SpeakOrEnqueue(Utterance* utterance) {
// If we're paused and we get an utterance that can't be queued, // If we're paused and we get an utterance that can't be queued,
// flush the queue but stay in the paused state. // flush the queue but stay in the paused state.
if (paused_ && !utterance->can_enqueue()) { if (paused_ && !utterance->can_enqueue()) {
...@@ -145,7 +149,7 @@ void TtsController::SpeakOrEnqueue(Utterance* utterance) { ...@@ -145,7 +149,7 @@ void TtsController::SpeakOrEnqueue(Utterance* utterance) {
} }
} }
void TtsController::SpeakNow(Utterance* utterance) { void TtsControllerImpl::SpeakNow(Utterance* utterance) {
// Ensure we have all built-in voices loaded. This is a no-op if already // Ensure we have all built-in voices loaded. This is a no-op if already
// loaded. // loaded.
bool loaded_built_in = bool loaded_built_in =
...@@ -236,7 +240,7 @@ void TtsController::SpeakNow(Utterance* utterance) { ...@@ -236,7 +240,7 @@ void TtsController::SpeakNow(Utterance* utterance) {
} }
} }
void TtsController::Stop() { void TtsControllerImpl::Stop() {
paused_ = false; paused_ = false;
if (current_utterance_ && !current_utterance_->extension_id().empty()) { if (current_utterance_ && !current_utterance_->extension_id().empty()) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
...@@ -255,7 +259,7 @@ void TtsController::Stop() { ...@@ -255,7 +259,7 @@ void TtsController::Stop() {
ClearUtteranceQueue(true); // Send events. ClearUtteranceQueue(true); // Send events.
} }
void TtsController::Pause() { void TtsControllerImpl::Pause() {
paused_ = true; paused_ = true;
if (current_utterance_ && !current_utterance_->extension_id().empty()) { if (current_utterance_ && !current_utterance_->extension_id().empty()) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
...@@ -268,7 +272,7 @@ void TtsController::Pause() { ...@@ -268,7 +272,7 @@ void TtsController::Pause() {
} }
} }
void TtsController::Resume() { void TtsControllerImpl::Resume() {
paused_ = false; paused_ = false;
if (current_utterance_ && !current_utterance_->extension_id().empty()) { if (current_utterance_ && !current_utterance_->extension_id().empty()) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
...@@ -283,7 +287,7 @@ void TtsController::Resume() { ...@@ -283,7 +287,7 @@ void TtsController::Resume() {
} }
} }
void TtsController::OnTtsEvent(int utterance_id, void TtsControllerImpl::OnTtsEvent(int utterance_id,
TtsEventType event_type, TtsEventType event_type,
int char_index, int char_index,
const std::string& error_message) { const std::string& error_message) {
...@@ -301,7 +305,7 @@ void TtsController::OnTtsEvent(int utterance_id, ...@@ -301,7 +305,7 @@ void TtsController::OnTtsEvent(int utterance_id,
} }
} }
void TtsController::GetVoices(Profile* profile, void TtsControllerImpl::GetVoices(Profile* profile,
std::vector<VoiceData>* out_voices) { std::vector<VoiceData>* out_voices) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
if (profile && tts_engine_delegate_) if (profile && tts_engine_delegate_)
...@@ -318,11 +322,11 @@ void TtsController::GetVoices(Profile* profile, ...@@ -318,11 +322,11 @@ void TtsController::GetVoices(Profile* profile,
} }
} }
bool TtsController::IsSpeaking() { bool TtsControllerImpl::IsSpeaking() {
return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking();
} }
void TtsController::FinishCurrentUtterance() { void TtsControllerImpl::FinishCurrentUtterance() {
if (current_utterance_) { if (current_utterance_) {
if (!current_utterance_->finished()) if (!current_utterance_->finished())
current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex,
...@@ -332,7 +336,7 @@ void TtsController::FinishCurrentUtterance() { ...@@ -332,7 +336,7 @@ void TtsController::FinishCurrentUtterance() {
} }
} }
void TtsController::SpeakNextUtterance() { void TtsControllerImpl::SpeakNextUtterance() {
if (paused_) if (paused_)
return; return;
...@@ -345,12 +349,12 @@ void TtsController::SpeakNextUtterance() { ...@@ -345,12 +349,12 @@ void TtsController::SpeakNextUtterance() {
} }
} }
void TtsController::RetrySpeakingQueuedUtterances() { void TtsControllerImpl::RetrySpeakingQueuedUtterances() {
if (current_utterance_ == NULL && !utterance_queue_.empty()) if (current_utterance_ == NULL && !utterance_queue_.empty())
SpeakNextUtterance(); SpeakNextUtterance();
} }
void TtsController::ClearUtteranceQueue(bool send_events) { void TtsControllerImpl::ClearUtteranceQueue(bool send_events) {
while (!utterance_queue_.empty()) { while (!utterance_queue_.empty()) {
Utterance* utterance = utterance_queue_.front(); Utterance* utterance = utterance_queue_.front();
utterance_queue_.pop(); utterance_queue_.pop();
...@@ -363,22 +367,22 @@ void TtsController::ClearUtteranceQueue(bool send_events) { ...@@ -363,22 +367,22 @@ void TtsController::ClearUtteranceQueue(bool send_events) {
} }
} }
void TtsController::SetPlatformImpl( void TtsControllerImpl::SetPlatformImpl(
TtsPlatformImpl* platform_impl) { TtsPlatformImpl* platform_impl) {
platform_impl_ = platform_impl; platform_impl_ = platform_impl;
} }
int TtsController::QueueSize() { int TtsControllerImpl::QueueSize() {
return static_cast<int>(utterance_queue_.size()); return static_cast<int>(utterance_queue_.size());
} }
TtsPlatformImpl* TtsController::GetPlatformImpl() { TtsPlatformImpl* TtsControllerImpl::GetPlatformImpl() {
if (!platform_impl_) if (!platform_impl_)
platform_impl_ = TtsPlatformImpl::GetInstance(); platform_impl_ = TtsPlatformImpl::GetInstance();
return platform_impl_; return platform_impl_;
} }
int TtsController::GetMatchingVoice( int TtsControllerImpl::GetMatchingVoice(
const Utterance* utterance, std::vector<VoiceData>& voices) { const Utterance* utterance, std::vector<VoiceData>& voices) {
// Make two passes: the first time, do strict language matching // Make two passes: the first time, do strict language matching
// ('fr-FR' does not match 'fr-CA'). The second time, do prefix // ('fr-FR' does not match 'fr-CA'). The second time, do prefix
...@@ -436,7 +440,7 @@ int TtsController::GetMatchingVoice( ...@@ -436,7 +440,7 @@ int TtsController::GetMatchingVoice(
return -1; return -1;
} }
void TtsController::VoicesChanged() { void TtsControllerImpl::VoicesChanged() {
for (std::set<VoicesChangedDelegate*>::iterator iter = for (std::set<VoicesChangedDelegate*>::iterator iter =
voices_changed_delegates_.begin(); voices_changed_delegates_.begin();
iter != voices_changed_delegates_.end(); ++iter) { iter != voices_changed_delegates_.end(); ++iter) {
...@@ -444,16 +448,17 @@ void TtsController::VoicesChanged() { ...@@ -444,16 +448,17 @@ void TtsController::VoicesChanged() {
} }
} }
void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { void TtsControllerImpl::AddVoicesChangedDelegate(
VoicesChangedDelegate* delegate) {
voices_changed_delegates_.insert(delegate); voices_changed_delegates_.insert(delegate);
} }
void TtsController::RemoveVoicesChangedDelegate( void TtsControllerImpl::RemoveVoicesChangedDelegate(
VoicesChangedDelegate* delegate) { VoicesChangedDelegate* delegate) {
voices_changed_delegates_.erase(delegate); voices_changed_delegates_.erase(delegate);
} }
void TtsController::SetTtsEngineDelegate( void TtsControllerImpl::SetTtsEngineDelegate(
TtsEngineDelegate* delegate) { TtsEngineDelegate* delegate) {
tts_engine_delegate_ = delegate; tts_engine_delegate_ = delegate;
} }
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_
#define CHROME_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_
#include <queue>
#include <set>
#include <string>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/speech/tts_controller.h"
#include "url/gurl.h"
// Singleton class that manages text-to-speech for the TTS and TTS engine
// extension APIs, maintaining a queue of pending utterances and keeping
// track of all state.
class TtsControllerImpl : public TtsController {
public:
// Get the single instance of this class.
static TtsControllerImpl* GetInstance();
// TtsController methods
virtual bool IsSpeaking() OVERRIDE;
virtual void SpeakOrEnqueue(Utterance* utterance) OVERRIDE;
virtual void Stop() OVERRIDE;
virtual void Pause() OVERRIDE;
virtual void Resume() OVERRIDE;
virtual void OnTtsEvent(int utterance_id,
TtsEventType event_type,
int char_index,
const std::string& error_message) OVERRIDE;
virtual void GetVoices(Profile* profile,
std::vector<VoiceData>* out_voices) OVERRIDE;
virtual void RetrySpeakingQueuedUtterances() OVERRIDE;
virtual void VoicesChanged() OVERRIDE;
virtual void AddVoicesChangedDelegate(
VoicesChangedDelegate* delegate) OVERRIDE;
virtual void RemoveVoicesChangedDelegate(
VoicesChangedDelegate* delegate) OVERRIDE;
virtual void SetTtsEngineDelegate(TtsEngineDelegate* delegate) OVERRIDE;
virtual void SetPlatformImpl(TtsPlatformImpl* platform_impl) OVERRIDE;
virtual int QueueSize() OVERRIDE;
protected:
TtsControllerImpl();
virtual ~TtsControllerImpl();
private:
// Get the platform TTS implementation (or injected mock).
TtsPlatformImpl* GetPlatformImpl();
// Start speaking the given utterance. Will either take ownership of
// |utterance| or delete it if there's an error. Returns true on success.
void SpeakNow(Utterance* utterance);
// Clear the utterance queue. If send_events is true, will send
// TTS_EVENT_CANCELLED events on each one.
void ClearUtteranceQueue(bool send_events);
// Finalize and delete the current utterance.
void FinishCurrentUtterance();
// Start speaking the next utterance in the queue.
void SpeakNextUtterance();
// Given an utterance and a vector of voices, return the
// index of the voice that best matches the utterance.
int GetMatchingVoice(const Utterance* utterance,
std::vector<VoiceData>& voices);
friend struct DefaultSingletonTraits<TtsControllerImpl>;
// The current utterance being spoken.
Utterance* current_utterance_;
// Whether the queue is paused or not.
bool paused_;
// A queue of utterances to speak after the current one finishes.
std::queue<Utterance*> utterance_queue_;
// A set of delegates that want to be notified when the voices change.
std::set<VoicesChangedDelegate*> voices_changed_delegates_;
// A pointer to the platform implementation of text-to-speech, for
// dependency injection.
TtsPlatformImpl* platform_impl_;
// The delegate that processes TTS requests with user-installed extensions.
TtsEngineDelegate* tts_engine_delegate_;
DISALLOW_COPY_AND_ASSIGN(TtsControllerImpl);
};
#endif // CHROME_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
// Unit tests for the TTS Controller. // Unit tests for the TTS Controller.
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/speech/tts_controller.h" #include "chrome/browser/speech/tts_controller_impl.h"
#include "chrome/browser/speech/tts_platform.h" #include "chrome/browser/speech/tts_platform.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -37,7 +37,7 @@ class DummyTtsPlatformImpl : public TtsPlatformImpl { ...@@ -37,7 +37,7 @@ class DummyTtsPlatformImpl : public TtsPlatformImpl {
}; };
// Subclass of TtsController with a public ctor and dtor. // Subclass of TtsController with a public ctor and dtor.
class TestableTtsController : public TtsController { class TestableTtsController : public TtsControllerImpl {
public: public:
TestableTtsController() {} TestableTtsController() {}
virtual ~TestableTtsController() {} virtual ~TestableTtsController() {}
......
...@@ -1253,8 +1253,9 @@ ...@@ -1253,8 +1253,9 @@
'browser/speech/tts_android.cc', 'browser/speech/tts_android.cc',
'browser/speech/tts_android.h', 'browser/speech/tts_android.h',
'browser/speech/tts_chromeos.cc', 'browser/speech/tts_chromeos.cc',
'browser/speech/tts_controller.cc',
'browser/speech/tts_controller.h', 'browser/speech/tts_controller.h',
'browser/speech/tts_controller_impl.cc',
'browser/speech/tts_controller_impl.h',
'browser/speech/tts_mac.mm', 'browser/speech/tts_mac.mm',
'browser/speech/tts_platform.cc', 'browser/speech/tts_platform.cc',
'browser/speech/tts_platform.h', 'browser/speech/tts_platform.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment