| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/browser/renderer_host/media/audio_output_device_enumerator.h" | |
| 6 | |
| 7 #include "base/callback_helpers.h" | |
| 8 #include "base/location.h" | |
| 9 #include "base/single_thread_task_runner.h" | |
| 10 #include "base/task_runner_util.h" | |
| 11 #include "base/threading/thread_task_runner_handle.h" | |
| 12 #include "media/audio/audio_device_description.h" | |
| 13 #include "media/audio/audio_manager.h" | |
| 14 | |
| 15 namespace content { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 AudioOutputDeviceEnumeration EnumerateDevicesOnDeviceThread( | |
| 20 media::AudioManager* audio_manager) { | |
| 21 DCHECK(audio_manager->GetTaskRunner()->BelongsToCurrentThread()); | |
| 22 | |
| 23 AudioOutputDeviceEnumeration snapshot; | |
| 24 media::AudioDeviceNames device_names; | |
| 25 audio_manager->GetAudioOutputDeviceNames(&device_names); | |
| 26 | |
| 27 snapshot.has_actual_devices = !device_names.empty(); | |
| 28 | |
| 29 // If no devices in enumeration, return a list with a default device | |
| 30 if (!snapshot.has_actual_devices) { | |
| 31 snapshot.devices.push_back( | |
| 32 {media::AudioDeviceDescription::kDefaultDeviceId, | |
| 33 media::AudioDeviceDescription::GetDefaultDeviceName(), | |
| 34 audio_manager->GetGroupIDOutput( | |
| 35 media::AudioDeviceDescription::kDefaultDeviceId), | |
| 36 audio_manager->GetDefaultOutputStreamParameters()}); | |
| 37 return snapshot; | |
| 38 } | |
| 39 | |
| 40 for (const media::AudioDeviceName& name : device_names) { | |
| 41 snapshot.devices.push_back( | |
| 42 {name.unique_id, name.device_name, | |
| 43 audio_manager->GetGroupIDOutput(name.unique_id), | |
| 44 name.unique_id == media::AudioDeviceDescription::kDefaultDeviceId | |
| 45 ? audio_manager->GetDefaultOutputStreamParameters() | |
| 46 : audio_manager->GetOutputStreamParameters(name.unique_id)}); | |
| 47 } | |
| 48 return snapshot; | |
| 49 } | |
| 50 | |
| 51 } // namespace | |
| 52 | |
| 53 AudioOutputDeviceInfo::AudioOutputDeviceInfo() {} | |
| 54 | |
| 55 AudioOutputDeviceInfo::~AudioOutputDeviceInfo() {} | |
| 56 | |
| 57 AudioOutputDeviceInfo::AudioOutputDeviceInfo( | |
| 58 const std::string& unique_id, | |
| 59 const std::string& device_name, | |
| 60 const std::string& group_id, | |
| 61 media::AudioParameters output_params) | |
| 62 : unique_id(unique_id), | |
| 63 device_name(device_name), | |
| 64 group_id(group_id), | |
| 65 output_params(output_params) {} | |
| 66 | |
| 67 AudioOutputDeviceInfo::AudioOutputDeviceInfo( | |
| 68 const AudioOutputDeviceInfo& audio_output_device_info) = default; | |
| 69 | |
| 70 AudioOutputDeviceInfo::AudioOutputDeviceInfo( | |
| 71 AudioOutputDeviceInfo&& audio_output_device_info) = default; | |
| 72 | |
| 73 AudioOutputDeviceInfo& AudioOutputDeviceInfo::operator=( | |
| 74 const AudioOutputDeviceInfo& audio_output_device_info) = default; | |
| 75 | |
| 76 AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration( | |
| 77 const std::vector<AudioOutputDeviceInfo>& devices, | |
| 78 bool has_actual_devices) | |
| 79 : devices(devices), has_actual_devices(has_actual_devices) {} | |
| 80 | |
| 81 AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration() | |
| 82 : has_actual_devices(false) {} | |
| 83 | |
| 84 AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration( | |
| 85 const AudioOutputDeviceEnumeration& other) = default; | |
| 86 | |
| 87 AudioOutputDeviceEnumeration::~AudioOutputDeviceEnumeration() {} | |
| 88 | |
| 89 AudioOutputDeviceEnumerator::AudioOutputDeviceEnumerator( | |
| 90 media::AudioManager* audio_manager, | |
| 91 CachePolicy cache_policy) | |
| 92 : audio_manager_(audio_manager), | |
| 93 cache_policy_(cache_policy), | |
| 94 current_event_sequence_(0), | |
| 95 seq_last_enumeration_(0), | |
| 96 seq_last_invalidation_(0), | |
| 97 is_enumeration_ongoing_(false), | |
| 98 weak_factory_(this) {} | |
| 99 | |
| 100 AudioOutputDeviceEnumerator::~AudioOutputDeviceEnumerator() { | |
| 101 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 102 } | |
| 103 | |
| 104 void AudioOutputDeviceEnumerator::Enumerate( | |
| 105 const AudioOutputDeviceEnumerationCB& callback) { | |
| 106 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 107 | |
| 108 // If caching is disabled, force a cache invalidation | |
| 109 if (cache_policy_ == CACHE_POLICY_NO_CACHING) { | |
| 110 InvalidateCache(); | |
| 111 } | |
| 112 | |
| 113 if (IsLastEnumerationValid()) { | |
| 114 DCHECK(pending_callbacks_.empty()); | |
| 115 callback.Run(cache_); | |
| 116 } else { | |
| 117 pending_callbacks_.push_back(callback); | |
| 118 if (!is_enumeration_ongoing_) { | |
| 119 DoEnumerateDevices(); | |
| 120 } | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 void AudioOutputDeviceEnumerator::InvalidateCache() { | |
| 125 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 126 seq_last_invalidation_ = NewEventSequence(); | |
| 127 } | |
| 128 | |
| 129 void AudioOutputDeviceEnumerator::SetCachePolicy(CachePolicy policy) { | |
| 130 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 131 if (policy == CACHE_POLICY_NO_CACHING) | |
| 132 InvalidateCache(); | |
| 133 | |
| 134 cache_policy_ = policy; | |
| 135 } | |
| 136 | |
| 137 bool AudioOutputDeviceEnumerator::IsCacheEnabled() { | |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 139 return cache_policy_ != CACHE_POLICY_NO_CACHING; | |
| 140 } | |
| 141 | |
| 142 void AudioOutputDeviceEnumerator::DoEnumerateDevices() { | |
| 143 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 144 is_enumeration_ongoing_ = true; | |
| 145 seq_last_enumeration_ = NewEventSequence(); | |
| 146 base::PostTaskAndReplyWithResult( | |
| 147 audio_manager_->GetTaskRunner(), FROM_HERE, | |
| 148 base::Bind(&EnumerateDevicesOnDeviceThread, audio_manager_), | |
| 149 base::Bind(&AudioOutputDeviceEnumerator::DevicesEnumerated, | |
| 150 weak_factory_.GetWeakPtr())); | |
| 151 } | |
| 152 | |
| 153 void AudioOutputDeviceEnumerator::DevicesEnumerated( | |
| 154 const AudioOutputDeviceEnumeration& snapshot) { | |
| 155 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 156 is_enumeration_ongoing_ = false; | |
| 157 if (IsLastEnumerationValid()) { | |
| 158 cache_ = snapshot; | |
| 159 while (!pending_callbacks_.empty()) { | |
| 160 AudioOutputDeviceEnumerationCB callback = pending_callbacks_.front(); | |
| 161 pending_callbacks_.pop_front(); | |
| 162 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 163 FROM_HERE, base::Bind(callback, snapshot)); | |
| 164 } | |
| 165 pending_callbacks_.clear(); | |
| 166 } else { | |
| 167 DoEnumerateDevices(); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 int64_t AudioOutputDeviceEnumerator::NewEventSequence() { | |
| 172 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 173 return ++current_event_sequence_; | |
| 174 } | |
| 175 | |
| 176 bool AudioOutputDeviceEnumerator::IsLastEnumerationValid() const { | |
| 177 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 178 return seq_last_enumeration_ > seq_last_invalidation_ && | |
| 179 !is_enumeration_ongoing_; | |
| 180 } | |
| 181 | |
| 182 } // namespace content | |
| OLD | NEW |