diff options
Diffstat (limited to '')
-rw-r--r-- | widget/cocoa/MediaHardwareKeysEventSourceMacMediaCenter.mm | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/widget/cocoa/MediaHardwareKeysEventSourceMacMediaCenter.mm b/widget/cocoa/MediaHardwareKeysEventSourceMacMediaCenter.mm new file mode 100644 index 0000000000..9637c11d81 --- /dev/null +++ b/widget/cocoa/MediaHardwareKeysEventSourceMacMediaCenter.mm @@ -0,0 +1,172 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#import <MediaPlayer/MediaPlayer.h> + +#include "MediaHardwareKeysEventSourceMacMediaCenter.h" + +#include "mozilla/dom/MediaControlUtils.h" +#include "nsCocoaUtils.h" + +using namespace mozilla::dom; + +// avoid redefined macro in unified build +#undef LOG +#define LOG(msg, ...) \ + MOZ_LOG(gMediaControlLog, LogLevel::Debug, \ + ("MediaHardwareKeysEventSourceMacMediaCenter=%p, " msg, this, ##__VA_ARGS__)) + +namespace mozilla { +namespace widget { + +MediaCenterEventHandler MediaHardwareKeysEventSourceMacMediaCenter::CreatePlayPauseHandler() { + return Block_copy(^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent* event) { + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + center.playbackState = center.playbackState == MPNowPlayingPlaybackStatePlaying + ? MPNowPlayingPlaybackStatePaused + : MPNowPlayingPlaybackStatePlaying; + HandleEvent(MediaControlKey::Playpause); + return MPRemoteCommandHandlerStatusSuccess; + }); +} + +MediaCenterEventHandler MediaHardwareKeysEventSourceMacMediaCenter::CreateNextTrackHandler() { + return Block_copy(^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent* event) { + HandleEvent(MediaControlKey::Nexttrack); + return MPRemoteCommandHandlerStatusSuccess; + }); +} + +MediaCenterEventHandler MediaHardwareKeysEventSourceMacMediaCenter::CreatePreviousTrackHandler() { + return Block_copy(^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent* event) { + HandleEvent(MediaControlKey::Previoustrack); + return MPRemoteCommandHandlerStatusSuccess; + }); +} + +MediaCenterEventHandler MediaHardwareKeysEventSourceMacMediaCenter::CreatePlayHandler() { + return Block_copy(^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent* event) { + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + if (center.playbackState != MPNowPlayingPlaybackStatePlaying) { + center.playbackState = MPNowPlayingPlaybackStatePlaying; + } + HandleEvent(MediaControlKey::Play); + return MPRemoteCommandHandlerStatusSuccess; + }); +} + +MediaCenterEventHandler MediaHardwareKeysEventSourceMacMediaCenter::CreatePauseHandler() { + return Block_copy(^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent* event) { + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + if (center.playbackState != MPNowPlayingPlaybackStatePaused) { + center.playbackState = MPNowPlayingPlaybackStatePaused; + } + HandleEvent(MediaControlKey::Pause); + return MPRemoteCommandHandlerStatusSuccess; + }); +} + +MediaHardwareKeysEventSourceMacMediaCenter::MediaHardwareKeysEventSourceMacMediaCenter() { + mPlayPauseHandler = CreatePlayPauseHandler(); + mNextTrackHandler = CreateNextTrackHandler(); + mPreviousTrackHandler = CreatePreviousTrackHandler(); + mPlayHandler = CreatePlayHandler(); + mPauseHandler = CreatePauseHandler(); + LOG("Create MediaHardwareKeysEventSourceMacMediaCenter"); +} + +MediaHardwareKeysEventSourceMacMediaCenter::~MediaHardwareKeysEventSourceMacMediaCenter() { + LOG("Destroy MediaHardwareKeysEventSourceMacMediaCenter"); + EndListeningForEvents(); + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + center.playbackState = MPNowPlayingPlaybackStateStopped; +} + +void MediaHardwareKeysEventSourceMacMediaCenter::BeginListeningForEvents() { + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + center.playbackState = MPNowPlayingPlaybackStatePlaying; + MPRemoteCommandCenter* commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; + commandCenter.togglePlayPauseCommand.enabled = true; + [commandCenter.togglePlayPauseCommand addTargetWithHandler:mPlayPauseHandler]; + commandCenter.nextTrackCommand.enabled = true; + [commandCenter.nextTrackCommand addTargetWithHandler:mNextTrackHandler]; + commandCenter.previousTrackCommand.enabled = true; + [commandCenter.previousTrackCommand addTargetWithHandler:mPreviousTrackHandler]; + commandCenter.playCommand.enabled = true; + [commandCenter.playCommand addTargetWithHandler:mPlayHandler]; + commandCenter.pauseCommand.enabled = true; + [commandCenter.pauseCommand addTargetWithHandler:mPauseHandler]; +} + +void MediaHardwareKeysEventSourceMacMediaCenter::EndListeningForEvents() { + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + center.playbackState = MPNowPlayingPlaybackStatePaused; + center.nowPlayingInfo = nil; + MPRemoteCommandCenter* commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; + commandCenter.togglePlayPauseCommand.enabled = false; + [commandCenter.togglePlayPauseCommand removeTarget:nil]; + commandCenter.nextTrackCommand.enabled = false; + [commandCenter.nextTrackCommand removeTarget:nil]; + commandCenter.previousTrackCommand.enabled = false; + [commandCenter.previousTrackCommand removeTarget:nil]; + commandCenter.playCommand.enabled = false; + [commandCenter.playCommand removeTarget:nil]; + commandCenter.pauseCommand.enabled = false; + [commandCenter.pauseCommand removeTarget:nil]; +} + +bool MediaHardwareKeysEventSourceMacMediaCenter::Open() { + LOG("Open MediaHardwareKeysEventSourceMacMediaCenter"); + mOpened = true; + BeginListeningForEvents(); + return true; +} + +void MediaHardwareKeysEventSourceMacMediaCenter::Close() { + LOG("Close MediaHardwareKeysEventSourceMacMediaCenter"); + SetPlaybackState(dom::MediaSessionPlaybackState::None); + EndListeningForEvents(); + mOpened = false; + MediaControlKeySource::Close(); +} + +bool MediaHardwareKeysEventSourceMacMediaCenter::IsOpened() const { return mOpened; } + +void MediaHardwareKeysEventSourceMacMediaCenter::HandleEvent(MediaControlKey aEvent) { + for (auto iter = mListeners.begin(); iter != mListeners.end(); ++iter) { + (*iter)->OnActionPerformed(MediaControlAction(aEvent)); + } +} + +void MediaHardwareKeysEventSourceMacMediaCenter::SetPlaybackState( + MediaSessionPlaybackState aState) { + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + if (aState == MediaSessionPlaybackState::Playing) { + center.playbackState = MPNowPlayingPlaybackStatePlaying; + } else if (aState == MediaSessionPlaybackState::Paused) { + center.playbackState = MPNowPlayingPlaybackStatePaused; + } else if (aState == MediaSessionPlaybackState::None) { + center.playbackState = MPNowPlayingPlaybackStateStopped; + } + MediaControlKeySource::SetPlaybackState(aState); +} + +void MediaHardwareKeysEventSourceMacMediaCenter::SetMediaMetadata( + const dom::MediaMetadataBase& aMetadata) { + NSMutableDictionary* nowPlayingInfo = [NSMutableDictionary dictionary]; + [nowPlayingInfo setObject:nsCocoaUtils::ToNSString(aMetadata.mTitle) + forKey:MPMediaItemPropertyTitle]; + [nowPlayingInfo setObject:nsCocoaUtils::ToNSString(aMetadata.mArtist) + forKey:MPMediaItemPropertyArtist]; + [nowPlayingInfo setObject:nsCocoaUtils::ToNSString(aMetadata.mAlbum) + forKey:MPMediaItemPropertyAlbumTitle]; + // The procedure of updating `nowPlayingInfo` is actually an async operation + // from our testing, Apple's documentation doesn't mention that though. So be + // aware that checking `nowPlayingInfo` immedately after setting it might not + // yield the expected result. + [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nowPlayingInfo; +} + +} // namespace widget +} // namespace mozilla |