[vlc-commits] macosx: add remote control service and export now playing metadata
Felix Paul Kühne
git at videolan.org
Fri Jun 8 20:15:04 CEST 2018
vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Sun Apr 22 12:49:03 2018 +0200| [64a43503534ffc895f1788a6b1c9fbecb2ad8491] | committer: Felix Paul Kühne
macosx: add remote control service and export now playing metadata
Fixes #17727
Note that out-of-rate position changes within VLC are not yet communicated to the OS
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=64a43503534ffc895f1788a6b1c9fbecb2ad8491
---
.../package/macosx/VLC.xcodeproj/project.pbxproj | 10 +-
modules/gui/macosx/CompatibilityFixes.h | 52 +++++++-
modules/gui/macosx/Makefile.am | 3 +-
modules/gui/macosx/VLCCoreInteraction.h | 4 +-
modules/gui/macosx/VLCCoreInteraction.m | 19 ++-
modules/gui/macosx/VLCInputManager.m | 74 ++++++++++-
modules/gui/macosx/VLCRemoteControlService.h | 32 +++++
modules/gui/macosx/VLCRemoteControlService.m | 147 +++++++++++++++++++++
modules/gui/macosx/misc.m | 2 +-
9 files changed, 331 insertions(+), 12 deletions(-)
diff --git a/extras/package/macosx/VLC.xcodeproj/project.pbxproj b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
index 3e5aa4963a..60e4f00d37 100644
--- a/extras/package/macosx/VLC.xcodeproj/project.pbxproj
+++ b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
@@ -120,6 +120,7 @@
6BF56C3E1FCF00AF004A411A /* audiotoolbox_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BF56C3D1FCF00AF004A411A /* audiotoolbox_midi.c */; };
6BF5C5041EFE66EF008A9C12 /* VLCHUDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5C5031EFE66EF008A9C12 /* VLCHUDTableView.m */; };
6BF5C5071EFE7E58008A9C12 /* VLCTintedImageButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5C5061EFE7E58008A9C12 /* VLCTintedImageButtonCell.m */; };
+ 7DD2F5C52081B73B007EE187 /* VLCRemoteControlService.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DD2F5C42081B73B007EE187 /* VLCRemoteControlService.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -485,6 +486,8 @@
7DB65D5218ABD6380053B874 /* VLCAddonsWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCAddonsWindowController.h; sourceTree = "<group>"; };
7DB65D5318ABD6380053B874 /* VLCAddonsWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCAddonsWindowController.m; sourceTree = "<group>"; };
7DBB06631CC2314D004C74D2 /* caopengllayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = caopengllayer.m; path = ../../../modules/video_output/caopengllayer.m; sourceTree = "<group>"; };
+ 7DD2F5C32081B73B007EE187 /* VLCRemoteControlService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCRemoteControlService.h; sourceTree = "<group>"; };
+ 7DD2F5C42081B73B007EE187 /* VLCRemoteControlService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCRemoteControlService.m; sourceTree = "<group>"; };
7DF0435E1972E26A0022B534 /* VLCAddonListItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCAddonListItem.h; sourceTree = "<group>"; };
7DF0435F1972E26A0022B534 /* VLCAddonListItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCAddonListItem.m; sourceTree = "<group>"; };
7DF812ED1B555A340052293C /* VLCInputManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCInputManager.h; sourceTree = "<group>"; };
@@ -689,6 +692,8 @@
7D871D391B5E684D000B56C0 /* helpers.h */,
7DF812ED1B555A340052293C /* VLCInputManager.h */,
7DF812EE1B555A340052293C /* VLCInputManager.m */,
+ 7DD2F5C32081B73B007EE187 /* VLCRemoteControlService.h */,
+ 7DD2F5C42081B73B007EE187 /* VLCRemoteControlService.m */,
7D871D371B5E6844000B56C0 /* VLCMain+OldPrefs.h */,
7D871D381B5E6844000B56C0 /* VLCMain+OldPrefs.m */,
8ED6C27C03E2EB1C0059A3A7 /* VLCMain.h */,
@@ -1309,7 +1314,7 @@
};
};
};
- buildConfigurationList = C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "vlc" */;
+ buildConfigurationList = C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "VLC" */;
compatibilityVersion = "Xcode 6.3";
developmentRegion = English;
hasScannedForEncodings = 1;
@@ -1395,6 +1400,7 @@
6BF5C5041EFE66EF008A9C12 /* VLCHUDTableView.m in Sources */,
6BBB05E01EEFF165003A1019 /* VLCHUDTableCornerView.m in Sources */,
1C31139D1E508C6900D4DD76 /* VLCControlsBarCommon.m in Sources */,
+ 7DD2F5C52081B73B007EE187 /* VLCRemoteControlService.m in Sources */,
1C31139F1E508C6900D4DD76 /* VLCMainWindowControlsBar.m in Sources */,
1C3113A11E508C6900D4DD76 /* VLCConvertAndSaveWindowController.m in Sources */,
1C3113A31E508C6900D4DD76 /* VLCCoreDialogProvider.m in Sources */,
@@ -1657,7 +1663,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
- C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "vlc" */ = {
+ C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "VLC" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2F2A6EB09588F1B00018C74 /* Development */,
diff --git a/modules/gui/macosx/CompatibilityFixes.h b/modules/gui/macosx/CompatibilityFixes.h
index 069aefd8d7..3a52279975 100644
--- a/modules/gui/macosx/CompatibilityFixes.h
+++ b/modules/gui/macosx/CompatibilityFixes.h
@@ -1,7 +1,7 @@
/*****************************************************************************
* CompatibilityFixes.h: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2011-2017 VLC authors and VideoLAN
+ * Copyright (C) 2011-2018 VLC authors and VideoLAN
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
@@ -32,9 +32,9 @@
#define OSX_YOSEMITE_AND_HIGHER (NSAppKitVersionNumber >= 1334)
#define OSX_EL_CAPITAN_AND_HIGHER (NSAppKitVersionNumber >= 1404)
#define OSX_SIERRA_AND_HIGHER (NSAppKitVersionNumber >= 1485)
+#define OSX_SIERRA_DOT_TWO_AND_HIGHER (NSAppKitVersionNumber >= 1504.76) // this is needed to check for MPRemoteCommandCenter
#define OSX_HIGH_SIERRA_AND_HIGHER (NSAppKitVersionNumber >= 1560)
-
// Sierra only APIs
#ifndef MAC_OS_X_VERSION_10_12
@@ -56,5 +56,51 @@ typedef NSUInteger NSWindowStyleMask;
#endif
-void swapoutOverride(Class _Nonnull cls, SEL _Nonnull selector);
+#ifndef MAC_OS_X_VERSION_10_12_2
+
+typedef NS_ENUM(NSUInteger, MPNowPlayingInfoMediaType) {
+ MPNowPlayingInfoMediaTypeNone = 0,
+ MPNowPlayingInfoMediaTypeAudio,
+ MPNowPlayingInfoMediaTypeVideo,
+};
+
+typedef NS_ENUM(NSUInteger, MPNowPlayingPlaybackState) {
+ MPNowPlayingPlaybackStateUnknown = 0,
+ MPNowPlayingPlaybackStatePlaying,
+ MPNowPlayingPlaybackStatePaused,
+ MPNowPlayingPlaybackStateStopped,
+ MPNowPlayingPlaybackStateInterrupted
+};
+
+NSString * const MPNowPlayingInfoPropertyElapsedPlaybackTime;
+NSString * const MPNowPlayingInfoPropertyPlaybackRate;
+NSString * const MPNowPlayingInfoPropertyDefaultPlaybackRate;
+NSString * const MPNowPlayingInfoPropertyPlaybackQueueIndex;
+NSString * const MPNowPlayingInfoPropertyPlaybackQueueCount;
+NSString * const MPNowPlayingInfoPropertyChapterNumber;
+NSString * const MPNowPlayingInfoPropertyChapterCount
+NSString * const MPNowPlayingInfoPropertyIsLiveStream;
+NSString * const MPNowPlayingInfoPropertyAvailableLanguageOptions;
+NSString * const MPNowPlayingInfoPropertyCurrentLanguageOptions;
+NSString * const MPNowPlayingInfoCollectionIdentifier;
+NSString * const MPNowPlayingInfoPropertyExternalContentIdentifier;
+NSString * const MPNowPlayingInfoPropertyExternalUserProfileIdentifier
+NSString * const MPNowPlayingInfoPropertyServiceIdentifier;
+NSString * const MPNowPlayingInfoPropertyPlaybackProgress
+NSString * const MPNowPlayingInfoPropertyMediaType
+NSString * const MPNowPlayingInfoPropertyAssetURL;
+NSString * const MPNowPlayingInfoPropertyCurrentPlaybackDate;
+ at interface MPNowPlayingInfoCenter : NSObject
++ (MPNowPlayingInfoCenter *)defaultCenter;
++ (instancetype)new NS_UNAVAILABLE;
+- (instancetype)init NS_UNAVAILABLE;
+
+ at property (nonatomic, copy, nullable) NSDictionary<NSString *, id> *nowPlayingInfo;
+ at property (nonatomic) MPNowPlayingPlaybackState playbackState MP_API(macos(10.12.2));
+
+ at end
+
+#endif
+
+void swapoutOverride(Class _Nonnull cls, SEL _Nonnull selector);
diff --git a/modules/gui/macosx/Makefile.am b/modules/gui/macosx/Makefile.am
index b85af0db4e..27955bb3c7 100644
--- a/modules/gui/macosx/Makefile.am
+++ b/modules/gui/macosx/Makefile.am
@@ -6,7 +6,7 @@ libmacosx_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(guidir)' \
-Wl,-framework,AVFoundation -Wl,-framework,CoreMedia -Wl,-framework,IOKit \
-Wl,-framework,AddressBook -Wl,-framework,WebKit -Wl,-framework,CoreAudio \
-Wl,-framework,SystemConfiguration -Wl,-framework,ScriptingBridge \
- -Wl,-framework,QuartzCore
+ -Wl,-framework,QuartzCore -Wl,-framework,MediaPlayer
if HAVE_SPARKLE
libmacosx_plugin_la_LDFLAGS += -Wl,-framework,Sparkle
@@ -78,6 +78,7 @@ libmacosx_plugin_la_SOURCES = \
gui/macosx/VLCHUDTableView.h gui/macosx/VLCHUDTableView.m \
gui/macosx/VLCHUDTableCornerView.h gui/macosx/VLCHUDTableCornerView.m \
gui/macosx/VLCInputManager.h gui/macosx/VLCInputManager.m \
+ gui/macosx/VLCRemoteControlService.h gui/macosx/VLCRemoteControlService.m \
gui/macosx/VLCMainWindow.h gui/macosx/VLCMainWindow.m \
gui/macosx/VLCRendererDiscovery.h gui/macosx/VLCRendererDiscovery.m \
gui/macosx/VLCRendererItem.h gui/macosx/VLCRendererItem.m \
diff --git a/modules/gui/macosx/VLCCoreInteraction.h b/modules/gui/macosx/VLCCoreInteraction.h
index 6d49c9a9e2..3616c181c5 100644
--- a/modules/gui/macosx/VLCCoreInteraction.h
+++ b/modules/gui/macosx/VLCCoreInteraction.h
@@ -1,7 +1,7 @@
/*****************************************************************************
* CoreInteraction.h: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2011-2015 Felix Paul Kühne
+ * Copyright (C) 2011-2018 Felix Paul Kühne
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
@@ -36,6 +36,7 @@
@property (readonly) NSString * nameOfCurrentPlaylistItem;
@property (nonatomic, readwrite) BOOL mute;
+- (void)play;
- (void)playOrPause;
- (void)pause;
- (void)stop;
@@ -55,6 +56,7 @@
- (void)backwardMedium;
- (void)forwardLong;
- (void)backwardLong;
+- (void)jumpToTime:(mtime_t)time;
- (void)repeatOne;
- (void)repeatAll;
diff --git a/modules/gui/macosx/VLCCoreInteraction.m b/modules/gui/macosx/VLCCoreInteraction.m
index 1f13283938..220a19fb8b 100644
--- a/modules/gui/macosx/VLCCoreInteraction.m
+++ b/modules/gui/macosx/VLCCoreInteraction.m
@@ -1,7 +1,7 @@
/*****************************************************************************
* CoreInteraction.m: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2011-2015 Felix Paul Kühne
+ * Copyright (C) 2011-2018 Felix Paul Kühne
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
@@ -129,6 +129,13 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
#pragma mark - Playback Controls
+- (void)play
+{
+ playlist_t *p_playlist = pl_Get(getIntf());
+
+ playlist_Play(p_playlist);
+}
+
- (void)playOrPause
{
input_thread_t *p_input = pl_CurrentInput(getIntf());
@@ -532,6 +539,16 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
}
}
+- (void)jumpToTime:(mtime_t)time
+{
+ input_thread_t * p_input = pl_CurrentInput(getIntf());
+ if (p_input) {
+ mtime_t currentTime = var_GetInteger(p_input, "time");
+ var_SetInteger(p_input, "time", time);
+ vlc_object_release(p_input);
+ }
+}
+
- (void)volumeUp
{
intf_thread_t *p_intf = getIntf();
diff --git a/modules/gui/macosx/VLCInputManager.m b/modules/gui/macosx/VLCInputManager.m
index 69d746c71c..db8d9a3008 100644
--- a/modules/gui/macosx/VLCInputManager.m
+++ b/modules/gui/macosx/VLCInputManager.m
@@ -1,7 +1,7 @@
/*****************************************************************************
* VLCInputManager.m: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2015 VLC authors and VideoLAN
+ * Copyright (C) 2015-2018 VLC authors and VideoLAN
* $Id$
*
* This program is free software; you can redistribute it and/or modify
@@ -34,10 +34,13 @@
#import "VLCResumeDialogController.h"
#import "VLCTrackSynchronizationWindowController.h"
#import "VLCVoutView.h"
+#import "VLCRemoteControlService.h"
#import "iTunes.h"
#import "Spotify.h"
+#import <MediaPlayer/MediaPlayer.h>
+
#pragma mark Callbacks
static int InputThreadChanged(vlc_object_t *p_this, const char *psz_var,
@@ -155,6 +158,9 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
BOOL b_has_itunes_paused;
BOOL b_has_spotify_paused;
+ /* remote control support */
+ VLCRemoteControlService *_remoteControlService;
+
NSTimer *hasEndedTimer;
}
@end
@@ -182,6 +188,8 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
informInputChangedQueue = dispatch_queue_create("org.videolan.vlc.inputChangedQueue", DISPATCH_QUEUE_SERIAL);
+ _remoteControlService = [[VLCRemoteControlService alloc] init];
+ [_remoteControlService subscribeToRemoteCommands];
}
return self;
}
@@ -196,6 +204,8 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
- (void)deinit
{
msg_Dbg(getIntf(), "Deinitializing input manager");
+ [_remoteControlService unsubscribeFromRemoteCommands];
+
if (p_current_input) {
/* continue playback where you left off */
[self storePlaybackPositionForItem:p_current_input];
@@ -283,7 +293,6 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
return;
}
- intf_thread_t *p_intf = getIntf();
int state = -1;
if (p_current_input) {
state = var_GetInteger(p_current_input, "state");
@@ -304,14 +313,29 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
[[o_main mainMenu] setPause];
[[o_main mainWindow] setPause];
+
+ if (OSX_SIERRA_DOT_TWO_AND_HIGHER) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+ [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStatePlaying;
+#pragma clang diagnostic pop
+ }
} else {
[[o_main mainMenu] setSubmenusEnabled: FALSE];
[[o_main mainMenu] setPlay];
[[o_main mainWindow] setPlay];
- if (state == PAUSE_S)
+ if (state == PAUSE_S) {
[self releaseSleepBlockers];
+ if (OSX_SIERRA_DOT_TWO_AND_HIGHER) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+ [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStatePaused;
+#pragma clang diagnostic pop
+ }
+ }
+
if (state == END_S || state == -1) {
/* continue playback where you left off */
if (p_current_input)
@@ -325,6 +349,13 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
selector: @selector(onPlaybackHasEnded:)
userInfo: nil
repeats: NO];
+
+ if (OSX_SIERRA_DOT_TWO_AND_HIGHER) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+ [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStateStopped;
+#pragma clang diagnostic pop
+ }
}
}
@@ -490,6 +521,43 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
[[[o_main playlist] model] updateItem:p_input_item];
[[[VLCMain sharedInstance] currentMediaInfoPanel] updatePanelWithItem:p_input_item];
+
+ if (!OSX_SIERRA_DOT_TWO_AND_HIGHER) {
+ return;
+ }
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+ if (!p_input_item) {
+ return;
+ }
+
+ NSMutableDictionary *currentlyPlayingTrackInfo = [NSMutableDictionary dictionary];
+
+ currentlyPlayingTrackInfo[MPMediaItemPropertyPlaybackDuration] = @(input_item_GetDuration(p_input_item) / CLOCK_FREQ);
+ currentlyPlayingTrackInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(var_GetInteger(p_current_input, "time"));
+ currentlyPlayingTrackInfo[MPNowPlayingInfoPropertyPlaybackRate] = @(var_GetFloat(p_current_input, "rate"));
+
+ char *psz_title = input_item_GetTitle(p_input_item);
+ if (!psz_title)
+ psz_title = input_item_GetName(p_input_item);
+ currentlyPlayingTrackInfo[MPMediaItemPropertyTitle] = toNSStr(psz_title);
+ FREENULL(psz_title);
+
+ char *psz_artist = input_item_GetArtist(p_input_item);
+ currentlyPlayingTrackInfo[MPMediaItemPropertyArtist] = toNSStr(psz_artist);
+ FREENULL(psz_artist);
+
+ char *psz_album = input_item_GetAlbum(p_input_item);
+ currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTitle] = toNSStr(psz_album);
+ FREENULL(psz_album);
+
+ char *psz_track_number = input_item_GetTrackNumber(p_input_item);
+ currentlyPlayingTrackInfo[MPMediaItemPropertyAlbumTrackNumber] = toNSStr(psz_track_number);
+ FREENULL(psz_track_number);
+
+ [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
+#pragma clang diagnostic pop
}
- (void)updateMainWindow
diff --git a/modules/gui/macosx/VLCRemoteControlService.h b/modules/gui/macosx/VLCRemoteControlService.h
new file mode 100644
index 0000000000..3d9a1f3679
--- /dev/null
+++ b/modules/gui/macosx/VLCRemoteControlService.h
@@ -0,0 +1,32 @@
+/*****************************************************************************
+ * VLCRemoteControlService.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2017, 2018 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Carola Nitz <nitz.carola # gmail.com>
+ * Felix Paul Kühne <fkuehne # videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+ at interface VLCRemoteControlService : NSObject
+
+- (void)subscribeToRemoteCommands;
+- (void)unsubscribeFromRemoteCommands;
+
+ at end
diff --git a/modules/gui/macosx/VLCRemoteControlService.m b/modules/gui/macosx/VLCRemoteControlService.m
new file mode 100644
index 0000000000..8c1237fe52
--- /dev/null
+++ b/modules/gui/macosx/VLCRemoteControlService.m
@@ -0,0 +1,147 @@
+/*****************************************************************************
+ * VLCRemoteControlService.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2017, 2018 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Carola Nitz <nitz.carola # gmail.com>
+ * Felix Paul Kühne <fkuehne # videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "VLCRemoteControlService.h"
+#import "VLCCoreInteraction.h"
+#import "VLCMain.h"
+#import <MediaPlayer/MediaPlayer.h>
+#import "CompatibilityFixes.h"
+
+#define kVLCSettingPlaybackForwardSkipLength @(60)
+#define kVLCSettingPlaybackBackwardSkipLength @(60)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+
+ at implementation VLCRemoteControlService
+
+static inline NSArray * RemoteCommandCenterCommandsToHandle()
+{
+ MPRemoteCommandCenter *cc = [MPRemoteCommandCenter sharedCommandCenter];
+ NSMutableArray *commands = [NSMutableArray arrayWithObjects:
+ cc.playCommand,
+ cc.pauseCommand,
+ cc.stopCommand,
+ cc.togglePlayPauseCommand,
+ cc.nextTrackCommand,
+ cc.previousTrackCommand,
+ cc.skipForwardCommand,
+ cc.skipBackwardCommand,
+ cc.changePlaybackPositionCommand,
+ nil];
+ return [commands copy];
+}
+
+- (void)subscribeToRemoteCommands
+{
+ if (!OSX_SIERRA_DOT_TWO_AND_HIGHER) {
+ return;
+ }
+
+ MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
+
+ //Enable when you want to support these
+ commandCenter.ratingCommand.enabled = NO;
+ commandCenter.likeCommand.enabled = NO;
+ commandCenter.dislikeCommand.enabled = NO;
+ commandCenter.bookmarkCommand.enabled = NO;
+ commandCenter.enableLanguageOptionCommand.enabled = NO;
+ commandCenter.disableLanguageOptionCommand.enabled = NO;
+ commandCenter.changeRepeatModeCommand.enabled = NO;
+ commandCenter.changeShuffleModeCommand.enabled = NO;
+ commandCenter.seekForwardCommand.enabled = NO;
+ commandCenter.seekBackwardCommand.enabled = NO;
+
+ commandCenter.skipForwardCommand.preferredIntervals = @[kVLCSettingPlaybackForwardSkipLength];
+ commandCenter.skipBackwardCommand.preferredIntervals = @[kVLCSettingPlaybackBackwardSkipLength];
+
+ for (MPRemoteCommand *command in RemoteCommandCenterCommandsToHandle()) {
+ [command addTarget:self action:@selector(remoteCommandEvent:)];
+ }
+}
+
+- (void)unsubscribeFromRemoteCommands
+{
+ if (!OSX_SIERRA_DOT_TWO_AND_HIGHER) {
+ return;
+ }
+
+ [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nil;
+
+ for (MPRemoteCommand *command in RemoteCommandCenterCommandsToHandle()) {
+ [command removeTarget:self];
+ }
+}
+
+- (MPRemoteCommandHandlerStatus )remoteCommandEvent:(MPRemoteCommandEvent *)event
+{
+ MPRemoteCommandCenter *cc = [MPRemoteCommandCenter sharedCommandCenter];
+ VLCCoreInteraction *coreInteraction = [VLCCoreInteraction sharedInstance];
+
+ if (event.command == cc.playCommand) {
+ [coreInteraction play];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.pauseCommand) {
+ [coreInteraction pause];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.stopCommand) {
+ [coreInteraction stop];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.togglePlayPauseCommand) {
+ [coreInteraction playOrPause];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.nextTrackCommand) {
+ [coreInteraction next];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.previousTrackCommand) {
+ [coreInteraction previous];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.skipForwardCommand) {
+ [coreInteraction forwardMedium];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.skipBackwardCommand) {
+ [coreInteraction backwardMedium];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.changePlaybackPositionCommand) {
+ MPChangePlaybackPositionCommandEvent *positionEvent = (MPChangePlaybackPositionCommandEvent *)event;
+ [coreInteraction jumpToTime:positionEvent.positionTime * CLOCK_FREQ];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+
+ NSAssert(NO, @"remote control event not handled");
+ msg_Dbg(getIntf(), "%s Wasn't able to handle remote control event: %s",__PRETTY_FUNCTION__,[event.description UTF8String]);
+ return MPRemoteCommandHandlerStatusCommandFailed;
+}
+
+ at end
+
+#pragma clang diagnostic pop
diff --git a/modules/gui/macosx/misc.m b/modules/gui/macosx/misc.m
index acffad80bb..ac80878619 100644
--- a/modules/gui/macosx/misc.m
+++ b/modules/gui/macosx/misc.m
@@ -24,11 +24,11 @@
#import "CompatibilityFixes.h"
#import "misc.h"
-#import "VLCMain.h" /* VLCApplication */
#import "VLCMainWindow.h"
#import "VLCMainMenu.h"
#import "VLCControlsBarCommon.h"
#import "VLCCoreInteraction.h"
+#import "VLCStringUtility.h"
#import <vlc_actions.h>
/*****************************************************************************
More information about the vlc-commits
mailing list