1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_SPEECH_SPEECH_INPUT_BUBBLE_H_ 6 #define CHROME_BROWSER_SPEECH_SPEECH_INPUT_BUBBLE_H_ 7 #pragma once 8 9 #include <vector> 10 11 #include "base/memory/scoped_ptr.h" 12 #include "base/string16.h" 13 #include "base/task.h" 14 15 namespace gfx { 16 class Canvas; 17 class Rect; 18 } 19 class SkBitmap; 20 class SkCanvas; 21 class TabContents; 22 23 // SpeechInputBubble displays a popup info bubble during speech recognition, 24 // points to the html element which requested speech input and shows recognition 25 // progress events. The popup is closed by the user clicking anywhere outside 26 // the popup window, or by the caller destroying this object. 27 class SpeechInputBubble { 28 public: 29 // The various buttons which may be part of the bubble. 30 enum Button { 31 BUTTON_TRY_AGAIN, 32 BUTTON_CANCEL 33 }; 34 35 // Informs listeners of user actions in the bubble. 36 class Delegate { 37 public: 38 // Invoked when the user selects a button in the info bubble. The InfoBubble 39 // is still active and the caller should close it if necessary. 40 virtual void InfoBubbleButtonClicked(Button button) = 0; 41 42 // Invoked when the user clicks outside the InfoBubble causing it to close. 43 // The InfoBubble window is no longer visible on screen and the caller can 44 // free the InfoBubble instance. This callback is not issued if the bubble 45 // got closed because the object was destroyed by the caller. 46 virtual void InfoBubbleFocusChanged() = 0; 47 48 protected: ~Delegate()49 virtual ~Delegate() { 50 } 51 }; 52 53 // Factory method to create new instances. 54 // Creates the bubble, call |Show| to display it on screen. 55 // |tab_contents| is the TabContents hosting the page. 56 // |element_rect| is the display bounds of the html element requesting speech 57 // input (in page coordinates). 58 static SpeechInputBubble* Create(TabContents* tab_contents, 59 Delegate* delegate, 60 const gfx::Rect& element_rect); 61 62 // This is implemented by platform specific code to create the underlying 63 // bubble window. Not to be called directly by users of this class. 64 static SpeechInputBubble* CreateNativeBubble(TabContents* tab_contents, 65 Delegate* delegate, 66 const gfx::Rect& element_rect); 67 68 // |Create| uses the currently registered FactoryMethod to create the 69 // SpeechInputBubble instances. FactoryMethod is intended for testing. 70 typedef SpeechInputBubble* (*FactoryMethod)(TabContents*, 71 Delegate*, 72 const gfx::Rect&); 73 // Sets the factory used by the static method Create. SpeechInputBubble does 74 // not take ownership of |factory|. A value of NULL results in a 75 // SpeechInputBubble being created directly. 76 #if defined(UNIT_TEST) set_factory(FactoryMethod factory)77 static void set_factory(FactoryMethod factory) { factory_ = factory; } 78 #endif 79 ~SpeechInputBubble()80 virtual ~SpeechInputBubble() {} 81 82 // Indicates to the user that audio hardware is initializing. If the bubble is 83 // hidden, |Show| must be called to make it appear on screen. 84 virtual void SetWarmUpMode() = 0; 85 86 // Indicates to the user that audio recording is in progress. If the bubble is 87 // hidden, |Show| must be called to make it appear on screen. 88 virtual void SetRecordingMode() = 0; 89 90 // Indicates to the user that recognition is in progress. If the bubble is 91 // hidden, |Show| must be called to make it appear on screen. 92 virtual void SetRecognizingMode() = 0; 93 94 // Displays the given string with the 'Try again' and 'Cancel' buttons. If the 95 // bubble is hidden, |Show| must be called to make it appear on screen. 96 virtual void SetMessage(const string16& text) = 0; 97 98 // Brings up the bubble on screen. 99 virtual void Show() = 0; 100 101 // Hides the info bubble, resulting in a call to 102 // |Delegate::InfoBubbleFocusChanged| as well. 103 virtual void Hide() = 0; 104 105 // Updates and draws the current captured audio volume displayed on screen. 106 virtual void SetInputVolume(float volume, float noise_volume) = 0; 107 108 // Returns the TabContents for which this bubble gets displayed. 109 virtual TabContents* tab_contents() = 0; 110 111 // The horizontal distance between the start of the html widget and the speech 112 // bubble's arrow. 113 static const int kBubbleTargetOffsetX; 114 115 private: 116 static FactoryMethod factory_; 117 }; 118 119 // Base class for the platform specific bubble implementations, this contains 120 // the platform independent code for SpeechInputBubble. 121 class SpeechInputBubbleBase : public SpeechInputBubble { 122 public: 123 // The current display mode of the bubble, useful only for the platform 124 // specific implementation. 125 enum DisplayMode { 126 DISPLAY_MODE_WARM_UP, 127 DISPLAY_MODE_RECORDING, 128 DISPLAY_MODE_RECOGNIZING, 129 DISPLAY_MODE_MESSAGE 130 }; 131 132 explicit SpeechInputBubbleBase(TabContents* tab_contents); 133 virtual ~SpeechInputBubbleBase(); 134 135 // SpeechInputBubble methods 136 virtual void SetWarmUpMode(); 137 virtual void SetRecordingMode(); 138 virtual void SetRecognizingMode(); 139 virtual void SetMessage(const string16& text); 140 virtual void SetInputVolume(float volume, float noise_volume); 141 virtual TabContents* tab_contents(); 142 143 protected: 144 // Updates the platform specific UI layout for the current display mode. 145 virtual void UpdateLayout() = 0; 146 147 // Overridden by subclasses to copy |icon_image()| to the screen. 148 virtual void UpdateImage() = 0; 149 display_mode()150 DisplayMode display_mode() { 151 return display_mode_; 152 } 153 message_text()154 string16 message_text() { 155 return message_text_; 156 } 157 158 SkBitmap icon_image(); 159 160 private: 161 void DoRecognizingAnimationStep(); 162 void DoWarmingUpAnimationStep(); 163 void SetImage(const SkBitmap& image); 164 165 void DrawVolumeOverlay(SkCanvas* canvas, 166 const SkBitmap& bitmap, 167 float volume); 168 169 // Task factory used for animation timer. 170 ScopedRunnableMethodFactory<SpeechInputBubbleBase> task_factory_; 171 int animation_step_; // Current index/step of the animation. 172 std::vector<SkBitmap> animation_frames_; 173 std::vector<SkBitmap> warming_up_frames_; 174 175 DisplayMode display_mode_; 176 string16 message_text_; // Text displayed in DISPLAY_MODE_MESSAGE 177 // The current microphone image with volume level indication. 178 scoped_ptr<SkBitmap> mic_image_; 179 // A temporary buffer image used in creating the above mic image. 180 scoped_ptr<SkBitmap> buffer_image_; 181 // TabContents in which this this bubble gets displayed. 182 TabContents* tab_contents_; 183 // The current image displayed in the bubble's icon widget. 184 scoped_ptr<SkBitmap> icon_image_; 185 }; 186 187 // This typedef is to workaround the issue with certain versions of 188 // Visual Studio where it gets confused between multiple Delegate 189 // classes and gives a C2500 error. (I saw this error on the try bots - 190 // the workaround was not needed for my machine). 191 typedef SpeechInputBubble::Delegate SpeechInputBubbleDelegate; 192 193 #endif // CHROME_BROWSER_SPEECH_SPEECH_INPUT_BUBBLE_H_ 194