Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: content/browser/media/session/audio_focus_manager.cc

Issue 2274873003: Letting Flash join MediaSession (stack implementaion) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@media_session_type
Patch Set: fixed unduck bug Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/media/session/audio_focus_manager.h" 5 #include "content/browser/media/session/audio_focus_manager.h"
6 6
7 #include "base/memory/ptr_util.h"
7 #include "content/browser/media/session/media_session.h" 8 #include "content/browser/media/session/media_session.h"
8 #include "content/public/browser/web_contents.h" 9 #include "content/public/browser/web_contents.h"
9 10
10 namespace content { 11 namespace content {
11 12
12 namespace {
13
14 const double kDuckingVolumeMultiplier = 0.2;
15 const double kDefaultVolumeMultiplier = 1.0;
16
17 } // anonymous namespace
18
19 AudioFocusManager::AudioFocusEntry::AudioFocusEntry( 13 AudioFocusManager::AudioFocusEntry::AudioFocusEntry(
20 WebContents* web_contents, 14 WebContents* web_contents,
21 AudioFocusManager* audio_focus_manager, 15 AudioFocusManager* audio_focus_manager,
22 AudioFocusType type) 16 AudioFocusType type)
23 : WebContentsObserver(web_contents), 17 : WebContentsObserver(web_contents),
24 audio_focus_manager_(audio_focus_manager) {} 18 audio_focus_manager_(audio_focus_manager),
19 type_(type) {}
whywhat 2016/08/30 21:09:37 nit: this sounds like an initialization bug, shoul
25 20
26 AudioFocusManager::AudioFocusType 21 AudioFocusManager::AudioFocusType
27 AudioFocusManager::AudioFocusEntry::type() const { 22 AudioFocusManager::AudioFocusEntry::type() const {
28 return type_; 23 return type_;
29 } 24 }
30 25
31 void AudioFocusManager::AudioFocusEntry::WebContentsDestroyed() { 26 void AudioFocusManager::AudioFocusEntry::WebContentsDestroyed() {
32 audio_focus_manager_->OnWebContentsDestroyed(web_contents()); 27 audio_focus_manager_->OnWebContentsDestroyed(web_contents());
33 // |this| will be destroyed now. 28 // |this| will be destroyed now.
34 } 29 }
35 30
36 // static 31 // static
37 AudioFocusManager* AudioFocusManager::GetInstance() { 32 AudioFocusManager* AudioFocusManager::GetInstance() {
38 return base::Singleton<AudioFocusManager>::get(); 33 return base::Singleton<AudioFocusManager>::get();
39 } 34 }
40 35
41 void AudioFocusManager::RequestAudioFocus(MediaSession* media_session, 36 void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
42 AudioFocusType type) { 37 AudioFocusType type) {
43 WebContents* web_contents = media_session->web_contents(); 38 WebContents* web_contents = media_session->web_contents();
44 39
40 if (!audio_focus_stack_.empty() &&
41 audio_focus_stack_.back()->web_contents() == web_contents)
42 return;
43
44 MaybeRemoveFocusEntry(web_contents);
45
45 if (type == AudioFocusType::GainTransientMayDuck) { 46 if (type == AudioFocusType::GainTransientMayDuck) {
47 for (const auto& focus_entry : audio_focus_stack_) {
48 MediaSession::Get(focus_entry->web_contents())->Duck();
whywhat 2016/08/30 21:09:37 nit: a one-liner, remove the {}
49 }
50 } else {
51 for (const auto& focus_entry : audio_focus_stack_) {
52 MediaSession* session = MediaSession::Get(focus_entry->web_contents());
53 if (session->IsActive())
whywhat 2016/08/30 21:09:37 can we have more than one active session at the ti
54 session->Suspend(MediaSession::SuspendType::SYSTEM);
55 }
56 }
57 if (!audio_focus_stack_.empty()) {
58 MediaSession::Get(audio_focus_stack_.back()->web_contents())
59 ->SetOnTop(false);
whywhat 2016/08/30 21:09:37 SetOnTop sounds like a dirty hack
60 }
61
62 audio_focus_stack_.push_back(base::MakeUnique<AudioFocusEntry>(
63 web_contents, this, type));
64 MediaSession::Get(audio_focus_stack_.back()->web_contents())->Unduck();
whywhat 2016/08/30 21:09:37 replace audio_focus_stack_.back()->web_contents()
65 MediaSession::Get(audio_focus_stack_.back()->web_contents())->SetOnTop(true);
66 }
67
68 void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) {
69 WebContents* web_contents = media_session->web_contents();
70
71 if (audio_focus_stack_.back()->web_contents() != web_contents) {
46 MaybeRemoveFocusEntry(web_contents); 72 MaybeRemoveFocusEntry(web_contents);
47 transient_entries_[web_contents].reset(
48 new AudioFocusEntry(web_contents, this, type));
49 MaybeStartDucking();
50 return; 73 return;
51 } 74 }
52 75
53 DCHECK(type == AudioFocusType::Gain); 76 MediaSession::Get(audio_focus_stack_.back()->web_contents())->SetOnTop(false);
54 RequestAudioFocusGain(web_contents); 77 audio_focus_stack_.pop_back();
55 } 78 if (audio_focus_stack_.empty())
79 return;
56 80
57 void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) { 81 MediaSession::Get(audio_focus_stack_.back()->web_contents())->SetOnTop(true);
58 AbandonAudioFocusInternal(media_session->web_contents()); 82 // Only try to unduck the new MediaSession on top. The session might be still
83 // inactive but it will not be resumed (so it does surprise the user).
84 MediaSession::Get(audio_focus_stack_.back()->web_contents())->Unduck();
59 } 85 }
60 86
61 AudioFocusManager::AudioFocusManager() = default; 87 AudioFocusManager::AudioFocusManager() = default;
62 88
63 AudioFocusManager::~AudioFocusManager() = default; 89 AudioFocusManager::~AudioFocusManager() = default;
64 90
65 void AudioFocusManager::RequestAudioFocusGain(WebContents* web_contents) {
66 MaybeRemoveTransientEntry(web_contents);
67
68 if (focus_entry_) {
69 if (focus_entry_->web_contents() == web_contents)
70 return;
71
72 MediaSession* other_session =
73 MediaSession::Get(focus_entry_->web_contents());
74 if (other_session->IsActive())
75 other_session->Suspend(MediaSession::SuspendType::SYSTEM);
76 }
77
78 focus_entry_.reset(
79 new AudioFocusEntry(web_contents, this, AudioFocusType::Gain));
80 MaybeStartDucking();
81 }
82
83 void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) { 91 void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) {
84 AbandonAudioFocusInternal(web_contents); 92 AbandonAudioFocus(MediaSession::Get(web_contents));
85 }
86
87 void AudioFocusManager::AbandonAudioFocusInternal(WebContents* web_contents) {
88 MaybeRemoveTransientEntry(web_contents);
89 MaybeRemoveFocusEntry(web_contents);
90 }
91
92 void AudioFocusManager::MaybeStartDucking() const {
93 if (TransientMayDuckEntriesCount() != 1 || !focus_entry_)
94 return;
95
96 // TODO(mlamouri): add StartDuck to MediaSession.
97 MediaSession::Get(focus_entry_->web_contents())
98 ->SetVolumeMultiplier(kDuckingVolumeMultiplier);
99 }
100
101 void AudioFocusManager::MaybeStopDucking() const {
102 if (TransientMayDuckEntriesCount() != 0 || !focus_entry_)
103 return;
104
105 // TODO(mlamouri): add StopDuck to MediaSession.
106 MediaSession::Get(focus_entry_->web_contents())
107 ->SetVolumeMultiplier(kDefaultVolumeMultiplier);
108 }
109
110 int AudioFocusManager::TransientMayDuckEntriesCount() const {
111 return transient_entries_.size();
112 }
113
114 void AudioFocusManager::MaybeRemoveTransientEntry(WebContents* web_contents) {
115 transient_entries_.erase(web_contents);
116 MaybeStopDucking();
117 } 93 }
118 94
119 void AudioFocusManager::MaybeRemoveFocusEntry(WebContents* web_contents) { 95 void AudioFocusManager::MaybeRemoveFocusEntry(WebContents* web_contents) {
120 if (focus_entry_ && focus_entry_->web_contents() == web_contents) { 96 for (auto iter = audio_focus_stack_.begin(); iter != audio_focus_stack_.end();
121 MediaSession::Get(focus_entry_->web_contents()) 97 ++iter) {
122 ->SetVolumeMultiplier(kDefaultVolumeMultiplier); 98 if (web_contents == (*iter)->web_contents()) {
123 focus_entry_.reset(); 99 audio_focus_stack_.erase(iter);
whywhat 2016/08/30 21:09:37 Should you update OnTop in some cases?
100 return;
101 }
124 } 102 }
125 } 103 }
126 104
127 } // namespace content 105 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698