summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsatish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-27 13:34:09 +0000
committersatish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-27 13:34:09 +0000
commite5a00caa638c720ed9257c57e98b0f8476ce5853 (patch)
tree05173b4de12e94b37c63ce6c9d104cf828dbbb30
parenta0c0c0f2dc6f0f078902c068f805ee9df4899f36 (diff)
downloadchromium_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.grd6
-rw-r--r--chrome/browser/speech/speech_input_manager.cc69
-rw-r--r--chrome/browser/speech/speech_recognizer.cc1
-rw-r--r--chrome/browser/speech/speech_recognizer.h5
-rw-r--r--chrome/browser/speech/speech_recognizer_unittest.cc21
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