diff options
author | allanwoj@chromium.org <allanwoj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-21 16:45:06 +0000 |
---|---|---|
committer | allanwoj@chromium.org <allanwoj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-21 16:45:06 +0000 |
commit | 0944a72912b25707d953edcf029ab8c96594d825 (patch) | |
tree | 90854b8166be197413cfa11bb357e572d2ea5dc8 /content/browser | |
parent | f35a9d1b289827e2f21a23fdafadf5c3c6a21a2d (diff) | |
download | chromium_src-0944a72912b25707d953edcf029ab8c96594d825.zip chromium_src-0944a72912b25707d953edcf029ab8c96594d825.tar.gz chromium_src-0944a72912b25707d953edcf029ab8c96594d825.tar.bz2 |
Refactor SpeechInputManager between chrome/ and content/.
Moved requests_ (and related code) to SpeechInputManager. Added some pure virtual methods in SpeechInputManager that are implemented by ChromeSpeechInputManager.
BUG=95792
TEST=None
Review URL: http://codereview.chromium.org/7838028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102117 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r-- | content/browser/speech/speech_input_browsertest.cc | 18 | ||||
-rw-r--r-- | content/browser/speech/speech_input_manager.cc | 156 | ||||
-rw-r--r-- | content/browser/speech/speech_input_manager.h | 92 |
3 files changed, 259 insertions, 7 deletions
diff --git a/content/browser/speech/speech_input_browsertest.cc b/content/browser/speech/speech_input_browsertest.cc index 0da6e47..4909a31 100644 --- a/content/browser/speech/speech_input_browsertest.cc +++ b/content/browser/speech/speech_input_browsertest.cc @@ -92,6 +92,24 @@ class FakeSpeechInputManager : public SpeechInputManager { did_cancel_all_ = true; } + protected: + virtual void GetRequestInfo(bool* can_report_metrics, + std::string* request_info) {} + virtual void ShowRecognitionRequested(int caller_id, + int render_process_id, + int render_view_id, + const gfx::Rect& element_rect) {} + virtual void ShowWarmUp(int caller_id) {} + virtual void ShowRecognizing(int caller_id) {} + virtual void ShowRecording(int caller_id) {} + virtual void ShowInputVolume(int caller_id, + float volume, + float noise_volume) {} + virtual void ShowNoMicError(int caller_id) {} + virtual void ShowRecognizerError(int caller_id, + SpeechRecognizer::ErrorCode error) {} + virtual void DoClose(int caller_id) {} + private: void SetFakeRecognitionResult() { if (caller_id_) { // Do a check in case we were cancelled.. diff --git a/content/browser/speech/speech_input_manager.cc b/content/browser/speech/speech_input_manager.cc index 104d7e8..d115c89 100644 --- a/content/browser/speech/speech_input_manager.cc +++ b/content/browser/speech/speech_input_manager.cc @@ -9,10 +9,24 @@ namespace speech_input { -SpeechInputManager::SpeechInputManager() : censor_results_(true) { +SpeechInputManager::SpeechInputManager() + : can_report_metrics_(false), + censor_results_(true), + recording_caller_id_(0) { } SpeechInputManager::~SpeechInputManager() { + while (requests_.begin() != requests_.end()) + CancelRecognition(requests_.begin()->first); +} + +bool SpeechInputManager::HasPendingRequest(int caller_id) const { + return requests_.find(caller_id) != requests_.end(); +} + +SpeechInputManagerDelegate* SpeechInputManager::GetDelegate( + int caller_id) const { + return requests_.find(caller_id)->second.delegate; } void SpeechInputManager::ShowAudioInputSettings() { @@ -30,4 +44,144 @@ void SpeechInputManager::ShowAudioInputSettings() { AudioManager::GetAudioManager()->ShowAudioInputSettings(); } +void SpeechInputManager::StartRecognition( + SpeechInputManagerDelegate* delegate, + int caller_id, + int render_process_id, + int render_view_id, + const gfx::Rect& element_rect, + const std::string& language, + const std::string& grammar, + const std::string& origin_url) { + DCHECK(!HasPendingRequest(caller_id)); + + ShowRecognitionRequested( + caller_id, render_process_id, render_view_id, element_rect); + GetRequestInfo(&can_report_metrics_, &request_info_); + + SpeechInputRequest* request = &requests_[caller_id]; + request->delegate = delegate; + request->recognizer = new SpeechRecognizer( + this, caller_id, language, grammar, censor_results(), + request_info_, can_report_metrics_ ? origin_url : ""); + request->is_active = false; + + StartRecognitionForRequest(caller_id); +} + +void SpeechInputManager::StartRecognitionForRequest(int caller_id) { + DCHECK(HasPendingRequest(caller_id)); + + // If we are currently recording audio for another caller, abort that cleanly. + if (recording_caller_id_) + CancelRecognitionAndInformDelegate(recording_caller_id_); + + if (!AudioManager::GetAudioManager()->HasAudioInputDevices()) { + ShowNoMicError(caller_id); + } else { + recording_caller_id_ = caller_id; + requests_[caller_id].is_active = true; + requests_[caller_id].recognizer->StartRecording(); + ShowWarmUp(caller_id); + } +} + +void SpeechInputManager::CancelRecognition(int caller_id) { + DCHECK(HasPendingRequest(caller_id)); + if (requests_[caller_id].is_active) + requests_[caller_id].recognizer->CancelRecognition(); + requests_.erase(caller_id); + if (recording_caller_id_ == caller_id) + recording_caller_id_ = 0; + DoClose(caller_id); +} + +void SpeechInputManager::CancelAllRequestsWithDelegate( + SpeechInputManagerDelegate* delegate) { + SpeechRecognizerMap::iterator it = requests_.begin(); + while (it != requests_.end()) { + if (it->second.delegate == delegate) { + CancelRecognition(it->first); + // This map will have very few elements so it is simpler to restart. + it = requests_.begin(); + } else { + ++it; + } + } +} + +void SpeechInputManager::StopRecording(int caller_id) { + DCHECK(HasPendingRequest(caller_id)); + requests_[caller_id].recognizer->StopRecording(); +} + +void SpeechInputManager::SetRecognitionResult( + int caller_id, bool error, const SpeechInputResultArray& result) { + DCHECK(HasPendingRequest(caller_id)); + GetDelegate(caller_id)->SetRecognitionResult(caller_id, result); +} + +void SpeechInputManager::DidCompleteRecording(int caller_id) { + DCHECK(recording_caller_id_ == caller_id); + DCHECK(HasPendingRequest(caller_id)); + recording_caller_id_ = 0; + GetDelegate(caller_id)->DidCompleteRecording(caller_id); + ShowRecognizing(caller_id); +} + +void SpeechInputManager::DidCompleteRecognition(int caller_id) { + GetDelegate(caller_id)->DidCompleteRecognition(caller_id); + requests_.erase(caller_id); + DoClose(caller_id); +} + +void SpeechInputManager::OnRecognizerError( + int caller_id, SpeechRecognizer::ErrorCode error) { + if (caller_id == recording_caller_id_) + recording_caller_id_ = 0; + requests_[caller_id].is_active = false; + ShowRecognizerError(caller_id, error); +} + +void SpeechInputManager::DidStartReceivingAudio(int caller_id) { + DCHECK(HasPendingRequest(caller_id)); + DCHECK(recording_caller_id_ == caller_id); + ShowRecording(caller_id); +} + +void SpeechInputManager::DidCompleteEnvironmentEstimation(int caller_id) { + DCHECK(HasPendingRequest(caller_id)); + DCHECK(recording_caller_id_ == caller_id); +} + +void SpeechInputManager::SetInputVolume(int caller_id, float volume, + float noise_volume) { + DCHECK(HasPendingRequest(caller_id)); + DCHECK_EQ(recording_caller_id_, caller_id); + ShowInputVolume(caller_id, volume, noise_volume); +} + +void SpeechInputManager::CancelRecognitionAndInformDelegate( + int caller_id) { + SpeechInputManagerDelegate* cur_delegate = GetDelegate(caller_id); + CancelRecognition(caller_id); + cur_delegate->DidCompleteRecording(caller_id); + cur_delegate->DidCompleteRecognition(caller_id); +} + +void SpeechInputManager::OnFocusChanged(int caller_id) { + // Ignore if the caller id was not in our active recognizers list because the + // user might have clicked more than once, or recognition could have been + // ended due to other reasons before the user click was processed. + if (HasPendingRequest(caller_id)) { + // If this is an ongoing recording or if we were displaying an error message + // to the user, abort it since user has switched focus. Otherwise + // recognition has started and keep that going so user can start speaking to + // another element while this gets the results in parallel. + if (recording_caller_id_ == caller_id || !requests_[caller_id].is_active) { + CancelRecognitionAndInformDelegate(caller_id); + } + } +} + } // namespace speech_input diff --git a/content/browser/speech/speech_input_manager.h b/content/browser/speech/speech_input_manager.h index a68e790..afac442 100644 --- a/content/browser/speech/speech_input_manager.h +++ b/content/browser/speech/speech_input_manager.h @@ -5,7 +5,11 @@ #ifndef CONTENT_BROWSER_SPEECH_SPEECH_INPUT_MANAGER_H_ #define CONTENT_BROWSER_SPEECH_SPEECH_INPUT_MANAGER_H_ +#include <map> +#include <string> + #include "base/basictypes.h" +#include "content/browser/speech/speech_recognizer.h" #include "content/common/content_export.h" #include "content/common/speech_input_result.h" #include "ui/gfx/rect.h" @@ -16,7 +20,7 @@ namespace speech_input { // handles requests received from various render views and makes sure only one // of them can use speech recognition at a time. It also sends recognition // results and status events to the render views when required. -class SpeechInputManager { +class SpeechInputManager : public SpeechRecognizerDelegate { public: // Implemented by the dispatcher host to relay events to the render views. class Delegate { @@ -54,18 +58,94 @@ class SpeechInputManager { const gfx::Rect& element_rect, const std::string& language, const std::string& grammar, - const std::string& origin_url) = 0; - virtual void CancelRecognition(int caller_id) = 0; - virtual void StopRecording(int caller_id) = 0; - - virtual void CancelAllRequestsWithDelegate(Delegate* delegate) = 0; + const std::string& origin_url); + virtual void CancelRecognition(int caller_id); + virtual void CancelAllRequestsWithDelegate(Delegate* delegate); + virtual void StopRecording(int caller_id); + + // SpeechRecognizer::Delegate methods. + virtual void DidStartReceivingAudio(int caller_id); + virtual void SetRecognitionResult(int caller_id, + bool error, + const SpeechInputResultArray& result); + virtual void DidCompleteRecording(int caller_id); + virtual void DidCompleteRecognition(int caller_id); + virtual void OnRecognizerError(int caller_id, + SpeechRecognizer::ErrorCode error); + virtual void DidCompleteEnvironmentEstimation(int caller_id); + virtual void SetInputVolume(int caller_id, float volume, float noise_volume); void set_censor_results(bool censor) { censor_results_ = censor; } bool censor_results() { return censor_results_; } + protected: + // The pure virtual methods are used for displaying the current state of + // recognition and for fetching optional request information. + + // Get the optional request information if available. + virtual void GetRequestInfo(bool* can_report_metrics, + std::string* request_info) = 0; + + // Called when recognition has been requested from point |element_rect_| on + // the view port for the given caller. + virtual void ShowRecognitionRequested(int caller_id, + int render_process_id, + int render_view_id, + const gfx::Rect& element_rect) = 0; + + // Called when recognition is starting up. + virtual void ShowWarmUp(int caller_id) = 0; + + // Called when recognition has started. + virtual void ShowRecognizing(int caller_id) = 0; + + // Called when recording has started. + virtual void ShowRecording(int caller_id) = 0; + + // Continuously updated with the current input volume. + virtual void ShowInputVolume(int caller_id, + float volume, + float noise_volume) = 0; + + // Called when no microphone has been found. + virtual void ShowNoMicError(int caller_id) = 0; + + // Called when there has been a error with the recognition. + virtual void ShowRecognizerError(int caller_id, + SpeechRecognizer::ErrorCode error) = 0; + + // Called when recognition has ended or has been canceled. + virtual void DoClose(int caller_id) = 0; + + // Cancels recognition for the specified caller if it is active. + void OnFocusChanged(int caller_id); + + bool HasPendingRequest(int caller_id) const; + + // Starts/restarts recognition for an existing request. + void StartRecognitionForRequest(int caller_id); + + void CancelRecognitionAndInformDelegate(int caller_id); + private: + struct SpeechInputRequest { + SpeechInputRequest(); + ~SpeechInputRequest(); + + Delegate* delegate; + scoped_refptr<SpeechRecognizer> recognizer; + bool is_active; // Set to true when recording or recognition is going on. + }; + + Delegate* GetDelegate(int caller_id) const; + + typedef std::map<int, SpeechInputRequest> SpeechRecognizerMap; + SpeechRecognizerMap requests_; + std::string request_info_; + bool can_report_metrics_; bool censor_results_; + int recording_caller_id_; }; // This typedef is to workaround the issue with certain versions of |