[vlc-commits] macosx: refactor and simplify MPNowPlayingInfoCenter integration
Felix Paul Kühne
git at videolan.org
Mon Sep 16 22:02:58 CEST 2019
vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Mon Sep 16 21:48:59 2019 +0200| [0da2ab7bb6d3710f971918b77fe3eb3d01c8001f] | committer: Felix Paul Kühne
macosx: refactor and simplify MPNowPlayingInfoCenter integration
This also fixes #20838.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=0da2ab7bb6d3710f971918b77fe3eb3d01c8001f
---
.../os-integration/VLCRemoteControlService.m | 149 ++++++++++++++++++---
modules/gui/macosx/playlist/VLCPlayerController.m | 70 ++--------
2 files changed, 146 insertions(+), 73 deletions(-)
diff --git a/modules/gui/macosx/os-integration/VLCRemoteControlService.m b/modules/gui/macosx/os-integration/VLCRemoteControlService.m
index 2f9a613e6f..ac3c5524f0 100644
--- a/modules/gui/macosx/os-integration/VLCRemoteControlService.m
+++ b/modules/gui/macosx/os-integration/VLCRemoteControlService.m
@@ -28,6 +28,8 @@
#import "main/CompatibilityFixes.h"
#import "playlist/VLCPlaylistController.h"
#import "playlist/VLCPlayerController.h"
+#import "library/VLCInputItem.h"
+#import "extensions/NSString+Helpers.h"
#define kVLCSettingPlaybackForwardSkipLength @(60)
#define kVLCSettingPlaybackBackwardSkipLength @(60)
@@ -35,6 +37,13 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
+ at interface VLCRemoteControlService()
+{
+ VLCPlaylistController *_playlistController;
+ VLCPlayerController *_playerController;
+}
+ at end
+
@implementation VLCRemoteControlService
static inline NSArray * RemoteCommandCenterCommandsToHandle()
@@ -54,6 +63,118 @@ static inline NSArray * RemoteCommandCenterCommandsToHandle()
return [commands copy];
}
+- (instancetype)init
+{
+ self = [super init];
+ if (self) {
+ _playlistController = [[VLCMain sharedInstance] playlistController];
+ _playerController = [_playlistController playerController];
+
+ NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+ [notificationCenter addObserver:self
+ selector:@selector(playbackPositionUpdated:)
+ name:VLCPlayerTimeAndPositionChanged
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(metaDataChangedForCurrentMedia:)
+ name:VLCPlayerMetadataChangedForCurrentMedia
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(playbackRateChanged:)
+ name:VLCPlayerRateChanged
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(metaDataChangedForCurrentMedia:)
+ name:VLCPlaylistCurrentItemChanged
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(playbackStateChanged:)
+ name:VLCPlayerStateChanged
+ object:nil];
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)playbackStateChanged:(NSNotification *)aNotification
+{
+ enum vlc_player_state playerState = _playerController.playerState;
+ MPNowPlayingInfoCenter *nowPlayingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
+
+ switch (playerState) {
+ case VLC_PLAYER_STATE_PLAYING:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStatePlaying;
+ break;
+
+ case VLC_PLAYER_STATE_PAUSED:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStatePaused;
+ break;
+
+ case VLC_PLAYER_STATE_STOPPED:
+ case VLC_PLAYER_STATE_STOPPING:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStateStopped;
+ break;
+
+ default:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStateUnknown;
+ break;
+ }
+}
+
+- (void)playbackPositionUpdated:(NSNotification *)aNotification
+{
+ MPNowPlayingInfoCenter *nowPlayingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
+
+ NSMutableDictionary *currentlyPlayingTrackInfo = [nowPlayingInfoCenter.nowPlayingInfo mutableCopy];
+ [self setTimeInformationForDictionary:currentlyPlayingTrackInfo];
+
+ nowPlayingInfoCenter.nowPlayingInfo = currentlyPlayingTrackInfo;
+}
+
+- (void)playbackRateChanged:(NSNotification *)aNotification
+{
+ MPNowPlayingInfoCenter *nowPlayingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
+
+ NSMutableDictionary *currentlyPlayingTrackInfo = [nowPlayingInfoCenter.nowPlayingInfo mutableCopy];
+ [self setRateInformationForDictionary:currentlyPlayingTrackInfo];
+
+ nowPlayingInfoCenter.nowPlayingInfo = currentlyPlayingTrackInfo;
+}
+
+- (void)metaDataChangedForCurrentMedia:(NSNotification *)aNotification
+{
+ VLCInputItem *inputItem = _playerController.currentMedia;
+
+ NSMutableDictionary *currentlyPlayingTrackInfo = [NSMutableDictionary dictionary];
+ [self setTimeInformationForDictionary:currentlyPlayingTrackInfo];
+ [self setRateInformationForDictionary:currentlyPlayingTrackInfo];
+
+ currentlyPlayingTrackInfo[MPMediaItemPropertyTitle] = inputItem.title;
+ currentlyPlayingTrackInfo[MPMediaItemPropertyArtist] = inputItem.artist;
+ currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTitle] = inputItem.albumName;
+ currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTrackNumber] = @([inputItem.trackNumber intValue]);
+ currentlyPlayingTrackInfo[MPMediaItemPropertyPlaybackDuration] = @(SEC_FROM_VLC_TICK(inputItem.duration));
+
+ [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
+}
+
+- (void)setTimeInformationForDictionary:(NSMutableDictionary *)dictionary
+{
+ /* we don't set the duration here because this would add a dependency on the input item
+ * additionally, when duration changes, the metadata callback is triggered anyway */
+ dictionary[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(SEC_FROM_VLC_TICK([_playerController time]));
+ dictionary[MPNowPlayingInfoPropertyPlaybackProgress] = @([_playerController position]);
+}
+
+- (void)setRateInformationForDictionary:(NSMutableDictionary *)dictionary
+{
+ dictionary[MPNowPlayingInfoPropertyPlaybackRate] = @([_playerController playbackRate]);
+}
+
- (void)subscribeToRemoteCommands
{
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
@@ -89,41 +210,39 @@ static inline NSArray * RemoteCommandCenterCommandsToHandle()
- (MPRemoteCommandHandlerStatus )remoteCommandEvent:(MPRemoteCommandEvent *)event
{
MPRemoteCommandCenter *cc = [MPRemoteCommandCenter sharedCommandCenter];
- VLCPlaylistController *playlistController = [[VLCMain sharedInstance] playlistController];
- VLCPlayerController *playerController = [playlistController playerController];
if (event.command == cc.playCommand) {
- return [playlistController startPlaylist] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusNoActionableNowPlayingItem;
+ return [_playlistController startPlaylist] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusNoActionableNowPlayingItem;
}
if (event.command == cc.pauseCommand) {
- [playlistController pausePlayback];
+ [_playlistController pausePlayback];
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.stopCommand) {
- [playlistController stopPlayback];
+ [_playlistController stopPlayback];
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.togglePlayPauseCommand) {
- [playerController togglePlayPause];
+ [_playerController togglePlayPause];
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.nextTrackCommand) {
- return [playlistController playNextItem] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusCommandFailed;
+ return [_playlistController playNextItem] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusCommandFailed;
}
if (event.command == cc.previousTrackCommand) {
- return [playlistController playPreviousItem] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusCommandFailed;
+ return [_playlistController playPreviousItem] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusCommandFailed;
}
if (event.command == cc.skipForwardCommand) {
- [playerController jumpForwardMedium];
+ [_playerController jumpForwardMedium];
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.skipBackwardCommand) {
- [playerController jumpBackwardMedium];
+ [_playerController jumpBackwardMedium];
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.changePlaybackPositionCommand) {
MPChangePlaybackPositionCommandEvent *positionEvent = (MPChangePlaybackPositionCommandEvent *)event;
- [playerController setTimeFast:vlc_tick_from_sec( positionEvent.positionTime )];
+ [_playerController setTimeFast:vlc_tick_from_sec( positionEvent.positionTime )];
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.changeRepeatModeCommand) {
@@ -131,21 +250,21 @@ static inline NSArray * RemoteCommandCenterCommandsToHandle()
MPRepeatType repeatType = repeatEvent.repeatType;
switch (repeatType) {
case MPRepeatTypeAll:
- [playlistController setPlaybackRepeat:VLC_PLAYLIST_PLAYBACK_REPEAT_ALL];
+ [_playlistController setPlaybackRepeat:VLC_PLAYLIST_PLAYBACK_REPEAT_ALL];
break;
case MPRepeatTypeOne:
- [playlistController setPlaybackRepeat:VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT];
+ [_playlistController setPlaybackRepeat:VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT];
break;
default:
- [playlistController setPlaybackRepeat:VLC_PLAYLIST_PLAYBACK_REPEAT_NONE];;
+ [_playlistController setPlaybackRepeat:VLC_PLAYLIST_PLAYBACK_REPEAT_NONE];;
break;
}
return MPRemoteCommandHandlerStatusSuccess;
}
if (event.command == cc.changeShuffleModeCommand) {
- [playlistController setPlaybackOrder:[playlistController playbackOrder] == VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL ? VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM : VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL];
+ [_playlistController setPlaybackOrder:[_playlistController playbackOrder] == VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL ? VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM : VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL];
return MPRemoteCommandHandlerStatusSuccess;
}
diff --git a/modules/gui/macosx/playlist/VLCPlayerController.m b/modules/gui/macosx/playlist/VLCPlayerController.m
index f9cf0c6854..5d98c3cc3b 100644
--- a/modules/gui/macosx/playlist/VLCPlayerController.m
+++ b/modules/gui/macosx/playlist/VLCPlayerController.m
@@ -34,8 +34,6 @@
#import "windows/video/VLCVoutView.h"
#import "windows/video/VLCVideoWindowCommon.h"
-#import <MediaPlayer/MediaPlayer.h>
-
NSString *VLCPlayerElementaryStreamID = @"VLCPlayerElementaryStreamID";
NSString *VLCTick = @"VLCTick";
NSString *VLCPlayerCurrentMediaItemChanged = @"VLCPlayerCurrentMediaItemChanged";
@@ -585,6 +583,10 @@ static int BossCallback(vlc_object_t *p_this,
selector:@selector(applicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:nil];
+ [_defaultNotificationCenter addObserver:self
+ selector:@selector(applicationDidFinishLaunching:)
+ name:NSApplicationDidFinishLaunchingNotification
+ object:nil];
_position = -1.f;
_time = VLC_TICK_INVALID;
_p_player = player;
@@ -603,16 +605,19 @@ static int BossCallback(vlc_object_t *p_this,
libvlc_int_t *libvlc = vlc_object_instance(getIntf());
var_AddCallback(libvlc, "intf-boss", BossCallback, (__bridge void *)self);
-
- if (@available(macOS 10.12.2, *)) {
- _remoteControlService = [[VLCRemoteControlService alloc] init];
- [_remoteControlService subscribeToRemoteCommands];
- }
}
return self;
}
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ if (@available(macOS 10.12.2, *)) {
+ _remoteControlService = [[VLCRemoteControlService alloc] init];
+ [_remoteControlService subscribeToRemoteCommands];
+ }
+}
+
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
libvlc_int_t *libvlc = vlc_object_instance(getIntf());
@@ -709,36 +714,6 @@ static int BossCallback(vlc_object_t *p_this,
- (void)metaDataChangedForInput:(input_item_t *)inputItem
{
- if (@available(macOS 10.12.2, *)) {
- NSMutableDictionary *currentlyPlayingTrackInfo = [NSMutableDictionary dictionary];
-
- currentlyPlayingTrackInfo[MPMediaItemPropertyPlaybackDuration] = @(SEC_FROM_VLC_TICK(input_item_GetDuration(inputItem)));
- currentlyPlayingTrackInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(SEC_FROM_VLC_TICK([self time]));
- currentlyPlayingTrackInfo[MPNowPlayingInfoPropertyPlaybackRate] = @([self playbackRate]);
-
- char *psz_title = input_item_GetTitle(inputItem);
- if (!psz_title)
- psz_title = input_item_GetName(inputItem);
- currentlyPlayingTrackInfo[MPMediaItemPropertyTitle] = toNSStr(psz_title);
- FREENULL(psz_title);
-
- char *psz_artist = input_item_GetArtist(inputItem);
- currentlyPlayingTrackInfo[MPMediaItemPropertyArtist] = toNSStr(psz_artist);
- FREENULL(psz_artist);
-
- char *psz_album = input_item_GetAlbum(inputItem);
- currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTitle] = toNSStr(psz_album);
- FREENULL(psz_album);
-
- char *psz_track_number = input_item_GetTrackNumber(inputItem);
- currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTrackNumber] = @([toNSStr(psz_track_number) intValue]);
- FREENULL(psz_track_number);
-
- [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
- }
-
- input_item_Release(inputItem);
-
[_defaultNotificationCenter postNotificationName:VLCPlayerMetadataChangedForCurrentMedia
object:self];
}
@@ -835,27 +810,6 @@ static int BossCallback(vlc_object_t *p_this,
[_defaultNotificationCenter postNotificationName:VLCPlayerStateChanged
object:self];
- if (@available(macOS 10.12.2, *)) {
- switch (_playerState) {
- case VLC_PLAYER_STATE_PLAYING:
- [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStatePlaying;
- break;
-
- case VLC_PLAYER_STATE_PAUSED:
- [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStatePaused;
- break;
-
- case VLC_PLAYER_STATE_STOPPED:
- case VLC_PLAYER_STATE_STOPPING:
- [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStateStopped;
- break;
-
- default:
- [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStateUnknown;
- break;
- }
- }
-
/* notify third party apps through an informal protocol that our state changed */
[[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"VLCPlayerStateDidChange"
object:nil
More information about the vlc-commits
mailing list