Chromium Code Reviews| Index: media/audio/linux/audio_manager_linux.cc |
| =================================================================== |
| --- media/audio/linux/audio_manager_linux.cc (revision 86276) |
| +++ media/audio/linux/audio_manager_linux.cc (working copy) |
| @@ -30,8 +30,31 @@ |
| } |
| bool AudioManagerLinux::HasAudioInputDevices() { |
| - // TODO(satish): Make this actually query audio devices. |
| - return true; |
| + if (!initialized()) { |
| + return false; |
| + } |
| + |
| + // Constants specified by the ALSA API for device hints. |
| + static const int kGetAllDevices = -1; |
| + static const char kPcmInterfaceName[] = "pcm"; |
| + bool has_device = false; |
| + void** hints = NULL; |
| + |
| + // Use the same approach to find the devices as in |
| + // AlsaPcmOutputStream::FindDeviceForChannels |
| + // Get Alsa device hints. |
| + int error = wrapper_->DeviceNameHint(kGetAllDevices, |
| + kPcmInterfaceName, |
| + &hints); |
| + if (error == 0) { |
| + has_device = HasAnyValidAudioInputDevice(hints); |
| + } else { |
| + LOG(ERROR) << "Unable to get device hints: " << wrapper_->StrError(error); |
| + } |
| + |
| + // Destroy the hint now that we're done with it. |
| + wrapper_->DeviceNameFreeHint(hints); |
| + return has_device; |
| } |
| AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream( |
| @@ -96,8 +119,8 @@ |
| } |
| AudioManagerLinux::~AudioManagerLinux() { |
| - // Make sure we stop the thread first. If we let the default destructor to |
| - // destruct the members, we may destroy audio streams before stopping the |
| + // Make sure we stop the thread first. If we allow the default destructor to |
| + // destroy the members, we may destroy audio streams before stopping the |
| // thread, resulting an unexpected behavior. |
| // This way we make sure activities of the audio streams are all stopped |
| // before we destroy them. |
| @@ -147,6 +170,73 @@ |
| base::LaunchApp(CommandLine(FilePath(command)), false, false, NULL); |
| } |
| +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 = std::string("0"); |
| + device_names->push_back(name); |
| + } |
| +} |
| + |
| +bool AudioManagerLinux::HasAnyValidAudioInputDevice(void** hints) { |
| + static const char kIoHintName[] = "IOID"; |
| + static const char kNameHintName[] = "NAME"; |
| + |
| + // Since "default", "pulse" and "dmix" devices are virtual devices mapped to |
| + // real devices, we remove them from the list to avoiding duplicate counting. |
| + // In addition, note that we support no more than 2 channels for recording, |
| + // hence surround devices are not stored in the list. Finally, output and |
| + // null devices are not considered as valid devices for recording. |
| + static const char kOutputDevice[] = "Output"; |
| + static const char kNotWantedDefaultDevice[] = "default"; |
| + static const char kNotWantedNullDevice[] = "null"; |
| + static const char kNotWantedPulseDevice[] = "pulse"; |
| + static const char kNotWantedDmixDevice[] = "dmix"; |
| + static const char kNotWantedSurroundDevice[] = "surround"; |
|
scherkus (not reviewing)
2011/05/27 19:10:37
you missed this comment.. thoughts?
"what about a
xians
2011/05/27 23:57:04
Sorry, I wrote my replay in somewhere else by mist
|
| + |
| + for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { |
| + // Only examine devices that are input capable.. Valid values are |
| + // "Input", "Output", and NULL which means both input and output. |
| + scoped_ptr_malloc<char> io(wrapper_->DeviceNameGetHint(*hint_iter, |
| + kIoHintName)); |
| + // Wrong device type, skip it. |
| + if (io != NULL && |
| + strncmp(kOutputDevice, io.get(), strlen(kOutputDevice)) == 0) |
| + continue; |
| + |
| + scoped_ptr_malloc<char> hint_device_name( |
| + wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName)); |
| + // Now check if if it is a valid device. |
| + if (hint_device_name != NULL && |
| + strncmp(kNotWantedDefaultDevice, |
| + hint_device_name.get(), |
| + strlen(kNotWantedDefaultDevice)) != 0 && |
| + strncmp(kNotWantedNullDevice, |
| + hint_device_name.get(), |
| + strlen(kNotWantedNullDevice)) != 0 && |
| + strncmp(kNotWantedPulseDevice, |
| + hint_device_name.get(), |
| + strlen(kNotWantedPulseDevice)) != 0 && |
| + strncmp(kNotWantedDmixDevice, |
| + hint_device_name.get(), |
| + strlen(kNotWantedDmixDevice)) != 0 && |
| + strncmp(kNotWantedSurroundDevice, |
| + hint_device_name.get(), |
| + strlen(kNotWantedSurroundDevice)) != 0) { |
| + return true; |
| + } |
| + } |
| + |
| + // Did not find a valid device. |
| + return false; |
| +} |
| + |
| // static |
| AudioManager* AudioManager::CreateAudioManager() { |
| return new AudioManagerLinux(); |