diff --git a/Example/.DS_Store b/Example/.DS_Store index ceb45c32b..edbbd4a9b 100644 Binary files a/Example/.DS_Store and b/Example/.DS_Store differ diff --git a/Example/Pods/Local Podspecs/SJBaseVideoPlayer.podspec.json b/Example/Pods/Local Podspecs/SJBaseVideoPlayer.podspec.json new file mode 100644 index 000000000..8a030f99a --- /dev/null +++ b/Example/Pods/Local Podspecs/SJBaseVideoPlayer.podspec.json @@ -0,0 +1,121 @@ +{ + "name": "SJBaseVideoPlayer", + "version": "3.5.2", + "summary": "video player.", + "description": "https://github.com/changsanjiang/SJBaseVideoPlayer/blob/master/README.md", + "homepage": "https://github.com/changsanjiang/SJBaseVideoPlayer", + "license": { + "type": "MIT", + "file": "LICENSE.md" + }, + "authors": { + "SanJiang": "changsanjiang@gmail.com" + }, + "platforms": { + "ios": "8.0" + }, + "source": { + "git": "https://github.com/changsanjiang/SJBaseVideoPlayer.git", + "tag": "v3.5.2" + }, + "frameworks": [ + "UIKit", + "AVFoundation" + ], + "requires_arc": true, + "source_files": "SJBaseVideoPlayer/*.{h,m}", + "default_subspecs": [ + "Common", + "AVPlayer" + ], + "dependencies": { + "Masonry": [ + + ], + "SJUIKit/AttributesFactory": [ + ">= 0.0.0.38" + ], + "SJUIKit/ObserverHelper": [ + + ], + "SJUIKit/Queues": [ + + ], + "SJUIKit/SQLite3": [ + + ] + }, + "subspecs": [ + { + "name": "Common", + "source_files": "SJBaseVideoPlayer/Common/**/*.{h,m}", + "dependencies": { + "SJBaseVideoPlayer/ResourceLoader": [ + + ] + } + }, + { + "name": "ResourceLoader", + "source_files": "SJBaseVideoPlayer/ResourceLoader/*.{h,m}", + "resources": "SJBaseVideoPlayer/ResourceLoader/SJBaseVideoPlayerResources.bundle" + }, + { + "name": "AVPlayer", + "source_files": "SJBaseVideoPlayer/AVPlayer/**/*.{h,m}", + "dependencies": { + "SJBaseVideoPlayer/Common": [ + + ] + } + }, + { + "name": "IJKPlayer", + "source_files": "SJBaseVideoPlayer/IJKPlayer/**/*.{h,m}", + "dependencies": { + "ijkplayerssl": [ + + ], + "SJBaseVideoPlayer/Common": [ + + ] + } + }, + { + "name": "AliPlayer", + "source_files": "SJBaseVideoPlayer/AliPlayer/**/*.{h,m}", + "dependencies": { + "AliPlayerSDK_iOS": [ + + ], + "SJBaseVideoPlayer/Common": [ + + ] + } + }, + { + "name": "AliVodPlayer", + "source_files": "SJBaseVideoPlayer/AliVodPlayer/**/*.{h,m}", + "dependencies": { + "AliyunPlayer_iOS/AliyunVodPlayerSDK": [ + + ], + "SJBaseVideoPlayer/Common": [ + + ] + } + }, + { + "name": "PLPlayer", + "source_files": "SJBaseVideoPlayer/PLPlayer/**/*.{h,m}", + "dependencies": { + "PLPlayerKit": [ + + ], + "SJBaseVideoPlayer/Common": [ + + ] + } + } + ] +} diff --git a/Example/SJVideoPlayer.xcodeproj/project.pbxproj b/Example/SJVideoPlayer.xcodeproj/project.pbxproj index d8d1e24d6..57bd0eb84 100644 --- a/Example/SJVideoPlayer.xcodeproj/project.pbxproj +++ b/Example/SJVideoPlayer.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 13FEB85DCAAE0D2C731299D6 /* libPods-SJVideoPlayer_Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CCD2CA6C02217556CFBFA7AB /* libPods-SJVideoPlayer_Example.a */; }; + 3B070E8C25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B070E8B25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.m */; }; + 3B070EA225FC916300960506 /* SJFloatSmallViewTransitionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B070EA025FC916300960506 /* SJFloatSmallViewTransitionController.m */; }; 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; @@ -28,7 +30,6 @@ 7700905F24988F6900A99906 /* SJDYUserHomepageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7700905924988F6900A99906 /* SJDYUserHomepageViewController.m */; }; 7700906024988F6900A99906 /* SJDYMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7700905B24988F6900A99906 /* SJDYMainViewController.m */; }; 771BFDBB25AFE1EC0026C277 /* SJFloatModeDemoViewController1.m in Sources */ = {isa = PBXBuildFile; fileRef = 771BFDBA25AFE1EC0026C277 /* SJFloatModeDemoViewController1.m */; }; - 771BFDC025AFE2340026C277 /* SJFloatSmallViewTransitionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 771BFDBE25AFE2340026C277 /* SJFloatSmallViewTransitionController.m */; }; 77357E462373DA3E00B81EE4 /* SJTestAliViewController3.m in Sources */ = {isa = PBXBuildFile; fileRef = 77357E442373DA3E00B81EE4 /* SJTestAliViewController3.m */; }; 77357E472373DA3E00B81EE4 /* SJTestAliViewController3.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77357E452373DA3E00B81EE4 /* SJTestAliViewController3.xib */; }; 77357E622375523C00B81EE4 /* SJSubtitlesTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 77357E612375523C00B81EE4 /* SJSubtitlesTestViewController.m */; }; @@ -131,6 +132,10 @@ /* Begin PBXFileReference section */ 0913D8D9BFC4EE68E3F1EF64 /* Pods-SJVideoPlayer_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SJVideoPlayer_Example.release.xcconfig"; path = "Target Support Files/Pods-SJVideoPlayer_Example/Pods-SJVideoPlayer_Example.release.xcconfig"; sourceTree = ""; }; + 3B070E8A25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SJBaseVideoPlayer+ListPlaybackExtended.h"; sourceTree = ""; }; + 3B070E8B25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SJBaseVideoPlayer+ListPlaybackExtended.m"; sourceTree = ""; }; + 3B070EA025FC916300960506 /* SJFloatSmallViewTransitionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SJFloatSmallViewTransitionController.m; sourceTree = ""; }; + 3B070EA125FC916300960506 /* SJFloatSmallViewTransitionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SJFloatSmallViewTransitionController.h; sourceTree = ""; }; 3DE6356926AEF70F060F33F3 /* SJVideoPlayer.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = SJVideoPlayer.podspec; path = ../SJVideoPlayer.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 6003F58A195388D20070C39A /* 播放器.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "播放器.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -164,8 +169,6 @@ 7700905B24988F6900A99906 /* SJDYMainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SJDYMainViewController.m; sourceTree = ""; }; 771BFDB925AFE1EC0026C277 /* SJFloatModeDemoViewController1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SJFloatModeDemoViewController1.h; sourceTree = ""; }; 771BFDBA25AFE1EC0026C277 /* SJFloatModeDemoViewController1.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SJFloatModeDemoViewController1.m; sourceTree = ""; }; - 771BFDBE25AFE2340026C277 /* SJFloatSmallViewTransitionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SJFloatSmallViewTransitionController.m; sourceTree = ""; }; - 771BFDBF25AFE2340026C277 /* SJFloatSmallViewTransitionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SJFloatSmallViewTransitionController.h; sourceTree = ""; }; 77357E432373DA3E00B81EE4 /* SJTestAliViewController3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SJTestAliViewController3.h; sourceTree = ""; }; 77357E442373DA3E00B81EE4 /* SJTestAliViewController3.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SJTestAliViewController3.m; sourceTree = ""; }; 77357E452373DA3E00B81EE4 /* SJTestAliViewController3.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SJTestAliViewController3.xib; sourceTree = ""; }; @@ -498,8 +501,8 @@ children = ( 771BFDB925AFE1EC0026C277 /* SJFloatModeDemoViewController1.h */, 771BFDBA25AFE1EC0026C277 /* SJFloatModeDemoViewController1.m */, - 771BFDBF25AFE2340026C277 /* SJFloatSmallViewTransitionController.h */, - 771BFDBE25AFE2340026C277 /* SJFloatSmallViewTransitionController.m */, + 3B070EA125FC916300960506 /* SJFloatSmallViewTransitionController.h */, + 3B070EA025FC916300960506 /* SJFloatSmallViewTransitionController.m */, ); path = 1; sourceTree = ""; @@ -838,6 +841,8 @@ A6C5D23322AC249800D63D1C /* SJRemoteCommandHandler.m */, A6A2554122ABCE9200E42998 /* SJViewController1.h */, A6A2554222ABCE9200E42998 /* SJViewController1.m */, + 3B070E8A25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.h */, + 3B070E8B25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.m */, A6A2554322ABCE9200E42998 /* SJViewController1.xib */, A6A2555422ABD00200E42998 /* Core */, ); @@ -1138,8 +1143,10 @@ A6C5D23422AC249800D63D1C /* SJRemoteCommandHandler.m in Sources */, 77357E622375523C00B81EE4 /* SJSubtitlesTestViewController.m in Sources */, 7784A7FA237D3860000BA67E /* SJBarrageTestViewController.m in Sources */, + 3B070EA225FC916300960506 /* SJFloatSmallViewTransitionController.m in Sources */, 77788FDF22C36CF300E26599 /* SJRecommendVideosTableViewCell.m in Sources */, 771BFDBB25AFE1EC0026C277 /* SJFloatModeDemoViewController1.m in Sources */, + 3B070E8C25FC88C300960506 /* SJBaseVideoPlayer+ListPlaybackExtended.m in Sources */, A65FE539248A891700A5D4A6 /* SJKeyboardDemoViewController1.m in Sources */, 774AF08722DC790D005FE462 /* SJView.m in Sources */, 77391C46246801D100443844 /* SJExtendedMediaCollectionViewModel.m in Sources */, @@ -1149,7 +1156,6 @@ 77391C292467DFA500443844 /* SJTopView.m in Sources */, 7756F58522E173D400F9DC7D /* SJTestViewController.m in Sources */, 77391C1A2467D62200443844 /* SJUITableViewDemoViewController3.m in Sources */, - 771BFDC025AFE2340026C277 /* SJFloatSmallViewTransitionController.m in Sources */, 77391C1D2467D6EF00443844 /* SJUITableViewDemoViewController4.m in Sources */, 77391C382467F01500443844 /* SJUICollectionViewDemoViewController4.m in Sources */, A6A2562622AC1C3500E42998 /* SJViewController5.m in Sources */, diff --git a/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/UserInterfaceState.xcuserstate b/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/UserInterfaceState.xcuserstate index 2acac3033..2b207cb42 100644 Binary files a/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/UserInterfaceState.xcuserstate and b/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 0818086de..88e50c57a 100644 --- a/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/Example/SJVideoPlayer.xcworkspace/xcuserdata/bdoffice.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -3,4 +3,18 @@ uuid = "4AC450A5-5FFE-40B1-BE68-399D3F02D8DE" type = "0" version = "2.0"> + + + + + + diff --git "a/Example/SJVideoPlayer/Demos/iPhone Demo/App\345\206\205\345\260\217\347\252\227\346\202\254\346\265\256/.DS_Store" "b/Example/SJVideoPlayer/Demos/iPhone Demo/App\345\206\205\345\260\217\347\252\227\346\202\254\346\265\256/.DS_Store" new file mode 100644 index 000000000..0ce08b24b Binary files /dev/null and "b/Example/SJVideoPlayer/Demos/iPhone Demo/App\345\206\205\345\260\217\347\252\227\346\202\254\346\265\256/.DS_Store" differ diff --git "a/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJBaseVideoPlayer+ListPlaybackExtended.h" "b/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJBaseVideoPlayer+ListPlaybackExtended.h" new file mode 100644 index 000000000..028ec8d09 --- /dev/null +++ "b/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJBaseVideoPlayer+ListPlaybackExtended.h" @@ -0,0 +1,28 @@ +// +// SJBaseVideoPlayer+ListPlaybackExtended.h +// SJVideoPlayer_Example +// +// Created by BD on 2021/3/13. +// Copyright © 2021 changsanjiang. All rights reserved. +// + +#import "SJBaseVideoPlayer.h" +@protocol SJBaseVideoPlayerAssetProvider; + +NS_ASSUME_NONNULL_BEGIN +@interface SJBaseVideoPlayer (ListPlaybackExtended) + +@property (nonatomic, weak, nullable) id assetProvider; +@property (nonatomic) NSInteger numberOfAssets; +@property (nonatomic, readonly) NSInteger currentAssetIndex; + +- (void)playPreviousAsset; +- (void)playNextAsset; +- (void)playAtIndex:(NSInteger)index; + +@end + +@protocol SJBaseVideoPlayerAssetProvider +- (SJVideoPlayerURLAsset *)videoPlayer:(__kindof SJBaseVideoPlayer *)player assetAtIndex:(NSInteger)index; +@end +NS_ASSUME_NONNULL_END diff --git "a/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJBaseVideoPlayer+ListPlaybackExtended.m" "b/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJBaseVideoPlayer+ListPlaybackExtended.m" new file mode 100644 index 000000000..134e22091 --- /dev/null +++ "b/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJBaseVideoPlayer+ListPlaybackExtended.m" @@ -0,0 +1,122 @@ +// +// SJBaseVideoPlayer+ListPlaybackExtended.m +// SJVideoPlayer_Example +// +// Created by BD on 2021/3/13. +// Copyright © 2021 changsanjiang. All rights reserved. +// + +#import "SJBaseVideoPlayer+ListPlaybackExtended.h" +#import +#import + +@interface SJAssetItem : NSObject +- (instancetype)initWithIdx:(NSInteger)idx; +@property (nonatomic, readonly) NSInteger id; +@end + +@implementation SJAssetItem +- (instancetype)initWithIdx:(NSInteger)idx { + self = [super init]; + if ( self ) { + _id = idx; + } + return self; +} +@end + +@interface SJBaseVideoPlayer (ListPrivate) +@property (nonatomic, strong, readonly) SJPlaybackListController *listController; +@property (nonatomic, strong, readonly) SJPlaybackObservation *mPrivatePlaybackObserver; +@end + +@implementation SJBaseVideoPlayer (ListPrivate) +- (SJPlaybackListController *)listController { + SJPlaybackListController *listController = objc_getAssociatedObject(self, _cmd); + if ( listController == nil ) { + listController = SJPlaybackListController.alloc.init; + listController.delegate = self; + objc_setAssociatedObject(self, _cmd, listController, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return listController; +} + +- (SJPlaybackObservation *)mPrivatePlaybackObserver { + SJPlaybackObservation *observer = objc_getAssociatedObject(self, _cmd); + if ( observer == nil ) { + observer = [SJPlaybackObservation.alloc initWithPlayer:self]; + objc_setAssociatedObject(self, _cmd, observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return observer; +} + +- (void)listController:(id)listController needToPlayMedia:(id)media { + SJVideoPlayerURLAsset *asset = [self.assetProvider videoPlayer:self assetAtIndex:media.id]; + self.URLAsset = asset; +} + +- (void)listController:(id)listController needToReplayCurrentMedia:(id)media { + [self replay]; +} + +- (void)currentMediaForListControllerIsRemoved:(id)listController { } + +@end + +@interface SJBaseVideoPlayerAssetProviderWeak : NSObject +@property (nonatomic, weak, nullable) id assetProvider; +@end + +@implementation SJBaseVideoPlayerAssetProviderWeak + +@end + +@implementation SJBaseVideoPlayer (ListPlaybackExtended) + +- (void)setAssetProvider:(id)assetProvider { + SJBaseVideoPlayerAssetProviderWeak *weak = SJBaseVideoPlayerAssetProviderWeak.alloc.init; + weak.assetProvider = assetProvider; + objc_setAssociatedObject(self, @selector(assetProvider), weak, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (nullable id)assetProvider { + SJBaseVideoPlayerAssetProviderWeak *weak = objc_getAssociatedObject(self, _cmd); + return weak.assetProvider; +} + +- (void)setNumberOfAssets:(NSInteger)numberOfAssets { + [self.listController removeAllMedias]; + NSMutableArray *m = [NSMutableArray arrayWithCapacity:numberOfAssets]; + for ( int i = 0 ; i < numberOfAssets ; ++ i ) { + SJAssetItem *item = [SJAssetItem.alloc initWithIdx:i]; + [m addObject:item]; + } + [self.listController addMedias:m]; + + if ( self.mPrivatePlaybackObserver.playbackDidFinishExeBlock == nil ) { + self.mPrivatePlaybackObserver.playbackDidFinishExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull player) { + [player.listController currentMediaFinishedPlaying]; + }; + } +} + +- (NSInteger)numberOfAssets { + return self.listController.medias.count; +} + +- (NSInteger)currentAssetIndex { + return self.listController.currentMedia.id; +} + +- (void)playPreviousAsset { + [self.listController playPreviousMedia]; +} + +- (void)playNextAsset { + [self.listController playNextMedia]; +} + +- (void)playAtIndex:(NSInteger)index { + [self.listController playAtIndex:index]; +} +@end diff --git "a/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJViewController1.m" "b/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJViewController1.m" index 2dd73c6b6..6aab14e41 100644 --- "a/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJViewController1.m" +++ "b/Example/SJVideoPlayer/Demos/iPhone Demo/Playback List Control(\346\222\255\346\224\276\345\210\227\350\241\250\346\216\247\345\210\266)/SJViewController1.m" @@ -10,20 +10,19 @@ #import "SJTableViewCell1.h" #import "SJVideoModel.h" #import -#import #import #import #import "SJRemoteCommandHandler.h" +#import "SJBaseVideoPlayer+ListPlaybackExtended.h" NS_ASSUME_NONNULL_BEGIN static NSString *const SJTableViewCell1ID = @"SJTableViewCell1"; -@interface SJViewController1 () +@interface SJViewController1 () @property (weak, nonatomic) IBOutlet UIView *playerContainerVIew; @property (weak, nonatomic) IBOutlet UITableView *tableView; - @property (nonatomic, strong, nullable) SJVideoPlayer *player; -@property (nonatomic, strong, readonly) SJPlaybackListController *listController;; +@property (nonatomic, strong) NSMutableArray *videos; @end @implementation SJViewController1 @@ -38,11 +37,80 @@ - (void)viewDidLoad { #pragma mark - - (IBAction)playPreviousMedia:(id)sender { - [self.listController playPreviousMedia]; + [_player playPreviousAsset]; } - (IBAction)playNextMedia:(id)sender { - [self.listController playNextMedia]; + [_player playNextAsset]; +} + +#pragma mark - SJBaseVideoPlayerAssetProvider + +- (SJVideoPlayerURLAsset *)videoPlayer:(__kindof SJBaseVideoPlayer *)player assetAtIndex:(NSInteger)index { + SJVideoModel *item = self.videos[index]; + + SJVideoPlayerURLAsset *asset = [[SJVideoPlayerURLAsset alloc] initWithURL:item.URL]; + asset.title = item.mediaTitle; + + [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle]; + return asset; +} + +#pragma mark - + +- (void)_setupVideoPlayer { + _player = [SJVideoPlayer player]; + _player.pauseWhenAppDidEnterBackground = NO; ///< 开启后台播放 + [_player.defaultEdgeControlLayer.bottomAdapter removeItemForTag:SJEdgeControlLayerBottomItem_Separator]; + [_player.defaultEdgeControlLayer.bottomAdapter exchangeItemForTag:SJEdgeControlLayerBottomItem_DurationTime withItemForTag:SJEdgeControlLayerBottomItem_Progress]; + + _player.assetProvider = self; + // 在控制层添加下一首按钮 + SJEdgeControlButtonItem *nextItem = [[SJEdgeControlButtonItem alloc] initWithImage:[UIImage imageNamed:@"next"] target:_player action:@selector(playNextAsset) tag:1000]; + [_player.defaultEdgeControlLayer.bottomAdapter insertItem:nextItem frontItem:SJEdgeControlLayerBottomItem_Play]; + [_player.defaultEdgeControlLayer.bottomAdapter reload]; + + [_playerContainerVIew addSubview:_player.view]; + [_player.view mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.offset(0); + }]; + + __weak typeof(self) _self = self; + _player.playbackObserver.currentTimeDidChangeExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull player) { + __strong typeof(_self) self = _self; + if ( self == nil ) return; + SJVideoModel *item = self.videos[player.currentAssetIndex]; + NSDictionary *info = + @{MPMediaItemPropertyTitle:item.mediaTitle, + MPMediaItemPropertyMediaType:@(MPMediaTypeAny), + MPNowPlayingInfoPropertyElapsedPlaybackTime:@(player.currentTime), + MPMediaItemPropertyPlaybackDuration:@(player.duration), + MPNowPlayingInfoPropertyPlaybackRate:@(player.rate)}; + [SJRemoteCommandHandler.shared updateNowPlayingInfo:info]; + }; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self.player vc_viewDidAppear]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [self.player vc_viewWillDisappear]; +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + [self.player vc_viewDidDisappear]; +} + +- (BOOL)shouldAutorotate { + return NO; +} + +- (BOOL)prefersHomeIndicatorAutoHidden { + return YES; } - (void)_setupRemoteCommandHandler { @@ -62,13 +130,13 @@ - (void)_setupRemoteCommandHandler { SJRemoteCommandHandler.shared.previousCommandHandler = ^(id _Nonnull handler) { __strong typeof(_self) self = _self; if ( !self ) return ; - [self.listController playPreviousMedia]; + [self.player playPreviousAsset]; }; SJRemoteCommandHandler.shared.nextCommandHandler = ^(id _Nonnull handler) { __strong typeof(_self) self = _self; if ( !self ) return ; - [self.listController playNextMedia]; + [self.player playNextAsset]; }; SJRemoteCommandHandler.shared.seekToTimeCommandHandler = ^(id _Nonnull handler, NSTimeInterval secs) { @@ -77,62 +145,20 @@ - (void)_setupRemoteCommandHandler { [self.player seekToTime:secs completionHandler:nil]; }; } - -#pragma mark - - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [self.listController playAtIndex:indexPath.row]; -} - -- (void)listController:(id)listController needToPlayMedia:(id)media { - SJVideoModel *item = (id)media; - if ( _player == nil ) { - _player = [SJVideoPlayer player]; - [self _addListControlItemsToPlayer]; - [_playerContainerVIew addSubview:_player.view]; - [_player.view mas_makeConstraints:^(MASConstraintMaker *make) { - make.edges.offset(0); - }]; - __weak typeof(self) _self = self; - _player.playbackObserver.playbackDidFinishExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull player) { - __strong typeof(_self) self = _self; - if ( !self ) return; - [self.listController currentMediaFinishedPlaying]; - }; - _player.pauseWhenAppDidEnterBackground = NO; ///< 开启后台播放 - } - - _player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:item.URL]; - _player.URLAsset.title = item.mediaTitle; - - _player.playbackObserver.currentTimeDidChangeExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull player) { - NSDictionary *info = - @{MPMediaItemPropertyTitle:item.mediaTitle, - MPMediaItemPropertyMediaType:@(MPMediaTypeAny), - MPNowPlayingInfoPropertyElapsedPlaybackTime:@(player.currentTime), - MPMediaItemPropertyPlaybackDuration:@(player.duration), - MPNowPlayingInfoPropertyPlaybackRate:@(player.rate)}; - [SJRemoteCommandHandler.shared updateNowPlayingInfo:info]; - }; - - [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:[listController indexForMediaId:media.id] inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle]; -} - -- (void)listController:(id)listController needToReplayCurrentMedia:(id)media { - [_player replay]; -} - -- (void)currentMediaForListControllerIsRemoved:(id)listController {} - + #pragma mark - - (void)_setupViews { self.edgesForExtendedLayout = UIRectEdgeNone; self.title = NSStringFromClass(self.class); - _listController = [SJPlaybackListController new]; - _listController.delegate = self; + _videos = NSMutableArray.array; + [self _setupVideoPlayer]; + [self _setupTableView]; +} + +- (void)_setupTableView { _tableView.dataSource = self; _tableView.delegate = self; _tableView.estimatedRowHeight = 0; @@ -147,25 +173,31 @@ - (void)_setupViews { if ( !self ) return ; // 模拟数据 - NSMutableArray *m = [NSMutableArray arrayWithCapacity:tableView.sj_pageSize]; + NSMutableArray *videos = [NSMutableArray arrayWithCapacity:tableView.sj_pageSize]; for ( int i = 0; i < tableView.sj_pageSize ; ++ i ) { SJVideoModel *model = [SJVideoModel testItem]; - [m addObject:model]; + [videos addObject:model]; } if ( requestPageNum == tableView.sj_beginPageNum ) { - [self.listController removeAllMedias]; - self.player = nil; + [self.videos removeAllObjects]; } - [self.listController addMedias:(id)m]; + [self.videos addObjectsFromArray:videos]; + + // 刷新数量 + self.player.numberOfAssets = self.videos.count; [self.tableView reloadData]; - [self.tableView sj_endRefreshingWithItemCount:m.count]; + [self.tableView sj_endRefreshingWithItemCount:videos.count]; }]; } +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [_player playAtIndex:indexPath.row]; +} + - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.listController.medias.count; + return self.videos.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { @@ -173,46 +205,50 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } - (void)tableView:(UITableView *)tableView willDisplayCell:(SJTableViewCell1 *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - SJVideoModel *item = [self.listController mediaAtIndex:indexPath.row]; + SJVideoModel *item = _videos[indexPath.row]; cell.textLabel.text = [NSString stringWithFormat:@"%ld: %@", (long)indexPath.row, item.mediaTitle]; } -#pragma mark - -- (void)_addListControlItemsToPlayer { -// _player.defaultEdgeControlLayer.bottomContainerView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8]; - [_player.defaultEdgeControlLayer.bottomAdapter removeItemForTag:SJEdgeControlLayerBottomItem_Separator]; - [_player.defaultEdgeControlLayer.bottomAdapter exchangeItemForTag:SJEdgeControlLayerBottomItem_DurationTime withItemForTag:SJEdgeControlLayerBottomItem_Progress]; - - SJEdgeControlButtonItem *nextItem = [[SJEdgeControlButtonItem alloc] initWithImage:[UIImage imageNamed:@"next"] target:_listController action:@selector(playNextMedia) tag:1000]; - [_player.defaultEdgeControlLayer.bottomAdapter insertItem:nextItem frontItem:SJEdgeControlLayerBottomItem_Play]; - [_player.defaultEdgeControlLayer.bottomAdapter reload]; +@end +NS_ASSUME_NONNULL_END + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -} -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - [self.player vc_viewDidAppear]; -} -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - [self.player vc_viewWillDisappear]; -} -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; - [self.player vc_viewDidDisappear]; -} -- (BOOL)shouldAutorotate { - return NO; -} -- (BOOL)prefersHomeIndicatorAutoHidden { - return YES; -} -@end -NS_ASSUME_NONNULL_END #import