summaryrefslogtreecommitdiffstats
path: root/media/audio/win
diff options
context:
space:
mode:
authorhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-24 07:18:19 +0000
committerhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-24 07:18:19 +0000
commitd5577f7266e34ed412fd3b9b9aed2450094b5995 (patch)
tree806c82daafc17fc3700ea9800217dbbbf4fa9ea3 /media/audio/win
parenta3c8aa0b48eefddfe8718febb58bd7a685339e08 (diff)
downloadchromium_src-d5577f7266e34ed412fd3b9b9aed2450094b5995.zip
chromium_src-d5577f7266e34ed412fd3b9b9aed2450094b5995.tar.gz
chromium_src-d5577f7266e34ed412fd3b9b9aed2450094b5995.tar.bz2
Adds support for capture device enumeration on Windows.
Example output (two devices found on Windows 7 machine): device_name: Microphone (6- SB Arena Headset) unique_id: {0.0.1.00000000}.{24515814-26fd-4382-b4bc-0a8d847ed853} device_name: Microphone (Realtek High Definition Audio) unique_id: {0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574} BUG=None TEST=audio_input_device_unittest.cc Review URL: http://codereview.chromium.org/8606006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111500 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/win')
-rw-r--r--media/audio/win/audio_manager_win.cc29
-rw-r--r--media/audio/win/audio_manager_win.h19
-rw-r--r--media/audio/win/device_enumeration_win.cc125
-rw-r--r--media/audio/win/device_enumeration_win.h26
4 files changed, 191 insertions, 8 deletions
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index c999f61..92f59d8 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -24,6 +24,7 @@
#include "media/audio/win/audio_low_latency_input_win.h"
#include "media/audio/win/audio_low_latency_output_win.h"
#include "media/audio/win/audio_manager_win.h"
+#include "media/audio/win/device_enumeration_win.h"
#include "media/audio/win/wavein_input_win.h"
#include "media/audio/win/waveout_output_win.h"
#include "media/base/limits.h"
@@ -99,6 +100,13 @@ static string16 GetDeviceAndDriverInfo(HDEVINFO device_info,
AudioManagerWin::AudioManagerWin()
: num_output_streams_(0) {
+ if (base::win::GetVersion() <= base::win::VERSION_XP) {
+ // Use the Wave API for device enumeration if XP or lower.
+ enumeration_type_ = kWaveEnumeration;
+ } else {
+ // Use the MMDevice API for device enumeration if Vista or higher.
+ enumeration_type_ = kMMDeviceEnumeration;
+ }
}
AudioManagerWin::~AudioManagerWin() {
@@ -280,19 +288,26 @@ void AudioManagerWin::ShowAudioInputSettings() {
void AudioManagerWin::GetAudioInputDeviceNames(
media::AudioDeviceNames* device_names) {
- // TODO(xians): query a full list of valid devices.
- if (HasAudioInputDevices()) {
- // Add the default device to the list.
- // We use index 0 to make up the unique_id to identify the
- // default devices.
+ DCHECK(enumeration_type() != kUninitializedEnumeration);
+ // Enumerate all active audio-endpoint capture devices.
+ if (enumeration_type() == kWaveEnumeration) {
+ // Utilize the Wave API for Windows XP.
+ GetInputDeviceNamesWinXP(device_names);
+ } else {
+ // Utilize the MMDevice API (part of Core Audio) for Vista and higher.
+ GetInputDeviceNamesWin(device_names);
+ }
+
+ // Always add default device parameters as first element.
+ if (!device_names->empty()) {
media::AudioDeviceName name;
name.device_name = AudioManagerBase::kDefaultDeviceName;
name.unique_id = AudioManagerBase::kDefaultDeviceId;
- device_names->push_back(name);
+ device_names->push_front(name);
}
}
-// static
+/// 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 f1d73d8..6c519ee 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -6,9 +6,11 @@
#define MEDIA_AUDIO_WIN_AUDIO_MANAGER_WIN_H_
#include <windows.h>
+#include <string>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "media/audio/audio_manager_base.h"
class PCMWaveOutAudioOutputStream;
@@ -16,7 +18,7 @@ class PCMWaveOutAudioOutputStream;
// Windows implementation of the AudioManager singleton. This class is internal
// to the audio output and only internal users can call methods not exposed by
// the AudioManager class.
-class AudioManagerWin : public AudioManagerBase {
+class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
public:
AudioManagerWin();
// Implementation of AudioManager.
@@ -42,8 +44,23 @@ class AudioManagerWin : public AudioManagerBase {
void ReleaseInputStream(AudioInputStream* stream);
private:
+ enum EnumerationType {
+ kUninitializedEnumeration = 0,
+ kMMDeviceEnumeration,
+ kWaveEnumeration,
+ };
+
virtual ~AudioManagerWin();
+ // Allow unit test to modify the utilized enumeration API.
+ friend class AudioInputDeviceTest;
+
+ EnumerationType enumeration_type_;
+ EnumerationType enumeration_type() { return enumeration_type_; }
+ void SetEnumerationType(EnumerationType type) {
+ enumeration_type_ = type;
+ }
+
// Number of currently open output streams.
int num_output_streams_;
diff --git a/media/audio/win/device_enumeration_win.cc b/media/audio/win/device_enumeration_win.cc
new file mode 100644
index 0000000..0087a89
--- /dev/null
+++ b/media/audio/win/device_enumeration_win.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2011 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 <MMDeviceAPI.h>
+#include <mmsystem.h>
+#include <Functiondiscoverykeys_devpkey.h> // MMDeviceAPI.h must come first
+
+#include "media/audio/win/audio_manager_win.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/scoped_co_mem.h"
+#include "base/win/scoped_comptr.h"
+
+using media::AudioDeviceNames;
+using base::win::ScopedComPtr;
+using base::win::ScopedCoMem;
+
+bool GetInputDeviceNamesWin(AudioDeviceNames* device_names) {
+ // It is assumed that this method is called from a COM thread, i.e.,
+ // CoInitializeEx() is not called here again to avoid STA/MTA conflicts.
+ ScopedComPtr<IMMDeviceEnumerator> enumerator;
+ HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IMMDeviceEnumerator),
+ enumerator.ReceiveVoid());
+ if (FAILED(hr)) {
+ LOG(WARNING) << "Failed to create IMMDeviceEnumerator: " << std::hex << hr;
+ return false;
+ }
+
+ // Generate a collection of active audio capture endpoint devices.
+ // This method will succeed even if all devices are disabled.
+ ScopedComPtr<IMMDeviceCollection> collection;
+ hr = enumerator->EnumAudioEndpoints(eCapture,
+ DEVICE_STATE_ACTIVE,
+ collection.Receive());
+ if (FAILED(hr))
+ return false;
+
+ // Retrieve the number of active capture devices.
+ UINT number_of_active_devices = 0;
+ collection->GetCount(&number_of_active_devices);
+ if (number_of_active_devices == 0)
+ return true;
+
+ media::AudioDeviceName device;
+
+ // Loop over all active capture devices and add friendly name and
+ // unique ID to the |device_names| list.
+ for (UINT i = 0; i < number_of_active_devices; ++i) {
+ // Retrieve unique name of endpoint device.
+ // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}".
+ ScopedComPtr<IMMDevice> audio_device;
+ ScopedCoMem<WCHAR> endpoint_device_id;
+ hr = collection->Item(i, audio_device.Receive());
+ if (FAILED(hr))
+ continue;
+ audio_device->GetId(&endpoint_device_id);
+
+ // Store the unique name.
+ device.unique_id = WideToUTF8(static_cast<WCHAR*>(endpoint_device_id));
+
+ // Retrieve user-friendly name of endpoint device.
+ // Example: "Microphone (Realtek High Definition Audio)".
+ ScopedComPtr<IPropertyStore> properties;
+ hr = audio_device->OpenPropertyStore(STGM_READ, properties.Receive());
+ if (SUCCEEDED(hr)) {
+ PROPVARIANT friendly_name;
+ PropVariantInit(&friendly_name);
+ hr = properties->GetValue(PKEY_Device_FriendlyName, &friendly_name);
+
+ // Store the user-friendly name.
+ if (SUCCEEDED(hr) &&
+ friendly_name.vt == VT_LPWSTR && friendly_name.pwszVal) {
+ device.device_name = WideToUTF8(friendly_name.pwszVal);
+ }
+ PropVariantClear(&friendly_name);
+ }
+
+ // Add combination of user-friendly and unique name to the output list.
+ device_names->push_back(device);
+ }
+
+ return true;
+}
+
+bool GetInputDeviceNamesWinXP(AudioDeviceNames* device_names) {
+ // Retrieve the number of active waveform input devices.
+ UINT number_of_active_devices = waveInGetNumDevs();
+ if (number_of_active_devices == 0)
+ return true;
+
+ media::AudioDeviceName device;
+ WAVEINCAPS capabilities;
+ MMRESULT err = MMSYSERR_NOERROR;
+
+ // Loop over all active capture devices and add friendly name and
+ // unique ID to the |device_names| list. Note that, for Wave on XP,
+ // the "unique" name will simply be a copy of the friendly name since
+ // there is no safe method to retrieve a unique device name on XP.
+ for (UINT i = 0; i < number_of_active_devices; ++i) {
+ // Retrieve the capabilities of the specified waveform-audio input device.
+ err = waveInGetDevCaps(i, &capabilities, sizeof(capabilities));
+ if (err != MMSYSERR_NOERROR)
+ continue;
+
+ if (capabilities.szPname != NULL) {
+ // Store the user-friendly name. Max length is MAXPNAMELEN(=32)
+ // characters and the name cane be truncated on XP.
+ // Example: "Microphone (Realtek High Defini".
+ device.device_name = WideToUTF8(capabilities.szPname);
+
+ // Store the "unique" name (we use same as friendly name on Windows XP).
+ device.unique_id = WideToUTF8(capabilities.szPname);
+
+ // Add combination of user-friendly and unique name to the output list.
+ device_names->push_back(device);
+ }
+ }
+
+ return true;
+}
diff --git a/media/audio/win/device_enumeration_win.h b/media/audio/win/device_enumeration_win.h
new file mode 100644
index 0000000..a797eec
--- /dev/null
+++ b/media/audio/win/device_enumeration_win.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2011 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.
+
+#ifndef MEDIA_AUDIO_WIN_DEVICE_ENUMERATION_WIN_H_
+#define MEDIA_AUDIO_WIN_DEVICE_ENUMERATION_WIN_H_
+
+#include "media/audio/audio_device_name.h"
+
+// Returns a list of audio input device structures (name and unique device ID)
+// using the MMDevice API which is supported on Windows Vista and higher.
+// Example record in the output list:
+// - device_name: "Microphone (Realtek High Definition Audio)".
+// - unique_id: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}"
+// This method must be called from a COM thread using MTA.
+bool GetInputDeviceNamesWin(media::AudioDeviceNames* device_names);
+
+// Returns a list of audio input device structures (name and unique device ID)
+// using the WaveIn API which is supported on Windows XP and higher.
+// Example record in the output list:
+// - device_name: "Microphone (Realtek High Defini".
+// - unique_id: "Microphone (Realtek High Defini" (same as friendly name).
+bool GetInputDeviceNamesWinXP(media::AudioDeviceNames* device_names);
+
+#endif // MEDIA_AUDIO_WIN_DEVICE_ENUMERATION_WIN_H_
+