// // GKDYPlayerManager.m // GKDYVideo // // Created by QuintGao on 2023/3/17. // Copyright © 2023 QuintGao. All rights reserved. // #import "GKDYPlayerManager.h" #import #import #import #import "GKDYVideoCell.h" #import "GKRotationManager.h" #import "GKDYVideoPortraitCell.h" #import "GKDYVideoLandscapeCell.h" #import "GKDYVideoFullscreenView.h" @interface GKDYPlayerManager() @property (nonatomic, strong) ZFPlayerController *player; @property (nonatomic, strong) GKRotationManager *rotationManager; @property (nonatomic, assign) BOOL isSeeking; @property (nonatomic, strong) GKDYVideoFullscreenView *fullscreenView; @end @implementation GKDYPlayerManager - (instancetype)init { if (self = [super init]) { [self initPlayer]; } return self; } - (void)dealloc { NSLog(@"GKDYPlayerManager dealloc"); [self stop]; } - (void)initPlayer { // 初始化播放器 ZFAVPlayerManager *manager = [[ZFAVPlayerManager alloc] init]; ZFPlayerController *player = [[ZFPlayerController alloc] init]; player.shouldAutoPlay = YES; player.currentPlayerManager = manager; player.disableGestureTypes = ZFPlayerDisableGestureTypesPan | ZFPlayerDisableGestureTypesPinch; player.allowOrentitaionRotation = NO; // 禁止自动旋转 self.player = player; @weakify(self); // 播放结束回调 player.playerDidToEnd = ^(id _Nonnull asset) { @strongify(self); [self.scrollView scrollToNextPage]; }; // 播放失败回调 player.playerPlayFailed = ^(id _Nonnull asset, id _Nonnull error) { @strongify(self); self.portraitView.resumeButton.hidden = NO; }; // 加载状态 player.playerLoadStateChanged = ^(id _Nonnull asset, ZFPlayerLoadState loadState) { @strongify(self); if ((loadState == ZFPlayerLoadStatePrepare || loadState == ZFPlayerLoadStateStalled) && self.player.currentPlayerManager.isPlaying) { [self.portraitView.slider showLoading]; }else { [self.portraitView.slider hideLoading]; // [self.player.currentPlayerManager play]; } }; // 播放时间 player.playerPlayTimeChanged = ^(id _Nonnull asset, NSTimeInterval currentTime, NSTimeInterval duration) { @strongify(self); [self.portraitView.slider updateCurrentTime:currentTime totalTime:duration]; }; // 方向即将改变 player.orientationWillChange = ^(ZFPlayerController * _Nonnull player, BOOL isFullScreen) { @strongify(self); self.player.controlView.hidden = YES; if (player.isFullScreen) { [self.landscapeView startTimer]; }else { [self.landscapeView destoryTimer]; } }; // 方向已经改变 player.orientationDidChanged = ^(ZFPlayerController * _Nonnull player, BOOL isFullScreen) { @strongify(self); if (isFullScreen) { self.landscapeView.hidden = NO; self.player.controlView = self.landscapeView; }else { self.portraitView.hidden = NO; self.player.controlView = self.portraitView; } }; self.rotationManager = [GKRotationManager rotationManager]; self.rotationManager.contentView = self.player.currentPlayerManager.view; self.landscapeView.rotationManager = self.rotationManager; // 即将旋转时调用 self.rotationManager.orientationWillChange = ^(BOOL isFullscreen) { @strongify(self); self.player.controlView.hidden = YES; if (isFullscreen) { [self.landscapeView startTimer]; }else { self.player.currentPlayerManager.view.backgroundColor = UIColor.clearColor; self.portraitView.hidden = NO; [self.landscapeView destoryTimer]; if (self.landscapeScrollView) { UIView *superview = self.landscapeScrollView.superview; [superview addSubview:self.rotationManager.contentView]; [self.landscapeScrollView removeFromSuperview]; self.landscapeScrollView = nil; self.landscapeCell = nil; } } }; // 旋转结束时调用 self.rotationManager.orientationDidChanged = ^(BOOL isFullscreen) { @strongify(self); if (isFullscreen) { // self.portraitView.hidden = YES; self.landscapeView.hidden = NO; [self.landscapeView hideContainerView:NO]; if (!self.landscapeScrollView) { [self initLandscapeScrollView]; UIView *superview = self.rotationManager.contentView.superview; self.landscapeScrollView.frame = superview.bounds; [superview addSubview:self.landscapeScrollView]; self.landscapeScrollView.defaultIndex = self.scrollView.currentIndex; [self.landscapeScrollView reloadData]; } self.player.controlView = self.landscapeView; [self.currentCell resetView]; [self.landscapeCell hideTopView]; }else { self.portraitView.hidden = NO; self.landscapeView.hidden = YES; self.player.controlView = self.portraitView; if (self.player.containerView != self.currentCell.coverImgView) { self.player.containerView = self.currentCell.coverImgView; } self.player.currentPlayerManager.view.backgroundColor = UIColor.blackColor; } }; player.presentationSizeChanged = ^(id _Nonnull asset, CGSize size) { @strongify(self); self.videoSize = size; }; } - (void)initLandscapeScrollView { self.landscapeScrollView = [[GKDYVideoScrollView alloc] init]; self.landscapeScrollView.backgroundColor = UIColor.blackColor; self.landscapeScrollView.dataSource = self; self.landscapeScrollView.delegate = self; [self.landscapeScrollView registerClass:GKDYVideoLandscapeCell.class forCellReuseIdentifier:@"GKDYVideoLandscapeCell"]; } - (BOOL)isPlaying { return self.player.currentPlayerManager.isPlaying; } - (void)requestPlayUrlWithModel:(GKDYVideoModel *)model completion:(nullable void (^)(void))completion { if (model.videoInfo.video_url.length > 0) return; // if (model.task) { // [model.task cancel]; // model.task = nil; // } // // AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // // NSString *url = [NSString stringWithFormat:@"https://haokan.baidu.com/v?vid=%@&_format=json&", model.video_id]; // // model.task = [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // if ([responseObject[@"errno"] integerValue] == 0) { // NSDictionary *videoMeta = responseObject[@"data"][@"apiData"][@"curVideoMeta"]; // model.play_url = videoMeta[@"playurl"]; // model.comment = videoMeta[@"comment"]; // model.like = videoMeta[@"fmlike_num"]; // // __block NSInteger index = 0; // __block BOOL exist = NO; // [self.dataSources enumerateObjectsUsingBlock:^(GKDYVideoModel *obj, NSUInteger idx, BOOL * _Nonnull stop) { // if ([obj.video_id isEqualToString:model.video_id]) { // index = idx; // exist = YES; // *stop = YES; // } // }]; // [self.dataSources replaceObjectAtIndex:index withObject:model]; // model.task = nil; // !completion ?: completion(); // } // } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // model.task = nil; // NSLog(@"播放地址请求失败"); // }]; } - (void)playVideoWithCell:(GKDYVideoCell *)cell index:(NSInteger)index { if (self.dataSources.count - index < 2) { if ([self.delegate respondsToSelector:@selector(scrollViewShouldLoadMore)]) { [self.delegate scrollViewShouldLoadMore]; } } GKDYVideoModel *model = self.dataSources[index]; self.landscapeView.model = model; if ([cell isKindOfClass:GKDYVideoPortraitCell.class]) { self.currentCell = (GKDYVideoPortraitCell *)cell; self.portraitView = self.currentCell.portraitView; self.rotationManager.containerView = cell.coverImgView; if (self.rotationManager.isFullscreen) return; }else { self.landscapeCell = (GKDYVideoLandscapeCell *)cell; [self.landscapeCell autoHide]; [self.scrollView scrollToPageWithIndex:index]; } // 设置播放内容视图 if (self.player.containerView != cell.coverImgView) { self.player.containerView = cell.coverImgView; } // 设置播放器控制层视图 if ([cell isKindOfClass:GKDYVideoPortraitCell.class]) { GKDYVideoPortraitCell *portraitCell = (GKDYVideoPortraitCell *)cell; if (self.player.controlView != portraitCell.portraitView) { self.player.controlView = portraitCell.portraitView; self.portraitView = portraitCell.portraitView; } } // 设置封面图片 id manager = self.player.currentPlayerManager; [manager.view.coverImageView sd_setImageWithURL:[NSURL URLWithString:model.image_url]]; if (model.videoInfo.video_url.length > 0) { // 播放内容一致,不做处理 if ([self.player.assetURL.absoluteString isEqualToString:model.videoInfo.video_url]) return; // 设置播放地址 self.player.assetURL = [NSURL URLWithString:model.videoInfo.video_url]; self.portraitView.resumeButton.hidden = YES; if (self.isAppeared) { [self.player.currentPlayerManager play]; } }else { @weakify(self); [self requestPlayUrlWithModel:model completion:^{ @strongify(self); // 播放内容一致,不做处理 if ([self.player.assetURL.absoluteString isEqualToString:model.videoInfo.video_url]) return; // 设置播放地址 self.player.assetURL = [NSURL URLWithString:model.videoInfo.video_url]; self.portraitView.resumeButton.hidden = YES; if (self.isAppeared) { [self.player.currentPlayerManager play]; } }]; } } - (void)stopPlayWithCell:(GKDYVideoCell *)cell index:(NSInteger)index { GKDYVideoModel *model = self.dataSources[index]; if (![self.player.assetURL.absoluteString isEqualToString:model.videoInfo.video_url]) return; [self.player stop]; if ([self.player.controlView isKindOfClass:GKDYVideoPortraitView.class]) { [self.player.controlView removeFromSuperview]; self.player.controlView = nil; } [cell resetView]; } - (void)rotate { [self.rotationManager rotate]; } - (void)play { if (self.isPlaying) return; [self.player.currentPlayerManager play]; // [self.currentCell.portraitView handleSingleTapped]; } - (void)pause { if (!self.isPlaying) return; [self.player.currentPlayerManager pause]; } - (void)stop { [self.player.currentPlayerManager stop]; self.player = nil; } #pragma mark - Private - (void)likeVideoWithModel:(GKDYVideoModel *)model { if (model == nil) { model = self.currentCell.model; } model.is_collect = YES; [self.scrollView reloadData]; } #pragma mark - GKVideoScrollViewDataSource - (NSInteger)numberOfRowsInScrollView:(GKVideoScrollView *)scrollView { return self.dataSources.count; } - (GKVideoViewCell *)scrollView:(GKVideoScrollView *)scrollView cellForRowAtIndexPath:(NSIndexPath *)indexPath { GKDYVideoModel *model = self.dataSources[indexPath.row]; if (scrollView == self.scrollView) { GKDYVideoPortraitCell *cell = [scrollView dequeueReusableCellWithIdentifier:@"GKDYVideoPortraitCell" forIndexPath:indexPath]; cell.delegate = self; cell.manager = self; cell.portraitView.slider.player = self.player; [cell loadData:model]; return cell; }else { GKDYVideoLandscapeCell *cell = [scrollView dequeueReusableCellWithIdentifier:@"GKDYVideoLandscapeCell" forIndexPath:indexPath]; [cell loadData:model]; @weakify(self); cell.backClickBlock = ^{ @strongify(self); [self rotate]; }; [cell showTopView]; return cell; } } #pragma mark - GKDYVideoScrollViewDelegate - (void)scrollView:(GKVideoScrollView *)scrollView didEndScrollingCell:(GKVideoViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { [self playVideoWithCell:(GKDYVideoCell *)cell index:indexPath.row]; if ([self.delegate respondsToSelector:@selector(cellSwitchWithModel:)]) { [self.delegate cellSwitchWithModel:self.dataSources[indexPath.row]]; } } - (void)scrollView:(GKVideoScrollView *)scrollView didEndDisplayingCell:(GKVideoViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { [self stopPlayWithCell:(GKDYVideoCell *)cell index:indexPath.row]; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == self.scrollView) { if (self.scrollView.currentIndex == 0 && scrollView.contentOffset.y < 0) { self.scrollView.contentOffset = CGPointZero; } } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self.portraitView willBeginDragging]; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { [self.portraitView didEndDragging]; } - (void)scrollView:(GKDYVideoScrollView *)scrollView didPanWithDistance:(CGFloat)distance isEnd:(BOOL)isEnd { if ([self.delegate respondsToSelector:@selector(scrollViewDidPanDistance:isEnd:)]) { [self.delegate scrollViewDidPanDistance:distance isEnd:isEnd]; } } #pragma mark - GKDYVideoPortraitCellDelegate - (void)videoCell:(GKDYVideoPortraitCell *)cell didClickFavorite:(GKDYVideoModel *)model { [self.scrollView reloadData]; if ([self.delegate respondsToSelector:@selector(celldidClickFavorite:cell:)]) { [self.delegate celldidClickFavorite:model cell:cell]; } } - (void)videoCell:(GKDYVideoPortraitCell *)cell didClickEpiscode:(GKDYVideoModel *)model { if ([self.delegate respondsToSelector:@selector(celldidClickEpiscode:cell:)]) { [self.delegate celldidClickEpiscode:model cell:cell]; } } - (void)videoCell:(GKDYVideoPortraitCell *)cell didClickShare:(GKDYVideoModel *)model { if ([self.delegate respondsToSelector:@selector(celldidClickShare:cell:)]) { [self.delegate celldidClickShare:model cell:cell]; } } - (void)videoCell:(GKDYVideoPortraitCell *)cell didClickDanmu:(GKDYVideoModel *)model { } - (void)videoCell:(GKDYVideoPortraitCell *)cell didClickFullscreen:(GKDYVideoModel *)model { [self rotate]; } - (void)videoCell:(GKDYVideoPortraitCell *)cell zoomBegan:(GKDYVideoModel *)model { self.player.controlView.hidden = YES; if ([self.delegate respondsToSelector:@selector(cellZoomBegan:)]) { [self.delegate cellZoomBegan:model]; } } - (void)videoCell:(GKDYVideoPortraitCell *)cell zoomEnded:(GKDYVideoModel *)model isFullscreen:(BOOL)isFullscreen { if (isFullscreen) { self.fullscreenView.hidden = NO; if (self.player.controlView != self.fullscreenView) { self.player.controlView = self.fullscreenView; self.player.disableGestureTypes = ZFPlayerDisableGestureTypesPinch; } }else { self.currentCell.portraitView.hidden = NO; if (self.player.controlView != self.currentCell.portraitView) { self.player.controlView = self.currentCell.portraitView; self.player.disableGestureTypes = ZFPlayerDisableGestureTypesPan | ZFPlayerDisableGestureTypesPinch; } } if ([self.delegate respondsToSelector:@selector(cellZoomEnded:isFullscreen:)]) { [self.delegate cellZoomEnded:model isFullscreen:isFullscreen]; } } #pragma mark - Lazy - (GKDYVideoScrollView *)scrollView { if (!_scrollView) { _scrollView = [[GKDYVideoScrollView alloc] init]; _scrollView.dataSource = self; _scrollView.delegate = self; _scrollView.backgroundColor = UIColor.blackColor; [_scrollView registerClass:GKDYVideoPortraitCell.class forCellReuseIdentifier:@"GKDYVideoPortraitCell"]; [_scrollView addPanGesture]; } return _scrollView; } - (GKDYVideoLandscapeView *)landscapeView { if (!_landscapeView) { _landscapeView = [[GKDYVideoLandscapeView alloc] initWithFrame:UIScreen.mainScreen.bounds]; @weakify(self); _landscapeView.likeBlock = ^(GKDYVideoModel * _Nonnull model) { @strongify(self); [self likeVideoWithModel:model]; }; _landscapeView.singleTapBlock = ^{ @strongify(self); if (self.landscapeCell.isShowTop) { [self.landscapeCell hideTopView]; [self.landscapeView hideContainerView:NO]; }else { [self.landscapeView autoHide]; } }; } return _landscapeView; } - (GKDYVideoFullscreenView *)fullscreenView { if (!_fullscreenView) { _fullscreenView = [[GKDYVideoFullscreenView alloc] init]; @weakify(self); _fullscreenView.closeFullscreenBlock = ^{ @strongify(self); [self.currentCell closeFullscreen]; }; _fullscreenView.likeBlock = ^{ @strongify(self); [self likeVideoWithModel:nil]; }; } return _fullscreenView; } - (NSMutableArray *)dataSources { if (!_dataSources) { _dataSources = [NSMutableArray array]; } return _dataSources; } @end