summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/speech/speech_input_manager.cc79
-rw-r--r--chrome/browser/speech/speech_recognition_request.cc9
-rw-r--r--chrome/browser/speech/speech_recognition_request.h1
-rw-r--r--chrome/browser/speech/speech_recognition_request_unittest.cc3
-rw-r--r--chrome/browser/speech/speech_recognizer.cc6
-rw-r--r--chrome/browser/speech/speech_recognizer.h5
-rw-r--r--chrome/browser/speech/speech_recognizer_unittest.cc2
-rw-r--r--chrome/chrome_dll.gypi1
-rw-r--r--chrome/installer/util/wmi.cc40
-rw-r--r--chrome/installer/util/wmi.h9
-rw-r--r--media/audio/audio_manager.h5
-rw-r--r--media/audio/audio_manager_base.cc4
-rw-r--r--media/audio/audio_manager_base.h2
-rw-r--r--media/audio/win/audio_manager_win.cc116
-rw-r--r--media/audio/win/audio_manager_win.h1
15 files changed, 273 insertions, 10 deletions
diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc
index 181234e..7149223 100644
--- a/chrome/browser/speech/speech_input_manager.cc
+++ b/chrome/browser/speech/speech_input_manager.cc
@@ -5,18 +5,82 @@
#include "chrome/browser/speech/speech_input_manager.h"
#include "app/l10n_util.h"
+#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/singleton.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.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 "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "media/audio/audio_manager.h"
#include <map>
+#if defined(OS_WIN)
+#include "chrome/installer/util/wmi.h"
+#endif
+
+namespace {
+
+// Asynchronously fetches the PC and audio hardware/driver info on windows if
+// the user has opted into UMA. This information is sent with speech input
+// requests to the server for identifying and improving quality issues with
+// specific device configurations.
+class HardwareInfo : public base::RefCountedThreadSafe<HardwareInfo> {
+ public:
+ HardwareInfo() {}
+
+#if defined(OS_WIN)
+ void Refresh() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // UMA opt-in can be checked only from the UI thread, so switch to that.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &HardwareInfo::CheckUMAAndGetHardwareInfo));
+ }
+
+ void CheckUMAAndGetHardwareInfo() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (g_browser_process->local_state()->GetBoolean(
+ prefs::kMetricsReportingEnabled)) {
+ // Access potentially slow OS calls from the FILE thread.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &HardwareInfo::GetHardwareInfo));
+ }
+ }
+
+ void GetHardwareInfo() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ AutoLock lock(lock_);
+ value_ = UTF16ToUTF8(
+ installer::WMIComputerSystem::GetModel() + L"|" +
+ AudioManager::GetAudioManager()->GetAudioInputDeviceModel());
+ }
+
+ std::string value() {
+ AutoLock lock(lock_);
+ return value_;
+ }
+
+ private:
+ Lock lock_;
+ std::string value_;
+
+#else // defined(OS_WIN)
+ void Refresh() {}
+ std::string value() { return std::string(); }
+#endif // defined(OS_WIN)
+
+ DISALLOW_COPY_AND_ASSIGN(HardwareInfo);
+};
+
+}
+
namespace speech_input {
class SpeechInputManagerImpl : public SpeechInputManager,
@@ -75,6 +139,7 @@ class SpeechInputManagerImpl : public SpeechInputManager,
SpeechRecognizerMap requests_;
int recording_caller_id_;
scoped_refptr<SpeechInputBubbleController> bubble_controller_;
+ scoped_refptr<HardwareInfo> hardware_info_;
};
SpeechInputManager* SpeechInputManager::Get() {
@@ -114,10 +179,22 @@ void SpeechInputManagerImpl::StartRecognition(
bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id,
element_rect);
+ if (!hardware_info_.get()) {
+ hardware_info_ = new HardwareInfo();
+ // Since hardware info is optional with speech input requests, we start an
+ // asynchronous fetch here and move on with recording audio. This first
+ // speech input request would send an empty string for hardware info and
+ // subsequent requests may have the hardware info available if the fetch
+ // completed before them. This way we don't end up stalling the user with
+ // a long wait and disk seeks when they click on a UI element and start
+ // speaking.
+ hardware_info_->Refresh();
+ }
+
SpeechInputRequest* request = &requests_[caller_id];
request->delegate = delegate;
request->recognizer = new SpeechRecognizer(this, caller_id, language,
- grammar);
+ grammar, hardware_info_->value());
request->is_active = false;
StartRecognitionForRequest(caller_id);
diff --git a/chrome/browser/speech/speech_recognition_request.cc b/chrome/browser/speech/speech_recognition_request.cc
index b9ee40b..63a6c92 100644
--- a/chrome/browser/speech/speech_recognition_request.cc
+++ b/chrome/browser/speech/speech_recognition_request.cc
@@ -9,7 +9,6 @@
#include "app/l10n_util.h"
#include "base/json/json_reader.h"
#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/base/escape.h"
@@ -20,7 +19,7 @@
namespace {
const char* const kDefaultSpeechRecognitionUrl =
- "http://www.google.com/speech-api/v1/recognize?client=chromium&";
+ "https://www.google.com/speech-api/v1/recognize?client=chromium&";
const char* const kHypothesesString = "hypotheses";
const char* const kUtteranceString = "utterance";
const char* const kConfidenceString = "confidence";
@@ -123,6 +122,7 @@ SpeechRecognitionRequest::~SpeechRecognitionRequest() {}
bool SpeechRecognitionRequest::Send(const std::string& language,
const std::string& grammar,
+ const std::string& hardware_info,
const std::string& content_type,
const std::string& audio_data) {
DCHECK(!url_fetcher_.get());
@@ -145,7 +145,10 @@ bool SpeechRecognitionRequest::Send(const std::string& language,
parts.push_back("lang=" + EscapeQueryParamValue(lang_param, true));
if (!grammar.empty())
- parts.push_back("grammar=" + EscapeQueryParamValue(grammar, true));
+ parts.push_back("lm=" + EscapeQueryParamValue(grammar, true));
+ if (!hardware_info.empty())
+ parts.push_back("xhw=" + EscapeQueryParamValue(hardware_info, true));
+
GURL url(std::string(kDefaultSpeechRecognitionUrl) + JoinString(parts, '&'));
url_fetcher_.reset(URLFetcher::Create(url_fetcher_id_for_tests,
diff --git a/chrome/browser/speech/speech_recognition_request.h b/chrome/browser/speech/speech_recognition_request.h
index 89beed1..585b0a4 100644
--- a/chrome/browser/speech/speech_recognition_request.h
+++ b/chrome/browser/speech/speech_recognition_request.h
@@ -46,6 +46,7 @@ class SpeechRecognitionRequest : public URLFetcher::Delegate {
// previous request has completed.
bool Send(const std::string& language,
const std::string& grammar,
+ const std::string& hardware_info,
const std::string& content_type,
const std::string& audio_data);
diff --git a/chrome/browser/speech/speech_recognition_request_unittest.cc b/chrome/browser/speech/speech_recognition_request_unittest.cc
index a87bba8..e328eb4 100644
--- a/chrome/browser/speech/speech_recognition_request_unittest.cc
+++ b/chrome/browser/speech/speech_recognition_request_unittest.cc
@@ -45,7 +45,8 @@ class SpeechRecognitionRequestTest : public SpeechRecognitionRequestDelegate,
void SpeechRecognitionRequestTest::CreateAndTestRequest(
bool success, const std::string& http_response) {
SpeechRecognitionRequest request(NULL, this);
- request.Send(std::string(), std::string(), std::string(), std::string());
+ request.Send(std::string(), std::string(), std::string(), std::string(),
+ std::string());
TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
URLRequestStatus status;
diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc
index d56013a..4905914 100644
--- a/chrome/browser/speech/speech_recognizer.cc
+++ b/chrome/browser/speech/speech_recognizer.cc
@@ -110,11 +110,13 @@ void SpeexEncoder::Encode(const short* samples,
SpeechRecognizer::SpeechRecognizer(Delegate* delegate,
int caller_id,
const std::string& language,
- const std::string& grammar)
+ const std::string& grammar,
+ const std::string& hardware_info)
: delegate_(delegate),
caller_id_(caller_id),
language_(language),
grammar_(grammar),
+ hardware_info_(hardware_info),
encoder_(new SpeexEncoder()),
endpointer_(kAudioSampleRate),
num_samples_recorded_(0),
@@ -216,7 +218,7 @@ void SpeechRecognizer::StopRecording() {
DCHECK(!request_.get());
request_.reset(new SpeechRecognitionRequest(
Profile::GetDefaultRequestContext(), this));
- request_->Send(language_, grammar_, kContentTypeSpeex, data);
+ request_->Send(language_, grammar_, hardware_info_, kContentTypeSpeex, data);
ReleaseAudioBuffers(); // No need to keep the audio anymore.
}
diff --git a/chrome/browser/speech/speech_recognizer.h b/chrome/browser/speech/speech_recognizer.h
index 61226f4..3b0f707 100644
--- a/chrome/browser/speech/speech_recognizer.h
+++ b/chrome/browser/speech/speech_recognizer.h
@@ -76,7 +76,8 @@ class SpeechRecognizer
SpeechRecognizer(Delegate* delegate,
int caller_id,
const std::string& language,
- const std::string& grammar);
+ const std::string& grammar,
+ const std::string& hardware_info);
~SpeechRecognizer();
// Starts audio recording and does recognition after recording ends. The same
@@ -112,6 +113,7 @@ class SpeechRecognizer
private:
void ReleaseAudioBuffers();
void InformErrorAndCancelRecognition(ErrorCode error);
+ void SendRecordedAudioToServer();
void HandleOnError(int error_code); // Handles OnError in the IO thread.
@@ -122,6 +124,7 @@ class SpeechRecognizer
int caller_id_;
std::string language_;
std::string grammar_;
+ std::string hardware_info_;
// Buffer holding the recorded audio. Owns the strings inside the list.
typedef std::list<std::string*> AudioBufferQueue;
diff --git a/chrome/browser/speech/speech_recognizer_unittest.cc b/chrome/browser/speech/speech_recognizer_unittest.cc
index d71876f..44967b1 100644
--- a/chrome/browser/speech/speech_recognizer_unittest.cc
+++ b/chrome/browser/speech/speech_recognizer_unittest.cc
@@ -24,7 +24,7 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate,
: io_thread_(BrowserThread::IO, &message_loop_),
ALLOW_THIS_IN_INITIALIZER_LIST(
recognizer_(new SpeechRecognizer(this, 1, std::string(),
- std::string()))),
+ std::string(), std::string()))),
recording_complete_(false),
recognition_complete_(false),
result_received_(false),
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 3fbacbb..36b9af0 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -35,6 +35,7 @@
'urlmon.dll',
'imm32.dll',
'iphlpapi.dll',
+ 'setupapi.dll',
],
# Set /SUBSYSTEM:WINDOWS for chrome.dll (for consistency).
'SubSystem': '2',
diff --git a/chrome/installer/util/wmi.cc b/chrome/installer/util/wmi.cc
index fca2076..e873277 100644
--- a/chrome/installer/util/wmi.cc
+++ b/chrome/installer/util/wmi.cc
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
+#include "base/win/scoped_variant.h"
#pragma comment(lib, "wbemuuid.lib")
@@ -150,4 +151,43 @@ bool WMIProcess::Launch(const std::wstring& command_line, int* process_id) {
return true;
}
+string16 WMIComputerSystem::GetModel() {
+ base::win::ScopedComPtr<IWbemServices> services;
+ if (!WMI::CreateLocalConnection(true, services.Receive()))
+ return string16();
+
+ base::win::ScopedBstr query_language(L"WQL");
+ base::win::ScopedBstr query(L"SELECT * FROM Win32_ComputerSystem");
+ base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
+ HRESULT hr = services->ExecQuery(
+ query_language, query,
+ WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
+ enumerator.Receive());
+ if (FAILED(hr) || !enumerator)
+ return string16();
+
+ base::win::ScopedComPtr<IWbemClassObject> class_object;
+ ULONG items_returned = 0;
+ hr = enumerator->Next(WBEM_INFINITE, 1, class_object.Receive(),
+ &items_returned);
+ if (!items_returned)
+ return string16();
+
+ base::win::ScopedVariant manufacturer;
+ class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
+ base::win::ScopedVariant model;
+ class_object->Get(L"Model", 0, model.Receive(), 0, 0);
+
+ string16 model_string;
+ if (manufacturer.type() == VT_BSTR) {
+ model_string = V_BSTR(&manufacturer);
+ if (model.type() == VT_BSTR)
+ model_string += L" ";
+ }
+ if (model.type() == VT_BSTR)
+ model_string += V_BSTR(&model);
+
+ return model_string;
+}
+
} // namespace installer
diff --git a/chrome/installer/util/wmi.h b/chrome/installer/util/wmi.h
index 5d0a1a9..03106dc 100644
--- a/chrome/installer/util/wmi.h
+++ b/chrome/installer/util/wmi.h
@@ -21,6 +21,7 @@
#define CHROME_INSTALLER_UTIL_WMI_H_
#pragma once
+#include "base/string16.h"
#include <string>
#include <wbemidl.h>
@@ -73,6 +74,14 @@ class WMIProcess {
static bool Launch(const std::wstring& command_line, int* process_id);
};
+// This class contains functionality of the WMI class 'Win32_ComputerSystem'
+// more info: http://msdn.microsoft.com/en-us/library/aa394102(VS.85).aspx
+class WMIComputerSystem {
+ public:
+ // Returns a human readable string for the model/make of this computer.
+ static string16 GetModel();
+};
+
} // namespace installer
#endif // CHROME_INSTALLER_UTIL_WMI_H_
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 26f0acf..cba88a9 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -6,6 +6,7 @@
#define MEDIA_AUDIO_AUDIO_MANAGER_H_
#include "base/basictypes.h"
+#include "base/string16.h"
#include "media/audio/audio_parameters.h"
class AudioInputStream;
@@ -29,6 +30,10 @@ class AudioManager {
// sample rates.
virtual bool HasAudioInputDevices() = 0;
+ // Returns a human readable string for the model/make of the active audio
+ // input device for this computer.
+ virtual string16 GetAudioInputDeviceModel() = 0;
+
// Factory for all the supported stream formats. |params| defines parameters
// of the audio stream to be created.
//
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 7fa4761..95a47f1 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -13,6 +13,10 @@ void AudioManagerBase::Init() {
initialized_ = audio_thread_.Start();
}
+string16 AudioManagerBase::GetAudioInputDeviceModel() {
+ return string16();
+}
+
MessageLoop* AudioManagerBase::GetMessageLoop() {
DCHECK(initialized_);
return audio_thread_.message_loop();
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index 6d01c26..9665982 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -17,6 +17,8 @@ class AudioManagerBase : public AudioManager {
virtual MessageLoop* GetMessageLoop();
+ virtual string16 GetAudioInputDeviceModel();
+
protected:
virtual ~AudioManagerBase() {}
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index a2fbd92..84dba63 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -5,9 +5,15 @@
#include "media/audio/audio_io.h"
#include <windows.h>
+#include <objbase.h> // This has to be before initguid.h
+#include <initguid.h>
#include <mmsystem.h>
+#include <setupapi.h>
#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/win/audio_manager_win.h"
@@ -15,6 +21,17 @@
#include "media/audio/win/waveout_output_win.h"
#include "media/base/limits.h"
+// Libraries required for the SetupAPI and Wbem APIs used here.
+#pragma comment(lib, "setupapi.lib")
+
+// The following are defined in various DDK headers, and we (re)define them
+// here to avoid adding the DDK as a chrome dependency.
+#define DRV_QUERYDEVICEINTERFACE 0x80c
+#define DRVM_MAPPER_PREFERRED_GET 0x2015
+#define DRV_QUERYDEVICEINTERFACESIZE 0x80d
+DEFINE_GUID(AM_KSCATEGORY_AUDIO, 0x6994ad04, 0x93ef, 0x11d0,
+ 0xa3, 0xcc, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96);
+
namespace {
// Up to 8 channels can be passed to the driver.
@@ -30,7 +47,45 @@ const int kWinMaxInputChannels = 2;
// play.
const int kNumInputBuffers = 3;
-} // namespace.
+// Returns a string containing the given device's description and installed
+// driver version.
+string16 GetDeviceAndDriverInfo(HDEVINFO device_info,
+ SP_DEVINFO_DATA* device_data) {
+ // Save the old install params setting and set a flag for the
+ // SetupDiBuildDriverInfoList below to return only the installed drivers.
+ SP_DEVINSTALL_PARAMS old_device_install_params;
+ old_device_install_params.cbSize = sizeof(old_device_install_params);
+ SetupDiGetDeviceInstallParams(device_info, device_data,
+ &old_device_install_params);
+ SP_DEVINSTALL_PARAMS device_install_params = old_device_install_params;
+ device_install_params.FlagsEx |= DI_FLAGSEX_INSTALLEDDRIVER;
+ SetupDiSetDeviceInstallParams(device_info, device_data,
+ &device_install_params);
+
+ SP_DRVINFO_DATA driver_data;
+ driver_data.cbSize = sizeof(driver_data);
+ string16 device_and_driver_info;
+ if (SetupDiBuildDriverInfoList(device_info, device_data,
+ SPDIT_COMPATDRIVER)) {
+ if (SetupDiEnumDriverInfo(device_info, device_data, SPDIT_COMPATDRIVER, 0,
+ &driver_data)) {
+ DWORDLONG version = driver_data.DriverVersion;
+ device_and_driver_info = string16(driver_data.Description) + L" v" +
+ base::IntToString16((version >> 48) & 0xffff) + L"." +
+ base::IntToString16((version >> 32) & 0xffff) + L"." +
+ base::IntToString16((version >> 16) & 0xffff) + L"." +
+ base::IntToString16(version & 0xffff);
+ }
+ SetupDiDestroyDriverInfoList(device_info, device_data, SPDIT_COMPATDRIVER);
+ }
+
+ SetupDiSetDeviceInstallParams(device_info, device_data,
+ &old_device_install_params);
+
+ return device_and_driver_info;
+}
+
+} // namespace
bool AudioManagerWin::HasAudioOutputDevices() {
return (::waveOutGetNumDevs() != 0);
@@ -94,6 +149,65 @@ void AudioManagerWin::UnMuteAll() {
AudioManagerWin::~AudioManagerWin() {
}
+string16 AudioManagerWin::GetAudioInputDeviceModel() {
+ // Get the default audio capture device and its device interface name.
+ DWORD device_id = 0;
+ waveInMessage(reinterpret_cast<HWAVEIN>(WAVE_MAPPER),
+ DRVM_MAPPER_PREFERRED_GET,
+ reinterpret_cast<DWORD_PTR>(&device_id), NULL);
+ ULONG device_interface_name_size = 0;
+ waveInMessage(reinterpret_cast<HWAVEIN>(device_id),
+ DRV_QUERYDEVICEINTERFACESIZE,
+ reinterpret_cast<DWORD_PTR>(&device_interface_name_size), 0);
+ string16 device_interface_name;
+ string16::value_type* name_ptr = WriteInto(&device_interface_name,
+ device_interface_name_size / sizeof(string16::value_type));
+ waveInMessage(reinterpret_cast<HWAVEIN>(device_id),
+ DRV_QUERYDEVICEINTERFACE,
+ reinterpret_cast<DWORD_PTR>(name_ptr),
+ static_cast<DWORD_PTR>(device_interface_name_size));
+
+ // Enumerate all audio devices and find the one matching the above device
+ // interface name.
+ HDEVINFO device_info = SetupDiGetClassDevs(
+ &AM_KSCATEGORY_AUDIO, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
+ if (device_info == INVALID_HANDLE_VALUE)
+ return string16();
+
+ DWORD interface_index = 0;
+ SP_DEVICE_INTERFACE_DATA interface_data;
+ interface_data.cbSize = sizeof(interface_data);
+ while (SetupDiEnumDeviceInterfaces(device_info, 0, &AM_KSCATEGORY_AUDIO,
+ interface_index++, &interface_data)) {
+ // Query the size of the struct, allocate it and then query the data.
+ SP_DEVINFO_DATA device_data;
+ device_data.cbSize = sizeof(device_data);
+ DWORD interface_detail_size = 0;
+ SetupDiGetDeviceInterfaceDetail(device_info, &interface_data, 0, 0,
+ &interface_detail_size, &device_data);
+ if (!interface_detail_size)
+ continue;
+
+ scoped_array<char> interface_detail_buffer(new char[interface_detail_size]);
+ SP_DEVICE_INTERFACE_DETAIL_DATA* interface_detail =
+ reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(
+ interface_detail_buffer.get());
+ interface_detail->cbSize = interface_detail_size;
+ if (!SetupDiGetDeviceInterfaceDetail(device_info, &interface_data,
+ interface_detail,
+ interface_detail_size, NULL,
+ &device_data))
+ return string16();
+
+ bool device_found = (device_interface_name == interface_detail->DevicePath);
+
+ if (device_found)
+ return GetDeviceAndDriverInfo(device_info, &device_data);
+ }
+
+ return string16();
+}
+
// static
AudioManager* AudioManager::CreateAudioManager() {
return new AudioManagerWin();
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 2ea4c8f..05c80e4 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -26,6 +26,7 @@ class AudioManagerWin : public AudioManagerBase {
virtual AudioInputStream* MakeAudioInputStream(AudioParameters params);
virtual void MuteAll();
virtual void UnMuteAll();
+ virtual string16 GetAudioInputDeviceModel();
// Windows-only methods to free a stream created in MakeAudioStream. These
// are called internally by the audio stream when it has been closed.