summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/audio/win/audio_low_latency_input_win.cc43
-rw-r--r--media/audio/win/audio_low_latency_input_win.h10
-rw-r--r--media/audio/win/audio_manager_win.cc14
-rw-r--r--media/audio/win/wavein_input_win.cc58
-rw-r--r--media/audio/win/wavein_input_win.h13
5 files changed, 101 insertions, 37 deletions
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index dd83f7e..fc6630b 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -15,14 +15,15 @@ using base::win::ScopedComPtr;
using base::win::ScopedCOMInitializer;
WASAPIAudioInputStream::WASAPIAudioInputStream(
- AudioManagerWin* manager, const AudioParameters& params, ERole device_role)
+ AudioManagerWin* manager, const AudioParameters& params,
+ const std::string& device_id)
: com_init_(ScopedCOMInitializer::kMTA),
manager_(manager),
capture_thread_(NULL),
opened_(false),
started_(false),
endpoint_buffer_size_frames_(0),
- device_role_(device_role),
+ device_id_(device_id),
sink_(NULL) {
DCHECK(manager_);
@@ -78,9 +79,10 @@ bool WASAPIAudioInputStream::Open() {
if (opened_)
return false;
- // Obtain a reference to the IMMDevice interface of the default capturing
- // device with the specified role.
- HRESULT hr = SetCaptureDevice(device_role_);
+ // Obtain a reference to the IMMDevice interface of the capturing
+ // device with the specified unique identifier or role which was
+ // set at construction.
+ HRESULT hr = SetCaptureDevice();
if (FAILED(hr)) {
return false;
}
@@ -379,7 +381,7 @@ void WASAPIAudioInputStream::HandleError(HRESULT err) {
sink_->OnError(this, static_cast<int>(err));
}
-HRESULT WASAPIAudioInputStream::SetCaptureDevice(ERole device_role) {
+HRESULT WASAPIAudioInputStream::SetCaptureDevice() {
ScopedComPtr<IMMDeviceEnumerator> enumerator;
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL,
@@ -387,14 +389,27 @@ HRESULT WASAPIAudioInputStream::SetCaptureDevice(ERole device_role) {
__uuidof(IMMDeviceEnumerator),
enumerator.ReceiveVoid());
if (SUCCEEDED(hr)) {
- // Retrieve the default capture audio endpoint for the specified role.
- // Note that, in Windows Vista, the MMDevice API supports device roles
- // but the system-supplied user interface programs do not.
- hr = enumerator->GetDefaultAudioEndpoint(eCapture,
- device_role,
- endpoint_device_.Receive());
-
- // Verify that the audio endpoint device is active. That is, the audio
+ // Retrieve the IMMDevice by using the specified role or the specified
+ // unique endpoint device-identification string.
+ // TODO(henrika): possibly add suport for the eCommunications as well.
+ if (device_id_ == AudioManagerBase::kDefaultDeviceId) {
+ // Retrieve the default capture audio endpoint for the specified role.
+ // Note that, in Windows Vista, the MMDevice API supports device roles
+ // but the system-supplied user interface programs do not.
+ hr = enumerator->GetDefaultAudioEndpoint(eCapture,
+ eConsole,
+ endpoint_device_.Receive());
+ } else {
+ // Retrieve a capture endpoint device that is specified by an endpoint
+ // device-identification string.
+ hr = enumerator->GetDevice(UTF8ToUTF16(device_id_).c_str(),
+ endpoint_device_.Receive());
+ }
+
+ if (FAILED(hr))
+ return hr;
+
+ // Verify that the audio endpoint device is active, i.e., the audio
// adapter that connects to the endpoint device is present and enabled.
DWORD state = DEVICE_STATE_DISABLED;
hr = endpoint_device_->GetState(&state);
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h
index e255061..ebaab93 100644
--- a/media/audio/win/audio_low_latency_input_win.h
+++ b/media/audio/win/audio_low_latency_input_win.h
@@ -78,7 +78,7 @@ class MEDIA_EXPORT WASAPIAudioInputStream
// the audio manager who is creating this object.
WASAPIAudioInputStream(AudioManagerWin* manager,
const AudioParameters& params,
- ERole device_role);
+ const std::string& device_id);
// The dtor is typically called by the AudioManager only and it is usually
// triggered by calling AudioInputStream::Close().
virtual ~WASAPIAudioInputStream();
@@ -103,7 +103,7 @@ class MEDIA_EXPORT WASAPIAudioInputStream
void HandleError(HRESULT err);
// The Open() method is divided into these sub methods.
- HRESULT SetCaptureDevice(ERole device_role);
+ HRESULT SetCaptureDevice();
HRESULT ActivateCaptureDevice();
HRESULT GetAudioEngineStreamFormat();
bool DesiredFormatIsSupported();
@@ -145,8 +145,10 @@ class MEDIA_EXPORT WASAPIAudioInputStream
// Length of the audio endpoint buffer.
size_t endpoint_buffer_size_frames_;
- // Defines the role that the system has assigned to an audio endpoint device.
- ERole device_role_;
+ // Contains the unique name of the selected endpoint device.
+ // Note that AudioManagerBase::kDefaultDeviceId represents the default
+ // device role and is not a valid ID as such.
+ std::string device_id_;
// Conversion factor used in delay-estimation calculations.
// Converts a raw performance counter value to 100-nanosecond unit.
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index 9d38588..158053f 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -165,21 +165,15 @@ AudioInputStream* AudioManagerWin::MakeAudioInputStream(
return FakeAudioInputStream::MakeFakeStream(params);
} else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers,
- WAVE_MAPPER);
+ AudioManagerBase::kDefaultDeviceId);
} else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
if (!media::IsWASAPISupported()) {
// Fall back to Windows Wave implementation on Windows XP or lower.
DLOG(INFO) << "Using WaveIn since WASAPI requires at least Vista.";
- // TODO(xians): Handle the non-default device.
- if (device_id == AudioManagerBase::kDefaultDeviceId)
- return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers,
- WAVE_MAPPER);
+ return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers,
+ device_id);
} else {
- // TODO(henrika): improve possibility to specify audio endpoint.
- // Use the default device (same as for Wave) for now to be compatible.
- // TODO(xians): Handle the non-default device.
- if (device_id == AudioManagerBase::kDefaultDeviceId)
- return new WASAPIAudioInputStream(this, params, eConsole);
+ return new WASAPIAudioInputStream(this, params, device_id);
}
}
return NULL;
diff --git a/media/audio/win/wavein_input_win.cc b/media/audio/win/wavein_input_win.cc
index d9f600b..d3f1162 100644
--- a/media/audio/win/wavein_input_win.cc
+++ b/media/audio/win/wavein_input_win.cc
@@ -12,11 +12,14 @@
#include "media/audio/audio_io.h"
#include "media/audio/audio_util.h"
#include "media/audio/win/audio_manager_win.h"
+#include "media/audio/win/device_enumeration_win.h"
namespace {
const int kStopInputStreamCallbackTimeout = 3000; // Three seconds.
}
+using media::AudioDeviceNames;
+
// Our sound buffers are allocated once and kept in a linked list using the
// the WAVEHDR::dwUser variable. The last buffer points to the first buffer.
static WAVEHDR* GetNextBuffer(WAVEHDR* current) {
@@ -25,7 +28,7 @@ static WAVEHDR* GetNextBuffer(WAVEHDR* current) {
PCMWaveInAudioInputStream::PCMWaveInAudioInputStream(
AudioManagerWin* manager, const AudioParameters& params, int num_buffers,
- UINT device_id)
+ const std::string& device_id)
: state_(kStateEmpty),
manager_(manager),
device_id_(device_id),
@@ -58,10 +61,20 @@ bool PCMWaveInAudioInputStream::Open() {
return false;
if (num_buffers_ < 2 || num_buffers_ > 10)
return false;
- MMRESULT result = ::waveInOpen(&wavein_, device_id_, &format_,
- reinterpret_cast<DWORD_PTR>(WaveCallback),
- reinterpret_cast<DWORD_PTR>(this),
- CALLBACK_FUNCTION);
+
+ // Convert the stored device id string into an unsigned integer
+ // corresponding to the selected device.
+ UINT device_id = WAVE_MAPPER;
+ if (!GetDeviceId(&device_id)) {
+ return false;
+ }
+
+ // Open the specified input device for recording.
+ MMRESULT result = MMSYSERR_NOERROR;
+ result = ::waveInOpen(&wavein_, device_id, &format_,
+ reinterpret_cast<DWORD_PTR>(WaveCallback),
+ reinterpret_cast<DWORD_PTR>(this),
+ CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR)
return false;
@@ -185,6 +198,41 @@ void PCMWaveInAudioInputStream::QueueNextPacket(WAVEHDR *buffer) {
HandleError(res);
}
+bool PCMWaveInAudioInputStream::GetDeviceId(UINT* device_index) {
+ // Deliver the default input device id (WAVE_MAPPER) if the default
+ // device has been selected.
+ if (device_id_ == AudioManagerBase::kDefaultDeviceId) {
+ *device_index = WAVE_MAPPER;
+ return true;
+ }
+
+ // Get list of all available and active devices.
+ AudioDeviceNames device_names;
+ if (!GetInputDeviceNamesWinXP(&device_names))
+ return false;
+
+ if (device_names.empty())
+ return false;
+
+ // Search the full list of devices and compare with the specified
+ // device id which was specified in the constructor. Stop comparing
+ // when a match is found and return the corresponding index.
+ UINT index = 0;
+ bool found_device = false;
+ AudioDeviceNames::const_iterator it = device_names.begin();
+ while (it != device_names.end()) {
+ if (it->unique_id.compare(device_id_) == 0) {
+ *device_index = index;
+ found_device = true;
+ break;
+ }
+ ++index;
+ ++it;
+ }
+
+ return found_device;
+}
+
// Windows calls us back in this function when some events happen. Most notably
// when it has an audio buffer with recorded data.
void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg,
diff --git a/media/audio/win/wavein_input_win.h b/media/audio/win/wavein_input_win.h
index c16a4a7..ab8b95a 100644
--- a/media/audio/win/wavein_input_win.h
+++ b/media/audio/win/wavein_input_win.h
@@ -24,7 +24,7 @@ class PCMWaveInAudioInputStream : public AudioInputStream {
PCMWaveInAudioInputStream(AudioManagerWin* manager,
const AudioParameters& params,
int num_buffers,
- UINT device_id);
+ const std::string& device_id);
virtual ~PCMWaveInAudioInputStream();
// Implementation of AudioInputStream.
@@ -61,6 +61,10 @@ class PCMWaveInAudioInputStream : public AudioInputStream {
// Sends a buffer to the audio driver for recording.
void QueueNextPacket(WAVEHDR* buffer);
+ // Converts the stored device id string into an unsigned integer which
+ // can be used by waveInOpen() to open the specified capture device.
+ bool GetDeviceId(UINT* device_index);
+
// Reader beware. Visual C has stronger guarantees on volatile vars than
// most people expect. In fact, it has release semantics on write and
// acquire semantics on reads. See the msdn documentation.
@@ -82,9 +86,10 @@ class PCMWaveInAudioInputStream : public AudioInputStream {
// Channels, 1 or 2.
const int channels_;
- // The id assigned by the operating system to the selected wave output
- // hardware device. Usually this is just -1 which means 'default device'.
- UINT device_id_;
+ // Contains the unique name of the selected endpoint device.
+ // Note that AudioManagerBase::kDefaultDeviceId represents the default
+ // device role and is not a valid ID as such.
+ std::string device_id_;
// Windows native structure to encode the format parameters.
WAVEFORMATEX format_;