now_playing_info_center_delegate.mm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/system_media_controls/mac/now_playing_info_center_delegate.h"
  5. #import <MediaPlayer/MediaPlayer.h>
  6. #include "base/bind.h"
  7. #include "base/mac/mac_util.h"
  8. #include "base/notreached.h"
  9. #include "base/strings/sys_string_conversions.h"
  10. #include "components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.h"
  11. #include "skia/ext/skia_utils_mac.h"
  12. namespace system_media_controls {
  13. namespace internal {
  14. namespace {
  15. API_AVAILABLE(macos(10.13.1))
  16. MPNowPlayingPlaybackState PlaybackStatusToMPNowPlayingPlaybackState(
  17. SystemMediaControls::PlaybackStatus status) {
  18. switch (status) {
  19. case SystemMediaControls::PlaybackStatus::kPlaying:
  20. return MPNowPlayingPlaybackStatePlaying;
  21. case SystemMediaControls::PlaybackStatus::kPaused:
  22. return MPNowPlayingPlaybackStatePaused;
  23. case SystemMediaControls::PlaybackStatus::kStopped:
  24. return MPNowPlayingPlaybackStateStopped;
  25. default:
  26. NOTREACHED();
  27. }
  28. return MPNowPlayingPlaybackStateUnknown;
  29. }
  30. } // anonymous namespace
  31. NowPlayingInfoCenterDelegate::NowPlayingInfoCenterDelegate() {
  32. now_playing_info_center_delegate_cocoa_.reset(
  33. [[NowPlayingInfoCenterDelegateCocoa alloc] init]);
  34. }
  35. NowPlayingInfoCenterDelegate::~NowPlayingInfoCenterDelegate() {
  36. [now_playing_info_center_delegate_cocoa_ resetNowPlayingInfo];
  37. timer_->Stop();
  38. }
  39. void NowPlayingInfoCenterDelegate::SetPlaybackStatus(
  40. SystemMediaControls::PlaybackStatus status) {
  41. playback_status_ = status;
  42. StartTimer();
  43. }
  44. void NowPlayingInfoCenterDelegate::SetTitle(const std::u16string& title) {
  45. [now_playing_info_center_delegate_cocoa_
  46. setTitle:base::SysUTF16ToNSString(title)];
  47. [now_playing_info_center_delegate_cocoa_ updateNowPlayingInfo];
  48. }
  49. void NowPlayingInfoCenterDelegate::SetArtist(const std::u16string& artist) {
  50. [now_playing_info_center_delegate_cocoa_
  51. setArtist:base::SysUTF16ToNSString(artist)];
  52. [now_playing_info_center_delegate_cocoa_ updateNowPlayingInfo];
  53. }
  54. void NowPlayingInfoCenterDelegate::SetAlbum(const std::u16string& album) {
  55. [now_playing_info_center_delegate_cocoa_
  56. setAlbum:base::SysUTF16ToNSString(album)];
  57. [now_playing_info_center_delegate_cocoa_ updateNowPlayingInfo];
  58. }
  59. void NowPlayingInfoCenterDelegate::SetThumbnail(const SkBitmap& bitmap) {
  60. NSImage* image = skia::SkBitmapToNSImageWithColorSpace(
  61. bitmap, base::mac::GetSystemColorSpace());
  62. [now_playing_info_center_delegate_cocoa_ setThumbnail:image];
  63. [now_playing_info_center_delegate_cocoa_ updateNowPlayingInfo];
  64. }
  65. void NowPlayingInfoCenterDelegate::SetPosition(
  66. const media_session::MediaPosition& position) {
  67. position_ = position;
  68. StartTimer();
  69. }
  70. void NowPlayingInfoCenterDelegate::StartTimer() {
  71. timer_->Start(
  72. FROM_HERE, base::Milliseconds(100),
  73. base::BindOnce(
  74. &NowPlayingInfoCenterDelegate::UpdatePlaybackStatusAndPosition,
  75. base::Unretained(this)));
  76. }
  77. void NowPlayingInfoCenterDelegate::UpdatePlaybackStatusAndPosition() {
  78. auto position = position_.value_or(media_session::MediaPosition());
  79. auto playback_status =
  80. playback_status_.value_or(SystemMediaControls::PlaybackStatus::kStopped);
  81. MPNowPlayingPlaybackState state =
  82. PlaybackStatusToMPNowPlayingPlaybackState(playback_status);
  83. [now_playing_info_center_delegate_cocoa_ setPlaybackState:state];
  84. auto time_since_epoch =
  85. position.last_updated_time() - base::TimeTicks::UnixEpoch();
  86. [now_playing_info_center_delegate_cocoa_
  87. setCurrentPlaybackDate:
  88. [NSDate dateWithTimeIntervalSince1970:time_since_epoch.InSecondsF()]];
  89. [now_playing_info_center_delegate_cocoa_
  90. setDuration:[NSNumber numberWithFloat:position.duration().InSecondsF()]];
  91. // If we're not currently playing, then set the rate to zero.
  92. double rate =
  93. (playback_status == SystemMediaControls::PlaybackStatus::kPlaying)
  94. ? position.playback_rate()
  95. : 0;
  96. [now_playing_info_center_delegate_cocoa_
  97. setPlaybackRate:[NSNumber numberWithDouble:rate]];
  98. [now_playing_info_center_delegate_cocoa_
  99. setElapsedPlaybackTime:
  100. [NSNumber numberWithFloat:position
  101. .GetPositionAtTime(
  102. position.last_updated_time())
  103. .InSecondsF()]];
  104. [now_playing_info_center_delegate_cocoa_ updateNowPlayingInfo];
  105. }
  106. void NowPlayingInfoCenterDelegate::ClearMetadata() {
  107. [now_playing_info_center_delegate_cocoa_ clearMetadata];
  108. playback_status_.reset();
  109. position_.reset();
  110. timer_->Stop();
  111. }
  112. } // namespace internal
  113. } // namespace system_media_controls