[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