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.
5 #include "content/browser/renderer_host/media/audio_output_device_enumerator.h"
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/thread_task_runner_handle.h"
12 #include "media/audio/audio_manager_base.h"
18 AudioOutputDeviceEnumeration
EnumerateDevicesOnDeviceThread(
19 media::AudioManager
* audio_manager
) {
20 DCHECK(audio_manager
->GetWorkerTaskRunner()->BelongsToCurrentThread());
22 AudioOutputDeviceEnumeration snapshot
;
23 media::AudioDeviceNames device_names
;
24 audio_manager
->GetAudioOutputDeviceNames(&device_names
);
26 // If no devices in enumeration, return a list with a default device
27 if (device_names
.empty()) {
28 snapshot
.push_back({media::AudioManagerBase::kDefaultDeviceId
,
29 media::AudioManagerBase::kDefaultDeviceName
,
30 audio_manager
->GetDefaultOutputStreamParameters()});
34 for (const media::AudioDeviceName
& name
: device_names
) {
36 {name
.unique_id
, name
.device_name
,
37 name
.unique_id
== media::AudioManagerBase::kDefaultDeviceId
38 ? audio_manager
->GetDefaultOutputStreamParameters()
39 : audio_manager
->GetOutputStreamParameters(name
.unique_id
)});
46 AudioOutputDeviceEnumerator::AudioOutputDeviceEnumerator(
47 media::AudioManager
* audio_manager
,
48 CachePolicy cache_policy
)
49 : audio_manager_(audio_manager
),
50 cache_policy_(cache_policy
),
51 current_event_sequence_(0),
52 seq_last_enumeration_(0),
53 seq_last_invalidation_(0),
54 is_enumeration_ongoing_(false),
55 weak_factory_(this) {}
57 AudioOutputDeviceEnumerator::~AudioOutputDeviceEnumerator() {
58 DCHECK(thread_checker_
.CalledOnValidThread());
61 void AudioOutputDeviceEnumerator::Enumerate(
62 const AudioOutputDeviceEnumerationCB
& callback
) {
63 DCHECK(thread_checker_
.CalledOnValidThread());
65 // If caching is disabled, force a cache invalidation
66 if (cache_policy_
== CACHE_POLICY_NO_CACHING
) {
70 if (IsLastEnumerationValid()) {
71 DCHECK(pending_callbacks_
.empty());
74 pending_callbacks_
.push_back(callback
);
75 if (!is_enumeration_ongoing_
) {
81 void AudioOutputDeviceEnumerator::InvalidateCache() {
82 DCHECK(thread_checker_
.CalledOnValidThread());
83 seq_last_invalidation_
= NewEventSequence();
86 void AudioOutputDeviceEnumerator::SetCachePolicy(CachePolicy policy
) {
87 DCHECK(thread_checker_
.CalledOnValidThread());
88 if (policy
== CACHE_POLICY_NO_CACHING
)
91 cache_policy_
= policy
;
94 void AudioOutputDeviceEnumerator::DoEnumerateDevices() {
95 DCHECK(thread_checker_
.CalledOnValidThread());
96 is_enumeration_ongoing_
= true;
97 seq_last_enumeration_
= NewEventSequence();
98 base::PostTaskAndReplyWithResult(
99 audio_manager_
->GetWorkerTaskRunner().get(), FROM_HERE
,
100 base::Bind(&EnumerateDevicesOnDeviceThread
, audio_manager_
),
101 base::Bind(&AudioOutputDeviceEnumerator::DevicesEnumerated
,
102 weak_factory_
.GetWeakPtr()));
105 void AudioOutputDeviceEnumerator::DevicesEnumerated(
106 const AudioOutputDeviceEnumeration
& snapshot
) {
107 DCHECK(thread_checker_
.CalledOnValidThread());
108 is_enumeration_ongoing_
= false;
109 if (IsLastEnumerationValid()) {
111 while (!pending_callbacks_
.empty()) {
112 AudioOutputDeviceEnumerationCB callback
= pending_callbacks_
.front();
113 pending_callbacks_
.pop_front();
114 base::ThreadTaskRunnerHandle::Get()->PostTask(
115 FROM_HERE
, base::Bind(callback
, snapshot
));
117 pending_callbacks_
.clear();
119 DoEnumerateDevices();
123 int64_t AudioOutputDeviceEnumerator::NewEventSequence() {
124 DCHECK(thread_checker_
.CalledOnValidThread());
125 return ++current_event_sequence_
;
128 bool AudioOutputDeviceEnumerator::IsLastEnumerationValid() const {
129 DCHECK(thread_checker_
.CalledOnValidThread());
130 return seq_last_enumeration_
> seq_last_invalidation_
&&
131 !is_enumeration_ongoing_
;
134 } // namespace content