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_impl.h" | 5 #include "content/browser/media/session/media_session_impl.h" |
| 6 | 6 |
| 7 #include "content/browser/media/session/audio_focus_delegate.h" | 7 #include "content/browser/media/session/audio_focus_delegate.h" |
| 8 #include "content/browser/media/session/media_session_player_observer.h" | 8 #include "content/browser/media/session/media_session_player_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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 if (!session) { | 58 if (!session) { |
| 59 CreateForWebContents(web_contents); | 59 CreateForWebContents(web_contents); |
| 60 session = FromWebContents(web_contents); | 60 session = FromWebContents(web_contents); |
| 61 session->Initialize(); | 61 session->Initialize(); |
| 62 } | 62 } |
| 63 return session; | 63 return session; |
| 64 } | 64 } |
| 65 | 65 |
| 66 MediaSessionImpl::~MediaSessionImpl() { | 66 MediaSessionImpl::~MediaSessionImpl() { |
| 67 DCHECK(players_.empty()); | 67 DCHECK(players_.empty()); |
| 68 DCHECK(pepper_players_.empty()); | |
| 69 DCHECK(one_shot_players_.empty()); | |
| 68 DCHECK(audio_focus_state_ == State::INACTIVE); | 70 DCHECK(audio_focus_state_ == State::INACTIVE); |
| 69 for (auto& observer : observers_) | 71 for (auto& observer : observers_) |
| 70 observer.MediaSessionDestroyed(); | 72 observer.MediaSessionDestroyed(); |
| 71 } | 73 } |
| 72 | 74 |
| 73 void MediaSessionImpl::WebContentsDestroyed() { | 75 void MediaSessionImpl::WebContentsDestroyed() { |
| 74 // This should only work for tests. In production, all the players should have | 76 // This should only work for tests. In production, all the players should have |
| 75 // already been removed before WebContents is destroyed. | 77 // already been removed before WebContents is destroyed. |
| 76 | 78 |
| 77 // TODO(zqzhang): refactor MediaSessionImpl, maybe move the interface used to | 79 // TODO(zqzhang): refactor MediaSessionImpl, maybe move the interface used to |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 94 void MediaSessionImpl::SetMetadata( | 96 void MediaSessionImpl::SetMetadata( |
| 95 const base::Optional<MediaMetadata>& metadata) { | 97 const base::Optional<MediaMetadata>& metadata) { |
| 96 metadata_ = metadata; | 98 metadata_ = metadata; |
| 97 for (auto& observer : observers_) | 99 for (auto& observer : observers_) |
| 98 observer.MediaSessionMetadataChanged(metadata); | 100 observer.MediaSessionMetadataChanged(metadata); |
| 99 } | 101 } |
| 100 | 102 |
| 101 bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, | 103 bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, |
| 102 int player_id, | 104 int player_id, |
| 103 media::MediaContentType media_content_type) { | 105 media::MediaContentType media_content_type) { |
| 104 if (media_content_type == media::MediaContentType::Uncontrollable) | 106 if (media_content_type == media::MediaContentType::OneShot) |
| 105 return true; | 107 return AddOneShotPlayer(observer, player_id); |
| 106 if (media_content_type == media::MediaContentType::Pepper) | 108 if (media_content_type == media::MediaContentType::Pepper) |
| 107 return AddPepperPlayer(observer, player_id); | 109 return AddPepperPlayer(observer, player_id); |
| 108 | 110 |
| 109 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); | 111 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); |
| 110 | 112 |
| 111 // Determine the audio focus type required for playing the new player. | |
| 112 // TODO(zqzhang): handle duckable and uncontrollable. | |
| 113 // See https://crbug.com/639277. | |
| 114 AudioFocusManager::AudioFocusType required_audio_focus_type; | 113 AudioFocusManager::AudioFocusType required_audio_focus_type; |
| 115 if (media_content_type == media::MediaContentType::Persistent) { | 114 if (media_content_type == media::MediaContentType::Persistent) { |
| 116 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; | 115 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; |
| 117 } else { | 116 } else { |
| 118 required_audio_focus_type = | 117 required_audio_focus_type = |
| 119 AudioFocusManager::AudioFocusType::GainTransientMayDuck; | 118 AudioFocusManager::AudioFocusType::GainTransientMayDuck; |
| 120 } | 119 } |
| 121 | 120 |
| 122 // If the audio focus is already granted and is of type Content, there is | 121 // If the audio focus is already granted and is of type Content, there is |
| 123 // nothing to do. If it is granted of type Transient the requested type is | 122 // nothing to do. If it is granted of type Transient the requested type is |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 135 | 134 |
| 136 if (audio_focus_state_ != State::ACTIVE) | 135 if (audio_focus_state_ != State::ACTIVE) |
| 137 return false; | 136 return false; |
| 138 | 137 |
| 139 // The session should be reset if a player is starting while all players are | 138 // The session should be reset if a player is starting while all players are |
| 140 // suspended. | 139 // suspended. |
| 141 if (old_audio_focus_state != State::ACTIVE) | 140 if (old_audio_focus_state != State::ACTIVE) |
| 142 players_.clear(); | 141 players_.clear(); |
| 143 | 142 |
| 144 players_.insert(PlayerIdentifier(observer, player_id)); | 143 players_.insert(PlayerIdentifier(observer, player_id)); |
| 145 UpdateWebContents(); | 144 DispatchStateChange(); |
| 146 | 145 |
| 147 return true; | 146 return true; |
| 148 } | 147 } |
| 149 | 148 |
| 150 void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer, | 149 void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer, |
| 151 int player_id) { | 150 int player_id) { |
| 152 auto it = players_.find(PlayerIdentifier(observer, player_id)); | 151 auto it = players_.find(PlayerIdentifier(observer, player_id)); |
| 153 if (it != players_.end()) | 152 if (it != players_.end()) |
| 154 players_.erase(it); | 153 players_.erase(it); |
| 155 | 154 |
| 156 it = pepper_players_.find(PlayerIdentifier(observer, player_id)); | 155 it = pepper_players_.find(PlayerIdentifier(observer, player_id)); |
| 157 if (it != pepper_players_.end()) | 156 if (it != pepper_players_.end()) |
| 158 pepper_players_.erase(it); | 157 pepper_players_.erase(it); |
| 159 | 158 |
| 159 it = one_shot_players_.find(PlayerIdentifier(observer, player_id)); | |
| 160 if (it != one_shot_players_.end()) { | |
| 161 one_shot_players_.erase(it); | |
| 162 | |
| 163 // The session may become controllable after all one-shot players are | |
| 164 // removed. | |
| 165 if (one_shot_players_.empty()) | |
| 166 DispatchStateChange(); | |
| 167 } | |
| 168 | |
| 160 AbandonSystemAudioFocusIfNeeded(); | 169 AbandonSystemAudioFocusIfNeeded(); |
| 161 } | 170 } |
| 162 | 171 |
| 163 void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) { | 172 void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) { |
| 164 for (auto it = players_.begin(); it != players_.end();) { | 173 for (auto it = players_.begin(); it != players_.end();) { |
| 165 if (it->observer == observer) | 174 if (it->observer == observer) |
| 166 players_.erase(it++); | 175 players_.erase(it++); |
| 167 else | 176 else |
| 168 ++it; | 177 ++it; |
| 169 } | 178 } |
| 170 | 179 |
| 171 for (auto it = pepper_players_.begin(); it != pepper_players_.end();) { | 180 for (auto it = pepper_players_.begin(); it != pepper_players_.end();) { |
| 172 if (it->observer == observer) | 181 if (it->observer == observer) |
| 173 pepper_players_.erase(it++); | 182 pepper_players_.erase(it++); |
| 174 else | 183 else |
| 175 ++it; | 184 ++it; |
| 176 } | 185 } |
| 177 | 186 |
| 187 for (auto it = one_shot_players_.begin(); it != one_shot_players_.end();) { | |
| 188 if (it->observer == observer) | |
| 189 one_shot_players_.erase(it++); | |
| 190 else | |
| 191 ++it; | |
| 192 | |
| 193 // The session may become controllable after all one-shot players are | |
| 194 // removed. | |
| 195 if (one_shot_players_.empty()) | |
| 196 DispatchStateChange(); | |
| 197 } | |
| 198 | |
| 178 AbandonSystemAudioFocusIfNeeded(); | 199 AbandonSystemAudioFocusIfNeeded(); |
| 179 } | 200 } |
| 180 | 201 |
| 181 void MediaSessionImpl::RecordSessionDuck() { | 202 void MediaSessionImpl::RecordSessionDuck() { |
| 182 uma_helper_.RecordSessionSuspended( | 203 uma_helper_.RecordSessionSuspended( |
| 183 MediaSessionSuspendedSource::SystemTransientDuck); | 204 MediaSessionSuspendedSource::SystemTransientDuck); |
| 184 } | 205 } |
| 185 | 206 |
| 186 void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer, | 207 void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer, |
| 187 int player_id) { | 208 int player_id) { |
| 188 // If a playback is completed, BrowserMediaPlayerManager will call | 209 // If a playback is completed, BrowserMediaPlayerManager will call |
| 189 // OnPlayerPaused() after RemovePlayer(). This is a workaround. | 210 // OnPlayerPaused() after RemovePlayer(). This is a workaround. |
| 190 // Also, this method may be called when a player that is not added | 211 // Also, this method may be called when a player that is not added |
| 191 // to this session (e.g. a silent video) is paused. MediaSessionImpl | 212 // to this session (e.g. a silent video) is paused. MediaSessionImpl |
| 192 // should ignore the paused player for this case. | 213 // should ignore the paused player for this case. |
| 193 if (!players_.count(PlayerIdentifier(observer, player_id)) && | 214 if (!players_.count(PlayerIdentifier(observer, player_id)) && |
| 194 !pepper_players_.count(PlayerIdentifier(observer, player_id))) { | 215 !pepper_players_.count(PlayerIdentifier(observer, player_id)) && |
| 216 !one_shot_players_.count(PlayerIdentifier(observer, player_id))) { | |
| 195 return; | 217 return; |
| 196 } | 218 } |
| 197 | 219 |
| 198 // If the player to be removed is a pepper player, or there is more than one | 220 // If the player to be removed is a pepper player, or there is more than one |
| 199 // observer, remove the paused one from the session. | 221 // observer, remove the paused one from the session. |
| 200 if (pepper_players_.count(PlayerIdentifier(observer, player_id)) || | 222 if (pepper_players_.count(PlayerIdentifier(observer, player_id)) || |
| 201 players_.size() != 1) { | 223 players_.size() != 1) { |
| 202 RemovePlayer(observer, player_id); | 224 RemovePlayer(observer, player_id); |
| 203 return; | 225 return; |
| 204 } | 226 } |
| 205 | 227 |
| 228 // If the player is a one-shot player, just remove it since it is not expected | |
| 229 // to resume a one-shot player via resuming MediaSession. | |
| 230 if (one_shot_players_.count(PlayerIdentifier(observer, player_id))) { | |
| 231 RemovePlayer(observer, player_id); | |
| 232 return; | |
| 233 } | |
| 234 | |
| 206 // Otherwise, suspend the session. | 235 // Otherwise, suspend the session. |
| 207 DCHECK(!IsSuspended()); | 236 DCHECK(!IsSuspended()); |
| 208 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED); | 237 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED); |
| 209 } | 238 } |
| 210 | 239 |
| 211 void MediaSessionImpl::Resume(SuspendType suspend_type) { | 240 void MediaSessionImpl::Resume(SuspendType suspend_type) { |
| 212 DCHECK(IsReallySuspended()); | 241 DCHECK(IsReallySuspended()); |
| 213 | 242 |
| 214 // When the resume requests comes from another source than system, audio focus | 243 // When the resume requests comes from another source than system, audio focus |
| 215 // must be requested. | 244 // must be requested. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 return audio_focus_state_ == State::SUSPENDED; | 316 return audio_focus_state_ == State::SUSPENDED; |
| 288 } | 317 } |
| 289 | 318 |
| 290 bool MediaSessionImpl::IsSuspended() const { | 319 bool MediaSessionImpl::IsSuspended() const { |
| 291 // TODO(mlamouri): should be == State::SUSPENDED. | 320 // TODO(mlamouri): should be == State::SUSPENDED. |
| 292 return audio_focus_state_ != State::ACTIVE; | 321 return audio_focus_state_ != State::ACTIVE; |
| 293 } | 322 } |
| 294 | 323 |
| 295 bool MediaSessionImpl::IsControllable() const { | 324 bool MediaSessionImpl::IsControllable() const { |
| 296 // Only media session having focus Gain can be controllable unless it is | 325 // Only media session having focus Gain can be controllable unless it is |
| 297 // inactive. | 326 // inactive. Also, the session will be uncontrollable if it contains one-shot |
| 327 // players. | |
| 298 return audio_focus_state_ != State::INACTIVE && | 328 return audio_focus_state_ != State::INACTIVE && |
| 299 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain; | 329 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain && |
| 330 (one_shot_players_.empty()); | |
| 300 } | 331 } |
| 301 | 332 |
| 302 bool MediaSessionImpl::HasPepper() const { | 333 bool MediaSessionImpl::HasPepper() const { |
| 303 return !pepper_players_.empty(); | 334 return !pepper_players_.empty(); |
| 304 } | 335 } |
| 305 | 336 |
| 306 std::unique_ptr<base::CallbackList<void(MediaSessionImpl::State)>::Subscription> | 337 std::unique_ptr<base::CallbackList<void(MediaSessionImpl::State)>::Subscription> |
| 307 MediaSessionImpl::RegisterMediaSessionStateChangedCallbackForTest( | 338 MediaSessionImpl::RegisterMediaSessionStateChangedCallbackForTest( |
| 308 const StateChangedCallback& cb) { | 339 const StateChangedCallback& cb) { |
| 309 return media_session_state_listeners_.Add(cb); | 340 return media_session_state_listeners_.Add(cb); |
| 310 } | 341 } |
| 311 | 342 |
| 312 void MediaSessionImpl::SetDelegateForTests( | 343 void MediaSessionImpl::SetDelegateForTests( |
| 313 std::unique_ptr<AudioFocusDelegate> delegate) { | 344 std::unique_ptr<AudioFocusDelegate> delegate) { |
| 314 delegate_ = std::move(delegate); | 345 delegate_ = std::move(delegate); |
| 315 } | 346 } |
| 316 | 347 |
| 317 bool MediaSessionImpl::IsActiveForTest() const { | 348 bool MediaSessionImpl::IsActiveForTest() const { |
| 318 return audio_focus_state_ == State::ACTIVE; | 349 return audio_focus_state_ == State::ACTIVE; |
| 319 } | 350 } |
| 320 | 351 |
| 321 MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() { | 352 MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() { |
| 322 return &uma_helper_; | 353 return &uma_helper_; |
| 323 } | 354 } |
| 324 | 355 |
| 325 void MediaSessionImpl::RemoveAllPlayersForTest() { | 356 void MediaSessionImpl::RemoveAllPlayersForTest() { |
| 326 players_.clear(); | 357 players_.clear(); |
| 358 pepper_players_.clear(); | |
| 359 one_shot_players_.clear(); | |
|
whywhat
2016/11/03 14:32:17
nit: I feel there's more code duplication here w.r
Zhiqiang Zhang (Slow)
2016/11/04 14:10:54
Yeah, I feel this too. But as pepper_players_ is l
| |
| 327 AbandonSystemAudioFocusIfNeeded(); | 360 AbandonSystemAudioFocusIfNeeded(); |
| 328 } | 361 } |
| 329 | 362 |
| 330 void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type, | 363 void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type, |
| 331 State new_state) { | 364 State new_state) { |
| 332 DCHECK(!HasPepper()); | 365 DCHECK(!HasPepper()); |
| 333 | 366 |
| 334 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); | 367 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); |
| 335 // UI suspend cannot use State::INACTIVE. | 368 // UI suspend cannot use State::INACTIVE. |
| 336 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED); | 369 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED); |
| 337 | 370 |
| 371 if (!one_shot_players_.empty()) | |
| 372 return; | |
| 373 | |
| 338 if (audio_focus_state_ != State::ACTIVE) | 374 if (audio_focus_state_ != State::ACTIVE) |
| 339 return; | 375 return; |
| 340 | 376 |
| 341 switch (suspend_type) { | 377 switch (suspend_type) { |
| 342 case SuspendType::UI: | 378 case SuspendType::UI: |
| 343 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); | 379 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); |
| 344 break; | 380 break; |
| 345 case SuspendType::SYSTEM: | 381 case SuspendType::SYSTEM: |
| 346 switch (new_state) { | 382 switch (new_state) { |
| 347 case State::SUSPENDED: | 383 case State::SUSPENDED: |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 369 // SuspendType::CONTENT happens when the suspend action came from | 405 // SuspendType::CONTENT happens when the suspend action came from |
| 370 // the page in which case the player is already paused. | 406 // the page in which case the player is already paused. |
| 371 // Otherwise, the players need to be paused. | 407 // Otherwise, the players need to be paused. |
| 372 for (const auto& it : players_) | 408 for (const auto& it : players_) |
| 373 it.observer->OnSuspend(it.player_id); | 409 it.observer->OnSuspend(it.player_id); |
| 374 } | 410 } |
| 375 | 411 |
| 376 for (const auto& it : pepper_players_) | 412 for (const auto& it : pepper_players_) |
| 377 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier); | 413 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier); |
| 378 | 414 |
| 379 UpdateWebContents(); | 415 DispatchStateChange(); |
| 380 } | 416 } |
| 381 | 417 |
| 382 void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) { | 418 void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) { |
| 383 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) | 419 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) |
| 384 return; | 420 return; |
| 385 | 421 |
| 386 SetAudioFocusState(State::ACTIVE); | 422 SetAudioFocusState(State::ACTIVE); |
| 387 | 423 |
| 388 for (const auto& it : players_) | 424 for (const auto& it : players_) |
| 389 it.observer->OnResume(it.player_id); | 425 it.observer->OnResume(it.player_id); |
| 390 | 426 |
| 391 for (const auto& it : pepper_players_) | 427 for (const auto& it : pepper_players_) |
| 392 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); | 428 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); |
| 393 | 429 |
| 394 UpdateWebContents(); | 430 DispatchStateChange(); |
| 395 } | 431 } |
| 396 | 432 |
| 397 MediaSessionImpl::MediaSessionImpl(WebContents* web_contents) | 433 MediaSessionImpl::MediaSessionImpl(WebContents* web_contents) |
| 398 : WebContentsObserver(web_contents), | 434 : WebContentsObserver(web_contents), |
| 399 audio_focus_state_(State::INACTIVE), | 435 audio_focus_state_(State::INACTIVE), |
| 400 audio_focus_type_( | 436 audio_focus_type_( |
| 401 AudioFocusManager::AudioFocusType::GainTransientMayDuck), | 437 AudioFocusManager::AudioFocusType::GainTransientMayDuck), |
| 402 is_ducking_(false) { | 438 is_ducking_(false) { |
| 403 #if defined(OS_ANDROID) | 439 #if defined(OS_ANDROID) |
| 404 session_android_.reset(new MediaSessionAndroid(this)); | 440 session_android_.reset(new MediaSessionAndroid(this)); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 416 | 452 |
| 417 // MediaSessionImpl must change its state & audio focus type AFTER requesting | 453 // MediaSessionImpl must change its state & audio focus type AFTER requesting |
| 418 // audio focus. | 454 // audio focus. |
| 419 SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE); | 455 SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE); |
| 420 audio_focus_type_ = audio_focus_type; | 456 audio_focus_type_ = audio_focus_type; |
| 421 return result; | 457 return result; |
| 422 } | 458 } |
| 423 | 459 |
| 424 void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() { | 460 void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() { |
| 425 if (audio_focus_state_ == State::INACTIVE || !players_.empty() || | 461 if (audio_focus_state_ == State::INACTIVE || !players_.empty() || |
| 426 !pepper_players_.empty()) { | 462 !pepper_players_.empty() || !one_shot_players_.empty()) { |
| 427 return; | 463 return; |
| 428 } | 464 } |
| 429 delegate_->AbandonAudioFocus(); | 465 delegate_->AbandonAudioFocus(); |
| 430 | 466 |
| 431 SetAudioFocusState(State::INACTIVE); | 467 SetAudioFocusState(State::INACTIVE); |
| 432 UpdateWebContents(); | 468 DispatchStateChange(); |
| 433 } | 469 } |
| 434 | 470 |
| 435 void MediaSessionImpl::UpdateWebContents() { | 471 void MediaSessionImpl::DispatchStateChange() { |
| 436 media_session_state_listeners_.Notify(audio_focus_state_); | 472 media_session_state_listeners_.Notify(audio_focus_state_); |
| 437 for (auto& observer : observers_) | 473 for (auto& observer : observers_) |
| 438 observer.MediaSessionStateChanged(IsControllable(), IsSuspended()); | 474 observer.MediaSessionStateChanged(IsControllable(), IsSuspended()); |
| 439 } | 475 } |
| 440 | 476 |
| 441 void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) { | 477 void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) { |
| 442 if (audio_focus_state == audio_focus_state_) | 478 if (audio_focus_state == audio_focus_state_) |
| 443 return; | 479 return; |
| 444 | 480 |
| 445 audio_focus_state_ = audio_focus_state; | 481 audio_focus_state_ = audio_focus_state; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 459 bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer, | 495 bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer, |
| 460 int player_id) { | 496 int player_id) { |
| 461 bool success = | 497 bool success = |
| 462 RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain); | 498 RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain); |
| 463 DCHECK(success); | 499 DCHECK(success); |
| 464 | 500 |
| 465 pepper_players_.insert(PlayerIdentifier(observer, player_id)); | 501 pepper_players_.insert(PlayerIdentifier(observer, player_id)); |
| 466 | 502 |
| 467 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); | 503 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); |
| 468 | 504 |
| 505 DispatchStateChange(); | |
| 469 return true; | 506 return true; |
| 470 } | 507 } |
| 471 | 508 |
| 509 bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer, | |
| 510 int player_id) { | |
| 511 // Don't check whether the request is successful or not. One-shot players | |
| 512 // should play uninterrupted. | |
|
whywhat
2016/11/03 14:32:16
that means we'd play them even if the user is in t
Zhiqiang Zhang (Slow)
2016/11/04 14:10:54
OK, let's give a chance for the players to respond
| |
| 513 RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain); | |
| 514 | |
| 515 one_shot_players_.insert(PlayerIdentifier(observer, player_id)); | |
| 516 | |
| 517 DispatchStateChange(); | |
| 518 return true; | |
| 519 } | |
| 520 | |
| 472 } // namespace content | 521 } // namespace content |
| OLD | NEW |