Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / renderer_host / media / audio_output_device_enumerator.cc
blob516cde09ba31ba85a9bae2a8b4ec49b32357a514
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"
14 namespace content {
16 namespace {
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()});
31 return snapshot;
34 for (const media::AudioDeviceName& name : device_names) {
35 snapshot.push_back(
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)});
41 return snapshot;
44 } // namespace
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) {
67 InvalidateCache();
70 if (IsLastEnumerationValid()) {
71 DCHECK(pending_callbacks_.empty());
72 callback.Run(cache_);
73 } else {
74 pending_callbacks_.push_back(callback);
75 if (!is_enumeration_ongoing_) {
76 DoEnumerateDevices();
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)
89 InvalidateCache();
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()) {
110 cache_ = snapshot;
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();
118 } else {
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