blob: 4ff3491de482542efe4781d46d153e896df8eef4 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session.h"
#include "content/public/browser/web_contents.h"
namespace content {
AudioFocusManager::AudioFocusEntry::AudioFocusEntry(
WebContents* web_contents,
AudioFocusManager* audio_focus_manager,
AudioFocusType type)
: WebContentsObserver(web_contents),
audio_focus_manager_(audio_focus_manager) {}
AudioFocusManager::AudioFocusType
AudioFocusManager::AudioFocusEntry::type() const {
return type_;
}
void AudioFocusManager::AudioFocusEntry::WebContentsDestroyed() {
audio_focus_manager_->OnWebContentsDestroyed(web_contents());
// |this| will be destroyed now.
}
// static
AudioFocusManager* AudioFocusManager::GetInstance() {
return base::Singleton<AudioFocusManager>::get();
}
void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
AudioFocusType type) {
WebContents* web_contents = media_session->web_contents();
if (type == AudioFocusType::GainTransientMayDuck) {
MaybeRemoveFocusEntry(web_contents);
transient_entries_[web_contents].reset(
new AudioFocusEntry(web_contents, this, type));
MaybeStartDucking();
return;
}
DCHECK(type == AudioFocusType::Gain);
RequestAudioFocusGain(web_contents);
}
void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) {
AbandonAudioFocusInternal(media_session->web_contents());
}
AudioFocusManager::AudioFocusManager() = default;
AudioFocusManager::~AudioFocusManager() = default;
void AudioFocusManager::RequestAudioFocusGain(WebContents* web_contents) {
MaybeRemoveTransientEntry(web_contents);
if (focus_entry_) {
if (focus_entry_->web_contents() == web_contents)
return;
MediaSession* other_session =
MediaSession::Get(focus_entry_->web_contents());
if (other_session->IsActive())
other_session->Suspend(MediaSession::SuspendType::SYSTEM);
}
focus_entry_.reset(
new AudioFocusEntry(web_contents, this, AudioFocusType::Gain));
MaybeStartDucking();
}
void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) {
AbandonAudioFocusInternal(web_contents);
}
void AudioFocusManager::AbandonAudioFocusInternal(WebContents* web_contents) {
MaybeRemoveTransientEntry(web_contents);
MaybeRemoveFocusEntry(web_contents);
}
void AudioFocusManager::MaybeStartDucking() const {
if (TransientMayDuckEntriesCount() != 1 || !focus_entry_)
return;
MediaSession::Get(focus_entry_->web_contents())->StartDucking();
}
void AudioFocusManager::MaybeStopDucking() const {
if (TransientMayDuckEntriesCount() != 0 || !focus_entry_)
return;
MediaSession::Get(focus_entry_->web_contents())->StopDucking();
}
int AudioFocusManager::TransientMayDuckEntriesCount() const {
return transient_entries_.size();
}
void AudioFocusManager::MaybeRemoveTransientEntry(WebContents* web_contents) {
transient_entries_.erase(web_contents);
MaybeStopDucking();
}
void AudioFocusManager::MaybeRemoveFocusEntry(WebContents* web_contents) {
if (focus_entry_ && focus_entry_->web_contents() == web_contents) {
MediaSession::Get(focus_entry_->web_contents())->StopDucking();
focus_entry_.reset();
}
}
} // namespace content