From 52b40f80045942ecdf94dec0a772c11e279acd06 Mon Sep 17 00:00:00 2001 From: Erekle Date: Tue, 10 May 2016 23:57:47 +0400 Subject: [PATCH] ASVideoPlayerNodeControlType and fixes * changed static string to ASVideoPlayerNodeControlType * public property for duration * public method for seek * new _controlFlexGrowSpacerSpec; used to use flexible space in controlbar. for example if user does not want to have scrubber, he can replace it with flexible spacer and duration text node will be kept at the right edge. --- AsyncDisplayKit/ASVideoNode.h | 2 +- AsyncDisplayKit/ASVideoNode.mm | 2 +- AsyncDisplayKit/ASVideoPlayerNode.h | 14 +++++++ AsyncDisplayKit/ASVideoPlayerNode.mm | 63 +++++++++++++++++++--------- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/AsyncDisplayKit/ASVideoNode.h b/AsyncDisplayKit/ASVideoNode.h index aecc602913..14120a2eda 100644 --- a/AsyncDisplayKit/ASVideoNode.h +++ b/AsyncDisplayKit/ASVideoNode.h @@ -15,7 +15,7 @@ typedef enum { ASVideoNodePlayerStateUnknown, ASVideoNodePlayerStateReadyToPlay, - ASVideoNodePlayerStatePlaybackLikelyToKeepUp, + ASVideoNodePlayerStatePlaybackLikelyToKeepUpButNotPlaying, ASVideoNodePlayerStatePlaying, ASVideoNodePlayerStateLoading, ASVideoNodePlayerStatePaused, diff --git a/AsyncDisplayKit/ASVideoNode.mm b/AsyncDisplayKit/ASVideoNode.mm index ed50e25190..742a55026d 100644 --- a/AsyncDisplayKit/ASVideoNode.mm +++ b/AsyncDisplayKit/ASVideoNode.mm @@ -288,7 +288,7 @@ static NSString * const kStatus = @"status"; } } } else if ([keyPath isEqualToString:kPlaybackLikelyToKeepUpKey]) { - self.playerState = ASVideoNodePlayerStatePlaybackLikelyToKeepUp; + self.playerState = ASVideoNodePlayerStatePlaybackLikelyToKeepUpButNotPlaying; if (_shouldBePlaying && [change[NSKeyValueChangeNewKey] boolValue] == true && ASInterfaceStateIncludesVisible(self.interfaceState)) { [self play]; // autoresume after buffer catches up } diff --git a/AsyncDisplayKit/ASVideoPlayerNode.h b/AsyncDisplayKit/ASVideoPlayerNode.h index eec4e350d3..c7fdb8f66b 100644 --- a/AsyncDisplayKit/ASVideoPlayerNode.h +++ b/AsyncDisplayKit/ASVideoPlayerNode.h @@ -14,12 +14,26 @@ @class AVAsset; +typedef enum { + ASVideoPlayerNodeControlTypePlaybackButton, + ASVideoPlayerNodeControlTypeElapsedText, + ASVideoPlayerNodeControlTypeDurationText, + ASVideoPlayerNodeControlTypeScrubber, + ASVideoPlayerNodeControlTypeFlexGrowSpacer, +} ASVideoPlayerNodeControlType; + NS_ASSUME_NONNULL_BEGIN @interface ASVideoPlayerNode : ASDisplayNode +@property (nonatomic,assign,readonly) CGFloat duration; + - (instancetype)initWithUrl:(NSURL*)url; - (instancetype)initWithAsset:(AVAsset*)asset; + +#pragma mark - Public API +-(void)seekToTime:(CGFloat)percentComplete; + @end NS_ASSUME_NONNULL_END #endif diff --git a/AsyncDisplayKit/ASVideoPlayerNode.mm b/AsyncDisplayKit/ASVideoPlayerNode.mm index 542796e6b6..78fbaf9e07 100644 --- a/AsyncDisplayKit/ASVideoPlayerNode.mm +++ b/AsyncDisplayKit/ASVideoPlayerNode.mm @@ -9,11 +9,6 @@ #import "ASVideoPlayerNode.h" static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; -static NSString * const kASVideoPlayerNodeDurationKeyPath = @"duration"; -static NSString * const kASVideoPlayerNodePlaybackButton = @"playbackButtonNode"; -static NSString * const kASVideoPlayerNodeElapsedLabel = @"elapsedTextNode"; -static NSString * const kASVideoPlayerNodeDurationLabel = @"durationTextNode"; -static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNode"; @interface ASVideoPlayerNode() { @@ -34,6 +29,7 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod ASTextNode *_elapsedTextNode; ASTextNode *_durationTextNode; ASDisplayNode *_scrubberNode; + ASStackLayoutSpec *_controlFlexGrowSpacerSpec; BOOL _isSeeking; CGFloat _duration; @@ -104,7 +100,11 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod - (NSArray*)createNeededControlElementsArray { //TODO:: Maybe here we will ask delegate what he needs and we force delegate to use our static strings or something like that - return @[ kASVideoPlayerNodePlaybackButton, kASVideoPlayerNodeElapsedLabel, kASVideoPlayerNodeScrubber, kASVideoPlayerNodeDurationLabel ]; + return @[ @(ASVideoPlayerNodeControlTypePlaybackButton), + @(ASVideoPlayerNodeControlTypeElapsedText), + @(ASVideoPlayerNodeControlTypeScrubber), + @(ASVideoPlayerNodeControlTypeFlexGrowSpacer), + @(ASVideoPlayerNodeControlTypeDurationText) ]; } - (void)addObservers @@ -122,15 +122,26 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod { ASDN::MutexLocker l(_videoPlayerLock); - for (NSString *controlType in _neededControls) { - if ([controlType isEqualToString:kASVideoPlayerNodePlaybackButton]) { - [self createPlaybackButton]; - } else if ([controlType isEqualToString:kASVideoPlayerNodeElapsedLabel]) { - [self createElapsedTextField]; - } else if ([controlType isEqualToString:kASVideoPlayerNodeScrubber]) { - [self createScrubber]; - } else if ([controlType isEqualToString:kASVideoPlayerNodeDurationLabel]) { - [self createDurationTextField]; + for (int i = 0; i < _neededControls.count; i++) { + ASVideoPlayerNodeControlType type = (ASVideoPlayerNodeControlType)[[_neededControls objectAtIndex:i] integerValue]; + switch (type) { + case ASVideoPlayerNodeControlTypePlaybackButton: + [self createPlaybackButton]; + break; + case ASVideoPlayerNodeControlTypeElapsedText: + [self createElapsedTextField]; + break; + case ASVideoPlayerNodeControlTypeDurationText: + [self createDurationTextField]; + break; + case ASVideoPlayerNodeControlTypeScrubber: + [self createScrubber]; + break; + case ASVideoPlayerNodeControlTypeFlexGrowSpacer: + [self createControlFlexGrowSpacer]; + break; + default: + break; } } } @@ -163,7 +174,6 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod if (_elapsedTextNode == nil) { _elapsedTextNode = [[ASTextNode alloc] init]; _elapsedTextNode.attributedString = [self timeLabelAttributedStringForString:@"00:00"]; - _elapsedTextNode.flexGrow = YES; [_cachedControls addObject:_elapsedTextNode]; } @@ -175,7 +185,6 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod if (_durationTextNode == nil) { _durationTextNode = [[ASTextNode alloc] init]; _durationTextNode.attributedString = [self timeLabelAttributedStringForString:@"00:00"]; - _durationTextNode.flexGrow = YES; [_cachedControls addObject:_durationTextNode]; } @@ -205,6 +214,16 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod [self addSubnode:_scrubberNode]; } +- (void)createControlFlexGrowSpacer +{ + if (_controlFlexGrowSpacerSpec == nil) { + _controlFlexGrowSpacerSpec = [[ASStackLayoutSpec alloc] init]; + _controlFlexGrowSpacerSpec.flexGrow = YES; + } + + [_cachedControls addObject:_controlFlexGrowSpacerSpec]; +} + - (void)updateDurationTimeLabel { NSString *formatedDuration = [self timeFormatted:round(_duration)]; @@ -233,11 +252,12 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod #pragma mark - ASVideoNodeDelegate - (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate { - if(toSate == ASVideoNodePlayerStateReadyToPlay){ + if (toSate == ASVideoNodePlayerStateReadyToPlay) { _duration = CMTimeGetSeconds(_videoNode.currentItem.duration); [self updateDurationTimeLabel]; } } + - (void)videoNode:(ASVideoNode *)videoNode didPlayToSecond:(NSTimeInterval)second { if(_isSeeking){ @@ -277,13 +297,13 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod - (void)changedSeekValue:(UISlider*)slider { - CGFloat percentage = slider.value * 100; + CGFloat percentage = slider.value * 100; [self seekToTime:percentage]; } -(void)seekToTime:(CGFloat)percentComplete { - CGFloat seconds = (_duration * percentComplete) / 100; + CGFloat seconds = (_duration * percentComplete) / 100; [self updateElapsedTimeLabel:seconds]; [_videoNode.player seekToTime:CMTimeMakeWithSeconds(seconds, _videoNode.periodicTimeObserverTimescale)]; @@ -308,11 +328,14 @@ static NSString * const kASVideoPlayerNodeScrubber = @"elapsedScrubberNod justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:_cachedControls]; + controlbarSpec.alignSelf = ASStackLayoutAlignSelfStretch; UIEdgeInsets insets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0); ASInsetLayoutSpec *controlbarInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:controlbarSpec]; + controlbarInsetSpec.alignSelf = ASStackLayoutAlignSelfStretch; + ASStackLayoutSpec *mainVerticalStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:0.0 justifyContent:ASStackLayoutJustifyContentStart