diff options
author | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-27 13:34:09 +0000 |
---|---|---|
committer | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-27 13:34:09 +0000 |
commit | e5a00caa638c720ed9257c57e98b0f8476ce5853 (patch) | |
tree | 05173b4de12e94b37c63ce6c9d104cf828dbbb30 | |
parent | a0c0c0f2dc6f0f078902c068f805ee9df4899f36 (diff) | |
download | chromium_src-e5a00caa638c720ed9257c57e98b0f8476ce5853.zip chromium_src-e5a00caa638c720ed9257c57e98b0f8476ce5853.tar.gz chromium_src-e5a00caa638c720ed9257c57e98b0f8476ce5853.tar.bz2 |
Show proper messages if we find errors before or during audio recording.
BUG=none
TEST=manual, try clicking on speech input button without a mic connected.
Review URL: http://codereview.chromium.org/3240002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57672 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 6 | ||||
-rw-r--r-- | chrome/browser/speech/speech_input_manager.cc | 69 | ||||
-rw-r--r-- | chrome/browser/speech/speech_recognizer.cc | 1 | ||||
-rw-r--r-- | chrome/browser/speech/speech_recognizer.h | 5 | ||||
-rw-r--r-- | chrome/browser/speech/speech_recognizer_unittest.cc | 21 |
5 files changed, 90 insertions, 12 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 6b37b00..1253a50c 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -9475,6 +9475,12 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_SPEECH_INPUT_BUBBLE_HEADING" desc="First line in the content area of the speech input bubble. Instructs the user that they can start speaking."> Speak now </message> + <message name="IDS_SPEECH_INPUT_ERROR" desc="Message shown when audio recording failed with an error during speech recognition."> + There was an error in recording audio. Please check if a microphone properly connected before trying again. + </message> + <message name="IDS_SPEECH_INPUT_NO_MIC" desc="Message shown when speech recognizer could not find a suitable microphone or other audio input device."> + No audio recording devices found. Please check if you have a microphone properly connected before trying again. + </message> </messages> diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc index c22d732..707f8551 100644 --- a/chrome/browser/speech/speech_input_manager.cc +++ b/chrome/browser/speech/speech_input_manager.cc @@ -4,13 +4,17 @@ #include "chrome/browser/speech/speech_input_manager.h" +#include "app/l10n_util.h" #include "base/ref_counted.h" #include "base/singleton.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/speech/speech_input_bubble_controller.h" #include "chrome/browser/speech/speech_recognizer.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_util.h" +#include "grit/generated_resources.h" +#include "media/audio/audio_manager.h" #include <map> namespace speech_input { @@ -33,12 +37,20 @@ class SpeechInputManagerImpl : public SpeechInputManager, const string16& value); virtual void DidCompleteRecording(int caller_id); virtual void DidCompleteRecognition(int caller_id); + virtual void OnRecognizerError(int caller_id); // SpeechInputBubbleController::Delegate methods. virtual void RecognitionCancelled(int caller_id); virtual void SpeechInputFocusChanged(int caller_id); private: + struct SpeechInputRequest { + SpeechInputManagerDelegate* delegate; + scoped_refptr<SpeechRecognizer> recognizer; + int render_process_id; + int render_view_id; + }; + // Private constructor to enforce singleton. friend struct DefaultSingletonTraits<SpeechInputManagerImpl>; SpeechInputManagerImpl(); @@ -50,9 +62,15 @@ class SpeechInputManagerImpl : public SpeechInputManager, void CancelRecognitionAndInformDelegate(int caller_id); + // Shows an error message string as a simple alert info bar for the tab + // identified by |render_process_id| and |render_view_id|. + void ShowErrorMessage(int render_process_id, int render_view_id, + const string16& message); + static void ShowErrorMessageInUIThread( + int render_process_id, int render_view_id, + const string16& message); + SpeechInputManagerDelegate* delegate_; - typedef std::pair<SpeechInputManagerDelegate*, - scoped_refptr<SpeechRecognizer> > SpeechInputRequest; typedef std::map<int, SpeechInputRequest> SpeechRecognizerMap; SpeechRecognizerMap requests_; int recording_caller_id_; @@ -80,11 +98,11 @@ bool SpeechInputManagerImpl::HasPendingRequest(int caller_id) const { SpeechInputManagerDelegate* SpeechInputManagerImpl::GetDelegate( int caller_id) const { - return requests_.find(caller_id)->second.first; + return requests_.find(caller_id)->second.delegate; } SpeechRecognizer* SpeechInputManagerImpl::GetRecognizer(int caller_id) const { - return requests_.find(caller_id)->second.second; + return requests_.find(caller_id)->second.recognizer; } void SpeechInputManagerImpl::StartRecognition( @@ -99,14 +117,24 @@ void SpeechInputManagerImpl::StartRecognition( if (recording_caller_id_) CancelRecognitionAndInformDelegate(recording_caller_id_); + if (!AudioManager::GetAudioManager()->HasAudioInputDevices()) { + ShowErrorMessage(render_process_id, render_view_id, + l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_NO_MIC)); + delegate->DidCompleteRecognition(caller_id); + return; + } + bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id, element_rect); recording_caller_id_ = caller_id; - scoped_refptr<SpeechRecognizer> recognizer(new SpeechRecognizer(this, - caller_id)); - requests_[caller_id] = std::make_pair(delegate, recognizer); - recognizer->StartRecording(); + SpeechInputRequest request; + request.delegate = delegate; + request.recognizer = new SpeechRecognizer(this, caller_id); + request.render_process_id = render_process_id; + request.render_view_id = render_view_id; + requests_[caller_id] = request; + request.recognizer->StartRecording(); } void SpeechInputManagerImpl::CancelRecognition(int caller_id) { @@ -145,6 +173,12 @@ void SpeechInputManagerImpl::DidCompleteRecognition(int caller_id) { bubble_controller_->CloseBubble(caller_id); } +void SpeechInputManagerImpl::OnRecognizerError(int caller_id) { + const SpeechInputRequest& request = requests_.find(caller_id)->second; + ShowErrorMessage(request.render_process_id, request.render_view_id, + l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_ERROR)); +} + void SpeechInputManagerImpl::CancelRecognitionAndInformDelegate(int caller_id) { SpeechInputManagerDelegate* cur_delegate = GetDelegate(caller_id); CancelRecognition(caller_id); @@ -175,4 +209,23 @@ void SpeechInputManagerImpl::SpeechInputFocusChanged(int caller_id) { } } +void SpeechInputManagerImpl::ShowErrorMessage( + int render_process_id, int render_view_id, + const string16& message) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableFunction(&SpeechInputManagerImpl::ShowErrorMessageInUIThread, + render_process_id, render_view_id, message)); +} + +void SpeechInputManagerImpl::ShowErrorMessageInUIThread( + int render_process_id, int render_view_id, + const string16& message) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + TabContents* tab = tab_util::GetTabContentsByID(render_process_id, + render_view_id); + if (tab) // Check in case the tab was closed before we got this request. + tab->AddInfoBar(new SimpleAlertInfoBarDelegate(tab, message, NULL, true)); +} + } // namespace speech_input diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc index 027946a..9c186ea 100644 --- a/chrome/browser/speech/speech_recognizer.cc +++ b/chrome/browser/speech/speech_recognizer.cc @@ -231,6 +231,7 @@ void SpeechRecognizer::HandleOnError(int error_code) { if (!audio_controller_.get()) return; + delegate_->OnRecognizerError(caller_id_); CancelRecognition(); delegate_->DidCompleteRecording(caller_id_); delegate_->DidCompleteRecognition(caller_id_); diff --git a/chrome/browser/speech/speech_recognizer.h b/chrome/browser/speech/speech_recognizer.h index 308a93d..ea962ea 100644 --- a/chrome/browser/speech/speech_recognizer.h +++ b/chrome/browser/speech/speech_recognizer.h @@ -43,6 +43,11 @@ class SpeechRecognizer // sequence and the |SpeechRecognizer| object can be freed up if necessary. virtual void DidCompleteRecognition(int caller_id) = 0; + // Invoked if there was an error while recording or recognizing audio. The + // session may get terminated and the DidXxxx callbacks may be issued after + // this call. + virtual void OnRecognizerError(int caller_id) = 0; + protected: virtual ~Delegate() {} }; diff --git a/chrome/browser/speech/speech_recognizer_unittest.cc b/chrome/browser/speech/speech_recognizer_unittest.cc index 3163d4a..f4407a6 100644 --- a/chrome/browser/speech/speech_recognizer_unittest.cc +++ b/chrome/browser/speech/speech_recognizer_unittest.cc @@ -25,7 +25,11 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, SpeechRecognizerTest() : io_thread_(ChromeThread::IO, &message_loop_), ALLOW_THIS_IN_INITIALIZER_LIST( - recognizer_(new SpeechRecognizer(this, 1))) { + recognizer_(new SpeechRecognizer(this, 1))), + recording_complete_(false), + recognition_complete_(false), + result_received_(false), + error_(false) { } void StartTest() { @@ -47,11 +51,12 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, recognition_complete_ = true; } + virtual void OnRecognizerError(int caller_id) { + error_ = true; + } + // testing::Test methods. virtual void SetUp() { - result_received_ = false; - recording_complete_ = false; - recognition_complete_ = false; URLFetcher::set_factory(&url_fetcher_factory_); AudioInputController::set_factory(&audio_input_controller_factory_); } @@ -68,6 +73,7 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, bool recording_complete_; bool recognition_complete_; bool result_received_; + bool error_; TestURLFetcherFactory url_fetcher_factory_; TestAudioInputControllerFactory audio_input_controller_factory_; }; @@ -79,6 +85,7 @@ TEST_F(SpeechRecognizerTest, StopNoData) { EXPECT_FALSE(recording_complete_); EXPECT_FALSE(recognition_complete_); EXPECT_FALSE(result_received_); + EXPECT_FALSE(error_); } TEST_F(SpeechRecognizerTest, CancelNoData) { @@ -89,6 +96,7 @@ TEST_F(SpeechRecognizerTest, CancelNoData) { EXPECT_TRUE(recording_complete_); EXPECT_TRUE(recognition_complete_); EXPECT_FALSE(result_received_); + EXPECT_FALSE(error_); } TEST_F(SpeechRecognizerTest, StopWithData) { @@ -108,6 +116,7 @@ TEST_F(SpeechRecognizerTest, StopWithData) { EXPECT_TRUE(recording_complete_); EXPECT_FALSE(recognition_complete_); EXPECT_FALSE(result_received_); + EXPECT_FALSE(error_); // Issue the network callback to complete the process. TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); @@ -118,6 +127,7 @@ TEST_F(SpeechRecognizerTest, StopWithData) { status, 200, ResponseCookies(), ""); EXPECT_TRUE(recognition_complete_); EXPECT_TRUE(result_received_); + EXPECT_FALSE(error_); } TEST_F(SpeechRecognizerTest, CancelWithData) { @@ -136,6 +146,7 @@ TEST_F(SpeechRecognizerTest, CancelWithData) { EXPECT_FALSE(recording_complete_); EXPECT_FALSE(recognition_complete_); EXPECT_FALSE(result_received_); + EXPECT_FALSE(error_); } TEST_F(SpeechRecognizerTest, AudioControllerErrorNoData) { @@ -149,6 +160,7 @@ TEST_F(SpeechRecognizerTest, AudioControllerErrorNoData) { EXPECT_TRUE(recording_complete_); EXPECT_TRUE(recognition_complete_); EXPECT_FALSE(result_received_); + EXPECT_TRUE(error_); } TEST_F(SpeechRecognizerTest, AudioControllerErrorWithData) { @@ -167,6 +179,7 @@ TEST_F(SpeechRecognizerTest, AudioControllerErrorWithData) { EXPECT_TRUE(recording_complete_); EXPECT_TRUE(recognition_complete_); EXPECT_FALSE(result_received_); + EXPECT_TRUE(error_); } } // namespace speech_input |