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

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: addressed jochen's comments Created 4 years, 2 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 AudioFocusManager::AudioFocusEntry::AudioFocusEntry(
13 WebContents* web_contents,
14 AudioFocusManager* audio_focus_manager,
15 AudioFocusType type)
16 : WebContentsObserver(web_contents),
17 audio_focus_manager_(audio_focus_manager) {}
18
19 AudioFocusManager::AudioFocusType
20 AudioFocusManager::AudioFocusEntry::type() const {
21 return type_;
22 }
23
24 void AudioFocusManager::AudioFocusEntry::WebContentsDestroyed() {
25 audio_focus_manager_->OnWebContentsDestroyed(web_contents());
26 // |this| will be destroyed now.
27 }
28
29 // static 13 // static
30 AudioFocusManager* AudioFocusManager::GetInstance() { 14 AudioFocusManager* AudioFocusManager::GetInstance() {
31 return base::Singleton<AudioFocusManager>::get(); 15 return base::Singleton<AudioFocusManager>::get();
32 } 16 }
33 17
34 void AudioFocusManager::RequestAudioFocus(MediaSession* media_session, 18 void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
35 AudioFocusType type) { 19 AudioFocusType type) {
36 WebContents* web_contents = media_session->web_contents(); 20 if (!audio_focus_stack_.empty() &&
37 21 audio_focus_stack_.back() == media_session &&
38 if (type == AudioFocusType::GainTransientMayDuck) { 22 audio_focus_stack_.back()->audio_focus_type() == type &&
39 MaybeRemoveFocusEntry(web_contents); 23 audio_focus_stack_.back()->IsActive()) {
40 transient_entries_[web_contents].reset( 24 // Early returning if |media_session| is already on top (has focus) and is
41 new AudioFocusEntry(web_contents, this, type)); 25 // active.
42 MaybeStartDucking();
43 return; 26 return;
44 } 27 }
45 28
46 DCHECK(type == AudioFocusType::Gain); 29 MaybeRemoveFocusEntry(media_session);
47 RequestAudioFocusGain(web_contents); 30
31 // TODO(zqzhang): It seems like MediaSession is exposed to AudioFocusManager
32 // too much. Maybe it's better to do some abstraction and refactoring to clean
33 // up the relation between AudioFocusManager and MediaSession.
34 // See https://crbug.com/651069
35 if (type == AudioFocusType::GainTransientMayDuck) {
36 for (const auto old_session : audio_focus_stack_) {
37 old_session->StartDucking();
38 }
39 } else {
40 for (const auto old_session : audio_focus_stack_) {
41 if (old_session->IsActive()) {
42 if (old_session->HasPepper())
43 old_session->StartDucking();
44 else
45 old_session->Suspend(MediaSession::SuspendType::SYSTEM);
46 }
47 }
48 }
49
50 audio_focus_stack_.push_back(media_session);
51 audio_focus_stack_.back()->StopDucking();
48 } 52 }
49 53
50 void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) { 54 void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) {
51 AbandonAudioFocusInternal(media_session->web_contents()); 55 if (audio_focus_stack_.empty())
56 return;
57
58 if (audio_focus_stack_.back() != media_session) {
59 MaybeRemoveFocusEntry(media_session);
60 return;
61 }
62
63 audio_focus_stack_.pop_back();
64 if (audio_focus_stack_.empty())
65 return;
66
67 // Allow the top-most MediaSession having Pepper to unduck pepper even if it's
68 // not active.
69 for (auto iter = audio_focus_stack_.rbegin();
70 iter != audio_focus_stack_.rend(); ++iter) {
71 if (!(*iter)->HasPepper())
72 continue;
73
74 MediaSession* pepper_session = *iter;
75 pepper_session->StopDucking();
76 MaybeRemoveFocusEntry(pepper_session);
77 audio_focus_stack_.push_back(pepper_session);
78 return;
79 }
80 // Only try to unduck the new MediaSession on top. The session might be still
81 // inactive but it will not be resumed (so it doesn't surprise the user).
82 audio_focus_stack_.back()->StopDucking();
52 } 83 }
53 84
54 AudioFocusManager::AudioFocusManager() = default; 85 AudioFocusManager::AudioFocusManager() = default;
55 86
56 AudioFocusManager::~AudioFocusManager() = default; 87 AudioFocusManager::~AudioFocusManager() = default;
57 88
58 void AudioFocusManager::RequestAudioFocusGain(WebContents* web_contents) { 89 void AudioFocusManager::MaybeRemoveFocusEntry(MediaSession* media_session) {
59 MaybeRemoveTransientEntry(web_contents); 90 audio_focus_stack_.remove(media_session);
60
61 if (focus_entry_) {
62 if (focus_entry_->web_contents() == web_contents)
63 return;
64
65 MediaSession* other_session =
66 MediaSession::Get(focus_entry_->web_contents());
67 if (other_session->IsActive())
68 other_session->Suspend(MediaSession::SuspendType::SYSTEM);
69 }
70
71 focus_entry_.reset(
72 new AudioFocusEntry(web_contents, this, AudioFocusType::Gain));
73 MaybeStartDucking();
74 }
75
76 void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) {
77 AbandonAudioFocusInternal(web_contents);
78 }
79
80 void AudioFocusManager::AbandonAudioFocusInternal(WebContents* web_contents) {
81 MaybeRemoveTransientEntry(web_contents);
82 MaybeRemoveFocusEntry(web_contents);
83 }
84
85 void AudioFocusManager::MaybeStartDucking() const {
86 if (TransientMayDuckEntriesCount() != 1 || !focus_entry_)
87 return;
88
89 MediaSession::Get(focus_entry_->web_contents())->StartDucking();
90 }
91
92 void AudioFocusManager::MaybeStopDucking() const {
93 if (TransientMayDuckEntriesCount() != 0 || !focus_entry_)
94 return;
95
96 MediaSession::Get(focus_entry_->web_contents())->StopDucking();
97 }
98
99 int AudioFocusManager::TransientMayDuckEntriesCount() const {
100 return transient_entries_.size();
101 }
102
103 void AudioFocusManager::MaybeRemoveTransientEntry(WebContents* web_contents) {
104 transient_entries_.erase(web_contents);
105 MaybeStopDucking();
106 }
107
108 void AudioFocusManager::MaybeRemoveFocusEntry(WebContents* web_contents) {
109 if (focus_entry_ && focus_entry_->web_contents() == web_contents) {
110 MediaSession::Get(focus_entry_->web_contents())->StopDucking();
111 focus_entry_.reset();
112 }
113 } 91 }
114 92
115 } // namespace content 93 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/session/audio_focus_manager.h ('k') | content/browser/media/session/audio_focus_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698