moved spinner to ASVIdeoPlayerNode

This commit is contained in:
Erekle
2016-05-19 15:07:39 +04:00
parent 3d5385dad3
commit 100d2b4f26
5 changed files with 91 additions and 78 deletions

View File

@@ -74,7 +74,6 @@ static NSString * const kStatus = @"status";
ASImageNode *_placeholderImageNode; // TODO: Make ASVideoNode an ASImageNode subclass; remove this. ASImageNode *_placeholderImageNode; // TODO: Make ASVideoNode an ASImageNode subclass; remove this.
ASDisplayNode *_playerNode; ASDisplayNode *_playerNode;
ASDisplayNode *_spinnerNode;
NSString *_gravity; NSString *_gravity;
} }
@@ -220,13 +219,6 @@ static NSString * const kStatus = @"status";
[children addObject:_playerNode]; [children addObject:_playerNode];
} }
// Center spinner node
if (_spinnerNode) {
ASCenterLayoutSpec *centerLayoutSpec = [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionDefault child:_spinnerNode];
centerLayoutSpec.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(maxSize);
[children addObject:centerLayoutSpec];
}
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children]; return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children];
} }
@@ -303,7 +295,6 @@ static NSString * const kStatus = @"status";
if ([keyPath isEqualToString:kStatus]) { if ([keyPath isEqualToString:kStatus]) {
if ([change[NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusReadyToPlay) { if ([change[NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusReadyToPlay) {
self.playerState = ASVideoNodePlayerStateReadyToPlay; self.playerState = ASVideoNodePlayerStateReadyToPlay;
[self removeSpinner];
// If we don't yet have a placeholder image update it now that we should have data available for it // If we don't yet have a placeholder image update it now that we should have data available for it
if (_placeholderImageNode.image == nil) { if (_placeholderImageNode.image == nil) {
[self generatePlaceholderImage]; [self generatePlaceholderImage];
@@ -320,7 +311,6 @@ static NSString * const kStatus = @"status";
} else if ([keyPath isEqualToString:kplaybackBufferEmpty]) { } else if ([keyPath isEqualToString:kplaybackBufferEmpty]) {
if (_shouldBePlaying && [change[NSKeyValueChangeNewKey] boolValue] == true && ASInterfaceStateIncludesVisible(self.interfaceState)) { if (_shouldBePlaying && [change[NSKeyValueChangeNewKey] boolValue] == true && ASInterfaceStateIncludesVisible(self.interfaceState)) {
self.playerState = ASVideoNodePlayerStateLoading; self.playerState = ASVideoNodePlayerStateLoading;
[self showSpinner];
} }
} }
} }
@@ -559,9 +549,8 @@ static NSString * const kStatus = @"status";
_shouldBePlaying = YES; _shouldBePlaying = YES;
if (![self ready]) { if (![self ready]) {
[self showSpinner]; self.playerState = ASVideoNodePlayerStateLoading;
} else { } else {
[self removeSpinner];
self.playerState = ASVideoNodePlayerStatePlaying; self.playerState = ASVideoNodePlayerStatePlaying;
} }
} }
@@ -571,35 +560,6 @@ static NSString * const kStatus = @"status";
return _currentPlayerItem.status == AVPlayerItemStatusReadyToPlay; return _currentPlayerItem.status == AVPlayerItemStatusReadyToPlay;
} }
- (void)showSpinner
{
ASDN::MutexLocker l(_videoLock);
if (!_spinnerNode) {
_spinnerNode = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] init];
spinnnerView.color = [UIColor whiteColor];
return spinnnerView;
}];
_spinnerNode.preferredFrameSize = CGSizeMake(44.0, 44.0);
[self addSubnode:_spinnerNode];
[self setNeedsLayout];
}
[(UIActivityIndicatorView *)_spinnerNode.view startAnimating];
}
- (void)removeSpinner
{
ASDN::MutexLocker l(_videoLock);
if (!_spinnerNode) {
return;
}
[_spinnerNode removeFromSupernode];
_spinnerNode = nil;
}
- (void)pause - (void)pause
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
@@ -608,7 +568,6 @@ static NSString * const kStatus = @"status";
} }
self.playerState = ASVideoNodePlayerStatePaused; self.playerState = ASVideoNodePlayerStatePaused;
[_player pause]; [_player pause];
[self removeSpinner];
_shouldBePlaying = NO; _shouldBePlaying = NO;
} }
@@ -656,7 +615,6 @@ static NSString * const kStatus = @"status";
- (void)videoNodeDidStall:(NSNotification *)notification - (void)videoNodeDidStall:(NSNotification *)notification
{ {
self.playerState = ASVideoNodePlayerStateLoading; self.playerState = ASVideoNodePlayerStateLoading;
[self showSpinner];
if (_delegateFlags.delegateVideoNodeDidStallAtTimeInterval) { if (_delegateFlags.delegateVideoNodeDidStallAtTimeInterval) {
[_delegate videoNode:self didStallAtTimeInterval:CMTimeGetSeconds(_player.currentItem.currentTime)]; [_delegate videoNode:self didStallAtTimeInterval:CMTimeGetSeconds(_player.currentItem.currentTime)];
} }
@@ -680,13 +638,6 @@ static NSString * const kStatus = @"status";
} }
#pragma mark - Internal Properties #pragma mark - Internal Properties
- (ASDisplayNode *)spinner
{
ASDN::MutexLocker l(_videoLock);
return _spinnerNode;
}
- (ASImageNode *)placeholderImageNode - (ASImageNode *)placeholderImageNode
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);

View File

@@ -42,6 +42,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign, readwrite) BOOL shouldAutorepeat; @property (nonatomic, assign, readwrite) BOOL shouldAutorepeat;
@property (nonatomic, assign, readwrite) BOOL muted; @property (nonatomic, assign, readwrite) BOOL muted;
@property (nonatomic, assign, readonly) ASVideoNodePlayerState playerState; @property (nonatomic, assign, readonly) ASVideoNodePlayerState playerState;
@property (nonatomic, assign, readwrite) BOOL shouldAggressivelyRecoverFromStall;
//! Defaults to 100 //! Defaults to 100
@property (nonatomic, assign) int32_t periodicTimeObserverTimescale; @property (nonatomic, assign) int32_t periodicTimeObserverTimescale;
//! Defaults to AVLayerVideoGravityResizeAspect //! Defaults to AVLayerVideoGravityResizeAspect
@@ -95,6 +97,9 @@ NS_ASSUME_NONNULL_BEGIN
- (UIColor *)videoPlayerNodeScrubberThumbTint:(ASVideoPlayerNode *)videoPlayer; - (UIColor *)videoPlayerNodeScrubberThumbTint:(ASVideoPlayerNode *)videoPlayer;
- (UIImage *)videoPlayerNodeScrubberThumbImage:(ASVideoPlayerNode *)videoPlayer; - (UIImage *)videoPlayerNodeScrubberThumbImage:(ASVideoPlayerNode *)videoPlayer;
#pragma mark - Spinner delegate methods
- (UIColor *)videoPlayerNodeSpinnerTint:(ASVideoPlayerNode *)videoPlayer;
#pragma mark - Playback button delegate methods #pragma mark - Playback button delegate methods
- (UIColor *)videoPlayerNodePlaybackButtonTint:(ASVideoPlayerNode *)videoPlayer; - (UIColor *)videoPlayerNodePlaybackButtonTint:(ASVideoPlayerNode *)videoPlayer;

View File

@@ -19,6 +19,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
struct { struct {
unsigned int delegateNeededControls:1; unsigned int delegateNeededControls:1;
unsigned int delegateSpinnerTintColor:1;
unsigned int delegatePlaybackButtonTint:1; unsigned int delegatePlaybackButtonTint:1;
unsigned int delegateScrubberMaximumTrackTintColor:1; unsigned int delegateScrubberMaximumTrackTintColor:1;
unsigned int delegateScrubberMinimumTrackTintColor:1; unsigned int delegateScrubberMinimumTrackTintColor:1;
@@ -48,6 +49,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
ASTextNode *_durationTextNode; ASTextNode *_durationTextNode;
ASDisplayNode *_scrubberNode; ASDisplayNode *_scrubberNode;
ASStackLayoutSpec *_controlFlexGrowSpacerSpec; ASStackLayoutSpec *_controlFlexGrowSpacerSpec;
ASDisplayNode *_spinnerNode;
BOOL _isSeeking; BOOL _isSeeking;
CMTime _duration; CMTime _duration;
@@ -60,6 +62,8 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
int32_t _periodicTimeObserverTimescale; int32_t _periodicTimeObserverTimescale;
NSString *_gravity; NSString *_gravity;
BOOL _shouldAggressivelyRecoverFromStall;
UIColor *_defaultControlsColor; UIColor *_defaultControlsColor;
} }
@@ -355,9 +359,18 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
if (toState == ASVideoNodePlayerStatePlaying) { if (toState == ASVideoNodePlayerStatePlaying) {
_playbackButtonNode.buttonType = ASDefaultPlaybackButtonTypePause; _playbackButtonNode.buttonType = ASDefaultPlaybackButtonTypePause;
} else { [self removeSpinner];
} else if (toState != ASVideoNodePlayerStatePlaybackLikelyToKeepUpButNotPlaying && toState != ASVideoNodePlayerStateReadyToPlay) {
_playbackButtonNode.buttonType = ASDefaultPlaybackButtonTypePlay; _playbackButtonNode.buttonType = ASDefaultPlaybackButtonTypePlay;
} }
if (toState == ASVideoNodePlayerStateLoading || toState == ASVideoNodePlayerStateInitialLoading) {
[self showSpinner];
}
if (toState == ASVideoNodePlayerStateReadyToPlay || toState == ASVideoNodePlayerStatePaused || toState == ASVideoNodePlayerStatePlaybackLikelyToKeepUpButNotPlaying) {
[self removeSpinner];
}
} }
- (BOOL)videoNode:(ASVideoNode *)videoNode shouldChangePlayerStateTo:(ASVideoNodePlayerState)state - (BOOL)videoNode:(ASVideoNode *)videoNode shouldChangePlayerStateTo:(ASVideoNodePlayerState)state
@@ -402,16 +415,12 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
if (_delegateFlags.delegateDidTapVideoPlayerNode) { if (_delegateFlags.delegateDidTapVideoPlayerNode) {
[_delegate didTapVideoPlayerNode:self]; [_delegate didTapVideoPlayerNode:self];
} else { } else {
if (videoNode.playerState == ASVideoNodePlayerStatePlaying) { [self manageVideoNodePlayback];
[videoNode pause];
} else {
[videoNode play];
}
} }
} }
#pragma mark - Actions #pragma mark - Actions
- (void)didTapPlaybackButton:(ASControlNode*)node - (void)manageVideoNodePlayback
{ {
if (_videoNode.playerState == ASVideoNodePlayerStatePlaying) { if (_videoNode.playerState == ASVideoNodePlayerStatePlaying) {
[_videoNode pause]; [_videoNode pause];
@@ -420,6 +429,43 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
} }
} }
- (void)showSpinner
{
ASDN::MutexLocker l(_videoPlayerLock);
if (!_spinnerNode) {
_spinnerNode = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] init];
spinnnerView.color = _defaultControlsColor;
if (_delegateFlags.delegateSpinnerTintColor) {
spinnnerView.color = [_delegate videoPlayerNodeSpinnerTint:self];
}
return spinnnerView;
}];
_spinnerNode.preferredFrameSize = CGSizeMake(44.0, 44.0);
[self addSubnode:_spinnerNode];
[self setNeedsLayout];
}
[(UIActivityIndicatorView *)_spinnerNode.view startAnimating];
}
- (void)removeSpinner
{
ASDN::MutexLocker l(_videoPlayerLock);
if (!_spinnerNode) {
return;
}
[_spinnerNode removeFromSupernode];
_spinnerNode = nil;
}
- (void)didTapPlaybackButton:(ASControlNode*)node
{
[self manageVideoNodePlayback];
}
- (void)beginSeek - (void)beginSeek
{ {
_isSeeking = YES; _isSeeking = YES;
@@ -445,7 +491,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
[_videoNode.player seekToTime:CMTimeMakeWithSeconds(seconds, _videoNode.periodicTimeObserverTimescale)]; [_videoNode.player seekToTime:CMTimeMakeWithSeconds(seconds, _videoNode.periodicTimeObserverTimescale)];
if (_videoNode.playerState != ASVideoNodePlayerStatePlaying) { if (_videoNode.playerState != ASVideoNodePlayerStatePlaying) {
[_videoNode play]; [self manageVideoNodePlayback];
} }
} }
@@ -510,10 +556,20 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
layoutSpec = [self defaultLayoutSpecThatFits:maxSize]; layoutSpec = [self defaultLayoutSpecThatFits:maxSize];
} }
NSMutableArray *children = [[NSMutableArray alloc] init];
if (_spinnerNode) {
ASCenterLayoutSpec *centerLayoutSpec = [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionDefault child:_spinnerNode];
centerLayoutSpec.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(maxSize);
[children addObject:centerLayoutSpec];
}
ASOverlayLayoutSpec *overlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_videoNode overlay:layoutSpec]; ASOverlayLayoutSpec *overlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_videoNode overlay:layoutSpec];
overlaySpec.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(maxSize); overlaySpec.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(maxSize);
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[overlaySpec]]; [children addObject:overlaySpec];
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children];
} }
- (ASLayoutSpec*)defaultLayoutSpecThatFits:(CGSize)maxSize - (ASLayoutSpec*)defaultLayoutSpecThatFits:(CGSize)maxSize
@@ -559,6 +615,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
memset(&_delegateFlags, 0, sizeof(_delegateFlags)); memset(&_delegateFlags, 0, sizeof(_delegateFlags));
} else { } else {
_delegateFlags.delegateNeededControls = [_delegate respondsToSelector:@selector(videoPlayerNodeNeededControls:)]; _delegateFlags.delegateNeededControls = [_delegate respondsToSelector:@selector(videoPlayerNodeNeededControls:)];
_delegateFlags.delegateSpinnerTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeSpinnerTint:)];
_delegateFlags.delegateScrubberMaximumTrackTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberMaximumTrackTint:)]; _delegateFlags.delegateScrubberMaximumTrackTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberMaximumTrackTint:)];
_delegateFlags.delegateScrubberMinimumTrackTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberMinimumTrackTint:)]; _delegateFlags.delegateScrubberMinimumTrackTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberMinimumTrackTint:)];
_delegateFlags.delegateScrubberThumbTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberThumbTint:)]; _delegateFlags.delegateScrubberThumbTintColor = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberThumbTint:)];
@@ -629,6 +686,17 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
return _videoNode.playerState; return _videoNode.playerState;
} }
- (BOOL)shouldAggressivelyRecoverFromStall
{
return _videoNode.shouldAggressivelyRecoverFromStall;
}
- (void)setShouldAggressivelyRecoverFromStall:(BOOL)shouldAggressivelyRecoverFromStall
{
_shouldAggressivelyRecoverFromStall = shouldAggressivelyRecoverFromStall;
_videoNode.shouldAggressivelyRecoverFromStall = _shouldAggressivelyRecoverFromStall;
}
#pragma mark - Helpers #pragma mark - Helpers
- (NSString *)timeStringForCMTime:(CMTime)time forTimeLabelType:(ASVideoPlayerNodeControlType)type - (NSString *)timeStringForCMTime:(CMTime)time forTimeLabelType:(ASVideoPlayerNodeControlType)type
{ {

View File

@@ -50,13 +50,6 @@
_requestedKeys = @[ @"playable" ]; _requestedKeys = @[ @"playable" ];
} }
- (void)testSpinnerDefaultsToNil
{
XCTAssertNil(_videoNode.spinner);
}
- (void)testOnPlayIfVideoIsNotReadyInitializeSpinnerAndAddAsSubnode - (void)testOnPlayIfVideoIsNotReadyInitializeSpinnerAndAddAsSubnode
{ {
_videoNode.asset = _firstAsset; _videoNode.asset = _firstAsset;
@@ -73,8 +66,6 @@
{ {
_videoNode.interfaceState = ASInterfaceStateFetchData; _videoNode.interfaceState = ASInterfaceStateFetchData;
[_videoNode play]; [_videoNode play];
XCTAssertNotNil(_videoNode.spinner);
} }
@@ -97,7 +88,6 @@
[_videoNode play]; [_videoNode play];
[_videoNode pause]; [_videoNode pause];
XCTAssertFalse(((UIActivityIndicatorView *)_videoNode.spinner.view).isAnimating);
} }
@@ -119,8 +109,6 @@
[_videoNode play]; [_videoNode play];
[_videoNode observeValueForKeyPath:@"status" ofObject:[_videoNode currentItem] change:@{NSKeyValueChangeNewKey : @(AVPlayerItemStatusReadyToPlay)} context:NULL]; [_videoNode observeValueForKeyPath:@"status" ofObject:[_videoNode currentItem] change:@{NSKeyValueChangeNewKey : @(AVPlayerItemStatusReadyToPlay)} context:NULL];
XCTAssertFalse(((UIActivityIndicatorView *)_videoNode.spinner.view).isAnimating);
} }

View File

@@ -31,7 +31,6 @@
{ {
self = [super init]; self = [super init];
if (self) { if (self) {
_videoModel = video; _videoModel = video;
_titleNode = [[ASTextNode alloc] init]; _titleNode = [[ASTextNode alloc] init];
@@ -55,6 +54,7 @@
_videoPlayerNode = [[ASVideoPlayerNode alloc] initWithUrl:_videoModel.url]; _videoPlayerNode = [[ASVideoPlayerNode alloc] initWithUrl:_videoModel.url];
_videoPlayerNode.delegate = self; _videoPlayerNode.delegate = self;
_videoPlayerNode.backgroundColor = [UIColor blackColor];
[self addSubnode:_videoPlayerNode]; [self addSubnode:_videoPlayerNode];
} }
return self; return self;
@@ -101,19 +101,20 @@
#pragma mark - ASVideoPlayerNodeDelegate #pragma mark - ASVideoPlayerNodeDelegate
- (void)didTapVideoPlayerNode:(ASVideoPlayerNode *)videoPlayer - (void)didTapVideoPlayerNode:(ASVideoPlayerNode *)videoPlayer
{ {
if (_videoPlayerNode.playerState == ASVideoNodePlayerStatePlaying) { if (_videoPlayerNode.isPlaying) {
NSLog(@"TRANSITION"); NSLog(@"TRANSITION");
[_videoPlayerNode pause];
} else { } else {
[_videoPlayerNode play]; [_videoPlayerNode play];
} }
} }
- (NSArray *)videoPlayerNodeNeededControls:(ASVideoPlayerNode *)videoPlayer /*- (NSArray *)videoPlayerNodeNeededControls:(ASVideoPlayerNode *)videoPlayer
{ {
return @[ @(ASVideoPlayerNodeControlTypePlaybackButton) ]; return @[ @(ASVideoPlayerNodeControlTypePlaybackButton) ];
} }*/
- (ASLayoutSpec *)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer forControls:(NSDictionary *)controls forMaximumSize:(CGSize)maxSize /*- (ASLayoutSpec *)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer forControls:(NSDictionary *)controls forMaximumSize:(CGSize)maxSize
{ {
NSMutableArray *bottomControls = [[NSMutableArray alloc] init]; NSMutableArray *bottomControls = [[NSMutableArray alloc] init];
@@ -147,5 +148,5 @@
return mainVerticalStack; return mainVerticalStack;
} }*/
@end @end