From 3e8437ae559487362fae3525beb79c534c213a51 Mon Sep 17 00:00:00 2001 From: 单军华 Date: Thu, 12 Jul 2018 13:44:34 +0800 Subject: [PATCH] bug修复和功能优化 --- screendisplay/Pods/ZFPlayer/ZFPlayer/Classes/Core/ZFPlayerController.m | 875 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 875 insertions(+), 0 deletions(-) diff --git a/screendisplay/Pods/ZFPlayer/ZFPlayer/Classes/Core/ZFPlayerController.m b/screendisplay/Pods/ZFPlayer/ZFPlayer/Classes/Core/ZFPlayerController.m new file mode 100644 index 0000000..ff3be56 --- /dev/null +++ b/screendisplay/Pods/ZFPlayer/ZFPlayer/Classes/Core/ZFPlayerController.m @@ -0,0 +1,875 @@ +// +// ZFPlayer.m +// ZFPlayer +// +// Copyright (c) 2016��� ��������� ( http://github.com/renzifeng ) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "ZFPlayerController.h" +#import <objc/runtime.h> +#import <MediaPlayer/MediaPlayer.h> +#import <AVFoundation/AVFoundation.h> +#import "ZFPlayerNotification.h" +#import "UIScrollView+ZFPlayer.h" +#import "ZFReachabilityManager.h" +#import "ZFPlayer.h" + +@interface ZFPlayerController () + +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) ZFPlayerNotification *notification; +@property (nonatomic, strong) id<ZFPlayerMediaPlayback> currentPlayerManager; +@property (nonatomic, strong, nullable) UIScrollView *scrollView; +@property (nonatomic, assign, getter=isPauseByUser) BOOL pauseByUser; +@property (nonatomic, strong) UISlider *volumeViewSlider; +@property (nonatomic, assign) NSTimeInterval currentTime; +@property (nonatomic, assign) NSTimeInterval totalTime; +@property (nonatomic, assign) NSTimeInterval bufferTime; +/// The view tag that the player display in scrollView. +@property (nonatomic, assign) NSInteger containerViewTag; + +@end + +@implementation ZFPlayerController + +- (instancetype)init { + self = [super init]; + if (self) { + @weakify(self) + [[ZFReachabilityManager sharedManager] startMonitoring]; + [[ZFReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(ZFReachabilityStatus status) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(videoPlayer:reachabilityChanged:)]) { + [self.controlView videoPlayer:self reachabilityChanged:status]; + } + }]; + [self configureVolume]; + } + return self; +} + +/// Get system volume +- (void)configureVolume { + MPVolumeView *volumeView = [[MPVolumeView alloc] init]; + self.volumeViewSlider = nil; + for (UIView *view in [volumeView subviews]){ + if ([view.class.description isEqualToString:@"MPVolumeSlider"]){ + self.volumeViewSlider = (UISlider *)view; + break; + } + } + // Apps using this category don't mute when the phone's mute button is turned on, but play sound when the phone is silent + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; + [[AVAudioSession sharedInstance] setActive:YES error:nil]; +} + +- (void)dealloc { + [self.currentPlayerManager stop]; +} + ++ (instancetype)playerWithPlayerManager:(id<ZFPlayerMediaPlayback>)playerManager containerView:(nonnull UIView *)containerView { + ZFPlayerController *player = [[self alloc] init]; + player.currentPlayerManager = playerManager; + player.containerView = containerView; + return player; +} + ++ (instancetype)playerWithScrollView:(UIScrollView *)scrollView playerManager:(id<ZFPlayerMediaPlayback>)playerManager containerViewTag:(NSInteger)containerViewTag { + ZFPlayerController *player = [[self alloc] init]; + player.scrollView = scrollView; + player.currentPlayerManager = playerManager; + player.containerViewTag = containerViewTag; + return player; +} + +- (instancetype)initWithPlayerManager:(id<ZFPlayerMediaPlayback>)playerManager containerView:(nonnull UIView *)containerView { + ZFPlayerController *player = [self init]; + player.currentPlayerManager = playerManager; + player.containerView = containerView; + return player; +} + +- (instancetype)initWithScrollView:(UIScrollView *)scrollView playerManager:(id<ZFPlayerMediaPlayback>)playerManager containerViewTag:(NSInteger)containerViewTag { + ZFPlayerController *player = [self init]; + player.scrollView = scrollView; + player.currentPlayerManager = playerManager; + player.containerViewTag = containerViewTag; + return player; +} + +- (void)playerManagerCallbcak { + @weakify(self) + self.currentPlayerManager.playerPlayTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval currentTime, NSTimeInterval duration) { + @strongify(self) + self.currentTime = currentTime; + self.totalTime = duration; + if ([self.controlView respondsToSelector:@selector(videoPlayer:currentTime:totalTime:)]) { + [self.controlView videoPlayer:self currentTime:currentTime totalTime:duration]; + } + }; + + self.currentPlayerManager.playerBufferTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval bufferTime) { + @strongify(self) + self.bufferTime = bufferTime; + if ([self.controlView respondsToSelector:@selector(videoPlayer:bufferTime:)]) { + [self.controlView videoPlayer:self bufferTime:bufferTime]; + } + }; + + self.currentPlayerManager.playerPrepareToPlay = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSURL * _Nonnull assetURL) { + @strongify(self) + self.currentPlayerManager.view.hidden = NO; + if ([self.controlView respondsToSelector:@selector(videoPlayer:prepareToPlay:)]) { + [self.controlView videoPlayer:self prepareToPlay:assetURL]; + } + }; + + self.currentPlayerManager.playerPlayStatChanged = ^(id _Nonnull asset, ZFPlayerPlaybackState playState) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(videoPlayer:playStateChanged:)]) { + [self.controlView videoPlayer:self playStateChanged:playState]; + } + }; + + self.currentPlayerManager.playerLoadStatChanged = ^(id _Nonnull asset, ZFPlayerLoadState loadState) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(videoPlayer:loadStateChanged:)]) { + [self.controlView videoPlayer:self loadStateChanged:loadState]; + } + }; + + self.currentPlayerManager.playerDidToEnd = ^(id _Nonnull asset) { + @strongify(self) + if (self.playerDidToEnd) self.playerDidToEnd(asset); + if ([self.controlView respondsToSelector:@selector(videoPlayerPlayEnd:)]) { + [self.controlView videoPlayerPlayEnd:self]; + } + }; +} + +- (void)layoutPlayerSubViews { + self.containerView.userInteractionEnabled = YES; + [self.containerView addSubview:self.currentPlayerManager.view]; + [self.currentPlayerManager.view addSubview:self.controlView]; + + self.currentPlayerManager.view.frame = self.controlView.bounds; + self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.controlView.frame = self.currentPlayerManager.view.bounds; + self.controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; +} + +#pragma mark - getter + +- (ZFPlayerNotification *)notification { + if (!_notification) { + _notification = [[ZFPlayerNotification alloc] init]; + @weakify(self) + _notification.willResignActive = ^(ZFPlayerNotification * _Nonnull registrar) { + @strongify(self) + if (self.pauseWhenAppResignActive && self.currentPlayerManager.isPlaying) { + [self.currentPlayerManager pause]; + self.pauseByUser = YES; + } + }; + _notification.didBecomeActive = ^(ZFPlayerNotification * _Nonnull registrar) { + @strongify(self) + if (self.isPauseByUser) { + [self.currentPlayerManager play]; + self.pauseByUser = NO; + } + }; + _notification.oldDeviceUnavailable = ^(ZFPlayerNotification * _Nonnull registrar) { + @strongify(self) + if (self.currentPlayerManager.isPlaying) { + [self.currentPlayerManager play]; + } + }; + } + return _notification; +} + +#pragma mark - setter + +- (void)setCurrentPlayerManager:(id<ZFPlayerMediaPlayback>)currentPlayerManager { + if (!currentPlayerManager) return; + _currentPlayerManager = currentPlayerManager; + _currentPlayerManager.view.hidden = YES; + self.gestureControl.disableTypes = self.disableGestureTypes; + [self.gestureControl addGestureToView:currentPlayerManager.view]; + [self playerManagerCallbcak]; + [self.notification addNotification]; +} + +- (void)setContainerView:(UIView *)containerView { + if (!containerView) return; + _containerView = containerView; + containerView.userInteractionEnabled = YES; + [containerView addSubview:self.currentPlayerManager.view]; + self.currentPlayerManager.view.frame = containerView.bounds; + self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.orientationObserver addDeviceOrientationObserver]; +} + +- (void)setControlView:(UIView<ZFPlayerMediaControl> *)controlView { + if (!controlView) return; + _controlView = controlView; + controlView.player = self; + [self.currentPlayerManager.view addSubview:controlView]; + controlView.frame = self.currentPlayerManager.view.bounds; + controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; +} + +@end + +@implementation ZFPlayerController (ZFPlayerTimeControl) + +- (float)progress { + if (self.totalTime == 0) return 0; + return self.currentTime/self.totalTime; +} + +- (float)bufferProgress { + if (self.totalTime == 0) return 0; + return self.bufferTime/self.totalTime; +} + +- (void)seekToTime:(NSTimeInterval)time completionHandler:(void (^)(BOOL))completionHandler { + [self.currentPlayerManager seekToTime:time completionHandler:completionHandler]; +} + +@end + +@implementation ZFPlayerController (ZFPlayerPlaybackControl) + +- (void)stop { + [self.notification removeNotification]; + [self.orientationObserver removeDeviceOrientationObserver]; + [self.currentPlayerManager stop]; + + [self.currentPlayerManager.view removeFromSuperview]; +} + +- (void)replaceCurrentPlayerManager:(id<ZFPlayerMediaPlayback>)manager { + if (self.currentPlayerManager.isPreparedToPlay) { + [self.notification removeNotification]; + [self.orientationObserver removeDeviceOrientationObserver]; + [self stop]; + } + [self.gestureControl removeGestureToView:self.currentPlayerManager.view]; + self.currentPlayerManager = manager; + [self layoutPlayerSubViews]; +} + +- (void)playTheNext { + if (self.assetURLs.count > 0) { + NSInteger index = self.currentPlayIndex + 1; + if (index >= self.assetURLs.count) return; + NSURL *assetURL = [self.assetURLs objectAtIndex:index]; + self.assetURL = assetURL; + self.currentPlayIndex = [self.assetURLs indexOfObject:assetURL]; + } +} + +- (void)playThePrevious { + if (self.assetURLs.count > 0) { + NSInteger index = self.currentPlayIndex - 1; + if (index < 0) return; + NSURL *assetURL = [self.assetURLs objectAtIndex:index]; + self.assetURL = assetURL; + self.currentPlayIndex = [self.assetURLs indexOfObject:assetURL]; + } +} + +- (void)playTheIndex:(NSInteger)index { + if (self.assetURLs.count > 0) { + if (index >= self.assetURLs.count) return; + NSURL *assetURL = [self.assetURLs objectAtIndex:index]; + self.assetURL = assetURL; + self.currentPlayIndex = index; + } +} + +#pragma mark - getter + +- (NSURL *)assetURL { + return objc_getAssociatedObject(self, _cmd); +} + +- (NSArray<NSURL *> *)assetURLs { + return objc_getAssociatedObject(self, _cmd); +} + +- (BOOL)isLastAssetURL { + if (self.assetURLs.count > 0) { + return self.assetURL == self.assetURLs.lastObject; + } + return NO; +} + +- (BOOL)isFirstAssetURL { + if (self.assetURLs.count > 0) { + return self.assetURL == self.assetURLs.firstObject; + } + return NO; +} + +- (BOOL)isWWANAutoPlay { + NSNumber *number = objc_getAssociatedObject(self, _cmd); + if (number) return number.boolValue; + self.WWANAutoPlay = YES; + return YES; +} + +- (float)brightness { + return [UIScreen mainScreen].brightness; +} + +- (float)volume { + CGFloat volume = self.volumeViewSlider.value; + if (volume == 0) { + volume = [[AVAudioSession sharedInstance] outputVolume]; + } + return volume; +} + +- (BOOL)isMuted { + return self.volume == 0; +} + +- (float)lastVolumeValue { + return [objc_getAssociatedObject(self, _cmd) floatValue]; +} + +- (ZFPlayerPlaybackState)playState { + return self.currentPlayerManager.playState; +} + +- (BOOL)isPlaying { + return self.currentPlayerManager.isPlaying; +} + +- (BOOL)pauseWhenAppResignActive { + NSNumber *number = objc_getAssociatedObject(self, _cmd); + if (number) return number.boolValue; + self.pauseWhenAppResignActive = YES; + return YES; +} + +- (void (^)(id _Nonnull))playerDidToEnd { + return objc_getAssociatedObject(self, _cmd); +} + +- (NSInteger)currentPlayIndex { + return [objc_getAssociatedObject(self, _cmd) integerValue]; +} + +#pragma mark - setter + +- (void)setAssetURL:(NSURL *)assetURL { + objc_setAssociatedObject(self, @selector(assetURL), assetURL, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + if (self.currentPlayerManager.isPreparedToPlay) [self.currentPlayerManager stop]; + if (!self.currentPlayerManager.view.superview) self.containerView = self.containerView; + self.currentPlayerManager.assetURL = assetURL; +} + +- (void)setAssetURLs:(NSArray<NSURL *> * _Nullable)assetURLs { + objc_setAssociatedObject(self, @selector(assetURLs), assetURLs, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setWWANAutoPlay:(BOOL)WWANAutoPlay { + objc_setAssociatedObject(self, @selector(isWWANAutoPlay), @(WWANAutoPlay), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + if (self.scrollView) self.scrollView.zf_WWANAutoPlay = self.isWWANAutoPlay; +} + +- (void)setVolume:(float)volume { + volume = MIN(MAX(0, volume), 1); + objc_setAssociatedObject(self, @selector(volume), @(volume), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.volumeViewSlider.value = volume; +} + +- (void)setMuted:(BOOL)muted { + if (muted) { + self.lastVolumeValue = self.volumeViewSlider.value; + self.volumeViewSlider.value = 0; + } else { + self.volumeViewSlider.value = self.lastVolumeValue; + } +} + +- (void)setLastVolumeValue:(float)lastVolumeValue { + objc_setAssociatedObject(self, @selector(lastVolumeValue), @(lastVolumeValue), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setBrightness:(float)brightness { + brightness = MIN(MAX(0, brightness), 1); + objc_setAssociatedObject(self, @selector(brightness), @(brightness), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [UIScreen mainScreen].brightness = brightness; +} + +- (void)setPauseWhenAppResignActive:(BOOL)pauseWhenAppResignActive { + objc_setAssociatedObject(self, @selector(pauseWhenAppResignActive), @(pauseWhenAppResignActive), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setPlayerDidToEnd:(void (^)(id _Nonnull))playerDidToEnd { + objc_setAssociatedObject(self, @selector(playerDidToEnd), playerDidToEnd, OBJC_ASSOCIATION_COPY); +} + +- (void)setCurrentPlayIndex:(NSInteger)currentPlayIndex { + objc_setAssociatedObject(self, @selector(currentPlayIndex), @(currentPlayIndex), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +@end + +@implementation ZFPlayerController (ZFPlayerOrientationRotation) + +- (void)addDeviceOrientationObserver { + [self.orientationObserver addDeviceOrientationObserver]; +} + +- (void)removeDeviceOrientationObserver { + [self.orientationObserver removeDeviceOrientationObserver]; +} + +- (void)enterLandscapeFullScreen:(UIInterfaceOrientation)orientation animated:(BOOL)animated { + self.orientationObserver.fullScreenMode = ZFFullScreenModeLandscape; + [self.orientationObserver enterLandscapeFullScreen:orientation animated:animated]; +} + +- (void)enterPortraitFullScreen:(BOOL)fullScreen animated:(BOOL)animated { + self.orientationObserver.fullScreenMode = ZFFullScreenModePortrait; + [self.orientationObserver enterPortraitFullScreen:fullScreen animated:YES]; +} + +- (void)enterFullScreen:(BOOL)fullScreen animated:(BOOL)animated { + if (self.orientationObserver.fullScreenMode == ZFFullScreenModePortrait) { + [self.orientationObserver enterPortraitFullScreen:fullScreen animated:YES]; + } else { + UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown; + orientation = fullScreen? UIInterfaceOrientationLandscapeRight : UIInterfaceOrientationPortrait; + [self.orientationObserver enterLandscapeFullScreen:orientation animated:animated]; + } +} + +#pragma mark - getter + +- (ZFOrientationObserver *)orientationObserver { + if (!self.currentPlayerManager.view && !self.containerView) return nil; + @weakify(self) + ZFOrientationObserver *orientationObserver = objc_getAssociatedObject(self, _cmd); + if (!orientationObserver) { + orientationObserver = [[ZFOrientationObserver alloc] initWithRotateView:self.currentPlayerManager.view containerView:self.containerView]; + orientationObserver.orientationWillChange = ^(ZFOrientationObserver * _Nonnull observer, BOOL isFullScreen) { + @strongify(self) + if (self.orientationWillChange) self.orientationWillChange(self, isFullScreen); + if ([self.controlView respondsToSelector:@selector(videoPlayer:orientationWillChange:)]) { + [self.controlView videoPlayer:self orientationWillChange:observer]; + } + [self.controlView setNeedsLayout]; + [self.controlView layoutIfNeeded]; + }; + orientationObserver.orientationDidChanged = ^(ZFOrientationObserver * _Nonnull observer, BOOL isFullScreen) { + @strongify(self) + if (self.orientationDidChanged) self.orientationDidChanged(self, isFullScreen); + if ([self.controlView respondsToSelector:@selector(videoPlayer:orientationDidChanged:)]) { + [self.controlView videoPlayer:self orientationDidChanged:observer]; + } + }; + objc_setAssociatedObject(self, _cmd, orientationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return orientationObserver; +} + +- (void (^)(ZFPlayerController * _Nonnull, BOOL))orientationWillChange { + return objc_getAssociatedObject(self, _cmd); +} + +- (void (^)(ZFPlayerController * _Nonnull, BOOL))orientationDidChanged { + return objc_getAssociatedObject(self, _cmd); +} + +- (BOOL)isFullScreen { + return self.orientationObserver.isFullScreen; +} + +- (UIInterfaceOrientation)currentOrientation { + return self.orientationObserver.currentOrientation; +} + +- (BOOL)isStatusBarHidden { + return self.orientationObserver.isStatusBarHidden; +} + +- (BOOL)isLockedScreen { + return self.orientationObserver.isLockedScreen; +} + +- (BOOL)shouldAutorotate { + return self.orientationObserver.shouldAutorotate; +} + +#pragma mark - setter + +- (void)setOrientationWillChange:(void (^)(ZFPlayerController * _Nonnull, BOOL))orientationWillChange { + objc_setAssociatedObject(self, @selector(orientationWillChange), orientationWillChange, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (void)setOrientationDidChanged:(void (^)(ZFPlayerController * _Nonnull, BOOL))orientationDidChanged { + objc_setAssociatedObject(self, @selector(orientationDidChanged), orientationDidChanged, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (void)setStatusBarHidden:(BOOL)statusBarHidden { + objc_setAssociatedObject(self, @selector(isStatusBarHidden), @(statusBarHidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.orientationObserver.statusBarHidden = statusBarHidden; +} + +- (void)setLockedScreen:(BOOL)lockedScreen { + objc_setAssociatedObject(self, @selector(isLockedScreen), @(lockedScreen), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.orientationObserver.lockedScreen = lockedScreen; + if ([self.controlView respondsToSelector:@selector(lockedVideoPlayer:lockedScreen:)]) { + [self.controlView lockedVideoPlayer:self lockedScreen:lockedScreen]; + } +} + +- (void)setShouldAutorotate:(BOOL)shouldAutorotate { + objc_setAssociatedObject(self, @selector(shouldAutorotate), @(shouldAutorotate), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.orientationObserver.shouldAutorotate = shouldAutorotate; +} + +@end + + +@implementation ZFPlayerController (ZFPlayerViewGesture) + +#pragma mark - getter + +- (ZFPlayerGestureControl *)gestureControl { + ZFPlayerGestureControl *gestureControl = objc_getAssociatedObject(self, _cmd); + if (!gestureControl) { + gestureControl = [[ZFPlayerGestureControl alloc] init]; + @weakify(self) + gestureControl.triggerCondition = ^BOOL(ZFPlayerGestureControl * _Nonnull control, ZFPlayerGestureType type, UIGestureRecognizer * _Nonnull gesture, UITouch *touch) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gestureTriggerCondition:gestureType:gestureRecognizer:touch:)]) { + return [self.controlView gestureTriggerCondition:control gestureType:type gestureRecognizer:gesture touch:touch]; + } + return YES; + }; + + gestureControl.singleTapped = ^(ZFPlayerGestureControl * _Nonnull control) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gestureSingleTapped:)]) { + [self.controlView gestureSingleTapped:control]; + } + }; + + gestureControl.doubleTapped = ^(ZFPlayerGestureControl * _Nonnull control) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gestureDoubleTapped:)]) { + [self.controlView gestureDoubleTapped:control]; + } + }; + + gestureControl.beganPan = ^(ZFPlayerGestureControl * _Nonnull control, ZFPanDirection direction, ZFPanLocation location) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gestureBeganPan:panDirection:panLocation:)]) { + [self.controlView gestureBeganPan:control panDirection:direction panLocation:location]; + } + }; + + gestureControl.changedPan = ^(ZFPlayerGestureControl * _Nonnull control, ZFPanDirection direction, ZFPanLocation location, CGPoint velocity) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gestureChangedPan:panDirection:panLocation:withVelocity:)]) { + [self.controlView gestureChangedPan:control panDirection:direction panLocation:location withVelocity:velocity]; + } + }; + + gestureControl.endedPan = ^(ZFPlayerGestureControl * _Nonnull control, ZFPanDirection direction, ZFPanLocation location) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gestureEndedPan:panDirection:panLocation:)]) { + [self.controlView gestureEndedPan:control panDirection:direction panLocation:location]; + } + }; + + gestureControl.pinched = ^(ZFPlayerGestureControl * _Nonnull control, float scale) { + @strongify(self) + if ([self.controlView respondsToSelector:@selector(gesturePinched:scale:)]) { + [self.controlView gesturePinched:control scale:scale]; + } + }; + objc_setAssociatedObject(self, _cmd, gestureControl, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return gestureControl; +} + +- (ZFPlayerDisableGestureTypes)disableGestureTypes { + return [objc_getAssociatedObject(self, _cmd) unsignedIntegerValue]; +} + +#pragma mark - setter + +- (void)setDisableGestureTypes:(ZFPlayerDisableGestureTypes)disableGestureTypes { + objc_setAssociatedObject(self, @selector(disableGestureTypes), @(disableGestureTypes), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.gestureControl.disableTypes = disableGestureTypes; +} + +@end + +@implementation ZFPlayerController (ZFPlayerScrollView) + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + SEL selectors[] = { + NSSelectorFromString(@"dealloc") + }; + + for (NSInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) { + SEL originalSelector = selectors[index]; + SEL swizzledSelector = NSSelectorFromString([@"zf_" stringByAppendingString:NSStringFromSelector(originalSelector)]); + Method originalMethod = class_getInstanceMethod(self, originalSelector); + Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector); + if (class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) { + class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } + } + }); +} + +- (void)zf_dealloc { + [self.smallFloatView removeFromSuperview]; + self.smallFloatView = nil; + [self zf_dealloc]; +} + +//// Add video to the cell +- (void)addPlayerViewToCell { + self.isSmallFloatViewShow = NO; + self.smallFloatView.hidden = YES; + UIView *cell = [self.scrollView zf_getCellForIndexPath:self.playingIndexPath]; + self.containerView = [cell viewWithTag:self.containerViewTag]; + [self.containerView addSubview:self.currentPlayerManager.view]; + self.currentPlayerManager.view.frame = self.containerView.bounds; + self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.orientationObserver cellModelRotateView:self.currentPlayerManager.view rotateViewAtCell:cell playerViewTag:self.containerViewTag]; +} + +/// Add to the keyWindow +- (void)addPlayerViewToKeyWindow { + self.isSmallFloatViewShow = YES; + self.smallFloatView.hidden = NO; + [self.smallFloatView addSubview:self.currentPlayerManager.view]; + self.currentPlayerManager.view.frame = self.smallFloatView.bounds; + self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.orientationObserver cellSmallModelRotateView:self.currentPlayerManager.view containerView:self.smallFloatView]; +} + +#pragma mark - setter + +- (void)setScrollView:(UIScrollView *)scrollView { + objc_setAssociatedObject(self, @selector(scrollView), scrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.scrollView.zf_WWANAutoPlay = self.isWWANAutoPlay; + @weakify(self) + scrollView.zf_enableScrollHook = YES; + scrollView.zf_playerDidAppearInScrollView = ^(NSIndexPath * _Nonnull indexPath) { + @strongify(self) + if (self.isFullScreen) return; + if ([self.controlView respondsToSelector:@selector(playerDidAppearInScrollView:)]) { + [self.controlView playerDidAppearInScrollView:self]; + } + if (!self.stopWhileNotVisible) { + [self addPlayerViewToCell]; + } + }; + + scrollView.zf_playerWillDisappearInScrollView = ^(NSIndexPath * _Nonnull indexPath) { + @strongify(self) + if (self.isFullScreen) return; + if ([self.controlView respondsToSelector:@selector(playerWillDisappearInScrollView:)]) { + [self.controlView playerWillDisappearInScrollView:self]; + } + }; + + scrollView.zf_playerDisappearHalfInScrollView = ^(NSIndexPath * _Nonnull indexPath) { + @strongify(self) + if (self.isFullScreen) return; + if ([self.controlView respondsToSelector:@selector(playerDisappearHalfInScrollView:)]) { + [self.controlView playerDisappearHalfInScrollView:self]; + } + if (self.stopWhileNotVisible) { + [self stopCurrentPlayingCell]; + } + }; + + scrollView.zf_playerDidDisappearInScrollView = ^(NSIndexPath * _Nonnull indexPath) { + @strongify(self) + if (self.isFullScreen) return; + if ([self.controlView respondsToSelector:@selector(playerDidDisappearInScrollView:)]) { + [self.controlView playerDidDisappearInScrollView:self]; + } + if (!self.stopWhileNotVisible) { + [self addPlayerViewToKeyWindow]; + } else { + [self stopCurrentPlayingCell]; + } + }; +} + +- (void)setStopWhileNotVisible:(BOOL)stopWhileNotVisible { + self.scrollView.zf_stopWhileNotVisible = stopWhileNotVisible; + objc_setAssociatedObject(self, @selector(stopWhileNotVisible), @(stopWhileNotVisible), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setContainerViewTag:(NSInteger)containerViewTag { + objc_setAssociatedObject(self, @selector(containerViewTag), @(containerViewTag), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + self.scrollView.zf_containerViewTag = containerViewTag; +} + +- (void)setPlayingIndexPath:(NSIndexPath *)playingIndexPath { + objc_setAssociatedObject(self, @selector(playingIndexPath), playingIndexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + if (playingIndexPath) { + [self stopCurrentPlayingCell]; + UIView *cell = [self.scrollView zf_getCellForIndexPath:playingIndexPath]; + self.containerView = [cell viewWithTag:self.containerViewTag]; + [self.orientationObserver cellModelRotateView:self.currentPlayerManager.view rotateViewAtCell:cell playerViewTag:self.containerViewTag]; + [self.orientationObserver addDeviceOrientationObserver]; + self.scrollView.zf_playingIndexPath = playingIndexPath; + } +} + +- (void)setShouldAutoPlay:(BOOL)shouldAutoPlay { + self.scrollView.zf_shouldAutoPlay = shouldAutoPlay; +} + +- (void)setSectionAssetURLs:(NSArray<NSArray<NSURL *> *> * _Nullable)sectionAssetURLs { + objc_setAssociatedObject(self, @selector(sectionAssetURLs), sectionAssetURLs, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setSmallFloatView:(ZFFloatView * _Nullable)smallFloatView { + objc_setAssociatedObject(self, @selector(smallFloatView), smallFloatView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setIsSmallFloatViewShow:(BOOL)isSmallFloatViewShow { + objc_setAssociatedObject(self, @selector(isSmallFloatViewShow), @(isSmallFloatViewShow), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +#pragma mark - getter + +- (UIScrollView *)scrollView { + UIScrollView *scrollView = objc_getAssociatedObject(self, _cmd); + return scrollView; +} + +- (BOOL)stopWhileNotVisible { + NSNumber *number = objc_getAssociatedObject(self, _cmd); + if (number) return number.boolValue; + self.stopWhileNotVisible = YES; + return YES; +} + +- (NSInteger)containerViewTag { + return [objc_getAssociatedObject(self, _cmd) integerValue]; +} + +- (ZFFloatView *)smallFloatView { + ZFFloatView *smallFloatView = objc_getAssociatedObject(self, _cmd); + if (!smallFloatView) { + smallFloatView = [[ZFFloatView alloc] init]; + smallFloatView.parentView = [UIApplication sharedApplication].keyWindow; + smallFloatView.hidden = YES; + self.smallFloatView = smallFloatView; + } + return smallFloatView; +} + +- (BOOL)isSmallFloatViewShow { + return [objc_getAssociatedObject(self, _cmd) boolValue]; +} + +- (NSIndexPath *)playingIndexPath { + return objc_getAssociatedObject(self, _cmd); +} + +- (NSArray<NSArray<NSURL *> *> *)sectionAssetURLs { + return objc_getAssociatedObject(self, _cmd); +} + +- (BOOL)shouldAutoPlay { + return self.scrollView.zf_shouldAutoPlay; +} + +- (void)playTheIndexPath:(NSIndexPath *)indexPath scrollToTop:(BOOL)scrollToTop completionHandler:(void (^ _Nullable)(void))completionHandler { + NSURL *assetURL; + if (self.sectionAssetURLs.count) { + assetURL = self.sectionAssetURLs[indexPath.section][indexPath.row]; + } else if (self.assetURLs.count) { + assetURL = self.assetURLs[indexPath.row]; + self.currentPlayIndex = indexPath.row; + } + if (scrollToTop) { + @weakify(self) + [self.scrollView zf_scrollToRowAtIndexPath:indexPath completionHandler:^{ + @strongify(self) + if (completionHandler) completionHandler(); + self.playingIndexPath = indexPath; + self.assetURL = assetURL; + [self.scrollView zf_scrollViewDidStopScroll]; + }]; + } else { + if (completionHandler) completionHandler(); + self.playingIndexPath = indexPath; + self.assetURL = assetURL; + } +} + +- (void)playTheIndexPath:(NSIndexPath *)indexPath scrollToTop:(BOOL)scrollToTop { + self.playingIndexPath = indexPath; + NSURL *assetURL; + if (self.sectionAssetURLs.count) { + assetURL = self.sectionAssetURLs[indexPath.section][indexPath.row]; + } else if (self.assetURLs.count) { + assetURL = self.assetURLs[indexPath.row]; + self.currentPlayIndex = indexPath.row; + } + self.assetURL = assetURL; + if (scrollToTop) { + [self.scrollView zf_scrollToRowAtIndexPath:indexPath completionHandler:nil]; + } +} + +- (void)playTheIndexPath:(NSIndexPath *)indexPath assetURL:(NSURL *)assetURL scrollToTop:(BOOL)scrollToTop { + self.playingIndexPath = indexPath; + self.assetURL = assetURL; + if (scrollToTop) { + [self.scrollView zf_scrollToRowAtIndexPath:indexPath completionHandler:nil]; + } +} + +- (void)stopCurrentPlayingCell { + if (self.scrollView.zf_playingIndexPath) { + [self stop]; + self.isSmallFloatViewShow = NO; + self.scrollView.zf_playingIndexPath = nil; + if (self.smallFloatView) self.smallFloatView.hidden = YES; + } +} + +@end -- Gitblit v1.8.0