summaryrefslogtreecommitdiffstats
path: root/chrome/browser/speech
diff options
context:
space:
mode:
authorsatish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-21 21:51:43 +0000
committersatish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-21 21:51:43 +0000
commitbd141d8f9578d87ebe7198c94186ba2ce2711312 (patch)
tree42aa948a353b49df7d276765b1a7f1d9d1b4f82b /chrome/browser/speech
parentb09df81df72de5476a35431d2b1f3793d48ef4f6 (diff)
downloadchromium_src-bd141d8f9578d87ebe7198c94186ba2ce2711312.zip
chromium_src-bd141d8f9578d87ebe7198c94186ba2ce2711312.tar.gz
chromium_src-bd141d8f9578d87ebe7198c94186ba2ce2711312.tar.bz2
Extend speech input bubble in Mac to display error messages with try-again and cancel buttons.
The SpeechInputBubbleImpl object now lives longer than the actual info bubble window, and allows the caller to create a bubble on screen or update with an error message when needed. When recording speech, the layout of controls are (vertical): - Label ('Speak now') - Icon (Mic or wait) - Button Bar (Horizontal, 1 button, 'Cancel') When showing a message, the layout of controls are (vertical): - Label (message text) - Button Bar (Horizontal, 2 buttons, 'Try Again' and 'Cancel') Also made a small correction to the info bubble's anchor point to get the arrow point at the correct starting point of the given element rect. XIB changes: - Added a 'try again' button and hooked it up to the tryAgainButton outlet in the controller - Moved position of the cancel button for easier editing in interface builder BUG=53598 TEST=manual, unplug mic and start recognition to check error message, and similarly give no speech to check. Review URL: http://codereview.chromium.org/3438002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60112 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/speech')
-rw-r--r--chrome/browser/speech/speech_input_bubble_browsertest.cc55
-rw-r--r--chrome/browser/speech/speech_input_bubble_mac.mm67
-rw-r--r--chrome/browser/speech/speech_recognizer.cc24
3 files changed, 110 insertions, 36 deletions
diff --git a/chrome/browser/speech/speech_input_bubble_browsertest.cc b/chrome/browser/speech/speech_input_bubble_browsertest.cc
new file mode 100644
index 0000000..fb96593
--- /dev/null
+++ b/chrome/browser/speech/speech_input_bubble_browsertest.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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.
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/speech/speech_input_bubble.h"
+#include "chrome/browser/browser.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "gfx/rect.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class SpeechInputBubbleTest : public SpeechInputBubbleDelegate,
+ public InProcessBrowserTest {
+ public:
+ // SpeechInputBubble::Delegate methods.
+ virtual void InfoBubbleButtonClicked(SpeechInputBubble::Button button) {}
+ virtual void InfoBubbleFocusChanged() {}
+
+ protected:
+};
+
+IN_PROC_BROWSER_TEST_F(SpeechInputBubbleTest, CreateAndDestroy) {
+ gfx::Rect element_rect(100, 100, 100, 100);
+ scoped_ptr<SpeechInputBubble> bubble(SpeechInputBubble::Create(
+ browser()->GetSelectedTabContents(), this, element_rect));
+ EXPECT_TRUE(bubble.get());
+}
+
+IN_PROC_BROWSER_TEST_F(SpeechInputBubbleTest, ShowAndDestroy) {
+ gfx::Rect element_rect(100, 100, 100, 100);
+ scoped_ptr<SpeechInputBubble> bubble(SpeechInputBubble::Create(
+ browser()->GetSelectedTabContents(), this, element_rect));
+ EXPECT_TRUE(bubble.get());
+ bubble->Show();
+}
+
+IN_PROC_BROWSER_TEST_F(SpeechInputBubbleTest, ShowAndHide) {
+ gfx::Rect element_rect(100, 100, 100, 100);
+ scoped_ptr<SpeechInputBubble> bubble(SpeechInputBubble::Create(
+ browser()->GetSelectedTabContents(), this, element_rect));
+ EXPECT_TRUE(bubble.get());
+ bubble->Show();
+ bubble->Hide();
+}
+
+IN_PROC_BROWSER_TEST_F(SpeechInputBubbleTest, ShowAndHideTwice) {
+ gfx::Rect element_rect(100, 100, 100, 100);
+ scoped_ptr<SpeechInputBubble> bubble(SpeechInputBubble::Create(
+ browser()->GetSelectedTabContents(), this, element_rect));
+ EXPECT_TRUE(bubble.get());
+ bubble->Show();
+ bubble->Hide();
+ bubble->Show();
+ bubble->Hide();
+}
diff --git a/chrome/browser/speech/speech_input_bubble_mac.mm b/chrome/browser/speech/speech_input_bubble_mac.mm
index f22db5f..a48eac6 100644
--- a/chrome/browser/speech/speech_input_bubble_mac.mm
+++ b/chrome/browser/speech/speech_input_bubble_mac.mm
@@ -10,6 +10,7 @@
#import "chrome/browser/cocoa/speech_input_window_controller.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "skia/ext/skia_utils_mac.h"
namespace {
@@ -29,51 +30,69 @@ class SpeechInputBubbleImpl : public SpeechInputBubbleBase {
private:
scoped_nsobject<SpeechInputWindowController> window_;
+ TabContents* tab_contents_;
+ Delegate* delegate_;
+ gfx::Rect element_rect_;
};
SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents,
Delegate* delegate,
- const gfx::Rect& element_rect) {
+ const gfx::Rect& element_rect)
+ : tab_contents_(tab_contents),
+ delegate_(delegate),
+ element_rect_(element_rect) {
+}
+
+SpeechInputBubbleImpl::~SpeechInputBubbleImpl() {
+ if (window_.get())
+ [window_.get() close];
+}
+
+void SpeechInputBubbleImpl::SetImage(const SkBitmap& image) {
+ if (window_.get())
+ [window_.get() setImage:gfx::SkBitmapToNSImage(image)];
+}
+
+void SpeechInputBubbleImpl::Show() {
+ if (window_.get()) {
+ [window_.get() show];
+ return;
+ }
+
// Find the screen coordinates for the given tab and position the bubble's
// arrow anchor point inside that to point at the bottom-left of the html
// input element rect.
- gfx::NativeView view = tab_contents->view()->GetNativeView();
+ gfx::NativeView view = tab_contents_->view()->GetNativeView();
NSRect tab_bounds = [view bounds];
NSPoint anchor = NSMakePoint(
- tab_bounds.origin.x + element_rect.x() + kBubbleTargetOffsetX,
- tab_bounds.origin.y + tab_bounds.size.height - element_rect.y() -
- element_rect.height());
+ tab_bounds.origin.x + element_rect_.x() + kBubbleTargetOffsetX,
+ tab_bounds.origin.y + tab_bounds.size.height - element_rect_.y() -
+ element_rect_.height());
anchor = [view convertPoint:anchor toView:nil];
anchor = [[view window] convertBaseToScreen:anchor];
window_.reset([[SpeechInputWindowController alloc]
- initWithParentWindow:tab_contents->view()->GetTopLevelNativeWindow()
- delegate:delegate
+ initWithParentWindow:tab_contents_->view()->GetTopLevelNativeWindow()
+ delegate:delegate_
anchoredAt:anchor]);
-}
-SpeechInputBubbleImpl::~SpeechInputBubbleImpl() {
- [window_.get() close];
-}
-
-void SpeechInputBubbleImpl::SetImage(const SkBitmap& image) {
- // TODO(satish): Implement.
- NOTREACHED();
-}
-
-void SpeechInputBubbleImpl::Show() {
- // TODO(satish): Implement.
- NOTREACHED();
+ UpdateLayout();
}
void SpeechInputBubbleImpl::Hide() {
- // TODO(satish): Implement.
- NOTREACHED();
+ if (!window_.get())
+ return;
+
+ [window_.get() close];
+ window_.reset();
}
void SpeechInputBubbleImpl::UpdateLayout() {
- // TODO(satish): Implement.
- NOTREACHED();
+ if (!window_.get())
+ return;
+
+ [window_.get() updateLayout:display_mode()
+ messageText:message_text()];
}
} // namespace
diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc
index 6eed2f5..ce1bfaa 100644
--- a/chrome/browser/speech/speech_recognizer.cc
+++ b/chrome/browser/speech/speech_recognizer.cc
@@ -31,11 +31,11 @@ COMPILE_ASSERT(kMaxSpeexFrameLength <= 0xFF, invalidLength);
// The following constants are related to the volume level indicator shown in
// the UI for recorded audio.
// Multiplier used when new volume is greater than previous level.
-const float kUpSmoothingFactor = 0.9f;
-// Multiplier used when new volume is lesser than previous level.
-const float kDownSmoothingFactor = 0.4f;
-const float kAudioMeterMinDb = 10.0f; // Lower bar for volume meter.
-const float kAudioMeterDbRange = 25.0f;
+const float kUpSmoothingFactor = 0.9f;
+// Multiplier used when new volume is lesser than previous level.
+const float kDownSmoothingFactor = 0.4f;
+const float kAudioMeterMinDb = 10.0f; // Lower bar for volume meter.
+const float kAudioMeterDbRange = 25.0f;
} // namespace
namespace speech_input {
@@ -293,13 +293,13 @@ void SpeechRecognizer::HandleOnData(string* data) {
// Calculate the input volume to display in the UI, smoothing towards the
// new level.
- float level = (rms - kAudioMeterMinDb) / kAudioMeterDbRange;
- level = std::min(std::max(0.0f, level), 1.0f);
- if (level > audio_level_) {
- audio_level_ += (level - audio_level_) * kUpSmoothingFactor;
- } else {
- audio_level_ += (level - audio_level_) * kDownSmoothingFactor;
- }
+ float level = (rms - kAudioMeterMinDb) / kAudioMeterDbRange;
+ level = std::min(std::max(0.0f, level), 1.0f);
+ if (level > audio_level_) {
+ audio_level_ += (level - audio_level_) * kUpSmoothingFactor;
+ } else {
+ audio_level_ += (level - audio_level_) * kDownSmoothingFactor;
+ }
delegate_->SetInputVolume(caller_id_, audio_level_);
if (endpointer_.speech_input_complete()) {