| 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 = "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";
|
| +
|
| + 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();
|
|
|