Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/media_session.h" | 5 #include "content/browser/media/session/media_session.h" |
| 6 | 6 |
| 7 #include "content/browser/media/session/media_session_delegate.h" | 7 #include "content/browser/media/session/media_session_delegate.h" |
| 8 #include "content/browser/media/session/media_session_observer.h" | 8 #include "content/browser/media/session/media_session_observer.h" |
| 9 #include "content/browser/web_contents/web_contents_impl.h" | 9 #include "content/browser/web_contents/web_contents_impl.h" |
| 10 #include "content/public/browser/web_contents.h" | 10 #include "content/public/browser/web_contents.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 session->Initialize(); | 53 session->Initialize(); |
| 54 } | 54 } |
| 55 return session; | 55 return session; |
| 56 } | 56 } |
| 57 | 57 |
| 58 MediaSession::~MediaSession() { | 58 MediaSession::~MediaSession() { |
| 59 DCHECK(players_.empty()); | 59 DCHECK(players_.empty()); |
| 60 DCHECK(audio_focus_state_ == State::INACTIVE); | 60 DCHECK(audio_focus_state_ == State::INACTIVE); |
| 61 } | 61 } |
| 62 | 62 |
| 63 void MediaSession::WasShown() { | |
| 64 if (IsSuspended()) | |
| 65 RequestSystemAudioFocus(audio_focus_type_); | |
| 66 } | |
| 67 | |
| 63 void MediaSession::SetMetadata(const MediaMetadata& metadata) { | 68 void MediaSession::SetMetadata(const MediaMetadata& metadata) { |
| 64 metadata_ = metadata; | 69 metadata_ = metadata; |
| 65 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the | 70 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the |
| 66 // media session play/pause state changes. Need to find a way to seprate the | 71 // media session play/pause state changes. Need to find a way to seprate the |
| 67 // state change and Metadata update. See https://crbug.com/621855. | 72 // state change and Metadata update. See https://crbug.com/621855. |
| 68 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); | 73 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); |
| 69 } | 74 } |
| 70 | 75 |
| 71 bool MediaSession::AddPlayer(MediaSessionObserver* observer, | 76 bool MediaSession::AddPlayer(MediaSessionObserver* observer, |
| 72 int player_id, | 77 int player_id, |
| 73 media::MediaContentType media_content_type) { | 78 media::MediaContentType media_content_type) { |
| 79 if (media_content_type == media::MediaContentType::Pepper) | |
| 80 return AddPepperPlayer(observer, player_id); | |
| 81 | |
| 74 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); | 82 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); |
| 75 | 83 |
| 76 // Determine the audio focus type required for playing the new player. | 84 // Determine the audio focus type required for playing the new player. |
| 77 // TODO(zqzhang): handle duckable and uncontrollable. | 85 // TODO(zqzhang): handle duckable and uncontrollable. |
| 78 // See https://crbug.com/639277. | 86 // See https://crbug.com/639277. |
| 79 AudioFocusManager::AudioFocusType required_audio_focus_type; | 87 AudioFocusManager::AudioFocusType required_audio_focus_type; |
| 80 if (media_content_type == media::MediaContentType::Persistent) { | 88 if (media_content_type == media::MediaContentType::Persistent) { |
| 81 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; | 89 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; |
| 82 } else { | 90 } else { |
| 83 required_audio_focus_type = | 91 required_audio_focus_type = |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 | 123 |
| 116 return true; | 124 return true; |
| 117 } | 125 } |
| 118 | 126 |
| 119 void MediaSession::RemovePlayer(MediaSessionObserver* observer, | 127 void MediaSession::RemovePlayer(MediaSessionObserver* observer, |
| 120 int player_id) { | 128 int player_id) { |
| 121 auto it = players_.find(PlayerIdentifier(observer, player_id)); | 129 auto it = players_.find(PlayerIdentifier(observer, player_id)); |
| 122 if (it != players_.end()) | 130 if (it != players_.end()) |
| 123 players_.erase(it); | 131 players_.erase(it); |
| 124 | 132 |
| 133 it = pepper_players_.find(PlayerIdentifier(observer, player_id)); | |
| 134 if (it != pepper_players_.end()) | |
| 135 pepper_players_.erase(it); | |
| 136 | |
| 125 AbandonSystemAudioFocusIfNeeded(); | 137 AbandonSystemAudioFocusIfNeeded(); |
| 126 } | 138 } |
| 127 | 139 |
| 128 void MediaSession::RemovePlayers(MediaSessionObserver* observer) { | 140 void MediaSession::RemovePlayers(MediaSessionObserver* observer) { |
| 129 for (auto it = players_.begin(); it != players_.end();) { | 141 for (auto it = players_.begin(); it != players_.end();) { |
| 130 if (it->observer == observer) | 142 if (it->observer == observer) |
| 131 players_.erase(it++); | 143 players_.erase(it++); |
| 132 else | 144 else |
| 133 ++it; | 145 ++it; |
| 134 } | 146 } |
| 135 | 147 |
| 148 for (auto it = pepper_players_.begin(); it != pepper_players_.end();) { | |
|
whywhat
2016/09/07 20:09:54
nit: add a space between ; and )
Zhiqiang Zhang (Slow)
2016/09/08 14:18:26
Done.
| |
| 149 if (it->observer == observer) | |
| 150 pepper_players_.erase(it++); | |
| 151 else | |
| 152 ++it; | |
| 153 } | |
| 154 | |
| 136 AbandonSystemAudioFocusIfNeeded(); | 155 AbandonSystemAudioFocusIfNeeded(); |
| 137 } | 156 } |
| 138 | 157 |
| 139 void MediaSession::RecordSessionDuck() { | 158 void MediaSession::RecordSessionDuck() { |
| 140 uma_helper_.RecordSessionSuspended( | 159 uma_helper_.RecordSessionSuspended( |
| 141 MediaSessionSuspendedSource::SystemTransientDuck); | 160 MediaSessionSuspendedSource::SystemTransientDuck); |
| 142 } | 161 } |
| 143 | 162 |
| 144 void MediaSession::OnPlayerPaused(MediaSessionObserver* observer, | 163 void MediaSession::OnPlayerPaused(MediaSessionObserver* observer, |
| 145 int player_id) { | 164 int player_id) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 if (suspend_type == SuspendType::SYSTEM) { | 216 if (suspend_type == SuspendType::SYSTEM) { |
| 198 OnSuspendInternal(suspend_type, State::INACTIVE); | 217 OnSuspendInternal(suspend_type, State::INACTIVE); |
| 199 return; | 218 return; |
| 200 } | 219 } |
| 201 | 220 |
| 202 if (audio_focus_state_ != State::SUSPENDED) | 221 if (audio_focus_state_ != State::SUSPENDED) |
| 203 OnSuspendInternal(suspend_type, State::SUSPENDED); | 222 OnSuspendInternal(suspend_type, State::SUSPENDED); |
| 204 | 223 |
| 205 DCHECK(audio_focus_state_ == State::SUSPENDED); | 224 DCHECK(audio_focus_state_ == State::SUSPENDED); |
| 206 players_.clear(); | 225 players_.clear(); |
| 226 | |
| 227 for (const auto& it : pepper_players_) | |
|
whywhat
2016/09/07 20:09:54
nit: add {}
Zhiqiang Zhang (Slow)
2016/09/08 14:18:26
Done.
| |
| 228 it.observer->OnSetVolumeMultiplier( | |
| 229 it.player_id, GetPepperVolumeMultiplier()); | |
| 230 | |
| 207 AbandonSystemAudioFocusIfNeeded(); | 231 AbandonSystemAudioFocusIfNeeded(); |
| 208 } | 232 } |
| 209 | 233 |
| 210 void MediaSession::StartDucking() { | 234 void MediaSession::StartDucking() { |
| 211 if (is_ducking_) | 235 if (is_ducking_) |
| 212 return; | 236 return; |
| 213 is_ducking_ = true; | 237 is_ducking_ = true; |
| 214 UpdateVolumeMultiplier(); | 238 UpdateVolumeMultiplier(); |
| 215 } | 239 } |
| 216 | 240 |
| 217 void MediaSession::StopDucking() { | 241 void MediaSession::StopDucking() { |
| 218 if (!is_ducking_) | 242 if (!is_ducking_) |
| 219 return; | 243 return; |
| 220 is_ducking_ = false; | 244 is_ducking_ = false; |
| 221 UpdateVolumeMultiplier(); | 245 UpdateVolumeMultiplier(); |
| 222 } | 246 } |
| 223 | 247 |
| 224 void MediaSession::UpdateVolumeMultiplier() { | 248 void MediaSession::UpdateVolumeMultiplier() { |
| 225 for (const auto& it : players_) | 249 for (const auto& it : players_) |
| 226 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); | 250 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); |
| 227 } | 251 } |
| 228 | 252 |
| 229 double MediaSession::GetVolumeMultiplier() const { | 253 double MediaSession::GetVolumeMultiplier() const { |
| 230 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier; | 254 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier; |
| 231 } | 255 } |
| 232 | 256 |
| 257 double MediaSession::GetPepperVolumeMultiplier() const { | |
| 258 if (is_on_top_) | |
| 259 return kDefaultVolumeMultiplier; | |
| 260 if (!IsActive() || is_ducking_) | |
| 261 return kDuckingVolumeMultiplier; | |
| 262 return kDefaultVolumeMultiplier; | |
| 263 } | |
| 264 | |
| 233 bool MediaSession::IsActive() const { | 265 bool MediaSession::IsActive() const { |
| 234 return audio_focus_state_ == State::ACTIVE; | 266 return audio_focus_state_ == State::ACTIVE; |
| 235 } | 267 } |
| 236 | 268 |
| 237 bool MediaSession::IsReallySuspended() const { | 269 bool MediaSession::IsReallySuspended() const { |
| 238 return audio_focus_state_ == State::SUSPENDED; | 270 return audio_focus_state_ == State::SUSPENDED; |
| 239 } | 271 } |
| 240 | 272 |
| 241 bool MediaSession::IsSuspended() const { | 273 bool MediaSession::IsSuspended() const { |
| 242 // TODO(mlamouri): should be == State::SUSPENDED. | 274 // TODO(mlamouri): should be == State::SUSPENDED. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 suspend_type_ = suspend_type; | 348 suspend_type_ = suspend_type; |
| 317 | 349 |
| 318 if (suspend_type != SuspendType::CONTENT) { | 350 if (suspend_type != SuspendType::CONTENT) { |
| 319 // SuspendType::CONTENT happens when the suspend action came from | 351 // SuspendType::CONTENT happens when the suspend action came from |
| 320 // the page in which case the player is already paused. | 352 // the page in which case the player is already paused. |
| 321 // Otherwise, the players need to be paused. | 353 // Otherwise, the players need to be paused. |
| 322 for (const auto& it : players_) | 354 for (const auto& it : players_) |
| 323 it.observer->OnSuspend(it.player_id); | 355 it.observer->OnSuspend(it.player_id); |
| 324 } | 356 } |
| 325 | 357 |
| 358 for (const auto& it : pepper_players_) | |
| 359 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier); | |
| 360 | |
| 326 UpdateWebContents(); | 361 UpdateWebContents(); |
| 327 } | 362 } |
| 328 | 363 |
| 329 void MediaSession::OnResumeInternal(SuspendType suspend_type) { | 364 void MediaSession::OnResumeInternal(SuspendType suspend_type) { |
| 330 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) | 365 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) |
| 331 return; | 366 return; |
| 332 | 367 |
| 333 SetAudioFocusState(State::ACTIVE); | 368 SetAudioFocusState(State::ACTIVE); |
| 334 | 369 |
| 335 for (const auto& it : players_) | 370 for (const auto& it : players_) |
| 336 it.observer->OnResume(it.player_id); | 371 it.observer->OnResume(it.player_id); |
| 337 | 372 |
| 373 for (const auto& it : pepper_players_) | |
| 374 it.observer->OnSetVolumeMultiplier( | |
| 375 it.player_id, GetPepperVolumeMultiplier()); | |
| 376 | |
| 338 UpdateWebContents(); | 377 UpdateWebContents(); |
| 339 } | 378 } |
| 340 | 379 |
| 341 MediaSession::MediaSession(WebContents* web_contents) | 380 MediaSession::MediaSession(WebContents* web_contents) |
| 342 : WebContentsObserver(web_contents), | 381 : WebContentsObserver(web_contents), |
| 343 audio_focus_state_(State::INACTIVE), | 382 audio_focus_state_(State::INACTIVE), |
| 344 audio_focus_type_( | 383 audio_focus_type_( |
| 345 AudioFocusManager::AudioFocusType::GainTransientMayDuck), | 384 AudioFocusManager::AudioFocusType::GainTransientMayDuck), |
| 346 is_ducking_(false) {} | 385 is_ducking_(false), |
| 386 is_on_top_(false) {} | |
| 347 | 387 |
| 348 void MediaSession::Initialize() { | 388 void MediaSession::Initialize() { |
| 349 delegate_ = MediaSessionDelegate::Create(this); | 389 delegate_ = MediaSessionDelegate::Create(this); |
| 350 } | 390 } |
| 351 | 391 |
| 352 bool MediaSession::RequestSystemAudioFocus( | 392 bool MediaSession::RequestSystemAudioFocus( |
| 353 AudioFocusManager::AudioFocusType audio_focus_type) { | 393 AudioFocusManager::AudioFocusType audio_focus_type) { |
| 354 bool result = delegate_->RequestAudioFocus(audio_focus_type); | 394 bool result = delegate_->RequestAudioFocus(audio_focus_type); |
| 355 uma_helper_.RecordRequestAudioFocusResult(result); | 395 uma_helper_.RecordRequestAudioFocusResult(result); |
| 356 return result; | 396 return result; |
| 357 } | 397 } |
| 358 | 398 |
| 359 void MediaSession::AbandonSystemAudioFocusIfNeeded() { | 399 void MediaSession::AbandonSystemAudioFocusIfNeeded() { |
| 360 if (audio_focus_state_ == State::INACTIVE || !players_.empty()) | 400 if (audio_focus_state_ == State::INACTIVE || !players_.empty() || |
| 401 !pepper_players_.empty()) | |
| 361 return; | 402 return; |
| 362 | 403 |
| 363 delegate_->AbandonAudioFocus(); | 404 delegate_->AbandonAudioFocus(); |
| 364 | 405 |
| 365 SetAudioFocusState(State::INACTIVE); | 406 SetAudioFocusState(State::INACTIVE); |
| 366 UpdateWebContents(); | 407 UpdateWebContents(); |
| 367 } | 408 } |
| 368 | 409 |
| 369 void MediaSession::UpdateWebContents() { | 410 void MediaSession::UpdateWebContents() { |
| 370 media_session_state_listeners_.Notify(audio_focus_state_); | 411 media_session_state_listeners_.Notify(audio_focus_state_); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 382 break; | 423 break; |
| 383 case State::SUSPENDED: | 424 case State::SUSPENDED: |
| 384 uma_helper_.OnSessionSuspended(); | 425 uma_helper_.OnSessionSuspended(); |
| 385 break; | 426 break; |
| 386 case State::INACTIVE: | 427 case State::INACTIVE: |
| 387 uma_helper_.OnSessionInactive(); | 428 uma_helper_.OnSessionInactive(); |
| 388 break; | 429 break; |
| 389 } | 430 } |
| 390 } | 431 } |
| 391 | 432 |
| 433 bool MediaSession::AddPepperPlayer(MediaSessionObserver* observer, | |
| 434 int player_id) { | |
| 435 AudioFocusManager::AudioFocusType focus_type = | |
| 436 AudioFocusManager::AudioFocusType::Gain; | |
| 437 State audio_focus_state = | |
| 438 RequestSystemAudioFocus(focus_type) ? State::ACTIVE : State::INACTIVE; | |
| 439 SetAudioFocusState(audio_focus_state); | |
| 440 audio_focus_type_ = focus_type; | |
| 441 pepper_players_.insert(PlayerIdentifier(observer, player_id)); | |
| 442 | |
| 443 observer->OnSetVolumeMultiplier(player_id, GetPepperVolumeMultiplier()); | |
| 444 | |
| 445 return true; | |
| 446 } | |
| 447 | |
| 448 void MediaSession::SetOnTop(bool is_on_top) { | |
| 449 if (is_on_top_ == is_on_top) | |
| 450 return; | |
| 451 | |
| 452 is_on_top_ = is_on_top; | |
| 453 for (const auto& it : pepper_players_) { | |
| 454 it.observer->OnSetVolumeMultiplier( | |
| 455 it.player_id, GetPepperVolumeMultiplier()); | |
| 456 } | |
| 457 } | |
| 458 | |
| 392 } // namespace content | 459 } // namespace content |
| OLD | NEW |