Index: media/audio/linux/audio_manager_linux.cc |
=================================================================== |
--- media/audio/linux/audio_manager_linux.cc (revision 104076) |
+++ media/audio/linux/audio_manager_linux.cc (working copy) |
@@ -39,54 +39,13 @@ |
"surround", |
}; |
-static bool IsValidAudioInputDevice(const char* device_name) { |
- if (!device_name) |
- return false; |
- |
- for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) { |
- if (strcmp(kInvalidAudioInputDevices[i], device_name) == 0) |
- return false; |
- } |
- |
- return true; |
-} |
- |
// Implementation of AudioManager. |
bool AudioManagerLinux::HasAudioOutputDevices() { |
- // TODO(ajwong): Make this actually query audio devices. |
- return true; |
+ return HasAnyAlsaAudioDevice(kStreamPlayback); |
} |
bool AudioManagerLinux::HasAudioInputDevices() { |
- if (!initialized()) { |
- return false; |
- } |
- |
- // Constants specified by the ALSA API for device hints. |
- static const char kPcmInterfaceName[] = "pcm"; |
- bool has_device = false; |
- void** hints = NULL; |
- int card = -1; |
- |
- // Loop through the sound cards to get Alsa device hints. |
- // Don't use snd_device_name_hint(-1,..) since there is a access violation |
- // inside this ALSA API with libasound.so.2.0.0. |
- while (!wrapper_->CardNext(&card) && (card >= 0) && !has_device) { |
- int error = wrapper_->DeviceNameHint(card, |
- kPcmInterfaceName, |
- &hints); |
- if (error == 0) { |
- has_device = HasAnyValidAudioInputDevice(hints); |
- |
- // Destroy the hints now that we're done with it. |
- wrapper_->DeviceNameFreeHint(hints); |
- hints = NULL; |
- } else { |
- LOG(ERROR) << "Unable to get device hints: " << wrapper_->StrError(error); |
- } |
- } |
- |
- return has_device; |
+ return HasAnyAlsaAudioDevice(kStreamCapture); |
} |
AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream( |
@@ -141,6 +100,7 @@ |
if (!initialized()) |
return NULL; |
+ // TODO(xians): Pass the device name From AudioInputController instead. |
std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice; |
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) { |
device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
@@ -213,21 +173,49 @@ |
void AudioManagerLinux::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. |
- media::AudioDeviceName name; |
- name.device_name = AudioManagerBase::kDefaultDeviceName; |
- name.unique_id = "0"; |
- device_names->push_back(name); |
+ // Empty the name list. |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
remove
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ device_names->clear(); |
+ |
+ GetAlsaAudioInputDevices(device_names); |
+ |
+ if (!device_names->empty()) { |
+ // Pre-pend the default device to the list. |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
Perhaps extend the comments why this is needed.
scherkus (not reviewing)
2011/10/07 16:54:45
nit: Pre-pend -> Prepend
also agree w/ henrik on
no longer working on chromium
2011/10/10 13:49:24
Done.
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ // We use index 0 to make up the unique_id to identify the default devices. |
+ device_names->push_front(media::AudioDeviceName( |
+ AudioManagerBase::kDefaultDeviceName, "0")); |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
indent by 4
no longer working on chromium
2011/10/10 13:49:24
Done.
|
} |
} |
-bool AudioManagerLinux::HasAnyValidAudioInputDevice(void** hints) { |
+void AudioManagerLinux::GetAlsaAudioInputDevices( |
+ media::AudioDeviceNames* device_names) { |
+ |
scherkus (not reviewing)
2011/10/07 16:54:45
nit: remove blank line
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ // Constants specified by the ALSA API for device hints. |
+ static const char kPcmInterfaceName[] = "pcm"; |
+ void** hints = NULL; |
+ int card = -1; |
+ |
+ // Loop through the sound cards to get Alsa device hints. |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
ALSA?
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ while (!wrapper_->CardNext(&card) && (card >= 0)) { |
+ int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints); |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
Do you allocate memory here?
I think you should m
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ if (!error) { |
+ // Get devices |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
remove
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ GetAlsaDevicesInfo(hints, device_names); |
+ |
+ // Destroy the hints now that we're done with it. |
+ wrapper_->DeviceNameFreeHint(hints); |
+ hints = NULL; |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
remove
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ } else { |
+ LOG(WARNING) << "GetAudioInputDevices error: unable to get device hints: " |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
DLOG
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ << wrapper_->StrError(error); |
+ } |
+ } |
+} |
+ |
+void AudioManagerLinux::GetAlsaDevicesInfo( |
+ void** hints, media::AudioDeviceNames* device_names) { |
static const char kIoHintName[] = "IOID"; |
static const char kNameHintName[] = "NAME"; |
+ static const char kDescriptionHintName[] = "DESC"; |
static const char kOutputDevice[] = "Output"; |
for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { |
@@ -238,15 +226,98 @@ |
if (io != NULL && strcmp(kOutputDevice, io.get()) == 0) |
continue; |
- scoped_ptr_malloc<char> hint_device_name( |
+ // Get the unique device name for the device. |
+ scoped_ptr_malloc<char> unique_device_name( |
wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName)); |
- if (IsValidAudioInputDevice(hint_device_name.get())) |
- return true; |
+ // Find out if the device is available. |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
empty line before
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ if (IsAlsaDeviceAvailable(unique_device_name.get())) { |
+ // Get the description for the device. |
+ scoped_ptr_malloc<char> desc(wrapper_->DeviceNameGetHint( |
+ *hint_iter, kDescriptionHintName)); |
+ |
+ media::AudioDeviceName name; |
+ name.unique_id = unique_device_name.get(); |
+ if (desc.get()) { |
+ // Use the more user friendly description as name. |
+ // Replace '\n' with '-'. |
+ char* pret = strchr(desc.get(), '\n'); |
+ if (pret) |
+ *pret = '-'; |
+ name.device_name = desc.get(); |
+ } else { |
+ // Virtual devices don't necessarily have descriptions. |
+ // Use their names instead. |
+ name.device_name = unique_device_name.get(); |
+ } |
+ |
+ // Store the device information. |
+ device_names->push_back(name); |
+ } |
} |
+} |
- return false; |
+bool AudioManagerLinux::IsAlsaDeviceAvailable(const char* device_name) { |
+ if (!device_name) |
+ return false; |
+ |
+ // Check if the device is in the list of invalid devices. |
+ for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) { |
+ if (!strncmp(kInvalidAudioInputDevices[i], device_name, |
+ strlen(kInvalidAudioInputDevices[i]))) |
scherkus (not reviewing)
2011/10/07 16:54:45
indent by 1 more space
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ return false; |
+ } |
+ |
+ // The only way to check if the device is available is to open/close the |
+ // device, return false if it fails either of operations. |
+ snd_pcm_t* device_handle = NULL; |
+ if (wrapper_->PcmOpen(&device_handle, device_name, |
scherkus (not reviewing)
2011/10/07 16:54:45
how long does this take to run?
The call stack is
no longer working on chromium
2011/10/10 13:49:24
I have totally 3 physical devices attached to PC,
|
+ SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0 || |
+ wrapper_->PcmClose(device_handle) < 0) { |
scherkus (not reviewing)
2011/10/07 16:54:45
could you re-write this to be more explicit? usin
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ return false; |
+ } |
+ |
+ return true; |
} |
+bool AudioManagerLinux::HasAnyAlsaAudioDevice(StreamType stream) { |
+ static const char kPcmInterfaceName[] = "pcm"; |
+ static const char kIoHintName[] = "IOID"; |
+ static const char* kNotWantedDevice = |
+ (stream == kStreamPlayback ? "Input" : "Output"); |
+ void** hints = NULL; |
+ bool has_device = false; |
+ int card = -1; |
+ |
+ // Loop through the sound cards. |
+ // Don't use snd_device_name_hint(-1,..) since there is a access violation |
+ // inside this ALSA API with libasound.so.2.0.0. |
scherkus (not reviewing)
2011/10/07 16:54:45
do you know whether we can do a compile time/run t
no longer working on chromium
2011/10/10 13:49:24
I am not sure, probably yes.
But I am not sure if
|
+ while (!wrapper_->CardNext(&card) && (card >= 0) && !has_device) { |
+ int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints); |
+ if(!error) { |
scherkus (not reviewing)
2011/10/07 16:54:45
space between if and (
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { |
+ // Only examine devices that are |stream| capable. Valid values are |
+ // "Input", "Output", and NULL which means both input and output. |
+ scoped_ptr_malloc<char> io(wrapper_->DeviceNameGetHint(*hint_iter, |
+ kIoHintName)); |
+ if (io != NULL && strcmp(kNotWantedDevice, io.get()) == 0) |
+ continue; // Wrong type, skip the device. |
+ |
+ // Found an input device. |
+ has_device = true; |
+ break; |
+ } |
+ // Destroy the hints now that we're done with it. |
scherkus (not reviewing)
2011/10/07 16:54:45
nit: blank line before this one
no longer working on chromium
2011/10/10 13:49:24
Done.
|
+ wrapper_->DeviceNameFreeHint(hints); |
+ hints = NULL; |
+ } else { |
+ LOG(WARNING) << "HasAnyAudioDevice warning: unable to get device hints: " |
henrika (OOO until Aug 14)
2011/10/07 12:07:51
DLOG
henrika (OOO until Aug 14)
2011/10/07 12:07:51
remove warning
|
+ << wrapper_->StrError(error); |
+ } |
+ } |
+ |
+ return has_device; |
+} |
+ |
// static |
AudioManager* AudioManager::CreateAudioManager() { |
return new AudioManagerLinux(); |