[vlc-commits] [Git][videolan/vlc][3.0.x] 3 commits: macosx: add support for the Touch Bar in current MacBooks
Jean-Baptiste Kempf
gitlab at videolan.org
Tue Jun 15 14:07:06 UTC 2021
Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC
Commits:
b5b55004 by Felix Paul Kühne at 2021-06-15T12:24:09+00:00
macosx: add support for the Touch Bar in current MacBooks
This implements playback control via touch bar and the activity widgets.
It also exposes related playback meta data. It is a manual backport of
the respective code on the master branch and fixes #25744.
- - - - -
8fd31abc by Felix Paul Kühne at 2021-06-15T12:24:09+00:00
macosx: do not try to seek unseekable content
Previously, external apps such as the Touchbar and AppleScript bindings
could attempt to seek non-seekable content leading to persistent silence
until playback was restarted.
- - - - -
d9de9c3e by Felix Paul Kühne at 2021-06-15T12:24:09+00:00
macosx: disable SPMediaKeyTap on macOS Sierra and later
On later releases, we will use the public API.
- - - - -
8 changed files:
- extras/package/macosx/vlc.xcodeproj/project.pbxproj
- modules/gui/macosx/Makefile.am
- modules/gui/macosx/VLCCoreInteraction.h
- modules/gui/macosx/VLCCoreInteraction.m
- modules/gui/macosx/VLCInputManager.h
- modules/gui/macosx/VLCInputManager.m
- + modules/gui/macosx/VLCRemoteControlService.h
- + modules/gui/macosx/VLCRemoteControlService.m
Changes:
=====================================
extras/package/macosx/vlc.xcodeproj/project.pbxproj
=====================================
@@ -106,6 +106,7 @@
6BF5C5011EFE03CF008A9C12 /* VLCHUDStepperCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5C5001EFE03CF008A9C12 /* VLCHUDStepperCell.m */; };
6BF5C5041EFE66EF008A9C12 /* VLCHUDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5C5031EFE66EF008A9C12 /* VLCHUDTableView.m */; };
6BF5C5071EFE7E58008A9C12 /* VLCTintedImageButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5C5061EFE7E58008A9C12 /* VLCTintedImageButtonCell.m */; };
+ 7D51CC072675FEF100EE18C2 /* VLCRemoteControlService.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D51CC062675FEF100EE18C2 /* VLCRemoteControlService.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -681,6 +682,8 @@
6BF5C5031EFE66EF008A9C12 /* VLCHUDTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCHUDTableView.m; sourceTree = "<group>"; };
6BF5C5051EFE7E58008A9C12 /* VLCTintedImageButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCTintedImageButtonCell.h; sourceTree = "<group>"; };
6BF5C5061EFE7E58008A9C12 /* VLCTintedImageButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCTintedImageButtonCell.m; sourceTree = "<group>"; };
+ 7D51CC052675FEF100EE18C2 /* VLCRemoteControlService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCRemoteControlService.h; sourceTree = "<group>"; };
+ 7D51CC062675FEF100EE18C2 /* VLCRemoteControlService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCRemoteControlService.m; sourceTree = "<group>"; };
7D5678EB1D5BA1DC002698F3 /* VLCApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCApplication.h; sourceTree = "<group>"; };
7D5678EC1D5BA1DC002698F3 /* VLCApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCApplication.m; sourceTree = "<group>"; };
7D5678EE1D5BA397002698F3 /* VLCMainWindowControlsBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCMainWindowControlsBar.h; sourceTree = "<group>"; };
@@ -931,6 +934,8 @@
7DF812F41B5599E40052293C /* VLCPLModel.m */,
1C7CB91A1D787E7600388902 /* VLCPopupPanelController.h */,
1C7CB91B1D787E7600388902 /* VLCPopupPanelController.m */,
+ 7D51CC052675FEF100EE18C2 /* VLCRemoteControlService.h */,
+ 7D51CC062675FEF100EE18C2 /* VLCRemoteControlService.m */,
633121CA1B51122700E636DA /* VLCResumeDialogController.h */,
633121CB1B51122700E636DA /* VLCResumeDialogController.m */,
6B13E2A61BC67678001AD24A /* VLCScrollingClipView.h */,
@@ -1822,6 +1827,7 @@
1C3113A71E508C6900D4DD76 /* VLCLogWindowController.m in Sources */,
6BF5C5071EFE7E58008A9C12 /* VLCTintedImageButtonCell.m in Sources */,
1C3113A91E508C6900D4DD76 /* VLCDocumentController.m in Sources */,
+ 7D51CC072675FEF100EE18C2 /* VLCRemoteControlService.m in Sources */,
1C3113AB1E508C6900D4DD76 /* VLCExtensionsDialogProvider.m in Sources */,
1C3113AD1E508C6900D4DD76 /* VLCExtensionsManager.m in Sources */,
1C3113AF1E508C6900D4DD76 /* VLCFSPanelController.m in Sources */,
=====================================
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,-weak_framework,MediaPlayer
if HAVE_SPARKLE
libmacosx_plugin_la_LDFLAGS += -Wl,-framework,Sparkle
@@ -106,7 +106,8 @@ libmacosx_plugin_la_SOURCES = \
gui/macosx/VLCSliderCell.h gui/macosx/VLCSliderCell.m \
gui/macosx/VLCVolumeSlider.h gui/macosx/VLCVolumeSlider.m \
gui/macosx/VLCVolumeSliderCell.h gui/macosx/VLCVolumeSliderCell.m \
- gui/macosx/VLCWrappableTextField.h gui/macosx/VLCWrappableTextField.m
+ gui/macosx/VLCWrappableTextField.h gui/macosx/VLCWrappableTextField.m \
+ gui/macosx/VLCRemoteControlService.h gui/macosx/VLCRemoteControlService.m
# PXSourceList sources
libmacosx_plugin_la_SOURCES += \
=====================================
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-2021 Felix Paul Kühne
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
@@ -30,13 +30,17 @@
@property (readwrite) int volume;
@property (readonly, nonatomic) float maxVolume;
@property (readwrite) int playbackRate;
+ at property (readonly) float internalPlaybackRate;
@property (nonatomic, readwrite) BOOL aspectRatioIsLocked;
@property (readonly) int durationOfCurrentPlaylistItem;
@property (readonly) NSURL * URLOfCurrentPlaylistItem;
@property (readonly) NSString * nameOfCurrentPlaylistItem;
@property (nonatomic, readwrite) BOOL mute;
+ at property (readonly) float currentPlaybackPosition;
+ at property (readonly) long long currentPlaybackTimeInSeconds;
- (void)playOrPause;
+- (void)play;
- (void)pause;
- (void)stop;
- (void)faster;
@@ -55,6 +59,7 @@
- (void)backwardMedium;
- (void)forwardLong;
- (void)backwardLong;
+- (BOOL)seekToTime:(mtime_t)time;
- (void)repeatOne;
- (void)repeatAll;
=====================================
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-2021 Felix Paul Kühne
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
@@ -40,6 +40,7 @@
#import "SPMediaKeyTap.h"
#import "AppleRemote.h"
#import "VLCInputManager.h"
+#import "CompatibilityFixes.h"
#import "NSSound+VLCAdditions.h"
@@ -98,15 +99,18 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
if (self) {
intf_thread_t *p_intf = getIntf();
- /* init media key support */
- b_mediaKeySupport = var_InheritBool(p_intf, "macosx-mediakeys");
- if (b_mediaKeySupport) {
- _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
+ /* init media key support on earlier macOS versions
+ * this feature is covered by VLCRemoteControlService in later releases */
+ if (!OSX_SIERRA_AND_HIGHER) {
+ b_mediaKeySupport = var_InheritBool(p_intf, "macosx-mediakeys");
+ if (b_mediaKeySupport) {
+ _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
+ }
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(coreChangedMediaKeySupportSetting:)
+ name:VLCMediaKeySupportSettingChangedNotification
+ object:nil];
}
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(coreChangedMediaKeySupportSetting:)
- name:VLCMediaKeySupportSettingChangedNotification
- object:nil];
/* init Apple Remote support */
_remote = [[AppleRemote alloc] init];
@@ -128,6 +132,12 @@ 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());
@@ -230,6 +240,19 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
return returnValue;
}
+- (float)internalPlaybackRate
+{
+ input_thread_t *p_input_thread = pl_CurrentInput(getIntf());
+ float rate = 0.;
+
+ if (p_input_thread) {
+ rate = var_GetFloat(p_input_thread, "rate");
+ vlc_object_release(p_input_thread);
+ }
+
+ return rate;
+}
+
- (void)previous
{
playlist_Prev(pl_Get(getIntf()));
@@ -331,6 +354,33 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
return o_name;
}
+- (long long)currentPlaybackTimeInSeconds
+{
+ input_thread_t *p_input_thread = pl_CurrentInput(getIntf());
+ long long timeInSeconds = 0;
+
+ if (p_input_thread) {
+ int64_t time = var_GetInteger(p_input_thread, "time");
+ timeInSeconds = time / CLOCK_FREQ;
+ vlc_object_release(p_input_thread);
+ }
+
+ return timeInSeconds;
+}
+
+- (float)currentPlaybackPosition
+{
+ input_thread_t * p_input_thread = pl_CurrentInput(getIntf());
+ float position = 0.;
+
+ if (p_input_thread) {
+ position = var_GetFloat(p_input_thread, "position");
+ vlc_object_release(p_input_thread);
+ }
+
+ return position;
+}
+
- (void)forward
{
//LEGACY SUPPORT
@@ -349,12 +399,15 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
if (!p_input)
return;
- int i_interval = var_InheritInteger( p_input, p_value );
- if (i_interval > 0) {
- mtime_t val = CLOCK_FREQ * i_interval;
- if (!b_value)
- val = val * -1;
- var_SetInteger( p_input, "time-offset", val );
+ bool b_seekable = var_GetBool(p_input, "can-seek");
+ if (b_seekable) {
+ long long i_interval = var_InheritInteger( p_input, p_value );
+ if (i_interval > 0) {
+ mtime_t val = CLOCK_FREQ * i_interval;
+ if (!b_value)
+ val = val * -1;
+ var_SetInteger( p_input, "time-offset", val );
+ }
}
vlc_object_release(p_input);
}
@@ -399,6 +452,21 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
[self jumpWithValue:"long-jump-size" forward:NO];
}
+- (BOOL)seekToTime:(mtime_t)time
+{
+ input_thread_t * p_input_thread = pl_CurrentInput(getIntf());
+ if (p_input_thread) {
+ bool b_seekable = var_GetBool(p_input_thread, "can-seek");
+ if (b_seekable) {
+ var_SetInteger(p_input_thread, "time", time);
+ vlc_object_release(p_input_thread);
+ return YES;
+ }
+ vlc_object_release(p_input_thread);
+ }
+ return NO;
+}
+
- (void)shuffle
{
intf_thread_t *p_intf = getIntf();
=====================================
modules/gui/macosx/VLCInputManager.h
=====================================
@@ -26,9 +26,10 @@
#import <IOKit/pwr_mgt/IOPMLib.h> /* for sleep prevention */
-
@class VLCMain;
+extern NSString *VLCPlayerRateChanged;
+
@interface VLCInputManager : NSObject
- (id)initWithMain:(VLCMain *)o_mainObj;
=====================================
modules/gui/macosx/VLCInputManager.m
=====================================
@@ -34,10 +34,13 @@
#import "VLCResumeDialogController.h"
#import "VLCTrackSynchronizationWindowController.h"
#import "VLCVoutView.h"
+#import "VLCRemoteControlService.h"
#import "iTunes.h"
#import "Spotify.h"
+NSString *VLCPlayerRateChanged = @"VLCPlayerRateChanged";
+
@interface VLCInputManager()
- (void)updateMainMenu;
- (void)updateMainWindow;
@@ -72,6 +75,7 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
break;
case INPUT_EVENT_RATE:
[[[VLCMain sharedInstance] mainMenu] performSelectorOnMainThread:@selector(updatePlaybackRate) withObject: nil waitUntilDone:NO];
+ [[NSNotificationCenter defaultCenter] postNotificationName:VLCPlayerRateChanged object:nil];
break;
case INPUT_EVENT_POSITION:
@@ -164,6 +168,8 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
BOOL b_has_spotify_paused;
NSTimer *hasEndedTimer;
+
+ VLCRemoteControlService *_remoteControlService;
}
@end
@@ -190,6 +196,10 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
informInputChangedQueue = dispatch_queue_create("org.videolan.vlc.inputChangedQueue", DISPATCH_QUEUE_SERIAL);
+ if (@available(macOS 10.12.2, *)) {
+ _remoteControlService = [[VLCRemoteControlService alloc] init];
+ [_remoteControlService subscribeToRemoteCommands];
+ }
}
return self;
}
@@ -213,6 +223,10 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
p_current_input = NULL;
}
+ if (@available(macOS 10.12.2, *)) {
+ [_remoteControlService unsubscribeFromRemoteCommands];
+ }
+
var_DelCallback(pl_Get(getIntf()), "input-current", InputThreadChanged, (__bridge void *)self);
#if !OS_OBJECT_USE_OBJC
@@ -281,6 +295,7 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
{
[[[VLCMain sharedInstance] mainWindow] updateTimeSlider];
[[[VLCMain sharedInstance] statusBarIcon] updateProgress];
+ [_remoteControlService playbackPositionUpdated];
}
- (void)playbackStatusUpdated
@@ -338,6 +353,7 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
[self updateMainWindow];
[self sendDistributedNotificationWithUpdatedPlaybackStatus];
+ [_remoteControlService playbackStateChangedTo:state];
}
// Called when playback has ended and likely no subsequent media will start playing
@@ -514,6 +530,7 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
{
if (!p_current_input) {
[[[VLCMain sharedInstance] currentMediaInfoPanel] updatePanelWithItem:nil];
+ [_remoteControlService metaDataChangedForCurrentMediaItem:NULL];
return;
}
@@ -521,6 +538,7 @@ 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];
+ [_remoteControlService metaDataChangedForCurrentMediaItem:p_input_item];
}
- (void)updateMainWindow
=====================================
modules/gui/macosx/VLCRemoteControlService.h
=====================================
@@ -0,0 +1,36 @@
+/*****************************************************************************
+ * VLCRemoteControlService.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2017, 2018, 2021 VLC authors and VideoLAN
+ *
+ * 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>
+#include <vlc_common.h>
+
+ at interface VLCRemoteControlService : NSObject
+
+- (void)subscribeToRemoteCommands;
+- (void)unsubscribeFromRemoteCommands;
+
+- (void)playbackPositionUpdated;
+- (void)playbackStateChangedTo:(int)state;
+- (void)metaDataChangedForCurrentMediaItem:(input_item_t *)p_input_item;
+
+ at end
=====================================
modules/gui/macosx/VLCRemoteControlService.m
=====================================
@@ -0,0 +1,297 @@
+/*****************************************************************************
+ * VLCRemoteControlService.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2017-2021 VLC authors and VideoLAN
+ *
+ * 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 <MediaPlayer/MediaPlayer.h>
+
+#import "VLCRemoteControlService.h"
+#import "VLCMain.h"
+#import "CompatibilityFixes.h"
+#import "VLCPlaylist.h"
+#import "VLCCoreInteraction.h"
+#import "VLCInputManager.h"
+
+#define kVLCSettingPlaybackForwardSkipLength @(60)
+#define kVLCSettingPlaybackBackwardSkipLength @(60)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+
+ at interface VLCRemoteControlService()
+{
+ VLCCoreInteraction *_coreInteraction;
+}
+ at end
+
+ 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];
+}
+
+- (instancetype)init
+{
+ self = [super init];
+ if (self) {
+ _coreInteraction = [VLCCoreInteraction sharedInstance];
+
+ NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+ [notificationCenter addObserver:self
+ selector:@selector(playbackRateChanged:)
+ name:VLCPlayerRateChanged
+ object:nil];
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)playbackStateChangedTo:(int)state
+{
+ MPNowPlayingInfoCenter *nowPlayingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
+
+ switch (state) {
+ case PLAYING_S:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStatePlaying;
+ break;
+
+ case PAUSE_S:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStatePaused;
+ break;
+
+ case END_S:
+ case -1:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStateStopped;
+ break;
+
+ default:
+ nowPlayingInfoCenter.playbackState = MPNowPlayingPlaybackStateUnknown;
+ break;
+ }
+}
+
+- (void)playbackPositionUpdated
+{
+ 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)metaDataChangedForCurrentMediaItem:(input_item_t *)p_input_item
+{
+ if (!p_input_item) {
+ [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nil;
+ return;
+ }
+
+ NSMutableDictionary *currentlyPlayingTrackInfo = [NSMutableDictionary dictionary];
+ [self setTimeInformationForDictionary:currentlyPlayingTrackInfo];
+ [self setRateInformationForDictionary:currentlyPlayingTrackInfo];
+
+ /* fill title info */
+ char *psz_title = input_item_GetTitle(p_input_item);
+ if (!psz_title)
+ psz_title = input_item_GetName(p_input_item);
+ [currentlyPlayingTrackInfo setValue:toNSStr(psz_title) forKey:MPMediaItemPropertyTitle];
+ free(psz_title);
+
+ char *psz_artist = input_item_GetArtist(p_input_item);
+ [currentlyPlayingTrackInfo setValue:toNSStr(psz_artist) forKey:MPMediaItemPropertyArtist];
+ free(psz_artist);
+
+ char *psz_albumName = input_item_GetAlbum(p_input_item);
+ [currentlyPlayingTrackInfo setValue:toNSStr(psz_albumName) forKey:MPMediaItemPropertyAlbumTitle];
+ free(psz_albumName);
+
+ char *psz_trackNumber = input_item_GetTrackNumber(p_input_item);
+ [currentlyPlayingTrackInfo setValue:[NSNumber numberWithInt:[toNSStr(psz_trackNumber) intValue]] forKey:MPMediaItemPropertyAlbumTrackNumber];
+ free(psz_trackNumber);
+
+ mtime_t duration = input_item_GetDuration(p_input_item) / 1000000;
+ [currentlyPlayingTrackInfo setValue:[NSNumber numberWithLongLong:duration] forKey:MPMediaItemPropertyPlaybackDuration];
+ if (duration > 0) {
+ [currentlyPlayingTrackInfo setValue:[NSNumber numberWithBool:NO] forKey:MPNowPlayingInfoPropertyIsLiveStream];
+ } else {
+ [currentlyPlayingTrackInfo setValue:[NSNumber numberWithBool:YES] forKey:MPNowPlayingInfoPropertyIsLiveStream];
+ }
+
+ char *psz_artworkURL = input_item_GetArtworkURL(p_input_item);
+ if (psz_artworkURL) {
+ NSString *artworkURL = toNSStr(psz_artworkURL);
+ if (![artworkURL hasPrefix:@"attachment://"]) {
+ NSImage *coverArtImage = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:artworkURL]];
+ if (coverArtImage) {
+ MPMediaItemArtwork *mpartwork = [[MPMediaItemArtwork alloc] initWithBoundsSize:coverArtImage.size
+ requestHandler:^NSImage* _Nonnull(CGSize size) {
+ return coverArtImage;
+ }];
+ [currentlyPlayingTrackInfo setValue:mpartwork forKey:MPMediaItemPropertyArtwork];
+ }
+ }
+ }
+ free(psz_artworkURL);
+
+ [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
+}
+
+- (void)setTimeInformationForDictionary:(NSMutableDictionary *)dictionary
+{
+ [dictionary setValue:[NSNumber numberWithLongLong:_coreInteraction.currentPlaybackTimeInSeconds] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
+ [dictionary setValue:[NSNumber numberWithFloat:_coreInteraction.currentPlaybackPosition] forKey:MPNowPlayingInfoPropertyPlaybackProgress];
+}
+
+- (void)setRateInformationForDictionary:(NSMutableDictionary *)dictionary
+{
+ [dictionary setValue:[NSNumber numberWithFloat:_coreInteraction.internalPlaybackRate] forKey:MPNowPlayingInfoPropertyPlaybackRate];
+}
+
+- (void)subscribeToRemoteCommands
+{
+ 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.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
+{
+ [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nil;
+
+ for (MPRemoteCommand *command in RemoteCommandCenterCommandsToHandle()) {
+ [command removeTarget:self];
+ }
+}
+
+- (MPRemoteCommandHandlerStatus)remoteCommandEvent:(MPRemoteCommandEvent *)event
+{
+ MPRemoteCommandCenter *cc = [MPRemoteCommandCenter sharedCommandCenter];
+
+ 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;
+ return [_coreInteraction seekToTime:positionEvent.positionTime * 1000000] ? MPRemoteCommandHandlerStatusSuccess : MPRemoteCommandHandlerStatusCommandFailed;
+ }
+ if (event.command == cc.changeRepeatModeCommand) {
+ MPChangeRepeatModeCommandEvent *repeatEvent = (MPChangeRepeatModeCommandEvent *)event;
+ MPRepeatType repeatType = repeatEvent.repeatType;
+ switch (repeatType) {
+ case MPRepeatTypeAll:
+ [_coreInteraction repeatAll];
+ break;
+
+ case MPRepeatTypeOne:
+ [_coreInteraction repeatOne];
+ break;
+
+ default:
+ [_coreInteraction repeatOff];
+ break;
+ }
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+ if (event.command == cc.changeShuffleModeCommand) {
+ [_coreInteraction shuffle];
+ return MPRemoteCommandHandlerStatusSuccess;
+ }
+
+ 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
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/627a60fee0325a26672e4f35c771d967ea3e8d6a...d9de9c3e49d3f252943b547de9f86036f2d97b0a
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/627a60fee0325a26672e4f35c771d967ea3e8d6a...d9de9c3e49d3f252943b547de9f86036f2d97b0a
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list