diff --git a/AsyncDisplayKit/ASVideoNode.h b/AsyncDisplayKit/ASVideoNode.h index 14120a2eda..e998c04bdf 100644 --- a/AsyncDisplayKit/ASVideoNode.h +++ b/AsyncDisplayKit/ASVideoNode.h @@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN * @param toSate player new state. * @discussion This method is called after each state change */ -- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate; +- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toState; /** * @abstract Ssks delegate if state change is allowed * ASVideoNodePlayerStatePlaying or ASVideoNodePlayerStatePaused. diff --git a/AsyncDisplayKit/ASVideoPlayerNode.h b/AsyncDisplayKit/ASVideoPlayerNode.h index 7373fb9f49..f3a9502d49 100644 --- a/AsyncDisplayKit/ASVideoPlayerNode.h +++ b/AsyncDisplayKit/ASVideoPlayerNode.h @@ -39,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN @end +#pragma mark - ASVideoPlayerNodeDelegate - @protocol ASVideoPlayerNodeDelegate @optional /** @@ -46,16 +47,66 @@ NS_ASSUME_NONNULL_BEGIN * @param videoPlayer */ - (NSArray *)videoPlayerNodeNeededControls:(ASVideoPlayerNode*)videoPlayer; + +/** + * @abstract Delegate method invoked in layoutSpecThatFits: + * @param videoPlayer + * @param controls - Dictionary of controls which are used in videoPlayer; Dictionary keys are ASVideoPlayerNodeControlType + * @param constrainedSize - ASSizeRange for ASVideoPlayerNode + * @discussion - Developer can layout whole ASVideoPlayerNode as he wants. ASVideoNode is locked and it can't be changed + */ +- (ASLayoutSpec *)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer + forControls:(NSDictionary *)controls + forConstrainedSize:(ASSizeRange)constrainedSize; + +#pragma mark Text delegate methods +/** + * @abstract Delegate method invoked before creating ASVideoPlayerNodeControlTypeElapsedText and ASVideoPlayerNodeControlTypeDurationText + * @param videoPlayer + * @param timeLabelType + */ - (NSDictionary *)videoPlayerNodeTimeLabelAttributes:(ASVideoPlayerNode *)videoPlayerNode timeLabelType:(ASVideoPlayerNodeControlType)timeLabelType; -#pragma mark - Scrubber delegate methods +#pragma mark Scrubber delegate methods - (UIColor *)videoPlayerNodeScrubberMaximumTrackTint:(ASVideoPlayerNode *)videoPlayer; - (UIColor *)videoPlayerNodeScrubberMinimumTrackTint:(ASVideoPlayerNode *)videoPlayer; - (UIColor *)videoPlayerNodeScrubberThumbTint:(ASVideoPlayerNode *)videoPlayer; - (UIImage *)videoPlayerNodeScrubberThumbImage:(ASVideoPlayerNode *)videoPlayer; -- (ASLayoutSpec *)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer - forControls:(NSDictionary *)controls - forConstrainedSize:(ASSizeRange)constrainedSize; + + +#pragma mark ASVideoNodeDelegate proxy methods +/** + * @abstract Delegate method invoked when ASVideoNode playback time is updated. + * @param videoPlayerNode The video node that was tapped. + * @param second current playback time. + */ +- (void)videoPlayerNode:(ASVideoPlayerNode *)videoPlayer didPlayToTime:(CMTime)time; + +/** + * @abstract Delegate method invoked when ASVideoNode changes state. + * @param videoPlayerNode The ASVideoPlayerNode whose ASVideoNode is changing state. + * @param state ASVideoNode state before this change. + * @param toSate ASVideoNode new state. + * @discussion This method is called after each state change + */ +- (void)videoPlayerNode:(ASVideoPlayerNode *)videoPlayer willChangeVideoNodeState:(ASVideoNodePlayerState)state toVideoNodeState:(ASVideoNodePlayerState)toSate; + +/** + * @abstract Delegate method is invoked when ASVideoNode decides to change state. + * @param videoPlayerNode The ASVideoPlayerNode whose ASVideoNode is changing state. + * @param state ASVideoNode that is going to be set. + * @discussion Delegate method invoked when player changes it's state to + * ASVideoNodePlayerStatePlaying or ASVideoNodePlayerStatePaused + * and asks delegate if state change is valid + */ +- (BOOL)videoPlayerNode:(ASVideoPlayerNode*)videoPlayer shouldChangeVideoNodeStateTo:(ASVideoNodePlayerState)state; + +/** + * @abstract Delegate method invoked when the ASVideoNode has played to its end time. + * @param videoPlayerNode The video node has played to its end time. + */ +- (void)videoPlayerNodePlaybackDidFinish:(ASVideoPlayerNode *)videoPlayer; + @end NS_ASSUME_NONNULL_END #endif diff --git a/AsyncDisplayKit/ASVideoPlayerNode.mm b/AsyncDisplayKit/ASVideoPlayerNode.mm index 5bbbf05373..ff2d825f87 100644 --- a/AsyncDisplayKit/ASVideoPlayerNode.mm +++ b/AsyncDisplayKit/ASVideoPlayerNode.mm @@ -24,6 +24,10 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; unsigned int delegateScrubberThumbImage:1; unsigned int delegateTimeLabelAttributes:1; unsigned int delegateLayoutSpecForControls:1; + unsigned int delegateVideoNodeDidPlayToTime:1; + unsigned int delegateVideoNodeWillChangeState:1; + unsigned int delegateVideoNodeShouldChangeState:1; + unsigned int delegateVideoNodePlaybackDidFinish:1; } _delegateFlags; NSURL *_url; @@ -297,17 +301,36 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; } #pragma mark - ASVideoNodeDelegate -- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate +- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toState { - if (toSate == ASVideoNodePlayerStateReadyToPlay) { + if (_delegateFlags.delegateVideoNodeWillChangeState) { + [_delegate videoPlayerNode:self willChangeVideoNodeState:state toVideoNodeState:toState]; + } + + if (toState == ASVideoNodePlayerStateReadyToPlay) { _duration = _videoNode.currentItem.duration; [self updateDurationTimeLabel]; } } +- (BOOL)videoNode:(ASVideoNode *)videoNode shouldChangePlayerStateTo:(ASVideoNodePlayerState)state +{ + if (_delegateFlags.delegateVideoNodeShouldChangeState) { + return [_delegate videoPlayerNode:self shouldChangeVideoNodeStateTo:state]; + } + return YES; +} + - (void)videoNode:(ASVideoNode *)videoNode didPlayToSecond:(NSTimeInterval)second { - if(_isSeeking){ + //TODO: ask Max about CMTime problem in ASVideoNode Header file + //as we said yesterday, we must use CMTime in ASVideoNode instead of NSTimeInterval + //when this will be done, must just proxy value to delegate + if (_delegateFlags.delegateVideoNodeDidPlayToTime) { + [_delegate videoPlayerNode:self didPlayToTime:_videoNode.player.currentTime]; + } + + if (_isSeeking) { return; } @@ -317,6 +340,9 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; - (void)videoPlaybackDidFinish:(ASVideoNode *)videoNode { + if (_delegateFlags.delegateVideoNodePlaybackDidFinish) { + [_delegate videoPlayerNodePlaybackDidFinish:self]; + } //[self removeControls]; } @@ -449,6 +475,10 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; _delegateFlags.delegateScrubberThumbImage = [_delegate respondsToSelector:@selector(videoPlayerNodeScrubberThumbImage:)]; _delegateFlags.delegateTimeLabelAttributes = [_delegate respondsToSelector:@selector(videoPlayerNodeTimeLabelAttributes:timeLabelType:)]; _delegateFlags.delegateLayoutSpecForControls = [_delegate respondsToSelector:@selector(videoPlayerNodeLayoutSpec:forControls:forConstrainedSize:)]; + _delegateFlags.delegateVideoNodeDidPlayToTime = [_delegate respondsToSelector:@selector(videoPlayerNode:didPlayToTime:)]; + _delegateFlags.delegateVideoNodeWillChangeState = [_delegate respondsToSelector:@selector(videoPlayerNode:willChangeVideoNodeState:toVideoNodeState:)]; + _delegateFlags.delegateVideoNodePlaybackDidFinish = [_delegate respondsToSelector:@selector(videoPlayerNodePlaybackDidFinish:)]; + _delegateFlags.delegateVideoNodeShouldChangeState = [_delegate respondsToSelector:@selector(videoPlayerNode:shouldChangeVideoNodeStateTo:)]; } } diff --git a/examples/ASDKTube/Sample/ViewController.m b/examples/ASDKTube/Sample/ViewController.m index 0f831e12d5..6087e9d95f 100644 --- a/examples/ASDKTube/Sample/ViewController.m +++ b/examples/ASDKTube/Sample/ViewController.m @@ -129,5 +129,4 @@ return mainVerticalStack; } - @end \ No newline at end of file