update
127
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/UIImageView+ZFCache.h
generated
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// UIImageView+ZFCache.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
typedef void (^ZFDownLoadDataCallBack)(NSData *data, NSError *error);
|
||||
typedef void (^ZFDownloadProgressBlock)(unsigned long long total, unsigned long long current);
|
||||
|
||||
@interface ZFImageDownloader : NSObject<NSURLSessionDownloadDelegate>
|
||||
|
||||
@property (nonatomic, strong) NSURLSession *session;
|
||||
@property (nonatomic, strong) NSURLSessionDownloadTask *task;
|
||||
|
||||
@property (nonatomic, assign) unsigned long long totalLength;
|
||||
@property (nonatomic, assign) unsigned long long currentLength;
|
||||
|
||||
@property (nonatomic, copy) ZFDownloadProgressBlock progressBlock;
|
||||
@property (nonatomic, copy) ZFDownLoadDataCallBack callbackOnFinished;
|
||||
|
||||
- (void)startDownloadImageWithUrl:(NSString *)url
|
||||
progress:(ZFDownloadProgressBlock)progress
|
||||
finished:(ZFDownLoadDataCallBack)finished;
|
||||
|
||||
@end
|
||||
|
||||
typedef void (^ZFImageBlock)(UIImage *image);
|
||||
|
||||
@interface UIImageView (ZFCache)
|
||||
|
||||
/**
|
||||
* Get/Set the callback block when download the image finished.
|
||||
*
|
||||
* The image object from network or from disk.
|
||||
*/
|
||||
@property (nonatomic, copy) ZFImageBlock completion;
|
||||
|
||||
/**
|
||||
* Image downloader
|
||||
*/
|
||||
@property (nonatomic, strong) ZFImageDownloader *imageDownloader;
|
||||
|
||||
/**
|
||||
* Specify the URL to download images fails, the number of retries, the default is 2
|
||||
*/
|
||||
@property (nonatomic, assign) NSUInteger attemptToReloadTimesForFailedURL;
|
||||
|
||||
/**
|
||||
* Will automatically download to cutting for UIImageView size of image.The default value is NO.
|
||||
* If set to YES, then the download after a successful store only after cutting the image
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL shouldAutoClipImageToViewSize;
|
||||
|
||||
/**
|
||||
* Set the imageView `image` with an `url` and a placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholderImageName The image name to be set initially, until the image request finishes.
|
||||
*/
|
||||
- (void)setImageWithURLString:(NSString *)url placeholderImageName:(NSString *)placeholderImageName;
|
||||
|
||||
/**
|
||||
* Set the imageView `image` with an `url` and a placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholderImage The image to be set initially, until the image request finishes.
|
||||
*/
|
||||
- (void)setImageWithURLString:(NSString *)url placeholder:(UIImage *)placeholderImage;
|
||||
|
||||
/**
|
||||
* Set the imageView `image` with an `url`, placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholderImage The image to be set initially, until the image request finishes.
|
||||
* @param completion A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
*/
|
||||
- (void)setImageWithURLString:(NSString *)url
|
||||
placeholder:(UIImage *)placeholderImage
|
||||
completion:(void (^)(UIImage *image))completion;
|
||||
|
||||
/**
|
||||
* Set the imageView `image` with an `url`, placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholderImageName The image name to be set initially, until the image request finishes.
|
||||
* @param completion A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
*/
|
||||
- (void)setImageWithURLString:(NSString *)url
|
||||
placeholderImageName:(NSString *)placeholderImageName
|
||||
completion:(void (^)(UIImage *image))completion;
|
||||
@end
|
||||
411
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/UIImageView+ZFCache.m
generated
Normal file
@@ -0,0 +1,411 @@
|
||||
//
|
||||
// UIImageView+ZFCache.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 "UIImageView+ZFCache.h"
|
||||
#import <objc/runtime.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
|
||||
@implementation ZFImageDownloader
|
||||
|
||||
- (void)startDownloadImageWithUrl:(NSString *)url
|
||||
progress:(ZFDownloadProgressBlock)progress
|
||||
finished:(ZFDownLoadDataCallBack)finished {
|
||||
self.progressBlock = progress;
|
||||
self.callbackOnFinished = finished;
|
||||
|
||||
if ([NSURL URLWithString:url] == nil) {
|
||||
if (finished) { finished(nil, nil); }
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
|
||||
cachePolicy:NSURLRequestReturnCacheDataElseLoad
|
||||
timeoutInterval:60];
|
||||
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
|
||||
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
|
||||
self.session = [NSURLSession sessionWithConfiguration:config
|
||||
delegate:self
|
||||
delegateQueue:queue];
|
||||
NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request];
|
||||
[task resume];
|
||||
self.task = task;
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
|
||||
NSData *data = [NSData dataWithContentsOfURL:location];
|
||||
|
||||
if (self.progressBlock) {
|
||||
self.progressBlock(self.totalLength, self.currentLength);
|
||||
}
|
||||
|
||||
if (self.callbackOnFinished) {
|
||||
self.callbackOnFinished(data, nil);
|
||||
|
||||
// 防止重复调用
|
||||
self.callbackOnFinished = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
|
||||
self.currentLength = totalBytesWritten;
|
||||
self.totalLength = totalBytesExpectedToWrite;
|
||||
|
||||
if (self.progressBlock) {
|
||||
self.progressBlock(self.totalLength, self.currentLength);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
||||
if ([error code] != NSURLErrorCancelled) {
|
||||
if (self.callbackOnFinished) {
|
||||
self.callbackOnFinished(nil, error);
|
||||
}
|
||||
self.callbackOnFinished = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface NSString (md5)
|
||||
|
||||
+ (NSString *)cachedFileNameForKey:(NSString *)key;
|
||||
+ (NSString *)zf_cachePath;
|
||||
+ (NSString *)zf_keyForRequest:(NSURLRequest *)request;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSString (md5)
|
||||
|
||||
+ (NSString *)zf_keyForRequest:(NSURLRequest *)request {
|
||||
return request.URL.absoluteString;
|
||||
}
|
||||
|
||||
+ (NSString *)zf_cachePath {
|
||||
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
|
||||
NSString *directoryPath = [NSString stringWithFormat:@"%@/%@/%@",cachePath,@"default",@"com.hackemist.SDWebImageCache.default"];
|
||||
return directoryPath;
|
||||
}
|
||||
|
||||
+ (NSString *)cachedFileNameForKey:(NSString *)key {
|
||||
const char *str = [key UTF8String];
|
||||
if (str == NULL) {
|
||||
str = "";
|
||||
}
|
||||
unsigned char r[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5(str, (CC_LONG)strlen(str), r);
|
||||
NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@",
|
||||
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10],
|
||||
r[11], r[12], r[13], r[14], r[15], [[key pathExtension] isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", [key pathExtension]]];
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface UIApplication (ZFCacheImage)
|
||||
|
||||
@property (nonatomic, strong, readonly) NSMutableDictionary *zf_cacheFaileTimes;
|
||||
|
||||
- (UIImage *)zf_cacheImageForRequest:(NSURLRequest *)request;
|
||||
- (void)zf_cacheImage:(UIImage *)image forRequest:(NSURLRequest *)request;
|
||||
- (void)zf_cacheFailRequest:(NSURLRequest *)request;
|
||||
- (NSUInteger)zf_failTimesForRequest:(NSURLRequest *)request;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIApplication (ZFCacheImage)
|
||||
|
||||
- (NSMutableDictionary *)zf_cacheFaileTimes {
|
||||
NSMutableDictionary *dict = objc_getAssociatedObject(self, _cmd);
|
||||
if (!dict) {
|
||||
dict = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
- (void)setZf_cacheFaileTimes:(NSMutableDictionary *)zf_cacheFaileTimes {
|
||||
objc_setAssociatedObject(self, @selector(zf_cacheFaileTimes), zf_cacheFaileTimes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)zf_clearCache {
|
||||
[self.zf_cacheFaileTimes removeAllObjects];
|
||||
self.zf_cacheFaileTimes = nil;
|
||||
}
|
||||
|
||||
- (void)zf_clearDiskCaches {
|
||||
NSString *directoryPath = [NSString zf_cachePath];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:nil]) {
|
||||
dispatch_queue_t ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL);
|
||||
dispatch_async(ioQueue, ^{
|
||||
[[NSFileManager defaultManager] removeItemAtPath:directoryPath error:nil];
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:directoryPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:nil];
|
||||
});
|
||||
}
|
||||
[self zf_clearCache];
|
||||
}
|
||||
|
||||
- (UIImage *)zf_cacheImageForRequest:(NSURLRequest *)request {
|
||||
if (request) {
|
||||
NSString *directoryPath = [NSString zf_cachePath];
|
||||
NSString *path = [NSString stringWithFormat:@"%@/%@", directoryPath, [NSString cachedFileNameForKey:[NSString zf_keyForRequest:request]]];
|
||||
return [UIImage imageWithContentsOfFile:path];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSUInteger)zf_failTimesForRequest:(NSURLRequest *)request {
|
||||
NSNumber *faileTimes = [self.zf_cacheFaileTimes objectForKey:[NSString cachedFileNameForKey:[NSString zf_keyForRequest:request]]];
|
||||
if (faileTimes && [faileTimes respondsToSelector:@selector(integerValue)]) {
|
||||
return faileTimes.integerValue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)zf_cacheFailRequest:(NSURLRequest *)request {
|
||||
NSNumber *faileTimes = [self.zf_cacheFaileTimes objectForKey:[NSString cachedFileNameForKey:[NSString zf_keyForRequest:request]]];
|
||||
NSUInteger times = 0;
|
||||
if (faileTimes && [faileTimes respondsToSelector:@selector(integerValue)]) {
|
||||
times = [faileTimes integerValue];
|
||||
}
|
||||
|
||||
times++;
|
||||
|
||||
[self.zf_cacheFaileTimes setObject:@(times) forKey:[NSString cachedFileNameForKey:[NSString zf_keyForRequest:request]]];
|
||||
}
|
||||
|
||||
- (void)zf_cacheImage:(UIImage *)image forRequest:(NSURLRequest *)request {
|
||||
if (!image || !request) { return; }
|
||||
|
||||
NSString *directoryPath = [NSString zf_cachePath];
|
||||
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:nil]) {
|
||||
NSError *error = nil;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:directoryPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:&error];
|
||||
if (error) { return; }
|
||||
}
|
||||
|
||||
NSString *path = [NSString stringWithFormat:@"%@/%@", directoryPath, [NSString cachedFileNameForKey:[NSString zf_keyForRequest:request]]];
|
||||
NSData *data = UIImagePNGRepresentation(image);
|
||||
if (data) {
|
||||
[[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation UIImageView (ZFCache)
|
||||
|
||||
#pragma mark - getter
|
||||
|
||||
- (ZFImageBlock)completion {
|
||||
return objc_getAssociatedObject(self, _cmd);
|
||||
}
|
||||
|
||||
- (ZFImageDownloader *)imageDownloader {
|
||||
return objc_getAssociatedObject(self, _cmd);
|
||||
}
|
||||
|
||||
- (NSUInteger)attemptToReloadTimesForFailedURL {
|
||||
NSUInteger count = [objc_getAssociatedObject(self, _cmd) integerValue];
|
||||
if (count == 0) { count = 2; }
|
||||
return count;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutoClipImageToViewSize {
|
||||
return [objc_getAssociatedObject(self, _cmd) boolValue];
|
||||
}
|
||||
|
||||
#pragma mark - setter
|
||||
|
||||
- (void)setCompletion:(ZFImageBlock)completion {
|
||||
objc_setAssociatedObject(self, @selector(completion), completion, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)setImageDownloader:(ZFImageDownloader *)imageDownloader {
|
||||
objc_setAssociatedObject(self, @selector(imageDownloader), imageDownloader, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)setAttemptToReloadTimesForFailedURL:(NSUInteger)attemptToReloadTimesForFailedURL {
|
||||
objc_setAssociatedObject(self, @selector(attemptToReloadTimesForFailedURL), @(attemptToReloadTimesForFailedURL), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)setShouldAutoClipImageToViewSize:(BOOL)shouldAutoClipImageToViewSize {
|
||||
objc_setAssociatedObject(self, @selector(shouldAutoClipImageToViewSize), @(shouldAutoClipImageToViewSize), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
#pragma mark - public method
|
||||
|
||||
- (void)setImageWithURLString:(NSString *)url
|
||||
placeholderImageName:(NSString *)placeholderImageName {
|
||||
return [self setImageWithURLString:url placeholderImageName:placeholderImageName completion:nil];
|
||||
}
|
||||
|
||||
- (void)setImageWithURLString:(NSString *)url placeholder:(UIImage *)placeholderImage {
|
||||
return [self setImageWithURLString:url placeholder:placeholderImage completion:nil];
|
||||
}
|
||||
|
||||
- (void)setImageWithURLString:(NSString *)url
|
||||
placeholderImageName:(NSString *)placeholderImage
|
||||
completion:(void (^)(UIImage *image))completion {
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:placeholderImage ofType:nil];
|
||||
UIImage *image = [UIImage imageWithContentsOfFile:path];
|
||||
if (image == nil) { image = [UIImage imageNamed:placeholderImage]; }
|
||||
|
||||
[self setImageWithURLString:url placeholder:image completion:completion];
|
||||
}
|
||||
|
||||
- (void)setImageWithURLString:(NSString *)url
|
||||
placeholder:(UIImage *)placeholderImageName
|
||||
completion:(void (^)(UIImage *image))completion {
|
||||
[self.layer removeAllAnimations];
|
||||
self.completion = completion;
|
||||
|
||||
if (url == nil || [url isKindOfClass:[NSNull class]] || (![url hasPrefix:@"http://"] && ![url hasPrefix:@"https://"])) {
|
||||
[self setImage:placeholderImageName isFromCache:YES];
|
||||
|
||||
if (completion) {
|
||||
self.completion(self.image);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
|
||||
[self downloadWithReqeust:request holder:placeholderImageName];
|
||||
}
|
||||
|
||||
#pragma mark - private method
|
||||
|
||||
- (void)downloadWithReqeust:(NSURLRequest *)theRequest holder:(UIImage *)holder {
|
||||
UIImage *cachedImage = [[UIApplication sharedApplication] zf_cacheImageForRequest:theRequest];
|
||||
|
||||
if (cachedImage) {
|
||||
[self setImage:cachedImage isFromCache:YES];
|
||||
if (self.completion) {
|
||||
self.completion(cachedImage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[self setImage:holder isFromCache:YES];
|
||||
|
||||
if ([[UIApplication sharedApplication] zf_failTimesForRequest:theRequest] >= self.attemptToReloadTimesForFailedURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self cancelRequest];
|
||||
self.imageDownloader = nil;
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
self.imageDownloader = [[ZFImageDownloader alloc] init];
|
||||
[self.imageDownloader startDownloadImageWithUrl:theRequest.URL.absoluteString progress:nil finished:^(NSData *data, NSError *error) {
|
||||
// success
|
||||
if (data != nil && error == nil) {
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
UIImage *image = [UIImage imageWithData:data];
|
||||
UIImage *finalImage = image;
|
||||
|
||||
if (image) {
|
||||
if (weakSelf.shouldAutoClipImageToViewSize) {
|
||||
// cutting
|
||||
if (fabs(weakSelf.frame.size.width - image.size.width) != 0
|
||||
&& fabs(weakSelf.frame.size.height - image.size.height) != 0) {
|
||||
finalImage = [self clipImage:image toSize:weakSelf.frame.size isScaleToMax:YES];
|
||||
}
|
||||
}
|
||||
|
||||
[[UIApplication sharedApplication] zf_cacheImage:finalImage forRequest:theRequest];
|
||||
} else {
|
||||
[[UIApplication sharedApplication] zf_cacheFailRequest:theRequest];
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (finalImage) {
|
||||
[weakSelf setImage:finalImage isFromCache:NO];
|
||||
|
||||
if (weakSelf.completion) {
|
||||
weakSelf.completion(weakSelf.image);
|
||||
}
|
||||
} else {// error data
|
||||
if (weakSelf.completion) {
|
||||
weakSelf.completion(weakSelf.image);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else { // error
|
||||
[[UIApplication sharedApplication] zf_cacheFailRequest:theRequest];
|
||||
|
||||
if (weakSelf.completion) {
|
||||
weakSelf.completion(weakSelf.image);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setImage:(UIImage *)image isFromCache:(BOOL)isFromCache {
|
||||
self.image = image;
|
||||
if (!isFromCache) {
|
||||
CATransition *animation = [CATransition animation];
|
||||
[animation setDuration:0.6f];
|
||||
[animation setType:kCATransitionFade];
|
||||
animation.removedOnCompletion = YES;
|
||||
[self.layer addAnimation:animation forKey:@"transition"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelRequest {
|
||||
[self.imageDownloader.task cancel];
|
||||
}
|
||||
|
||||
- (UIImage *)clipImage:(UIImage *)image toSize:(CGSize)size isScaleToMax:(BOOL)isScaleToMax {
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
|
||||
|
||||
CGSize aspectFitSize = CGSizeZero;
|
||||
if (image.size.width != 0 && image.size.height != 0) {
|
||||
CGFloat rateWidth = size.width / image.size.width;
|
||||
CGFloat rateHeight = size.height / image.size.height;
|
||||
|
||||
CGFloat rate = isScaleToMax ? MAX(rateHeight, rateWidth) : MIN(rateHeight, rateWidth);
|
||||
aspectFitSize = CGSizeMake(image.size.width * rate, image.size.height * rate);
|
||||
}
|
||||
|
||||
[image drawInRect:CGRectMake(0, 0, aspectFitSize.width, aspectFitSize.height)];
|
||||
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return finalImage;
|
||||
}
|
||||
|
||||
@end
|
||||
45
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/UIView+ZFFrame.h
generated
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// UIView+ZFFrame.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface UIView (ZFFrame)
|
||||
|
||||
@property (nonatomic) CGFloat zf_x;
|
||||
@property (nonatomic) CGFloat zf_y;
|
||||
@property (nonatomic) CGFloat zf_width;
|
||||
@property (nonatomic) CGFloat zf_height;
|
||||
|
||||
@property (nonatomic) CGFloat zf_top;
|
||||
@property (nonatomic) CGFloat zf_bottom;
|
||||
@property (nonatomic) CGFloat zf_left;
|
||||
@property (nonatomic) CGFloat zf_right;
|
||||
|
||||
@property (nonatomic) CGFloat zf_centerX;
|
||||
@property (nonatomic) CGFloat zf_centerY;
|
||||
|
||||
@property (nonatomic) CGPoint zf_origin;
|
||||
@property (nonatomic) CGSize zf_size;
|
||||
|
||||
@end
|
||||
149
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/UIView+ZFFrame.m
generated
Normal file
@@ -0,0 +1,149 @@
|
||||
//
|
||||
// UIView+ZFFrame.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 "UIView+ZFFrame.h"
|
||||
|
||||
@implementation UIView (ZFFrame)
|
||||
|
||||
- (CGFloat)zf_x {
|
||||
return self.frame.origin.x;
|
||||
}
|
||||
|
||||
- (void)setZf_x:(CGFloat)zf_x {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin.x = zf_x;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_y {
|
||||
return self.frame.origin.y;
|
||||
}
|
||||
|
||||
- (void)setZf_y:(CGFloat)zf_y {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin.y = zf_y;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_width {
|
||||
return CGRectGetWidth(self.bounds);
|
||||
}
|
||||
|
||||
- (void)setZf_width:(CGFloat)zf_width {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.size.width = zf_width;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_height {
|
||||
return CGRectGetHeight(self.bounds);
|
||||
}
|
||||
|
||||
- (void)setZf_height:(CGFloat)zf_height {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.size.height = zf_height;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_top {
|
||||
return self.frame.origin.y;
|
||||
}
|
||||
|
||||
- (void)setZf_top:(CGFloat)zf_top {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin.y = zf_top;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_bottom {
|
||||
return self.frame.origin.y + self.frame.size.height;
|
||||
}
|
||||
|
||||
- (void)setZf_bottom:(CGFloat)zf_bottom {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin.y = zf_bottom - self.frame.size.height;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_left {
|
||||
return self.frame.origin.x;
|
||||
}
|
||||
|
||||
- (void)setZf_left:(CGFloat)zf_left {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin.x = zf_left;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_right {
|
||||
return self.frame.origin.x + self.frame.size.width;
|
||||
}
|
||||
|
||||
- (void)setZf_right:(CGFloat)zf_right {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin.x = zf_right - self.frame.size.width;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_centerX {
|
||||
return self.center.x;
|
||||
}
|
||||
|
||||
- (void)setZf_centerX:(CGFloat)zf_centerX {
|
||||
CGPoint newCenter = self.center;
|
||||
newCenter.x = zf_centerX;
|
||||
self.center = newCenter;
|
||||
}
|
||||
|
||||
- (CGFloat)zf_centerY {
|
||||
return self.center.y;
|
||||
}
|
||||
|
||||
- (void)setZf_centerY:(CGFloat)zf_centerY {
|
||||
CGPoint newCenter = self.center;
|
||||
newCenter.y = zf_centerY;
|
||||
self.center = newCenter;
|
||||
}
|
||||
|
||||
- (CGPoint)zf_origin {
|
||||
return self.frame.origin;
|
||||
}
|
||||
|
||||
- (void)setZf_origin:(CGPoint)zf_origin {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.origin = zf_origin;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
- (CGSize)zf_size {
|
||||
return self.frame.size;
|
||||
}
|
||||
|
||||
- (void)setZf_size:(CGSize)zf_size {
|
||||
CGRect newFrame = self.frame;
|
||||
newFrame.size = zf_size;
|
||||
self.frame = newFrame;
|
||||
}
|
||||
|
||||
@end
|
||||
120
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFLandScapeControlView.h
generated
Executable file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// ZFLandScapeControlView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
#import "ZFSliderView.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayerController.h>)
|
||||
#import <ZFPlayer/ZFPlayerController.h>
|
||||
#else
|
||||
#import "ZFPlayerController.h"
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ZFLandScapeControlView : UIView
|
||||
|
||||
/// 顶部工具栏
|
||||
@property (nonatomic, strong, readonly) UIView *topToolView;
|
||||
|
||||
/// 返回按钮
|
||||
@property (nonatomic, strong, readonly) UIButton *backBtn;
|
||||
|
||||
/// 标题
|
||||
@property (nonatomic, strong, readonly) UILabel *titleLabel;
|
||||
|
||||
/// 底部工具栏
|
||||
@property (nonatomic, strong, readonly) UIView *bottomToolView;
|
||||
|
||||
/// 播放或暂停按钮
|
||||
@property (nonatomic, strong, readonly) UIButton *playOrPauseBtn;
|
||||
|
||||
/// 播放的当前时间
|
||||
@property (nonatomic, strong, readonly) UILabel *currentTimeLabel;
|
||||
|
||||
/// 滑杆
|
||||
@property (nonatomic, strong, readonly) ZFSliderView *slider;
|
||||
|
||||
/// 视频总时间
|
||||
@property (nonatomic, strong, readonly) UILabel *totalTimeLabel;
|
||||
|
||||
/// 锁定屏幕按钮
|
||||
@property (nonatomic, strong, readonly) UIButton *lockBtn;
|
||||
|
||||
/// 播放器
|
||||
@property (nonatomic, weak) ZFPlayerController *player;
|
||||
|
||||
/// slider滑动中
|
||||
@property (nonatomic, copy, nullable) void(^sliderValueChanging)(CGFloat value,BOOL forward);
|
||||
|
||||
/// slider滑动结束
|
||||
@property (nonatomic, copy, nullable) void(^sliderValueChanged)(CGFloat value);
|
||||
|
||||
/// 返回按钮点击回调
|
||||
@property (nonatomic, copy) void(^backBtnClickCallback)(void);
|
||||
|
||||
/// 如果是暂停状态,seek完是否播放,默认YES
|
||||
@property (nonatomic, assign) BOOL seekToPlay;
|
||||
|
||||
/// 全屏模式
|
||||
@property (nonatomic, assign) ZFFullScreenMode fullScreenMode;
|
||||
|
||||
/// 重置控制层
|
||||
- (void)resetControlView;
|
||||
|
||||
/// 显示控制层
|
||||
- (void)showControlView;
|
||||
|
||||
/// 隐藏控制层
|
||||
- (void)hideControlView;
|
||||
|
||||
/// 设置播放时间
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime;
|
||||
|
||||
/// 设置缓冲时间
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime;
|
||||
|
||||
/// 是否响应该手势
|
||||
- (BOOL)shouldResponseGestureWithPoint:(CGPoint)point withGestureType:(ZFPlayerGestureType)type touch:(nonnull UITouch *)touch;
|
||||
|
||||
/// 视频尺寸改变
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer presentationSizeChanged:(CGSize)size;
|
||||
|
||||
/// 标题和全屏模式
|
||||
- (void)showTitle:(NSString *_Nullable)title fullScreenMode:(ZFFullScreenMode)fullScreenMode;
|
||||
|
||||
/// 根据当前播放状态取反
|
||||
- (void)playOrPause;
|
||||
|
||||
/// 播放按钮状态
|
||||
- (void)playBtnSelectedState:(BOOL)selected;
|
||||
|
||||
/// 调节播放进度slider和当前时间更新
|
||||
- (void)sliderValueChanged:(CGFloat)value currentTimeString:(NSString *)timeString;
|
||||
|
||||
/// 滑杆结束滑动
|
||||
- (void)sliderChangeEnded;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
462
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFLandScapeControlView.m
generated
Executable file
@@ -0,0 +1,462 @@
|
||||
//
|
||||
// ZFLandScapeControlView.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 "ZFLandScapeControlView.h"
|
||||
#import "UIView+ZFFrame.h"
|
||||
#import "ZFUtilities.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayer.h>)
|
||||
#import <ZFPlayer/ZFPlayerConst.h>
|
||||
#else
|
||||
#import "ZFPlayerConst.h"
|
||||
#endif
|
||||
|
||||
@interface ZFLandScapeControlView () <ZFSliderViewDelegate>
|
||||
/// 顶部工具栏
|
||||
@property (nonatomic, strong) UIView *topToolView;
|
||||
/// 返回按钮
|
||||
@property (nonatomic, strong) UIButton *backBtn;
|
||||
/// 标题
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
/// 底部工具栏
|
||||
@property (nonatomic, strong) UIView *bottomToolView;
|
||||
/// 播放或暂停按钮
|
||||
@property (nonatomic, strong) UIButton *playOrPauseBtn;
|
||||
/// 播放的当前时间
|
||||
@property (nonatomic, strong) UILabel *currentTimeLabel;
|
||||
/// 滑杆
|
||||
@property (nonatomic, strong) ZFSliderView *slider;
|
||||
/// 视频总时间
|
||||
@property (nonatomic, strong) UILabel *totalTimeLabel;
|
||||
/// 锁定屏幕按钮
|
||||
@property (nonatomic, strong) UIButton *lockBtn;
|
||||
|
||||
@property (nonatomic, assign) BOOL isShow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFLandScapeControlView
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self addSubview:self.topToolView];
|
||||
[self.topToolView addSubview:self.backBtn];
|
||||
[self.topToolView addSubview:self.titleLabel];
|
||||
[self addSubview:self.bottomToolView];
|
||||
[self.bottomToolView addSubview:self.playOrPauseBtn];
|
||||
[self.bottomToolView addSubview:self.currentTimeLabel];
|
||||
|
||||
[self.bottomToolView addSubview:self.slider];
|
||||
[self.bottomToolView addSubview:self.totalTimeLabel];
|
||||
[self addSubview:self.lockBtn];
|
||||
|
||||
// 设置子控件的响应事件
|
||||
[self makeSubViewsAction];
|
||||
[self resetControlView];
|
||||
|
||||
/// statusBarFrame changed
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(layoutControllerViews) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.bounds.size.width;
|
||||
CGFloat min_view_h = self.bounds.size.height;
|
||||
|
||||
CGFloat min_margin = 9;
|
||||
|
||||
min_x = 0;
|
||||
min_y = 0;
|
||||
min_w = min_view_w;
|
||||
min_h = iPhoneX ? 110 : 80;
|
||||
self.topToolView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = (iPhoneX && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) ? 44: 15;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
min_y = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) ? 10 : (iPhoneX ? 40 : 20);
|
||||
} else {
|
||||
min_y = (iPhoneX && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) ? 10: (iPhoneX ? 40 : 20);
|
||||
}
|
||||
min_w = 40;
|
||||
min_h = 40;
|
||||
self.backBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = self.backBtn.zf_right + 5;
|
||||
min_y = 0;
|
||||
min_w = min_view_w - min_x - 15 ;
|
||||
min_h = 30;
|
||||
self.titleLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.titleLabel.zf_centerY = self.backBtn.zf_centerY;
|
||||
|
||||
min_h = iPhoneX ? 100 : 73;
|
||||
min_x = 0;
|
||||
min_y = min_view_h - min_h;
|
||||
min_w = min_view_w;
|
||||
self.bottomToolView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = (iPhoneX && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) ? 44: 15;
|
||||
min_y = 32;
|
||||
min_w = 30;
|
||||
min_h = 30;
|
||||
self.playOrPauseBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = self.playOrPauseBtn.zf_right + 4;
|
||||
min_y = 0;
|
||||
min_w = 62;
|
||||
min_h = 30;
|
||||
self.currentTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.currentTimeLabel.zf_centerY = self.playOrPauseBtn.zf_centerY;
|
||||
|
||||
min_w = 62;
|
||||
min_x = self.bottomToolView.zf_width - min_w - ((iPhoneX && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) ? 44: min_margin);
|
||||
min_y = 0;
|
||||
min_h = 30;
|
||||
self.totalTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.totalTimeLabel.zf_centerY = self.playOrPauseBtn.zf_centerY;
|
||||
|
||||
min_x = self.currentTimeLabel.zf_right + 4;
|
||||
min_y = 0;
|
||||
min_w = self.totalTimeLabel.zf_left - min_x - 4;
|
||||
min_h = 30;
|
||||
self.slider.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.slider.zf_centerY = self.playOrPauseBtn.zf_centerY;
|
||||
|
||||
min_x = (iPhoneX && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) ? 50: 18;
|
||||
min_y = 0;
|
||||
min_w = 40;
|
||||
min_h = 40;
|
||||
self.lockBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.lockBtn.zf_centerY = self.zf_centerY;
|
||||
|
||||
if (!self.isShow) {
|
||||
self.topToolView.zf_y = -self.topToolView.zf_height;
|
||||
self.bottomToolView.zf_y = self.zf_height;
|
||||
self.lockBtn.zf_left = iPhoneX ? -82: -47;
|
||||
} else {
|
||||
self.lockBtn.zf_left = iPhoneX ? 50: 18;
|
||||
if (self.player.isLockedScreen) {
|
||||
self.topToolView.zf_y = -self.topToolView.zf_height;
|
||||
self.bottomToolView.zf_y = self.zf_height;
|
||||
} else {
|
||||
self.topToolView.zf_y = 0;
|
||||
self.bottomToolView.zf_y = self.zf_height - self.bottomToolView.zf_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)makeSubViewsAction {
|
||||
[self.backBtn addTarget:self action:@selector(backBtnClickAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.playOrPauseBtn addTarget:self action:@selector(playPauseButtonClickAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.lockBtn addTarget:self action:@selector(lockButtonClickAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
|
||||
#pragma mark - action
|
||||
|
||||
- (void)layoutControllerViews {
|
||||
[self layoutIfNeeded];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)backBtnClickAction:(UIButton *)sender {
|
||||
self.lockBtn.selected = NO;
|
||||
self.player.lockedScreen = NO;
|
||||
self.lockBtn.selected = NO;
|
||||
if (self.player.orientationObserver.supportInterfaceOrientation & ZFInterfaceOrientationMaskPortrait) {
|
||||
[self.player enterFullScreen:NO animated:YES];
|
||||
}
|
||||
if (self.backBtnClickCallback) {
|
||||
self.backBtnClickCallback();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)playPauseButtonClickAction:(UIButton *)sender {
|
||||
[self playOrPause];
|
||||
}
|
||||
|
||||
/// 根据当前播放状态取反
|
||||
- (void)playOrPause {
|
||||
self.playOrPauseBtn.selected = !self.playOrPauseBtn.isSelected;
|
||||
self.playOrPauseBtn.isSelected? [self.player.currentPlayerManager play]: [self.player.currentPlayerManager pause];
|
||||
}
|
||||
|
||||
- (void)playBtnSelectedState:(BOOL)selected {
|
||||
self.playOrPauseBtn.selected = selected;
|
||||
}
|
||||
|
||||
- (void)lockButtonClickAction:(UIButton *)sender {
|
||||
sender.selected = !sender.selected;
|
||||
self.player.lockedScreen = sender.selected;
|
||||
}
|
||||
|
||||
#pragma mark - ZFSliderViewDelegate
|
||||
|
||||
- (void)sliderTouchBegan:(float)value {
|
||||
self.slider.isdragging = YES;
|
||||
}
|
||||
|
||||
- (void)sliderTouchEnded:(float)value {
|
||||
if (self.player.totalTime > 0) {
|
||||
self.slider.isdragging = YES;
|
||||
if (self.sliderValueChanging) self.sliderValueChanging(value, self.slider.isForward);
|
||||
@zf_weakify(self)
|
||||
[self.player seekToTime:self.player.totalTime*value completionHandler:^(BOOL finished) {
|
||||
@zf_strongify(self)
|
||||
if (finished) {
|
||||
self.slider.isdragging = NO;
|
||||
if (self.sliderValueChanged) self.sliderValueChanged(value);
|
||||
if (self.seekToPlay) {
|
||||
[self.player.currentPlayerManager play];
|
||||
}
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
self.slider.isdragging = NO;
|
||||
self.slider.value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sliderValueChanged:(float)value {
|
||||
if (self.player.totalTime == 0) {
|
||||
self.slider.value = 0;
|
||||
return;
|
||||
}
|
||||
self.slider.isdragging = YES;
|
||||
NSString *currentTimeString = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
self.currentTimeLabel.text = currentTimeString;
|
||||
if (self.sliderValueChanging) self.sliderValueChanging(value,self.slider.isForward);
|
||||
}
|
||||
|
||||
- (void)sliderTapped:(float)value {
|
||||
[self sliderTouchEnded:value];
|
||||
NSString *currentTimeString = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
self.currentTimeLabel.text = currentTimeString;
|
||||
}
|
||||
|
||||
#pragma mark - public method
|
||||
|
||||
/// 重置ControlView
|
||||
- (void)resetControlView {
|
||||
self.slider.value = 0;
|
||||
self.slider.bufferValue = 0;
|
||||
self.currentTimeLabel.text = @"00:00";
|
||||
self.totalTimeLabel.text = @"00:00";
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.playOrPauseBtn.selected = YES;
|
||||
self.titleLabel.text = @"";
|
||||
self.topToolView.alpha = 1;
|
||||
self.bottomToolView.alpha = 1;
|
||||
self.isShow = NO;
|
||||
}
|
||||
|
||||
- (void)showControlView {
|
||||
self.lockBtn.alpha = 1;
|
||||
self.isShow = YES;
|
||||
if (self.player.isLockedScreen) {
|
||||
self.topToolView.zf_y = -self.topToolView.zf_height;
|
||||
self.bottomToolView.zf_y = self.zf_height;
|
||||
} else {
|
||||
self.topToolView.zf_y = 0;
|
||||
self.bottomToolView.zf_y = self.zf_height - self.bottomToolView.zf_height;
|
||||
}
|
||||
self.lockBtn.zf_left = iPhoneX ? 50: 18;
|
||||
self.player.statusBarHidden = NO;
|
||||
if (self.player.isLockedScreen) {
|
||||
self.topToolView.alpha = 0;
|
||||
self.bottomToolView.alpha = 0;
|
||||
} else {
|
||||
self.topToolView.alpha = 1;
|
||||
self.bottomToolView.alpha = 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideControlView {
|
||||
self.isShow = NO;
|
||||
self.topToolView.zf_y = -self.topToolView.zf_height;
|
||||
self.bottomToolView.zf_y = self.zf_height;
|
||||
self.lockBtn.zf_left = iPhoneX ? -82: -47;
|
||||
self.player.statusBarHidden = YES;
|
||||
self.topToolView.alpha = 0;
|
||||
self.bottomToolView.alpha = 0;
|
||||
self.lockBtn.alpha = 0;
|
||||
}
|
||||
|
||||
- (BOOL)shouldResponseGestureWithPoint:(CGPoint)point withGestureType:(ZFPlayerGestureType)type touch:(nonnull UITouch *)touch {
|
||||
CGRect sliderRect = [self.bottomToolView convertRect:self.slider.frame toView:self];
|
||||
if (CGRectContainsPoint(sliderRect, point)) {
|
||||
return NO;
|
||||
}
|
||||
if (self.player.isLockedScreen && type != ZFPlayerGestureTypeSingleTap) { // 锁定屏幕方向后只相应tap手势
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer presentationSizeChanged:(CGSize)size {
|
||||
self.lockBtn.hidden = self.player.orientationObserver.fullScreenMode == ZFFullScreenModePortrait;
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
|
||||
if (!self.slider.isdragging) {
|
||||
NSString *currentTimeString = [ZFUtilities convertTimeSecond:currentTime];
|
||||
self.currentTimeLabel.text = currentTimeString;
|
||||
NSString *totalTimeString = [ZFUtilities convertTimeSecond:totalTime];
|
||||
self.totalTimeLabel.text = totalTimeString;
|
||||
self.slider.value = videoPlayer.progress;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime {
|
||||
self.slider.bufferValue = videoPlayer.bufferProgress;
|
||||
}
|
||||
|
||||
- (void)showTitle:(NSString *)title fullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
self.titleLabel.text = title;
|
||||
self.player.orientationObserver.fullScreenMode = fullScreenMode;
|
||||
self.lockBtn.hidden = fullScreenMode == ZFFullScreenModePortrait;
|
||||
}
|
||||
|
||||
/// 调节播放进度slider和当前时间更新
|
||||
- (void)sliderValueChanged:(CGFloat)value currentTimeString:(NSString *)timeString {
|
||||
self.slider.value = value;
|
||||
self.currentTimeLabel.text = timeString;
|
||||
self.slider.isdragging = YES;
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
self.slider.sliderBtn.transform = CGAffineTransformMakeScale(1.2, 1.2);
|
||||
}];
|
||||
}
|
||||
|
||||
/// 滑杆结束滑动
|
||||
- (void)sliderChangeEnded {
|
||||
self.slider.isdragging = NO;
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
self.slider.sliderBtn.transform = CGAffineTransformIdentity;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - setter
|
||||
|
||||
- (void)setFullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
_fullScreenMode = fullScreenMode;
|
||||
self.player.orientationObserver.fullScreenMode = fullScreenMode;
|
||||
self.lockBtn.hidden = fullScreenMode == ZFFullScreenModePortrait;
|
||||
}
|
||||
|
||||
#pragma mark - getter
|
||||
|
||||
- (UIView *)topToolView {
|
||||
if (!_topToolView) {
|
||||
_topToolView = [[UIView alloc] init];
|
||||
UIImage *image = ZFPlayer_Image(@"ZFPlayer_top_shadow");
|
||||
_topToolView.layer.contents = (id)image.CGImage;
|
||||
}
|
||||
return _topToolView;
|
||||
}
|
||||
|
||||
- (UIButton *)backBtn {
|
||||
if (!_backBtn) {
|
||||
_backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_backBtn setImage:ZFPlayer_Image(@"ZFPlayer_back_full") forState:UIControlStateNormal];
|
||||
}
|
||||
return _backBtn;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [[UILabel alloc] init];
|
||||
_titleLabel.textColor = [UIColor whiteColor];
|
||||
_titleLabel.font = [UIFont systemFontOfSize:15.0];
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UIView *)bottomToolView {
|
||||
if (!_bottomToolView) {
|
||||
_bottomToolView = [[UIView alloc] init];
|
||||
UIImage *image = ZFPlayer_Image(@"ZFPlayer_bottom_shadow");
|
||||
_bottomToolView.layer.contents = (id)image.CGImage;
|
||||
}
|
||||
return _bottomToolView;
|
||||
}
|
||||
|
||||
- (UIButton *)playOrPauseBtn {
|
||||
if (!_playOrPauseBtn) {
|
||||
_playOrPauseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_playOrPauseBtn setImage:ZFPlayer_Image(@"ZFPlayer_play") forState:UIControlStateNormal];
|
||||
[_playOrPauseBtn setImage:ZFPlayer_Image(@"ZFPlayer_pause") forState:UIControlStateSelected];
|
||||
}
|
||||
return _playOrPauseBtn;
|
||||
}
|
||||
|
||||
- (UILabel *)currentTimeLabel {
|
||||
if (!_currentTimeLabel) {
|
||||
_currentTimeLabel = [[UILabel alloc] init];
|
||||
_currentTimeLabel.textColor = [UIColor whiteColor];
|
||||
_currentTimeLabel.font = [UIFont systemFontOfSize:14.0f];
|
||||
_currentTimeLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _currentTimeLabel;
|
||||
}
|
||||
|
||||
- (ZFSliderView *)slider {
|
||||
if (!_slider) {
|
||||
_slider = [[ZFSliderView alloc] init];
|
||||
_slider.delegate = self;
|
||||
_slider.maximumTrackTintColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.8];
|
||||
_slider.bufferTrackTintColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
|
||||
_slider.minimumTrackTintColor = [UIColor whiteColor];
|
||||
[_slider setThumbImage:ZFPlayer_Image(@"ZFPlayer_slider") forState:UIControlStateNormal];
|
||||
_slider.sliderHeight = 2;
|
||||
}
|
||||
return _slider;
|
||||
}
|
||||
|
||||
- (UILabel *)totalTimeLabel {
|
||||
if (!_totalTimeLabel) {
|
||||
_totalTimeLabel = [[UILabel alloc] init];
|
||||
_totalTimeLabel.textColor = [UIColor whiteColor];
|
||||
_totalTimeLabel.font = [UIFont systemFontOfSize:14.0f];
|
||||
_totalTimeLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _totalTimeLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)lockBtn {
|
||||
if (!_lockBtn) {
|
||||
_lockBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_lockBtn setImage:ZFPlayer_Image(@"ZFPlayer_unlock-nor") forState:UIControlStateNormal];
|
||||
[_lockBtn setImage:ZFPlayer_Image(@"ZFPlayer_lock-nor") forState:UIControlStateSelected];
|
||||
}
|
||||
return _lockBtn;
|
||||
}
|
||||
|
||||
@end
|
||||
66
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFLoadingView.h
generated
Executable file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// ZFLoadingView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, ZFLoadingType) {
|
||||
ZFLoadingTypeKeep,
|
||||
ZFLoadingTypeFadeOut,
|
||||
};
|
||||
|
||||
@interface ZFLoadingView : UIView
|
||||
|
||||
/// default is ZFLoadingTypeKeep.
|
||||
@property (nonatomic, assign) ZFLoadingType animType;
|
||||
|
||||
/// default is whiteColor.
|
||||
@property (nonatomic, strong, null_resettable) UIColor *lineColor;
|
||||
|
||||
/// Sets the line width of the spinner's circle.
|
||||
@property (nonatomic) CGFloat lineWidth;
|
||||
|
||||
/// Sets whether the view is hidden when not animating.
|
||||
@property (nonatomic) BOOL hidesWhenStopped;
|
||||
|
||||
/// Property indicating the duration of the animation, default is 1.5s.
|
||||
@property (nonatomic, readwrite) NSTimeInterval duration;
|
||||
|
||||
/// anima state
|
||||
@property (nonatomic, assign, readonly, getter=isAnimating) BOOL animating;
|
||||
|
||||
/**
|
||||
* Starts animation of the spinner.
|
||||
*/
|
||||
- (void)startAnimating;
|
||||
|
||||
/**
|
||||
* Stops animation of the spinnner.
|
||||
*/
|
||||
- (void)stopAnimating;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
183
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFLoadingView.m
generated
Executable file
@@ -0,0 +1,183 @@
|
||||
//
|
||||
// ZFLoadingView.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 "ZFLoadingView.h"
|
||||
|
||||
@interface ZFLoadingView ()
|
||||
|
||||
@property (nonatomic, strong, readonly) CAShapeLayer *shapeLayer;
|
||||
@property (nonatomic, assign, getter=isAnimating) BOOL animating;
|
||||
@property (nonatomic, assign) BOOL strokeShow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFLoadingView
|
||||
|
||||
@synthesize lineColor = _lineColor;
|
||||
@synthesize shapeLayer = _shapeLayer;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self initialize];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if (self = [super initWithCoder:aDecoder]) {
|
||||
[self initialize];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
[self initialize];
|
||||
}
|
||||
|
||||
- (void)initialize {
|
||||
[self.layer addSublayer:self.shapeLayer];
|
||||
self.duration = 1;
|
||||
self.lineWidth = 1;
|
||||
self.lineColor = [UIColor whiteColor];
|
||||
self.userInteractionEnabled = NO;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGFloat width = MIN(self.bounds.size.width, self.bounds.size.height);
|
||||
CGFloat height = width;
|
||||
self.shapeLayer.frame = CGRectMake(0, 0, width, height);
|
||||
|
||||
CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
|
||||
CGFloat radius = MIN(CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2) - self.shapeLayer.lineWidth / 2;
|
||||
CGFloat startAngle = (CGFloat)(0);
|
||||
CGFloat endAngle = (CGFloat)(2*M_PI);
|
||||
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
|
||||
self.shapeLayer.path = path.CGPath;
|
||||
}
|
||||
|
||||
- (void)startAnimating {
|
||||
if (self.animating) return;
|
||||
self.animating = YES;
|
||||
if (self.animType == ZFLoadingTypeFadeOut) [self fadeOutShow];
|
||||
CABasicAnimation *rotationAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
|
||||
rotationAnim.toValue = [NSNumber numberWithFloat:2 * M_PI];
|
||||
rotationAnim.duration = self.duration;
|
||||
rotationAnim.repeatCount = CGFLOAT_MAX;
|
||||
rotationAnim.removedOnCompletion = NO;
|
||||
[self.shapeLayer addAnimation:rotationAnim forKey:@"rotation"];
|
||||
if (self.hidesWhenStopped) {
|
||||
self.hidden = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopAnimating {
|
||||
if (!self.animating) return;
|
||||
self.animating = NO;
|
||||
[self.shapeLayer removeAllAnimations];
|
||||
if (self.hidesWhenStopped) {
|
||||
self.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)fadeOutShow {
|
||||
CABasicAnimation *headAnimation = [CABasicAnimation animation];
|
||||
headAnimation.keyPath = @"strokeStart";
|
||||
headAnimation.duration = self.duration / 1.5f;
|
||||
headAnimation.fromValue = @(0.f);
|
||||
headAnimation.toValue = @(0.25f);
|
||||
|
||||
CABasicAnimation *tailAnimation = [CABasicAnimation animation];
|
||||
tailAnimation.keyPath = @"strokeEnd";
|
||||
tailAnimation.duration = self.duration / 1.5f;
|
||||
tailAnimation.fromValue = @(0.f);
|
||||
tailAnimation.toValue = @(1.f);
|
||||
|
||||
CABasicAnimation *endHeadAnimation = [CABasicAnimation animation];
|
||||
endHeadAnimation.keyPath = @"strokeStart";
|
||||
endHeadAnimation.beginTime = self.duration / 1.5f;
|
||||
endHeadAnimation.duration = self.duration / 3.0f;
|
||||
endHeadAnimation.fromValue = @(0.25f);
|
||||
endHeadAnimation.toValue = @(1.f);
|
||||
|
||||
CABasicAnimation *endTailAnimation = [CABasicAnimation animation];
|
||||
endTailAnimation.keyPath = @"strokeEnd";
|
||||
endTailAnimation.beginTime = self.duration / 1.5f;
|
||||
endTailAnimation.duration = self.duration / 3.0f;
|
||||
endTailAnimation.fromValue = @(1.f);
|
||||
endTailAnimation.toValue = @(1.f);
|
||||
|
||||
CAAnimationGroup *animations = [CAAnimationGroup animation];
|
||||
[animations setDuration:self.duration];
|
||||
[animations setAnimations:@[headAnimation, tailAnimation, endHeadAnimation, endTailAnimation]];
|
||||
animations.repeatCount = INFINITY;
|
||||
animations.removedOnCompletion = NO;
|
||||
[self.shapeLayer addAnimation:animations forKey:@"strokeAnim"];
|
||||
|
||||
if (self.hidesWhenStopped) {
|
||||
self.hidden = NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - setter and getter
|
||||
|
||||
- (CAShapeLayer *)shapeLayer {
|
||||
if (!_shapeLayer) {
|
||||
_shapeLayer = [CAShapeLayer layer];
|
||||
_shapeLayer.strokeColor = self.lineColor.CGColor;
|
||||
_shapeLayer.fillColor = [UIColor clearColor].CGColor;
|
||||
_shapeLayer.strokeStart = 0.1;
|
||||
_shapeLayer.strokeEnd = 1;
|
||||
_shapeLayer.lineCap = @"round";
|
||||
_shapeLayer.anchorPoint = CGPointMake(0.5, 0.5);
|
||||
}
|
||||
return _shapeLayer;
|
||||
}
|
||||
|
||||
- (UIColor *)lineColor {
|
||||
if (!_lineColor) {
|
||||
return [UIColor whiteColor];
|
||||
}
|
||||
return _lineColor;
|
||||
}
|
||||
|
||||
- (void)setLineWidth:(CGFloat)lineWidth {
|
||||
_lineWidth = lineWidth;
|
||||
self.shapeLayer.lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
- (void)setLineColor:(UIColor *)lineColor {
|
||||
if (!lineColor) return;
|
||||
_lineColor = lineColor;
|
||||
self.shapeLayer.strokeColor = lineColor.CGColor;
|
||||
}
|
||||
|
||||
- (void)setHidesWhenStopped:(BOOL)hidesWhenStopped {
|
||||
_hidesWhenStopped = hidesWhenStopped;
|
||||
self.hidden = !self.isAnimating && hidesWhenStopped;
|
||||
}
|
||||
|
||||
@end
|
||||
39
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFNetworkSpeedMonitor.h
generated
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// ZFNetworkSpeedMonitor.h
|
||||
// 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 <Foundation/Foundation.h>
|
||||
|
||||
extern NSString *const ZFDownloadNetworkSpeedNotificationKey;
|
||||
extern NSString *const ZFUploadNetworkSpeedNotificationKey;
|
||||
extern NSString *const ZFNetworkSpeedNotificationKey;
|
||||
|
||||
@interface ZFNetworkSpeedMonitor : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *downloadNetworkSpeed;
|
||||
@property (nonatomic, copy, readonly) NSString *uploadNetworkSpeed;
|
||||
|
||||
- (void)startNetworkSpeedMonitor;
|
||||
- (void)stopNetworkSpeedMonitor;
|
||||
|
||||
@end
|
||||
167
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFNetworkSpeedMonitor.m
generated
Normal file
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// ZFNetworkSpeedMonitor.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 "ZFNetworkSpeedMonitor.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayerLogManager.h>)
|
||||
#import <ZFPlayer/ZFPlayerLogManager.h>
|
||||
#else
|
||||
#import "ZFPlayerLogManager.h"
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
|
||||
NSString *const ZFDownloadNetworkSpeedNotificationKey = @"ZFDownloadNetworkSpeedNotificationKey";
|
||||
NSString *const ZFUploadNetworkSpeedNotificationKey = @"ZFUploadNetworkSpeedNotificationKey";
|
||||
NSString *const ZFNetworkSpeedNotificationKey = @"ZFNetworkSpeedNotificationKey";
|
||||
|
||||
@interface ZFNetworkSpeedMonitor () {
|
||||
// 总网速
|
||||
uint32_t _iBytes;
|
||||
uint32_t _oBytes;
|
||||
uint32_t _allFlow;
|
||||
|
||||
// wifi网速
|
||||
uint32_t _wifiIBytes;
|
||||
uint32_t _wifiOBytes;
|
||||
uint32_t _wifiFlow;
|
||||
|
||||
// 3G网速
|
||||
uint32_t _wwanIBytes;
|
||||
uint32_t _wwanOBytes;
|
||||
uint32_t _wwanFlow;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) NSTimer *timer;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFNetworkSpeedMonitor
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_iBytes = _oBytes = _allFlow = _wifiIBytes = _wifiOBytes = _wifiFlow = _wwanIBytes = _wwanOBytes = _wwanFlow = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// 开始监听网速
|
||||
- (void)startNetworkSpeedMonitor {
|
||||
if (!_timer) {
|
||||
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(checkNetworkSpeed) userInfo:nil repeats:YES];
|
||||
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
|
||||
[_timer fire];
|
||||
}
|
||||
}
|
||||
|
||||
// 停止监听网速
|
||||
- (void)stopNetworkSpeedMonitor {
|
||||
if ([_timer isValid]) {
|
||||
[_timer invalidate];
|
||||
_timer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)stringWithbytes:(int)bytes {
|
||||
if (bytes < 1024) { // B
|
||||
return [NSString stringWithFormat:@"%dB", bytes];
|
||||
} else if (bytes >= 1024 && bytes < 1024 * 1024) { // KB
|
||||
return [NSString stringWithFormat:@"%.0fKB", (double)bytes / 1024];
|
||||
} else if (bytes >= 1024 * 1024 && bytes < 1024 * 1024 * 1024) { // MB
|
||||
return [NSString stringWithFormat:@"%.1fMB", (double)bytes / (1024 * 1024)];
|
||||
} else { // GB
|
||||
return [NSString stringWithFormat:@"%.1fGB", (double)bytes / (1024 * 1024 * 1024)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)checkNetworkSpeed {
|
||||
struct ifaddrs *ifa_list = 0, *ifa;
|
||||
if (getifaddrs(&ifa_list) == -1) return;
|
||||
|
||||
uint32_t iBytes = 0;
|
||||
uint32_t oBytes = 0;
|
||||
uint32_t allFlow = 0;
|
||||
uint32_t wifiIBytes = 0;
|
||||
uint32_t wifiOBytes = 0;
|
||||
uint32_t wifiFlow = 0;
|
||||
uint32_t wwanIBytes = 0;
|
||||
uint32_t wwanOBytes = 0;
|
||||
uint32_t wwanFlow = 0;
|
||||
|
||||
for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
|
||||
if (AF_LINK != ifa->ifa_addr->sa_family) continue;
|
||||
if (!(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_RUNNING)) continue;
|
||||
if (ifa->ifa_data == 0) continue;
|
||||
|
||||
// network
|
||||
if (strncmp(ifa->ifa_name, "lo", 2)) {
|
||||
struct if_data* if_data = (struct if_data*)ifa->ifa_data;
|
||||
iBytes += if_data->ifi_ibytes;
|
||||
oBytes += if_data->ifi_obytes;
|
||||
allFlow = iBytes + oBytes;
|
||||
}
|
||||
|
||||
//wifi
|
||||
if (!strcmp(ifa->ifa_name, "en0")) {
|
||||
struct if_data* if_data = (struct if_data*)ifa->ifa_data;
|
||||
wifiIBytes += if_data->ifi_ibytes;
|
||||
wifiOBytes += if_data->ifi_obytes;
|
||||
wifiFlow = wifiIBytes + wifiOBytes;
|
||||
}
|
||||
|
||||
//3G or gprs
|
||||
if (!strcmp(ifa->ifa_name, "pdp_ip0")) {
|
||||
struct if_data* if_data = (struct if_data*)ifa->ifa_data;
|
||||
wwanIBytes += if_data->ifi_ibytes;
|
||||
wwanOBytes += if_data->ifi_obytes;
|
||||
wwanFlow = wwanIBytes + wwanOBytes;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifa_list);
|
||||
if (_iBytes != 0) {
|
||||
_downloadNetworkSpeed = [[self stringWithbytes:iBytes - _iBytes] stringByAppendingString:@"/s"];
|
||||
NSMutableDictionary *userInfo = @{}.mutableCopy;
|
||||
userInfo[ZFNetworkSpeedNotificationKey] = _downloadNetworkSpeed;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:ZFDownloadNetworkSpeedNotificationKey object:nil userInfo:userInfo];
|
||||
ZFPlayerLog(@"downloadNetworkSpeed : %@",_downloadNetworkSpeed);
|
||||
}
|
||||
|
||||
_iBytes = iBytes;
|
||||
|
||||
if (_oBytes != 0) {
|
||||
_uploadNetworkSpeed = [[self stringWithbytes:oBytes - _oBytes] stringByAppendingString:@"/s"];
|
||||
NSMutableDictionary *userInfo = @{}.mutableCopy;
|
||||
userInfo[ZFNetworkSpeedNotificationKey] = _uploadNetworkSpeed;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:ZFUploadNetworkSpeedNotificationKey object:nil userInfo:userInfo];
|
||||
ZFPlayerLog(@"uploadNetworkSpeed :%@",_uploadNetworkSpeed);
|
||||
}
|
||||
|
||||
_oBytes = oBytes;
|
||||
}
|
||||
|
||||
@end
|
||||
|
After Width: | Height: | Size: 339 B |
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 761 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 615 B |
|
After Width: | Height: | Size: 834 B |
|
After Width: | Height: | Size: 565 B |
|
After Width: | Height: | Size: 772 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 585 B |
|
After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 188 B |
|
After Width: | Height: | Size: 453 B |
|
After Width: | Height: | Size: 660 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFPlayer.bundle/ZFPlayer_slider.png
generated
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 577 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
151
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFPlayerControlView.h
generated
Executable file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// ZFPlayerControlView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
#import "ZFPortraitControlView.h"
|
||||
#import "ZFLandScapeControlView.h"
|
||||
#import "ZFSpeedLoadingView.h"
|
||||
#import "ZFSmallFloatControlView.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayerMediaControl.h>)
|
||||
#import <ZFPlayer/ZFPlayerMediaControl.h>
|
||||
#else
|
||||
#import "ZFPlayerMediaControl.h"
|
||||
#endif
|
||||
|
||||
@interface ZFPlayerControlView : UIView <ZFPlayerMediaControl>
|
||||
|
||||
/// 竖屏控制层的View
|
||||
@property (nonatomic, strong, readonly) ZFPortraitControlView *portraitControlView;
|
||||
|
||||
/// 横屏控制层的View
|
||||
@property (nonatomic, strong, readonly) ZFLandScapeControlView *landScapeControlView;
|
||||
|
||||
/// 加载loading
|
||||
@property (nonatomic, strong, readonly) ZFSpeedLoadingView *activity;
|
||||
|
||||
/// 快进快退View
|
||||
@property (nonatomic, strong, readonly) UIView *fastView;
|
||||
|
||||
/// 快进快退进度progress
|
||||
@property (nonatomic, strong, readonly) ZFSliderView *fastProgressView;
|
||||
|
||||
/// 快进快退时间
|
||||
@property (nonatomic, strong, readonly) UILabel *fastTimeLabel;
|
||||
|
||||
/// 快进快退ImageView
|
||||
@property (nonatomic, strong, readonly) UIImageView *fastImageView;
|
||||
|
||||
/// 加载失败按钮
|
||||
@property (nonatomic, strong, readonly) UIButton *failBtn;
|
||||
|
||||
/// 底部播放进度
|
||||
@property (nonatomic, strong, readonly) ZFSliderView *bottomPgrogress;
|
||||
|
||||
/// 封面图
|
||||
@property (nonatomic, strong, readonly) UIImageView *coverImageView;
|
||||
|
||||
/// 高斯模糊的背景图
|
||||
@property (nonatomic, strong, readonly) UIImageView *bgImgView;
|
||||
|
||||
/// 高斯模糊视图
|
||||
@property (nonatomic, strong, readonly) UIView *effectView;
|
||||
|
||||
/// 小窗口控制层
|
||||
@property (nonatomic, strong, readonly) ZFSmallFloatControlView *floatControlView;
|
||||
|
||||
/// 快进视图是否显示动画,默认NO.
|
||||
@property (nonatomic, assign) BOOL fastViewAnimated;
|
||||
|
||||
/// 视频之外区域是否高斯模糊显示,默认YES.
|
||||
@property (nonatomic, assign) BOOL effectViewShow;
|
||||
|
||||
/// 如果是暂停状态,seek完是否播放,默认YES
|
||||
@property (nonatomic, assign) BOOL seekToPlay;
|
||||
|
||||
/// 返回按钮点击回调
|
||||
@property (nonatomic, copy) void(^backBtnClickCallback)(void);
|
||||
|
||||
/// 控制层显示或者隐藏
|
||||
@property (nonatomic, readonly) BOOL controlViewAppeared;
|
||||
|
||||
/// 控制层显示或者隐藏的回调
|
||||
@property (nonatomic, copy) void(^controlViewAppearedCallback)(BOOL appeared);
|
||||
|
||||
/// 控制层自动隐藏的时间,默认2.5秒
|
||||
@property (nonatomic, assign) NSTimeInterval autoHiddenTimeInterval;
|
||||
|
||||
/// 控制层显示、隐藏动画的时长,默认0.25秒
|
||||
@property (nonatomic, assign) NSTimeInterval autoFadeTimeInterval;
|
||||
|
||||
/// 横向滑动控制播放进度时是否显示控制层,默认 YES.
|
||||
@property (nonatomic, assign) BOOL horizontalPanShowControlView;
|
||||
|
||||
/// prepare时候是否显示控制层,默认 NO.
|
||||
@property (nonatomic, assign) BOOL prepareShowControlView;
|
||||
|
||||
/// prepare时候是否显示loading,默认 NO.
|
||||
@property (nonatomic, assign) BOOL prepareShowLoading;
|
||||
|
||||
/// 是否自定义禁止pan手势,默认 NO.
|
||||
@property (nonatomic, assign) BOOL customDisablePanMovingDirection;
|
||||
|
||||
/// 全屏模式
|
||||
@property (nonatomic, assign) ZFFullScreenMode fullScreenMode;
|
||||
|
||||
/**
|
||||
设置标题、封面、全屏模式
|
||||
|
||||
@param title 视频的标题
|
||||
@param coverUrl 视频的封面,占位图默认是灰色的
|
||||
@param fullScreenMode 全屏模式
|
||||
*/
|
||||
- (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl fullScreenMode:(ZFFullScreenMode)fullScreenMode;
|
||||
|
||||
/**
|
||||
设置标题、封面、默认占位图、全屏模式
|
||||
|
||||
@param title 视频的标题
|
||||
@param coverUrl 视频的封面
|
||||
@param placeholder 指定封面的placeholder
|
||||
@param fullScreenMode 全屏模式
|
||||
*/
|
||||
- (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl placeholderImage:(UIImage *)placeholder fullScreenMode:(ZFFullScreenMode)fullScreenMode;
|
||||
|
||||
/**
|
||||
设置标题、UIImage封面、全屏模式
|
||||
|
||||
@param title 视频的标题
|
||||
@param image 视频的封面UIImage
|
||||
@param fullScreenMode 全屏模式
|
||||
*/
|
||||
- (void)showTitle:(NSString *)title coverImage:(UIImage *)image fullScreenMode:(ZFFullScreenMode)fullScreenMode;
|
||||
|
||||
//- (void)showFullScreen
|
||||
|
||||
/**
|
||||
重置控制层
|
||||
*/
|
||||
- (void)resetControlView;
|
||||
|
||||
@end
|
||||
836
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFPlayerControlView.m
generated
Executable file
@@ -0,0 +1,836 @@
|
||||
//
|
||||
// ZFPlayerControlView.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 "ZFPlayerControlView.h"
|
||||
#import <AVKit/AVKit.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "UIView+ZFFrame.h"
|
||||
#import "ZFSliderView.h"
|
||||
#import "ZFUtilities.h"
|
||||
#import "UIImageView+ZFCache.h"
|
||||
#import <MediaPlayer/MediaPlayer.h>
|
||||
#import "ZFVolumeBrightnessView.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayer.h>)
|
||||
#import <ZFPlayer/ZFPlayerConst.h>
|
||||
#else
|
||||
#import "ZFPlayerConst.h"
|
||||
#endif
|
||||
|
||||
|
||||
@interface ZFPlayerControlView () <ZFSliderViewDelegate>
|
||||
/// 竖屏控制层的View
|
||||
@property (nonatomic, strong) ZFPortraitControlView *portraitControlView;
|
||||
/// 横屏控制层的View
|
||||
@property (nonatomic, strong) ZFLandScapeControlView *landScapeControlView;
|
||||
/// 加载loading
|
||||
@property (nonatomic, strong) ZFSpeedLoadingView *activity;
|
||||
/// 快进快退View
|
||||
@property (nonatomic, strong) UIView *fastView;
|
||||
/// 快进快退进度progress
|
||||
@property (nonatomic, strong) ZFSliderView *fastProgressView;
|
||||
/// 快进快退时间
|
||||
@property (nonatomic, strong) UILabel *fastTimeLabel;
|
||||
/// 快进快退ImageView
|
||||
@property (nonatomic, strong) UIImageView *fastImageView;
|
||||
/// 加载失败按钮
|
||||
@property (nonatomic, strong) UIButton *failBtn;
|
||||
/// 底部播放进度
|
||||
@property (nonatomic, strong) ZFSliderView *bottomPgrogress;
|
||||
/// 是否显示了控制层
|
||||
@property (nonatomic, assign, getter=isShowing) BOOL showing;
|
||||
/// 是否播放结束
|
||||
@property (nonatomic, assign, getter=isPlayEnd) BOOL playeEnd;
|
||||
|
||||
@property (nonatomic, assign) BOOL controlViewAppeared;
|
||||
|
||||
@property (nonatomic, assign) NSTimeInterval sumTime;
|
||||
|
||||
@property (nonatomic, strong) dispatch_block_t afterBlock;
|
||||
|
||||
@property (nonatomic, strong) ZFSmallFloatControlView *floatControlView;
|
||||
|
||||
@property (nonatomic, strong) ZFVolumeBrightnessView *volumeBrightnessView;
|
||||
|
||||
@property (nonatomic, strong) UIImageView *bgImgView;
|
||||
|
||||
@property (nonatomic, strong) UIView *effectView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFPlayerControlView
|
||||
@synthesize player = _player;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self addAllSubViews];
|
||||
self.landScapeControlView.hidden = YES;
|
||||
self.floatControlView.hidden = YES;
|
||||
self.seekToPlay = YES;
|
||||
self.effectViewShow = YES;
|
||||
self.horizontalPanShowControlView = YES;
|
||||
self.autoFadeTimeInterval = 0.25;
|
||||
self.autoHiddenTimeInterval = 2.5;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(volumeChanged:)
|
||||
name:@"AVSystemController_SystemVolumeDidChangeNotification"
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.zf_width;
|
||||
CGFloat min_view_h = self.zf_height;
|
||||
|
||||
self.portraitControlView.frame = self.bounds;
|
||||
self.landScapeControlView.frame = self.bounds;
|
||||
self.floatControlView.frame = self.bounds;
|
||||
self.coverImageView.frame = self.bounds;
|
||||
self.bgImgView.frame = self.bounds;
|
||||
self.effectView.frame = self.bounds;
|
||||
|
||||
min_w = 80;
|
||||
min_h = 80;
|
||||
self.activity.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.activity.zf_centerX = self.zf_centerX;
|
||||
self.activity.zf_centerY = self.zf_centerY + 10;
|
||||
|
||||
min_w = 150;
|
||||
min_h = 30;
|
||||
self.failBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.failBtn.center = self.center;
|
||||
|
||||
min_w = 140;
|
||||
min_h = 80;
|
||||
self.fastView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.fastView.center = self.center;
|
||||
|
||||
min_w = 32;
|
||||
min_x = (self.fastView.zf_width - min_w) / 2;
|
||||
min_y = 5;
|
||||
min_h = 32;
|
||||
self.fastImageView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = self.fastImageView.zf_bottom + 2;
|
||||
min_w = self.fastView.zf_width;
|
||||
min_h = 20;
|
||||
self.fastTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 12;
|
||||
min_y = self.fastTimeLabel.zf_bottom + 5;
|
||||
min_w = self.fastView.zf_width - 2 * min_x;
|
||||
min_h = 10;
|
||||
self.fastProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = min_view_h - 1;
|
||||
min_w = min_view_w;
|
||||
min_h = 1;
|
||||
self.bottomPgrogress.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = iPhoneX ? 54 : 30;
|
||||
min_w = 170;
|
||||
min_h = 35;
|
||||
self.volumeBrightnessView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.volumeBrightnessView.zf_centerX = self.zf_centerX;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
|
||||
[self cancelAutoFadeOutControlView];
|
||||
}
|
||||
|
||||
/// 添加所有子控件
|
||||
- (void)addAllSubViews {
|
||||
[self addSubview:self.portraitControlView];
|
||||
[self addSubview:self.landScapeControlView];
|
||||
[self addSubview:self.floatControlView];
|
||||
[self addSubview:self.activity];
|
||||
[self addSubview:self.failBtn];
|
||||
[self addSubview:self.fastView];
|
||||
[self.fastView addSubview:self.fastImageView];
|
||||
[self.fastView addSubview:self.fastTimeLabel];
|
||||
[self.fastView addSubview:self.fastProgressView];
|
||||
[self addSubview:self.bottomPgrogress];
|
||||
[self addSubview:self.volumeBrightnessView];
|
||||
}
|
||||
|
||||
- (void)autoFadeOutControlView {
|
||||
self.controlViewAppeared = YES;
|
||||
[self cancelAutoFadeOutControlView];
|
||||
@zf_weakify(self)
|
||||
self.afterBlock = dispatch_block_create(0, ^{
|
||||
@zf_strongify(self)
|
||||
[self hideControlViewWithAnimated:YES];
|
||||
});
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.autoHiddenTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(),self.afterBlock);
|
||||
}
|
||||
|
||||
/// 取消延时隐藏controlView的方法
|
||||
- (void)cancelAutoFadeOutControlView {
|
||||
if (self.afterBlock) {
|
||||
dispatch_block_cancel(self.afterBlock);
|
||||
self.afterBlock = nil;
|
||||
}
|
||||
}
|
||||
|
||||
/// 隐藏控制层
|
||||
- (void)hideControlViewWithAnimated:(BOOL)animated {
|
||||
self.controlViewAppeared = NO;
|
||||
if (self.controlViewAppearedCallback) {
|
||||
self.controlViewAppearedCallback(NO);
|
||||
}
|
||||
[UIView animateWithDuration:animated ? self.autoFadeTimeInterval : 0 animations:^{
|
||||
if (self.player.isFullScreen) {
|
||||
[self.landScapeControlView hideControlView];
|
||||
} else {
|
||||
if (!self.player.isSmallFloatViewShow) {
|
||||
[self.portraitControlView hideControlView];
|
||||
}
|
||||
}
|
||||
} completion:^(BOOL finished) {
|
||||
self.bottomPgrogress.hidden = NO;
|
||||
}];
|
||||
}
|
||||
|
||||
/// 显示控制层
|
||||
- (void)showControlViewWithAnimated:(BOOL)animated {
|
||||
self.controlViewAppeared = YES;
|
||||
if (self.controlViewAppearedCallback) {
|
||||
self.controlViewAppearedCallback(YES);
|
||||
}
|
||||
[self autoFadeOutControlView];
|
||||
[UIView animateWithDuration:animated ? self.autoFadeTimeInterval : 0 animations:^{
|
||||
if (self.player.isFullScreen) {
|
||||
[self.landScapeControlView showControlView];
|
||||
} else {
|
||||
if (!self.player.isSmallFloatViewShow) {
|
||||
[self.portraitControlView showControlView];
|
||||
}
|
||||
}
|
||||
} completion:^(BOOL finished) {
|
||||
self.bottomPgrogress.hidden = YES;
|
||||
}];
|
||||
}
|
||||
|
||||
/// 音量改变的通知
|
||||
- (void)volumeChanged:(NSNotification *)notification {
|
||||
NSDictionary *userInfo = notification.userInfo;
|
||||
NSString *reasonstr = userInfo[@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"];
|
||||
if ([reasonstr isEqualToString:@"ExplicitVolumeChange"]) {
|
||||
float volume = [ userInfo[@"AVSystemController_AudioVolumeNotificationParameter"] floatValue];
|
||||
if (self.player.isFullScreen) {
|
||||
[self.volumeBrightnessView updateProgress:volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
|
||||
} else {
|
||||
[self.volumeBrightnessView addSystemVolumeView];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public Method
|
||||
|
||||
/// 重置控制层
|
||||
- (void)resetControlView {
|
||||
[self.portraitControlView resetControlView];
|
||||
[self.landScapeControlView resetControlView];
|
||||
[self cancelAutoFadeOutControlView];
|
||||
self.bottomPgrogress.value = 0;
|
||||
self.bottomPgrogress.bufferValue = 0;
|
||||
self.floatControlView.hidden = YES;
|
||||
self.failBtn.hidden = YES;
|
||||
self.volumeBrightnessView.hidden = YES;
|
||||
self.portraitControlView.hidden = self.player.isFullScreen;
|
||||
self.landScapeControlView.hidden = !self.player.isFullScreen;
|
||||
if (self.controlViewAppeared) {
|
||||
[self showControlViewWithAnimated:NO];
|
||||
} else {
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置标题、封面、全屏模式
|
||||
- (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl fullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
UIImage *placeholder = [ZFUtilities imageWithColor:[UIColor colorWithRed:220/255.0 green:220/255.0 blue:220/255.0 alpha:1] size:self.bgImgView.bounds.size];
|
||||
[self showTitle:title coverURLString:coverUrl placeholderImage:placeholder fullScreenMode:fullScreenMode];
|
||||
}
|
||||
|
||||
/// 设置标题、封面、默认占位图、全屏模式
|
||||
- (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl placeholderImage:(UIImage *)placeholder fullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
[self resetControlView];
|
||||
[self layoutIfNeeded];
|
||||
[self setNeedsDisplay];
|
||||
[self.portraitControlView showTitle:title fullScreenMode:fullScreenMode];
|
||||
[self.landScapeControlView showTitle:title fullScreenMode:fullScreenMode];
|
||||
/// 这里直接设置播放器视图里的coverImageView
|
||||
[self.player.currentPlayerManager.view.coverImageView setImageWithURLString:coverUrl placeholder:placeholder];
|
||||
[self.bgImgView setImageWithURLString:coverUrl placeholder:placeholder];
|
||||
if (self.prepareShowControlView) {
|
||||
[self showControlViewWithAnimated:NO];
|
||||
} else {
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置标题、UIImage封面、全屏模式
|
||||
- (void)showTitle:(NSString *)title coverImage:(UIImage *)image fullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
[self resetControlView];
|
||||
[self layoutIfNeeded];
|
||||
[self setNeedsDisplay];
|
||||
[self.portraitControlView showTitle:title fullScreenMode:fullScreenMode];
|
||||
[self.landScapeControlView showTitle:title fullScreenMode:fullScreenMode];
|
||||
self.coverImageView.image = image;
|
||||
self.bgImgView.image = image;
|
||||
if (self.prepareShowControlView) {
|
||||
[self showControlViewWithAnimated:NO];
|
||||
} else {
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ZFPlayerControlViewDelegate
|
||||
|
||||
/// 手势筛选,返回NO不响应该手势
|
||||
- (BOOL)gestureTriggerCondition:(ZFPlayerGestureControl *)gestureControl gestureType:(ZFPlayerGestureType)gestureType gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer touch:(nonnull UITouch *)touch {
|
||||
CGPoint point = [touch locationInView:self];
|
||||
if (self.player.isSmallFloatViewShow && !self.player.isFullScreen && gestureType != ZFPlayerGestureTypeSingleTap) {
|
||||
return NO;
|
||||
}
|
||||
if (self.player.isFullScreen) {
|
||||
if (!self.customDisablePanMovingDirection) {
|
||||
/// 不禁用滑动方向
|
||||
self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionNone;
|
||||
}
|
||||
return [self.landScapeControlView shouldResponseGestureWithPoint:point withGestureType:gestureType touch:touch];
|
||||
} else {
|
||||
if (!self.customDisablePanMovingDirection) {
|
||||
if (self.player.scrollView) { /// 列表时候禁止上下滑动(防止和列表滑动冲突)
|
||||
self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionVertical;
|
||||
} else { /// 不禁用滑动方向
|
||||
self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionNone;
|
||||
}
|
||||
}
|
||||
return [self.portraitControlView shouldResponseGestureWithPoint:point withGestureType:gestureType touch:touch];
|
||||
}
|
||||
}
|
||||
|
||||
/// 单击手势事件
|
||||
- (void)gestureSingleTapped:(ZFPlayerGestureControl *)gestureControl {
|
||||
if (!self.player) return;
|
||||
if (self.player.isSmallFloatViewShow && !self.player.isFullScreen) {
|
||||
[self.player enterFullScreen:YES animated:YES];
|
||||
} else {
|
||||
if (self.controlViewAppeared) {
|
||||
[self hideControlViewWithAnimated:YES];
|
||||
} else {
|
||||
/// 显示之前先把控制层复位,先隐藏后显示
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
[self showControlViewWithAnimated:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 双击手势事件
|
||||
- (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
|
||||
if (self.player.isFullScreen) {
|
||||
[self.landScapeControlView playOrPause];
|
||||
} else {
|
||||
[self.portraitControlView playOrPause];
|
||||
}
|
||||
}
|
||||
|
||||
/// 开始滑动手势事件
|
||||
- (void)gestureBeganPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
|
||||
if (direction == ZFPanDirectionH) {
|
||||
self.sumTime = self.player.currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// 滑动中手势事件
|
||||
- (void)gestureChangedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location withVelocity:(CGPoint)velocity {
|
||||
if (direction == ZFPanDirectionH) {
|
||||
// 每次滑动需要叠加时间
|
||||
self.sumTime += velocity.x / 200;
|
||||
// 需要限定sumTime的范围
|
||||
NSTimeInterval totalMovieDuration = self.player.totalTime;
|
||||
if (totalMovieDuration == 0) return;
|
||||
if (self.sumTime > totalMovieDuration) self.sumTime = totalMovieDuration;
|
||||
if (self.sumTime < 0) self.sumTime = 0;
|
||||
BOOL style = NO;
|
||||
if (velocity.x > 0) style = YES;
|
||||
if (velocity.x < 0) style = NO;
|
||||
if (velocity.x == 0) return;
|
||||
[self sliderValueChangingValue:self.sumTime/totalMovieDuration isForward:style];
|
||||
} else if (direction == ZFPanDirectionV) {
|
||||
if (location == ZFPanLocationLeft) { /// 调节亮度
|
||||
self.player.brightness -= (velocity.y) / 10000;
|
||||
[self.volumeBrightnessView updateProgress:self.player.brightness withVolumeBrightnessType:ZFVolumeBrightnessTypeumeBrightness];
|
||||
} else if (location == ZFPanLocationRight) { /// 调节声音
|
||||
self.player.volume -= (velocity.y) / 10000;
|
||||
if (self.player.isFullScreen) {
|
||||
[self.volumeBrightnessView updateProgress:self.player.volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 滑动结束手势事件
|
||||
- (void)gestureEndedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
|
||||
@zf_weakify(self)
|
||||
if (direction == ZFPanDirectionH && self.sumTime >= 0 && self.player.totalTime > 0) {
|
||||
[self.player seekToTime:self.sumTime completionHandler:^(BOOL finished) {
|
||||
if (finished) {
|
||||
@zf_strongify(self)
|
||||
/// 左右滑动调节播放进度
|
||||
[self.portraitControlView sliderChangeEnded];
|
||||
[self.landScapeControlView sliderChangeEnded];
|
||||
self.bottomPgrogress.isdragging = NO;
|
||||
if (self.controlViewAppeared) {
|
||||
[self autoFadeOutControlView];
|
||||
}
|
||||
}
|
||||
}];
|
||||
if (self.seekToPlay) {
|
||||
[self.player.currentPlayerManager play];
|
||||
}
|
||||
self.sumTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 捏合手势事件,这里改变了视频的填充模式
|
||||
- (void)gesturePinched:(ZFPlayerGestureControl *)gestureControl scale:(float)scale {
|
||||
if (scale > 1) {
|
||||
self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFill;
|
||||
} else {
|
||||
self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFit;
|
||||
}
|
||||
}
|
||||
|
||||
/// 准备播放
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer prepareToPlay:(NSURL *)assetURL {
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
}
|
||||
|
||||
/// 播放状态改变
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer playStateChanged:(ZFPlayerPlaybackState)state {
|
||||
if (state == ZFPlayerPlayStatePlaying) {
|
||||
[self.portraitControlView playBtnSelectedState:YES];
|
||||
[self.landScapeControlView playBtnSelectedState:YES];
|
||||
self.failBtn.hidden = YES;
|
||||
/// 开始播放时候判断是否显示loading
|
||||
if (videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStateStalled && !self.prepareShowLoading) {
|
||||
[self.activity startAnimating];
|
||||
} else if ((videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStateStalled || videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStatePrepare) && self.prepareShowLoading) {
|
||||
[self.activity startAnimating];
|
||||
}
|
||||
} else if (state == ZFPlayerPlayStatePaused) {
|
||||
[self.portraitControlView playBtnSelectedState:NO];
|
||||
[self.landScapeControlView playBtnSelectedState:NO];
|
||||
/// 暂停的时候隐藏loading
|
||||
[self.activity stopAnimating];
|
||||
self.failBtn.hidden = YES;
|
||||
} else if (state == ZFPlayerPlayStatePlayFailed) {
|
||||
self.failBtn.hidden = NO;
|
||||
[self.activity stopAnimating];
|
||||
}
|
||||
}
|
||||
|
||||
/// 加载状态改变
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer loadStateChanged:(ZFPlayerLoadState)state {
|
||||
if (state == ZFPlayerLoadStatePrepare) {
|
||||
self.coverImageView.hidden = NO;
|
||||
[self.portraitControlView playBtnSelectedState:videoPlayer.currentPlayerManager.shouldAutoPlay];
|
||||
[self.landScapeControlView playBtnSelectedState:videoPlayer.currentPlayerManager.shouldAutoPlay];
|
||||
} else if (state == ZFPlayerLoadStatePlaythroughOK || state == ZFPlayerLoadStatePlayable) {
|
||||
self.coverImageView.hidden = YES;
|
||||
if (self.effectViewShow) {
|
||||
self.effectView.hidden = NO;
|
||||
} else {
|
||||
self.effectView.hidden = YES;
|
||||
self.player.currentPlayerManager.view.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
}
|
||||
if (state == ZFPlayerLoadStateStalled && videoPlayer.currentPlayerManager.isPlaying && !self.prepareShowLoading) {
|
||||
[self.activity startAnimating];
|
||||
} else if ((state == ZFPlayerLoadStateStalled || state == ZFPlayerLoadStatePrepare) && videoPlayer.currentPlayerManager.isPlaying && self.prepareShowLoading) {
|
||||
[self.activity startAnimating];
|
||||
} else {
|
||||
[self.activity stopAnimating];
|
||||
}
|
||||
}
|
||||
|
||||
/// 播放进度改变回调
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
|
||||
[self.portraitControlView videoPlayer:videoPlayer currentTime:currentTime totalTime:totalTime];
|
||||
[self.landScapeControlView videoPlayer:videoPlayer currentTime:currentTime totalTime:totalTime];
|
||||
if (!self.bottomPgrogress.isdragging) {
|
||||
self.bottomPgrogress.value = videoPlayer.progress;
|
||||
}
|
||||
}
|
||||
|
||||
/// 缓冲改变回调
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime {
|
||||
[self.portraitControlView videoPlayer:videoPlayer bufferTime:bufferTime];
|
||||
[self.landScapeControlView videoPlayer:videoPlayer bufferTime:bufferTime];
|
||||
self.bottomPgrogress.bufferValue = videoPlayer.bufferProgress;
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer presentationSizeChanged:(CGSize)size {
|
||||
[self.landScapeControlView videoPlayer:videoPlayer presentationSizeChanged:size];
|
||||
}
|
||||
|
||||
/// 视频view即将旋转
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationWillChange:(ZFOrientationObserver *)observer {
|
||||
self.portraitControlView.hidden = observer.isFullScreen;
|
||||
self.landScapeControlView.hidden = !observer.isFullScreen;
|
||||
if (videoPlayer.isSmallFloatViewShow) {
|
||||
self.floatControlView.hidden = observer.isFullScreen;
|
||||
self.portraitControlView.hidden = YES;
|
||||
if (observer.isFullScreen) {
|
||||
self.controlViewAppeared = NO;
|
||||
[self cancelAutoFadeOutControlView];
|
||||
}
|
||||
}
|
||||
if (self.controlViewAppeared) {
|
||||
[self showControlViewWithAnimated:NO];
|
||||
} else {
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
}
|
||||
|
||||
if (observer.isFullScreen) {
|
||||
[self.volumeBrightnessView removeSystemVolumeView];
|
||||
} else {
|
||||
[self.volumeBrightnessView addSystemVolumeView];
|
||||
}
|
||||
}
|
||||
|
||||
/// 视频view已经旋转
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationDidChanged:(ZFOrientationObserver *)observer {
|
||||
if (self.controlViewAppeared) {
|
||||
[self showControlViewWithAnimated:NO];
|
||||
} else {
|
||||
[self hideControlViewWithAnimated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
/// 锁定旋转方向
|
||||
- (void)lockedVideoPlayer:(ZFPlayerController *)videoPlayer lockedScreen:(BOOL)locked {
|
||||
[self showControlViewWithAnimated:YES];
|
||||
}
|
||||
|
||||
/// 列表滑动时视频view已经显示
|
||||
- (void)playerDidAppearInScrollView:(ZFPlayerController *)videoPlayer {
|
||||
if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
|
||||
self.floatControlView.hidden = YES;
|
||||
self.portraitControlView.hidden = NO;
|
||||
}
|
||||
}
|
||||
|
||||
/// 列表滑动时视频view已经消失
|
||||
- (void)playerDidDisappearInScrollView:(ZFPlayerController *)videoPlayer {
|
||||
if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
|
||||
self.floatControlView.hidden = NO;
|
||||
self.portraitControlView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer floatViewShow:(BOOL)show {
|
||||
self.floatControlView.hidden = !show;
|
||||
self.portraitControlView.hidden = show;
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
|
||||
- (void)sliderValueChangingValue:(CGFloat)value isForward:(BOOL)forward {
|
||||
if (self.horizontalPanShowControlView) {
|
||||
/// 显示控制层
|
||||
[self showControlViewWithAnimated:NO];
|
||||
[self cancelAutoFadeOutControlView];
|
||||
}
|
||||
|
||||
self.fastProgressView.value = value;
|
||||
self.fastView.hidden = NO;
|
||||
self.fastView.alpha = 1;
|
||||
if (forward) {
|
||||
self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_forward");
|
||||
} else {
|
||||
self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_backward");
|
||||
}
|
||||
NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
NSString *totalTime = [ZFUtilities convertTimeSecond:self.player.totalTime];
|
||||
self.fastTimeLabel.text = [NSString stringWithFormat:@"%@ / %@",draggedTime,totalTime];
|
||||
/// 更新滑杆
|
||||
[self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
|
||||
[self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
|
||||
self.bottomPgrogress.isdragging = YES;
|
||||
self.bottomPgrogress.value = value;
|
||||
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideFastView) object:nil];
|
||||
[self performSelector:@selector(hideFastView) withObject:nil afterDelay:0.1];
|
||||
|
||||
if (self.fastViewAnimated) {
|
||||
[UIView animateWithDuration:0.4 animations:^{
|
||||
self.fastView.transform = CGAffineTransformMakeTranslation(forward?8:-8, 0);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/// 隐藏快进视图
|
||||
- (void)hideFastView {
|
||||
[UIView animateWithDuration:0.4 animations:^{
|
||||
self.fastView.transform = CGAffineTransformIdentity;
|
||||
self.fastView.alpha = 0;
|
||||
} completion:^(BOOL finished) {
|
||||
self.fastView.hidden = YES;
|
||||
}];
|
||||
}
|
||||
|
||||
/// 加载失败
|
||||
- (void)failBtnClick:(UIButton *)sender {
|
||||
[self.player.currentPlayerManager reloadPlayer];
|
||||
}
|
||||
|
||||
#pragma mark - setter
|
||||
|
||||
- (void)setPlayer:(ZFPlayerController *)player {
|
||||
_player = player;
|
||||
self.landScapeControlView.player = player;
|
||||
self.portraitControlView.player = player;
|
||||
/// 解决播放时候黑屏闪一下问题
|
||||
[player.currentPlayerManager.view insertSubview:self.bgImgView atIndex:0];
|
||||
[self.bgImgView addSubview:self.effectView];
|
||||
self.bgImgView.frame = player.currentPlayerManager.view.bounds;
|
||||
self.bgImgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.effectView.frame = self.bgImgView.bounds;
|
||||
}
|
||||
|
||||
- (void)setSeekToPlay:(BOOL)seekToPlay {
|
||||
_seekToPlay = seekToPlay;
|
||||
self.portraitControlView.seekToPlay = seekToPlay;
|
||||
self.landScapeControlView.seekToPlay = seekToPlay;
|
||||
}
|
||||
|
||||
- (void)setEffectViewShow:(BOOL)effectViewShow {
|
||||
_effectViewShow = effectViewShow;
|
||||
if (effectViewShow) {
|
||||
self.bgImgView.hidden = NO;
|
||||
} else {
|
||||
self.bgImgView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setFullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
_fullScreenMode = fullScreenMode;
|
||||
self.portraitControlView.fullScreenMode = fullScreenMode;
|
||||
self.landScapeControlView.fullScreenMode = fullScreenMode;
|
||||
self.player.orientationObserver.fullScreenMode = fullScreenMode;
|
||||
}
|
||||
|
||||
#pragma mark - getter
|
||||
|
||||
- (UIImageView *)bgImgView {
|
||||
if (!_bgImgView) {
|
||||
_bgImgView = [[UIImageView alloc] init];
|
||||
_bgImgView.userInteractionEnabled = YES;
|
||||
}
|
||||
return _bgImgView;
|
||||
}
|
||||
|
||||
- (UIView *)effectView {
|
||||
if (!_effectView) {
|
||||
if (@available(iOS 8.0, *)) {
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
|
||||
_effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
} else {
|
||||
UIToolbar *effectView = [[UIToolbar alloc] init];
|
||||
effectView.barStyle = UIBarStyleBlackTranslucent;
|
||||
_effectView = effectView;
|
||||
}
|
||||
}
|
||||
return _effectView;
|
||||
}
|
||||
|
||||
- (ZFPortraitControlView *)portraitControlView {
|
||||
if (!_portraitControlView) {
|
||||
@zf_weakify(self)
|
||||
_portraitControlView = [[ZFPortraitControlView alloc] init];
|
||||
_portraitControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
|
||||
@zf_strongify(self)
|
||||
NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
/// 更新滑杆和时间
|
||||
[self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
|
||||
self.fastProgressView.value = value;
|
||||
self.bottomPgrogress.isdragging = YES;
|
||||
self.bottomPgrogress.value = value;
|
||||
[self cancelAutoFadeOutControlView];
|
||||
};
|
||||
_portraitControlView.sliderValueChanged = ^(CGFloat value) {
|
||||
@zf_strongify(self)
|
||||
[self.landScapeControlView sliderChangeEnded];
|
||||
self.fastProgressView.value = value;
|
||||
self.bottomPgrogress.isdragging = NO;
|
||||
self.bottomPgrogress.value = value;
|
||||
[self autoFadeOutControlView];
|
||||
};
|
||||
}
|
||||
return _portraitControlView;
|
||||
}
|
||||
|
||||
- (ZFLandScapeControlView *)landScapeControlView {
|
||||
if (!_landScapeControlView) {
|
||||
@zf_weakify(self)
|
||||
_landScapeControlView = [[ZFLandScapeControlView alloc] init];
|
||||
_landScapeControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
|
||||
@zf_strongify(self)
|
||||
NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
/// 更新滑杆和时间
|
||||
[self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
|
||||
self.fastProgressView.value = value;
|
||||
self.bottomPgrogress.isdragging = YES;
|
||||
self.bottomPgrogress.value = value;
|
||||
[self cancelAutoFadeOutControlView];
|
||||
};
|
||||
_landScapeControlView.sliderValueChanged = ^(CGFloat value) {
|
||||
@zf_strongify(self)
|
||||
[self.portraitControlView sliderChangeEnded];
|
||||
self.fastProgressView.value = value;
|
||||
self.bottomPgrogress.isdragging = NO;
|
||||
self.bottomPgrogress.value = value;
|
||||
[self autoFadeOutControlView];
|
||||
};
|
||||
}
|
||||
return _landScapeControlView;
|
||||
}
|
||||
|
||||
- (ZFSpeedLoadingView *)activity {
|
||||
if (!_activity) {
|
||||
_activity = [[ZFSpeedLoadingView alloc] init];
|
||||
}
|
||||
return _activity;
|
||||
}
|
||||
|
||||
- (UIView *)fastView {
|
||||
if (!_fastView) {
|
||||
_fastView = [[UIView alloc] init];
|
||||
_fastView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
|
||||
_fastView.layer.cornerRadius = 4;
|
||||
_fastView.layer.masksToBounds = YES;
|
||||
_fastView.hidden = YES;
|
||||
}
|
||||
return _fastView;
|
||||
}
|
||||
|
||||
- (UIImageView *)fastImageView {
|
||||
if (!_fastImageView) {
|
||||
_fastImageView = [[UIImageView alloc] init];
|
||||
}
|
||||
return _fastImageView;
|
||||
}
|
||||
|
||||
- (UILabel *)fastTimeLabel {
|
||||
if (!_fastTimeLabel) {
|
||||
_fastTimeLabel = [[UILabel alloc] init];
|
||||
_fastTimeLabel.textColor = [UIColor whiteColor];
|
||||
_fastTimeLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_fastTimeLabel.font = [UIFont systemFontOfSize:14.0];
|
||||
_fastTimeLabel.adjustsFontSizeToFitWidth = YES;
|
||||
}
|
||||
return _fastTimeLabel;
|
||||
}
|
||||
|
||||
- (ZFSliderView *)fastProgressView {
|
||||
if (!_fastProgressView) {
|
||||
_fastProgressView = [[ZFSliderView alloc] init];
|
||||
_fastProgressView.maximumTrackTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.4];
|
||||
_fastProgressView.minimumTrackTintColor = [UIColor whiteColor];
|
||||
_fastProgressView.sliderHeight = 2;
|
||||
_fastProgressView.isHideSliderBlock = NO;
|
||||
}
|
||||
return _fastProgressView;
|
||||
}
|
||||
|
||||
- (UIButton *)failBtn {
|
||||
if (!_failBtn) {
|
||||
_failBtn = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
[_failBtn setTitle:@"加载失败,点击重试" forState:UIControlStateNormal];
|
||||
[_failBtn addTarget:self action:@selector(failBtnClick:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_failBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||
_failBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
|
||||
_failBtn.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
|
||||
_failBtn.hidden = YES;
|
||||
}
|
||||
return _failBtn;
|
||||
}
|
||||
|
||||
- (ZFSliderView *)bottomPgrogress {
|
||||
if (!_bottomPgrogress) {
|
||||
_bottomPgrogress = [[ZFSliderView alloc] init];
|
||||
_bottomPgrogress.maximumTrackTintColor = [UIColor clearColor];
|
||||
_bottomPgrogress.minimumTrackTintColor = [UIColor whiteColor];
|
||||
_bottomPgrogress.bufferTrackTintColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
|
||||
_bottomPgrogress.sliderHeight = 1;
|
||||
_bottomPgrogress.isHideSliderBlock = NO;
|
||||
}
|
||||
return _bottomPgrogress;
|
||||
}
|
||||
|
||||
- (ZFSmallFloatControlView *)floatControlView {
|
||||
if (!_floatControlView) {
|
||||
_floatControlView = [[ZFSmallFloatControlView alloc] init];
|
||||
@zf_weakify(self)
|
||||
_floatControlView.closeClickCallback = ^{
|
||||
@zf_strongify(self)
|
||||
if (self.player.containerType == ZFPlayerContainerTypeCell) {
|
||||
[self.player stopCurrentPlayingCell];
|
||||
} else if (self.player.containerType == ZFPlayerContainerTypeView) {
|
||||
[self.player stopCurrentPlayingView];
|
||||
}
|
||||
[self resetControlView];
|
||||
};
|
||||
}
|
||||
return _floatControlView;
|
||||
}
|
||||
|
||||
- (ZFVolumeBrightnessView *)volumeBrightnessView {
|
||||
if (!_volumeBrightnessView) {
|
||||
_volumeBrightnessView = [[ZFVolumeBrightnessView alloc] init];
|
||||
_volumeBrightnessView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
|
||||
_volumeBrightnessView.hidden = YES;
|
||||
}
|
||||
return _volumeBrightnessView;
|
||||
}
|
||||
|
||||
- (void)setBackBtnClickCallback:(void (^)(void))backBtnClickCallback {
|
||||
_backBtnClickCallback = [backBtnClickCallback copy];
|
||||
self.landScapeControlView.backBtnClickCallback = _backBtnClickCallback;
|
||||
}
|
||||
|
||||
@end
|
||||
111
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFPortraitControlView.h
generated
Executable file
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// ZFPortraitControlView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
#import "ZFSliderView.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayerController.h>)
|
||||
#import <ZFPlayer/ZFPlayerController.h>
|
||||
#else
|
||||
#import "ZFPlayerController.h"
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ZFPortraitControlView : UIView
|
||||
|
||||
/// 底部工具栏
|
||||
@property (nonatomic, strong, readonly) UIView *bottomToolView;
|
||||
|
||||
/// 顶部工具栏
|
||||
@property (nonatomic, strong, readonly) UIView *topToolView;
|
||||
|
||||
/// 标题
|
||||
@property (nonatomic, strong, readonly) UILabel *titleLabel;
|
||||
|
||||
/// 播放或暂停按钮
|
||||
@property (nonatomic, strong, readonly) UIButton *playOrPauseBtn;
|
||||
|
||||
/// 播放的当前时间
|
||||
@property (nonatomic, strong, readonly) UILabel *currentTimeLabel;
|
||||
|
||||
/// 滑杆
|
||||
@property (nonatomic, strong, readonly) ZFSliderView *slider;
|
||||
|
||||
/// 视频总时间
|
||||
@property (nonatomic, strong, readonly) UILabel *totalTimeLabel;
|
||||
|
||||
/// 全屏按钮
|
||||
@property (nonatomic, strong, readonly) UIButton *fullScreenBtn;
|
||||
|
||||
/// 播放器
|
||||
@property (nonatomic, weak) ZFPlayerController *player;
|
||||
|
||||
/// slider滑动中
|
||||
@property (nonatomic, copy, nullable) void(^sliderValueChanging)(CGFloat value,BOOL forward);
|
||||
|
||||
/// slider滑动结束
|
||||
@property (nonatomic, copy, nullable) void(^sliderValueChanged)(CGFloat value);
|
||||
|
||||
/// 如果是暂停状态,seek完是否播放,默认YES
|
||||
@property (nonatomic, assign) BOOL seekToPlay;
|
||||
|
||||
/// 全屏模式
|
||||
@property (nonatomic, assign) ZFFullScreenMode fullScreenMode;
|
||||
|
||||
/// 重置控制层
|
||||
- (void)resetControlView;
|
||||
|
||||
/// 显示控制层
|
||||
- (void)showControlView;
|
||||
|
||||
/// 隐藏控制层
|
||||
- (void)hideControlView;
|
||||
|
||||
/// 设置播放时间
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime;
|
||||
|
||||
/// 设置缓冲时间
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime;
|
||||
|
||||
/// 是否响应该手势
|
||||
- (BOOL)shouldResponseGestureWithPoint:(CGPoint)point withGestureType:(ZFPlayerGestureType)type touch:(nonnull UITouch *)touch;
|
||||
|
||||
/// 标题和全屏模式
|
||||
- (void)showTitle:(NSString *_Nullable)title fullScreenMode:(ZFFullScreenMode)fullScreenMode;
|
||||
|
||||
/// 根据当前播放状态取反
|
||||
- (void)playOrPause;
|
||||
|
||||
/// 播放按钮状态
|
||||
- (void)playBtnSelectedState:(BOOL)selected;
|
||||
|
||||
/// 调节播放进度slider和当前时间更新
|
||||
- (void)sliderValueChanged:(CGFloat)value currentTimeString:(NSString *)timeString;
|
||||
|
||||
/// 滑杆结束滑动
|
||||
- (void)sliderChangeEnded;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
387
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFPortraitControlView.m
generated
Executable file
@@ -0,0 +1,387 @@
|
||||
//
|
||||
// ZFPortraitControlView.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 "ZFPortraitControlView.h"
|
||||
#import "UIView+ZFFrame.h"
|
||||
#import "ZFUtilities.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayer.h>)
|
||||
#import <ZFPlayer/ZFPlayerConst.h>
|
||||
#else
|
||||
#import "ZFPlayerConst.h"
|
||||
#endif
|
||||
|
||||
@interface ZFPortraitControlView () <ZFSliderViewDelegate>
|
||||
/// 底部工具栏
|
||||
@property (nonatomic, strong) UIView *bottomToolView;
|
||||
/// 顶部工具栏
|
||||
@property (nonatomic, strong) UIView *topToolView;
|
||||
/// 标题
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
/// 播放或暂停按钮
|
||||
@property (nonatomic, strong) UIButton *playOrPauseBtn;
|
||||
/// 播放的当前时间
|
||||
@property (nonatomic, strong) UILabel *currentTimeLabel;
|
||||
/// 滑杆
|
||||
@property (nonatomic, strong) ZFSliderView *slider;
|
||||
/// 视频总时间
|
||||
@property (nonatomic, strong) UILabel *totalTimeLabel;
|
||||
/// 全屏按钮
|
||||
@property (nonatomic, strong) UIButton *fullScreenBtn;
|
||||
|
||||
@property (nonatomic, assign) BOOL isShow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFPortraitControlView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
// 添加子控件
|
||||
[self addSubview:self.topToolView];
|
||||
[self addSubview:self.bottomToolView];
|
||||
[self addSubview:self.playOrPauseBtn];
|
||||
[self.topToolView addSubview:self.titleLabel];
|
||||
[self.bottomToolView addSubview:self.currentTimeLabel];
|
||||
[self.bottomToolView addSubview:self.slider];
|
||||
[self.bottomToolView addSubview:self.totalTimeLabel];
|
||||
[self.bottomToolView addSubview:self.fullScreenBtn];
|
||||
|
||||
// 设置子控件的响应事件
|
||||
[self makeSubViewsAction];
|
||||
|
||||
[self resetControlView];
|
||||
self.clipsToBounds = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.bounds.size.width;
|
||||
CGFloat min_view_h = self.bounds.size.height;
|
||||
CGFloat min_margin = 9;
|
||||
|
||||
min_x = 0;
|
||||
min_y = 0;
|
||||
min_w = min_view_w;
|
||||
min_h = 40;
|
||||
self.topToolView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 15;
|
||||
min_y = 5;
|
||||
min_w = min_view_w - min_x - 15;
|
||||
min_h = 30;
|
||||
self.titleLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_h = 40;
|
||||
min_x = 0;
|
||||
min_y = min_view_h - min_h;
|
||||
min_w = min_view_w;
|
||||
self.bottomToolView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = 0;
|
||||
min_w = 44;
|
||||
min_h = min_w;
|
||||
self.playOrPauseBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.playOrPauseBtn.center = self.center;
|
||||
|
||||
min_x = min_margin;
|
||||
min_w = 62;
|
||||
min_h = 28;
|
||||
min_y = (self.bottomToolView.zf_height - min_h)/2;
|
||||
self.currentTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_w = 28;
|
||||
min_h = min_w;
|
||||
min_x = self.bottomToolView.zf_width - min_w - min_margin;
|
||||
min_y = 0;
|
||||
self.fullScreenBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.fullScreenBtn.zf_centerY = self.currentTimeLabel.zf_centerY;
|
||||
|
||||
min_w = 62;
|
||||
min_h = 28;
|
||||
min_x = self.fullScreenBtn.zf_left - min_w - 4;
|
||||
min_y = 0;
|
||||
self.totalTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.totalTimeLabel.zf_centerY = self.currentTimeLabel.zf_centerY;
|
||||
|
||||
min_x = self.currentTimeLabel.zf_right + 4;
|
||||
min_y = 0;
|
||||
min_w = self.totalTimeLabel.zf_left - min_x - 4;
|
||||
min_h = 30;
|
||||
self.slider.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.slider.zf_centerY = self.currentTimeLabel.zf_centerY;
|
||||
|
||||
if (!self.isShow) {
|
||||
self.topToolView.zf_y = -self.topToolView.zf_height;
|
||||
self.bottomToolView.zf_y = self.zf_height;
|
||||
self.playOrPauseBtn.alpha = 0;
|
||||
} else {
|
||||
self.topToolView.zf_y = 0;
|
||||
self.bottomToolView.zf_y = self.zf_height - self.bottomToolView.zf_height;
|
||||
self.playOrPauseBtn.alpha = 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)makeSubViewsAction {
|
||||
[self.playOrPauseBtn addTarget:self action:@selector(playPauseButtonClickAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.fullScreenBtn addTarget:self action:@selector(fullScreenButtonClickAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
|
||||
#pragma mark - action
|
||||
|
||||
- (void)playPauseButtonClickAction:(UIButton *)sender {
|
||||
[self playOrPause];
|
||||
}
|
||||
|
||||
- (void)fullScreenButtonClickAction:(UIButton *)sender {
|
||||
[self.player enterFullScreen:YES animated:YES];
|
||||
}
|
||||
|
||||
/// 根据当前播放状态取反
|
||||
- (void)playOrPause {
|
||||
self.playOrPauseBtn.selected = !self.playOrPauseBtn.isSelected;
|
||||
self.playOrPauseBtn.isSelected? [self.player.currentPlayerManager play]: [self.player.currentPlayerManager pause];
|
||||
}
|
||||
|
||||
- (void)playBtnSelectedState:(BOOL)selected {
|
||||
self.playOrPauseBtn.selected = selected;
|
||||
}
|
||||
|
||||
#pragma mark - ZFSliderViewDelegate
|
||||
|
||||
- (void)sliderTouchBegan:(float)value {
|
||||
self.slider.isdragging = YES;
|
||||
}
|
||||
|
||||
- (void)sliderTouchEnded:(float)value {
|
||||
if (self.player.totalTime > 0) {
|
||||
self.slider.isdragging = YES;
|
||||
if (self.sliderValueChanging) self.sliderValueChanging(value, self.slider.isForward);
|
||||
@zf_weakify(self)
|
||||
[self.player seekToTime:self.player.totalTime*value completionHandler:^(BOOL finished) {
|
||||
@zf_strongify(self)
|
||||
if (finished) {
|
||||
self.slider.isdragging = NO;
|
||||
if (self.sliderValueChanged) self.sliderValueChanged(value);
|
||||
}
|
||||
}];
|
||||
if (self.seekToPlay) {
|
||||
[self.player.currentPlayerManager play];
|
||||
}
|
||||
} else {
|
||||
self.slider.isdragging = NO;
|
||||
self.slider.value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sliderValueChanged:(float)value {
|
||||
if (self.player.totalTime == 0) {
|
||||
self.slider.value = 0;
|
||||
return;
|
||||
}
|
||||
self.slider.isdragging = YES;
|
||||
NSString *currentTimeString = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
self.currentTimeLabel.text = currentTimeString;
|
||||
if (self.sliderValueChanging) self.sliderValueChanging(value,self.slider.isForward);
|
||||
}
|
||||
|
||||
- (void)sliderTapped:(float)value {
|
||||
[self sliderTouchEnded:value];
|
||||
NSString *currentTimeString = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
|
||||
self.currentTimeLabel.text = currentTimeString;
|
||||
}
|
||||
|
||||
#pragma mark - public method
|
||||
|
||||
/** 重置ControlView */
|
||||
- (void)resetControlView {
|
||||
self.bottomToolView.alpha = 1;
|
||||
self.slider.value = 0;
|
||||
self.slider.bufferValue = 0;
|
||||
self.currentTimeLabel.text = @"00:00";
|
||||
self.totalTimeLabel.text = @"00:00";
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.playOrPauseBtn.selected = YES;
|
||||
self.titleLabel.text = @"";
|
||||
}
|
||||
|
||||
- (void)showControlView {
|
||||
self.topToolView.alpha = 1;
|
||||
self.bottomToolView.alpha = 1;
|
||||
self.isShow = YES;
|
||||
self.topToolView.zf_y = 0;
|
||||
self.bottomToolView.zf_y = self.zf_height - self.bottomToolView.zf_height;
|
||||
self.playOrPauseBtn.alpha = 1;
|
||||
self.player.statusBarHidden = NO;
|
||||
}
|
||||
|
||||
- (void)hideControlView {
|
||||
self.isShow = NO;
|
||||
self.topToolView.zf_y = -self.topToolView.zf_height;
|
||||
self.bottomToolView.zf_y = self.zf_height;
|
||||
self.player.statusBarHidden = NO;
|
||||
self.playOrPauseBtn.alpha = 0;
|
||||
self.topToolView.alpha = 0;
|
||||
self.bottomToolView.alpha = 0;
|
||||
}
|
||||
|
||||
- (BOOL)shouldResponseGestureWithPoint:(CGPoint)point withGestureType:(ZFPlayerGestureType)type touch:(nonnull UITouch *)touch {
|
||||
CGRect sliderRect = [self.bottomToolView convertRect:self.slider.frame toView:self];
|
||||
if (CGRectContainsPoint(sliderRect, point)) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
|
||||
if (!self.slider.isdragging) {
|
||||
NSString *currentTimeString = [ZFUtilities convertTimeSecond:currentTime];
|
||||
self.currentTimeLabel.text = currentTimeString;
|
||||
NSString *totalTimeString = [ZFUtilities convertTimeSecond:totalTime];
|
||||
self.totalTimeLabel.text = totalTimeString;
|
||||
self.slider.value = videoPlayer.progress;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime {
|
||||
self.slider.bufferValue = videoPlayer.bufferProgress;
|
||||
}
|
||||
|
||||
- (void)showTitle:(NSString *)title fullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
self.titleLabel.text = title;
|
||||
self.player.orientationObserver.fullScreenMode = fullScreenMode;
|
||||
}
|
||||
|
||||
/// 调节播放进度slider和当前时间更新
|
||||
- (void)sliderValueChanged:(CGFloat)value currentTimeString:(NSString *)timeString {
|
||||
self.slider.value = value;
|
||||
self.currentTimeLabel.text = timeString;
|
||||
self.slider.isdragging = YES;
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
self.slider.sliderBtn.transform = CGAffineTransformMakeScale(1.2, 1.2);
|
||||
}];
|
||||
}
|
||||
|
||||
/// 滑杆结束滑动
|
||||
- (void)sliderChangeEnded {
|
||||
self.slider.isdragging = NO;
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
self.slider.sliderBtn.transform = CGAffineTransformIdentity;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - setter
|
||||
|
||||
- (void)setFullScreenMode:(ZFFullScreenMode)fullScreenMode {
|
||||
_fullScreenMode = fullScreenMode;
|
||||
self.player.orientationObserver.fullScreenMode = fullScreenMode;
|
||||
}
|
||||
|
||||
#pragma mark - getter
|
||||
|
||||
- (UIView *)topToolView {
|
||||
if (!_topToolView) {
|
||||
_topToolView = [[UIView alloc] init];
|
||||
UIImage *image = ZFPlayer_Image(@"ZFPlayer_top_shadow");
|
||||
_topToolView.layer.contents = (id)image.CGImage;
|
||||
}
|
||||
return _topToolView;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [[UILabel alloc] init];
|
||||
_titleLabel.textColor = [UIColor whiteColor];
|
||||
_titleLabel.font = [UIFont systemFontOfSize:15.0];
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UIView *)bottomToolView {
|
||||
if (!_bottomToolView) {
|
||||
_bottomToolView = [[UIView alloc] init];
|
||||
UIImage *image = ZFPlayer_Image(@"ZFPlayer_bottom_shadow");
|
||||
_bottomToolView.layer.contents = (id)image.CGImage;
|
||||
}
|
||||
return _bottomToolView;
|
||||
}
|
||||
|
||||
- (UIButton *)playOrPauseBtn {
|
||||
if (!_playOrPauseBtn) {
|
||||
_playOrPauseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_playOrPauseBtn setImage:ZFPlayer_Image(@"new_allPlay_44x44_") forState:UIControlStateNormal];
|
||||
[_playOrPauseBtn setImage:ZFPlayer_Image(@"new_allPause_44x44_") forState:UIControlStateSelected];
|
||||
}
|
||||
return _playOrPauseBtn;
|
||||
}
|
||||
|
||||
- (UILabel *)currentTimeLabel {
|
||||
if (!_currentTimeLabel) {
|
||||
_currentTimeLabel = [[UILabel alloc] init];
|
||||
_currentTimeLabel.textColor = [UIColor whiteColor];
|
||||
_currentTimeLabel.font = [UIFont systemFontOfSize:14.0f];
|
||||
_currentTimeLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _currentTimeLabel;
|
||||
}
|
||||
|
||||
- (ZFSliderView *)slider {
|
||||
if (!_slider) {
|
||||
_slider = [[ZFSliderView alloc] init];
|
||||
_slider.delegate = self;
|
||||
_slider.maximumTrackTintColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.8];
|
||||
_slider.bufferTrackTintColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
|
||||
_slider.minimumTrackTintColor = [UIColor whiteColor];
|
||||
[_slider setThumbImage:ZFPlayer_Image(@"ZFPlayer_slider") forState:UIControlStateNormal];
|
||||
_slider.sliderHeight = 2;
|
||||
}
|
||||
return _slider;
|
||||
}
|
||||
|
||||
- (UILabel *)totalTimeLabel {
|
||||
if (!_totalTimeLabel) {
|
||||
_totalTimeLabel = [[UILabel alloc] init];
|
||||
_totalTimeLabel.textColor = [UIColor whiteColor];
|
||||
_totalTimeLabel.font = [UIFont systemFontOfSize:14.0f];
|
||||
_totalTimeLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _totalTimeLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)fullScreenBtn {
|
||||
if (!_fullScreenBtn) {
|
||||
_fullScreenBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_fullScreenBtn setImage:ZFPlayer_Image(@"ZFPlayer_fullscreen") forState:UIControlStateNormal];
|
||||
}
|
||||
return _fullScreenBtn;
|
||||
}
|
||||
|
||||
@end
|
||||
118
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFSliderView.h
generated
Normal file
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// ZFSliderView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
@protocol ZFSliderViewDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
// 滑块滑动开始
|
||||
- (void)sliderTouchBegan:(float)value;
|
||||
// 滑块滑动中
|
||||
- (void)sliderValueChanged:(float)value;
|
||||
// 滑块滑动结束
|
||||
- (void)sliderTouchEnded:(float)value;
|
||||
// 滑杆点击
|
||||
- (void)sliderTapped:(float)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface ZFSliderButton : UIButton
|
||||
|
||||
@end
|
||||
|
||||
@interface ZFSliderView : UIView
|
||||
|
||||
@property (nonatomic, weak) id<ZFSliderViewDelegate> delegate;
|
||||
|
||||
/** 滑块 */
|
||||
@property (nonatomic, strong, readonly) ZFSliderButton *sliderBtn;
|
||||
|
||||
/** 默认滑杆的颜色 */
|
||||
@property (nonatomic, strong) UIColor *maximumTrackTintColor;
|
||||
|
||||
/** 滑杆进度颜色 */
|
||||
@property (nonatomic, strong) UIColor *minimumTrackTintColor;
|
||||
|
||||
/** 缓存进度颜色 */
|
||||
@property (nonatomic, strong) UIColor *bufferTrackTintColor;
|
||||
|
||||
/** loading进度颜色 */
|
||||
@property (nonatomic, strong) UIColor *loadingTintColor;
|
||||
|
||||
/** 默认滑杆的图片 */
|
||||
@property (nonatomic, strong) UIImage *maximumTrackImage;
|
||||
|
||||
/** 滑杆进度的图片 */
|
||||
@property (nonatomic, strong) UIImage *minimumTrackImage;
|
||||
|
||||
/** 缓存进度的图片 */
|
||||
@property (nonatomic, strong) UIImage *bufferTrackImage;
|
||||
|
||||
/** 滑杆进度 */
|
||||
@property (nonatomic, assign) float value;
|
||||
|
||||
/** 缓存进度 */
|
||||
@property (nonatomic, assign) float bufferValue;
|
||||
|
||||
/** 是否允许点击,默认是YES */
|
||||
@property (nonatomic, assign) BOOL allowTapped;
|
||||
|
||||
/** 是否允许点击,默认是YES */
|
||||
@property (nonatomic, assign) BOOL animate;
|
||||
|
||||
/** 设置滑杆的高度 */
|
||||
@property (nonatomic, assign) CGFloat sliderHeight;
|
||||
|
||||
/** 设置滑杆的圆角 */
|
||||
@property (nonatomic, assign) CGFloat sliderRadius;
|
||||
|
||||
/** 是否隐藏滑块(默认为NO) */
|
||||
@property (nonatomic, assign) BOOL isHideSliderBlock;
|
||||
|
||||
/// 是否正在拖动
|
||||
@property (nonatomic, assign) BOOL isdragging;
|
||||
|
||||
/// 向前还是向后拖动
|
||||
@property (nonatomic, assign) BOOL isForward;
|
||||
|
||||
@property (nonatomic, assign) CGSize thumbSize;
|
||||
|
||||
/**
|
||||
* Starts animation of the spinner.
|
||||
*/
|
||||
- (void)startAnimating;
|
||||
|
||||
/**
|
||||
* Stops animation of the spinnner.
|
||||
*/
|
||||
- (void)stopAnimating;
|
||||
|
||||
// 设置滑块背景色
|
||||
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
|
||||
|
||||
// 设置滑块图片
|
||||
- (void)setThumbImage:(UIImage *)image forState:(UIControlState)state;
|
||||
|
||||
@end
|
||||
426
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFSliderView.m
generated
Normal file
@@ -0,0 +1,426 @@
|
||||
//
|
||||
// ZFSliderView.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 "ZFSliderView.h"
|
||||
#import "UIView+ZFFrame.h"
|
||||
|
||||
/** 滑块的大小 */
|
||||
static const CGFloat kSliderBtnWH = 19.0;
|
||||
/** 进度的高度 */
|
||||
static const CGFloat kProgressH = 1.0;
|
||||
/** 拖动slider动画的时间*/
|
||||
static const CGFloat kAnimate = 0.3;
|
||||
|
||||
@implementation ZFSliderButton
|
||||
|
||||
// 重写此方法将按钮的点击范围扩大
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
|
||||
CGRect bounds = self.bounds;
|
||||
// 扩大点击区域
|
||||
bounds = CGRectInset(bounds, -20, -20);
|
||||
// 若点击的点在新的bounds里面。就返回yes
|
||||
return CGRectContainsPoint(bounds, point);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ZFSliderView ()
|
||||
|
||||
/** 进度背景 */
|
||||
@property (nonatomic, strong) UIImageView *bgProgressView;
|
||||
/** 缓存进度 */
|
||||
@property (nonatomic, strong) UIImageView *bufferProgressView;
|
||||
/** 滑动进度 */
|
||||
@property (nonatomic, strong) UIImageView *sliderProgressView;
|
||||
/** 滑块 */
|
||||
@property (nonatomic, strong) ZFSliderButton *sliderBtn;
|
||||
|
||||
@property (nonatomic, strong) UIView *loadingBarView;
|
||||
|
||||
@property (nonatomic, assign) BOOL isLoading;
|
||||
|
||||
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFSliderView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.allowTapped = YES;
|
||||
self.animate = YES;
|
||||
[self addSubViews];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
self.allowTapped = YES;
|
||||
self.animate = YES;
|
||||
[self addSubViews];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
if (isnan(self.value) || isnan(self.bufferValue)) return;
|
||||
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.bounds.size.width;
|
||||
CGFloat min_view_h = self.bounds.size.height;
|
||||
|
||||
min_x = 0;
|
||||
min_w = min_view_w;
|
||||
min_y = 0;
|
||||
min_h = self.sliderHeight;
|
||||
self.bgProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = 0;
|
||||
min_w = self.thumbSize.width;
|
||||
min_h = self.thumbSize.height;
|
||||
self.sliderBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
self.sliderBtn.zf_centerX = self.bgProgressView.zf_width * self.value;
|
||||
|
||||
min_x = 0;
|
||||
min_y = 0;
|
||||
if (self.sliderBtn.hidden) {
|
||||
min_w = self.bgProgressView.zf_width * self.value;
|
||||
} else {
|
||||
min_w = self.sliderBtn.zf_centerX;
|
||||
}
|
||||
min_h = self.sliderHeight;
|
||||
self.sliderProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = 0;
|
||||
min_w = self.bgProgressView.zf_width * self.bufferValue;
|
||||
min_h = self.sliderHeight;
|
||||
self.bufferProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_w = 0.1;
|
||||
min_h = self.sliderHeight;
|
||||
min_x = (min_view_w - min_w)/2;
|
||||
min_y = (min_view_h - min_h)/2;
|
||||
self.loadingBarView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
self.bgProgressView.zf_centerY = min_view_h * 0.5;
|
||||
self.bufferProgressView.zf_centerY = min_view_h * 0.5;
|
||||
self.sliderProgressView.zf_centerY = min_view_h * 0.5;
|
||||
self.sliderBtn.zf_centerY = min_view_h * 0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
添加子视图
|
||||
*/
|
||||
- (void)addSubViews {
|
||||
self.thumbSize = CGSizeMake(kSliderBtnWH, kSliderBtnWH);
|
||||
self.sliderHeight = kProgressH;
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
[self addSubview:self.bgProgressView];
|
||||
[self addSubview:self.bufferProgressView];
|
||||
[self addSubview:self.sliderProgressView];
|
||||
[self addSubview:self.sliderBtn];
|
||||
[self addSubview:self.loadingBarView];
|
||||
|
||||
// 添加点击手势
|
||||
self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
|
||||
[self addGestureRecognizer:self.tapGesture];
|
||||
|
||||
// 添加滑动手势
|
||||
UIPanGestureRecognizer *sliderGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(sliderGesture:)];
|
||||
[self addGestureRecognizer:sliderGesture];
|
||||
}
|
||||
|
||||
#pragma mark - Setter
|
||||
|
||||
- (void)setMaximumTrackTintColor:(UIColor *)maximumTrackTintColor {
|
||||
_maximumTrackTintColor = maximumTrackTintColor;
|
||||
self.bgProgressView.backgroundColor = maximumTrackTintColor;
|
||||
}
|
||||
|
||||
- (void)setMinimumTrackTintColor:(UIColor *)minimumTrackTintColor {
|
||||
_minimumTrackTintColor = minimumTrackTintColor;
|
||||
self.sliderProgressView.backgroundColor = minimumTrackTintColor;
|
||||
}
|
||||
|
||||
- (void)setBufferTrackTintColor:(UIColor *)bufferTrackTintColor {
|
||||
_bufferTrackTintColor = bufferTrackTintColor;
|
||||
self.bufferProgressView.backgroundColor = bufferTrackTintColor;
|
||||
}
|
||||
|
||||
- (void)setLoadingTintColor:(UIColor *)loadingTintColor {
|
||||
_loadingTintColor = loadingTintColor;
|
||||
self.loadingBarView.backgroundColor = loadingTintColor;
|
||||
}
|
||||
|
||||
- (void)setMaximumTrackImage:(UIImage *)maximumTrackImage {
|
||||
_maximumTrackImage = maximumTrackImage;
|
||||
self.bgProgressView.image = maximumTrackImage;
|
||||
self.maximumTrackTintColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
- (void)setMinimumTrackImage:(UIImage *)minimumTrackImage {
|
||||
_minimumTrackImage = minimumTrackImage;
|
||||
self.sliderProgressView.image = minimumTrackImage;
|
||||
self.minimumTrackTintColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
- (void)setBufferTrackImage:(UIImage *)bufferTrackImage {
|
||||
_bufferTrackImage = bufferTrackImage;
|
||||
self.bufferProgressView.image = bufferTrackImage;
|
||||
self.bufferTrackTintColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state {
|
||||
[self.sliderBtn setBackgroundImage:image forState:state];
|
||||
}
|
||||
|
||||
- (void)setThumbImage:(UIImage *)image forState:(UIControlState)state {
|
||||
[self.sliderBtn setImage:image forState:state];
|
||||
}
|
||||
|
||||
- (void)setValue:(float)value {
|
||||
if (isnan(value)) return;
|
||||
value = MIN(1.0, value);
|
||||
_value = value;
|
||||
if (self.sliderBtn.hidden) {
|
||||
self.sliderProgressView.zf_width = self.bgProgressView.zf_width * value;
|
||||
} else {
|
||||
self.sliderBtn.zf_centerX = self.bgProgressView.zf_width * value;
|
||||
self.sliderProgressView.zf_width = self.sliderBtn.zf_centerX;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setBufferValue:(float)bufferValue {
|
||||
if (isnan(bufferValue)) return;
|
||||
bufferValue = MIN(1.0, bufferValue);
|
||||
_bufferValue = bufferValue;
|
||||
self.bufferProgressView.zf_width = self.bgProgressView.zf_width * bufferValue;
|
||||
}
|
||||
|
||||
- (void)setAllowTapped:(BOOL)allowTapped {
|
||||
_allowTapped = allowTapped;
|
||||
if (!allowTapped) {
|
||||
[self removeGestureRecognizer:self.tapGesture];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setSliderHeight:(CGFloat)sliderHeight {
|
||||
if (isnan(sliderHeight)) return;
|
||||
_sliderHeight = sliderHeight;
|
||||
self.bgProgressView.zf_height = sliderHeight;
|
||||
self.bufferProgressView.zf_height = sliderHeight;
|
||||
self.sliderProgressView.zf_height = sliderHeight;
|
||||
}
|
||||
|
||||
- (void)setSliderRadius:(CGFloat)sliderRadius {
|
||||
if (isnan(sliderRadius)) return;
|
||||
_sliderRadius = sliderRadius;
|
||||
self.bgProgressView.layer.cornerRadius = sliderRadius;
|
||||
self.bufferProgressView.layer.cornerRadius = sliderRadius;
|
||||
self.sliderProgressView.layer.cornerRadius = sliderRadius;
|
||||
self.bgProgressView.layer.masksToBounds = YES;
|
||||
self.bufferProgressView.layer.masksToBounds = YES;
|
||||
self.sliderProgressView.layer.masksToBounds = YES;
|
||||
}
|
||||
|
||||
- (void)setIsHideSliderBlock:(BOOL)isHideSliderBlock {
|
||||
_isHideSliderBlock = isHideSliderBlock;
|
||||
// 隐藏滑块,滑杆不可点击
|
||||
if (isHideSliderBlock) {
|
||||
self.sliderBtn.hidden = YES;
|
||||
self.bgProgressView.zf_left = 0;
|
||||
self.bufferProgressView.zf_left = 0;
|
||||
self.sliderProgressView.zf_left = 0;
|
||||
self.allowTapped = NO;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts animation of the spinner.
|
||||
*/
|
||||
- (void)startAnimating {
|
||||
if (self.isLoading) return;
|
||||
self.isLoading = YES;
|
||||
self.bufferProgressView.hidden = YES;
|
||||
self.sliderProgressView.hidden = YES;
|
||||
self.sliderBtn.hidden = YES;
|
||||
self.loadingBarView.hidden = NO;
|
||||
|
||||
[self.loadingBarView.layer removeAllAnimations];
|
||||
CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
|
||||
animationGroup.duration = 0.4;
|
||||
animationGroup.beginTime = CACurrentMediaTime() + 0.4;
|
||||
animationGroup.repeatCount = MAXFLOAT;
|
||||
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
|
||||
CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
|
||||
scaleAnimation.keyPath = @"transform.scale.x";
|
||||
scaleAnimation.fromValue = @(1000.0f);
|
||||
scaleAnimation.toValue = @(self.zf_width * 10);
|
||||
|
||||
CABasicAnimation *alphaAnimation = [CABasicAnimation animation];
|
||||
alphaAnimation.keyPath = @"opacity";
|
||||
alphaAnimation.fromValue = @(1.0f);
|
||||
alphaAnimation.toValue = @(0.0f);
|
||||
|
||||
[animationGroup setAnimations:@[scaleAnimation, alphaAnimation]];
|
||||
[self.loadingBarView.layer addAnimation:animationGroup forKey:@"loading"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops animation of the spinnner.
|
||||
*/
|
||||
- (void)stopAnimating {
|
||||
self.isLoading = NO;
|
||||
self.bufferProgressView.hidden = NO;
|
||||
self.sliderProgressView.hidden = NO;
|
||||
self.sliderBtn.hidden = self.isHideSliderBlock;
|
||||
self.loadingBarView.hidden = YES;
|
||||
[self.loadingBarView.layer removeAllAnimations];
|
||||
}
|
||||
|
||||
#pragma mark - User Action
|
||||
|
||||
- (void)sliderGesture:(UIGestureRecognizer *)gesture {
|
||||
switch (gesture.state) {
|
||||
case UIGestureRecognizerStateBegan: {
|
||||
[self sliderBtnTouchBegin:self.sliderBtn];
|
||||
}
|
||||
break;
|
||||
case UIGestureRecognizerStateChanged: {
|
||||
[self sliderBtnDragMoving:self.sliderBtn point:[gesture locationInView:self.bgProgressView]];
|
||||
}
|
||||
break;
|
||||
case UIGestureRecognizerStateEnded: {
|
||||
[self sliderBtnTouchEnded:self.sliderBtn];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sliderBtnTouchBegin:(UIButton *)btn {
|
||||
if ([self.delegate respondsToSelector:@selector(sliderTouchBegan:)]) {
|
||||
[self.delegate sliderTouchBegan:self.value];
|
||||
}
|
||||
if (self.animate) {
|
||||
[UIView animateWithDuration:kAnimate animations:^{
|
||||
btn.transform = CGAffineTransformMakeScale(1.2, 1.2);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sliderBtnTouchEnded:(UIButton *)btn {
|
||||
if ([self.delegate respondsToSelector:@selector(sliderTouchEnded:)]) {
|
||||
[self.delegate sliderTouchEnded:self.value];
|
||||
}
|
||||
if (self.animate) {
|
||||
[UIView animateWithDuration:kAnimate animations:^{
|
||||
btn.transform = CGAffineTransformIdentity;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sliderBtnDragMoving:(UIButton *)btn point:(CGPoint)touchPoint {
|
||||
// 点击的位置
|
||||
CGPoint point = touchPoint;
|
||||
// 获取进度值 由于btn是从 0-(self.width - btn.width)
|
||||
CGFloat value = (point.x - btn.zf_width * 0.5) / self.bgProgressView.zf_width;
|
||||
// value的值需在0-1之间
|
||||
value = value >= 1.0 ? 1.0 : value <= 0.0 ? 0.0 : value;
|
||||
if (self.value == value) return;
|
||||
self.isForward = self.value < value;
|
||||
self.value = value;
|
||||
if ([self.delegate respondsToSelector:@selector(sliderValueChanged:)]) {
|
||||
[self.delegate sliderValueChanged:value];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tapped:(UITapGestureRecognizer *)tap {
|
||||
CGPoint point = [tap locationInView:self.bgProgressView];
|
||||
// 获取进度
|
||||
CGFloat value = (point.x - self.sliderBtn.zf_width * 0.5) * 1.0 / self.bgProgressView.zf_width;
|
||||
value = value >= 1.0 ? 1.0 : value <= 0 ? 0 : value;
|
||||
self.value = value;
|
||||
if ([self.delegate respondsToSelector:@selector(sliderTapped:)]) {
|
||||
[self.delegate sliderTapped:value];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - getter
|
||||
|
||||
- (UIView *)bgProgressView {
|
||||
if (!_bgProgressView) {
|
||||
_bgProgressView = [UIImageView new];
|
||||
_bgProgressView.backgroundColor = [UIColor grayColor];
|
||||
_bgProgressView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_bgProgressView.clipsToBounds = YES;
|
||||
}
|
||||
return _bgProgressView;
|
||||
}
|
||||
|
||||
- (UIView *)bufferProgressView {
|
||||
if (!_bufferProgressView) {
|
||||
_bufferProgressView = [UIImageView new];
|
||||
_bufferProgressView.backgroundColor = [UIColor whiteColor];
|
||||
_bufferProgressView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_bufferProgressView.clipsToBounds = YES;
|
||||
}
|
||||
return _bufferProgressView;
|
||||
}
|
||||
|
||||
- (UIView *)sliderProgressView {
|
||||
if (!_sliderProgressView) {
|
||||
_sliderProgressView = [UIImageView new];
|
||||
_sliderProgressView.backgroundColor = [UIColor redColor];
|
||||
_sliderProgressView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_sliderProgressView.clipsToBounds = YES;
|
||||
}
|
||||
return _sliderProgressView;
|
||||
}
|
||||
|
||||
- (ZFSliderButton *)sliderBtn {
|
||||
if (!_sliderBtn) {
|
||||
_sliderBtn = [ZFSliderButton buttonWithType:UIButtonTypeCustom];
|
||||
[_sliderBtn setAdjustsImageWhenHighlighted:NO];
|
||||
}
|
||||
return _sliderBtn;
|
||||
}
|
||||
|
||||
- (UIView *)loadingBarView {
|
||||
if (!_loadingBarView) {
|
||||
_loadingBarView = [[UIView alloc] init];
|
||||
_loadingBarView.backgroundColor = [UIColor whiteColor];
|
||||
_loadingBarView.hidden = YES;
|
||||
}
|
||||
return _loadingBarView;
|
||||
}
|
||||
|
||||
@end
|
||||
31
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFSmallFloatControlView.h
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// ZFSmallFloatControlView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface ZFSmallFloatControlView : UIView
|
||||
|
||||
@property (nonatomic, copy, nullable) void(^closeClickCallback)(void);
|
||||
|
||||
@end
|
||||
72
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFSmallFloatControlView.m
generated
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// ZFSmallFloatControlView.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 "ZFSmallFloatControlView.h"
|
||||
#import "ZFUtilities.h"
|
||||
|
||||
@interface ZFSmallFloatControlView ()
|
||||
|
||||
@property (nonatomic, strong) UIButton *closeBtn;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFSmallFloatControlView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self addSubview:self.closeBtn];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.bounds.size.width;
|
||||
|
||||
min_x = min_view_w-20;
|
||||
min_y = -10;
|
||||
min_w = 30;
|
||||
min_h = min_w;
|
||||
self.closeBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
}
|
||||
|
||||
- (void)closeBtnClick:(UIButton *)sender {
|
||||
if (self.closeClickCallback) self.closeClickCallback();
|
||||
}
|
||||
|
||||
- (UIButton *)closeBtn {
|
||||
if (!_closeBtn) {
|
||||
_closeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_closeBtn setImage:ZFPlayer_Image(@"ZFPlayer_close") forState:UIControlStateNormal];
|
||||
[_closeBtn addTarget:self action:@selector(closeBtnClick:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _closeBtn;
|
||||
}
|
||||
|
||||
@end
|
||||
27
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFSpeedLoadingView.h
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// ZFSpeedLoadingView.h
|
||||
// Pods-ZFPlayer_Example
|
||||
//
|
||||
// Created by 紫枫 on 2018/6/27.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "ZFLoadingView.h"
|
||||
|
||||
@interface ZFSpeedLoadingView : UIView
|
||||
|
||||
@property (nonatomic, strong) ZFLoadingView *loadingView;
|
||||
|
||||
@property (nonatomic, strong) UILabel *speedTextLabel;
|
||||
|
||||
/**
|
||||
* Starts animation of the spinner.
|
||||
*/
|
||||
- (void)startAnimating;
|
||||
|
||||
/**
|
||||
* Stops animation of the spinnner.
|
||||
*/
|
||||
- (void)stopAnimating;
|
||||
|
||||
@end
|
||||
117
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFSpeedLoadingView.m
generated
Normal file
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// ZFSpeedLoadingView.m
|
||||
// Pods-ZFPlayer_Example
|
||||
//
|
||||
// Created by 紫枫 on 2018/6/27.
|
||||
//
|
||||
|
||||
#import "ZFSpeedLoadingView.h"
|
||||
#import "ZFNetworkSpeedMonitor.h"
|
||||
#import "UIView+ZFFrame.h"
|
||||
|
||||
@interface ZFSpeedLoadingView ()
|
||||
|
||||
@property (nonatomic, strong) ZFNetworkSpeedMonitor *speedMonitor;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFSpeedLoadingView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self initialize];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if (self = [super initWithCoder:aDecoder]) {
|
||||
[self initialize];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
[self initialize];
|
||||
}
|
||||
|
||||
- (void)initialize {
|
||||
self.userInteractionEnabled = NO;
|
||||
[self addSubview:self.loadingView];
|
||||
[self addSubview:self.speedTextLabel];
|
||||
[self.speedMonitor startNetworkSpeedMonitor];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkSpeedChanged:) name:ZFDownloadNetworkSpeedNotificationKey object:nil];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self.speedMonitor stopNetworkSpeedMonitor];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:ZFDownloadNetworkSpeedNotificationKey object:nil];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.zf_width;
|
||||
CGFloat min_view_h = self.zf_height;
|
||||
|
||||
min_w = 44;
|
||||
min_h = min_w;
|
||||
min_x = (min_view_w - min_w) / 2;
|
||||
min_y = (min_view_h - min_h) / 2 - 10;
|
||||
self.loadingView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = 0;
|
||||
min_y = self.loadingView.zf_bottom+5;
|
||||
min_w = min_view_w;
|
||||
min_h = 20;
|
||||
self.speedTextLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
}
|
||||
|
||||
- (void)networkSpeedChanged:(NSNotification *)sender {
|
||||
NSString *downloadSpped = [sender.userInfo objectForKey:ZFNetworkSpeedNotificationKey];
|
||||
self.speedTextLabel.text = downloadSpped;
|
||||
}
|
||||
|
||||
- (void)startAnimating {
|
||||
[self.loadingView startAnimating];
|
||||
self.hidden = NO;
|
||||
}
|
||||
|
||||
- (void)stopAnimating {
|
||||
[self.loadingView stopAnimating];
|
||||
self.hidden = YES;
|
||||
}
|
||||
|
||||
- (UILabel *)speedTextLabel {
|
||||
if (!_speedTextLabel) {
|
||||
_speedTextLabel = [UILabel new];
|
||||
_speedTextLabel.textColor = [UIColor whiteColor];
|
||||
_speedTextLabel.font = [UIFont systemFontOfSize:12.0];
|
||||
_speedTextLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _speedTextLabel;
|
||||
}
|
||||
|
||||
- (ZFNetworkSpeedMonitor *)speedMonitor {
|
||||
if (!_speedMonitor) {
|
||||
_speedMonitor = [[ZFNetworkSpeedMonitor alloc] init];
|
||||
}
|
||||
return _speedMonitor;
|
||||
}
|
||||
|
||||
- (ZFLoadingView *)loadingView {
|
||||
if (!_loadingView) {
|
||||
_loadingView = [[ZFLoadingView alloc] init];
|
||||
_loadingView.lineWidth = 0.8;
|
||||
_loadingView.duration = 1;
|
||||
_loadingView.hidesWhenStopped = YES;
|
||||
}
|
||||
return _loadingView;
|
||||
}
|
||||
|
||||
@end
|
||||
47
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFUtilities.h
generated
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// ZFUtilities.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 <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
/// iPhoneX iPhoneXS iPhoneXS Max iPhoneXR 机型判断
|
||||
#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? ((NSInteger)(([[UIScreen mainScreen] currentMode].size.height/[[UIScreen mainScreen] currentMode].size.width)*100) == 216) : NO)
|
||||
|
||||
#define ZFPlayer_Image(file) [ZFUtilities imageNamed:file]
|
||||
|
||||
// 屏幕的宽
|
||||
#define ZFPlayer_ScreenWidth [[UIScreen mainScreen] bounds].size.width
|
||||
// 屏幕的高
|
||||
#define ZFPlayer_ScreenHeight [[UIScreen mainScreen] bounds].size.height
|
||||
|
||||
@interface ZFUtilities : NSObject
|
||||
|
||||
+ (NSString *)convertTimeSecond:(NSInteger)timeSecond;
|
||||
|
||||
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size;
|
||||
|
||||
+ (UIImage *)imageNamed:(NSString *)name;
|
||||
|
||||
@end
|
||||
|
||||
74
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFUtilities.m
generated
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// ZFUtilities.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 "ZFUtilities.h"
|
||||
|
||||
@implementation ZFUtilities
|
||||
|
||||
+ (NSString *)convertTimeSecond:(NSInteger)timeSecond {
|
||||
NSString *theLastTime = nil;
|
||||
long second = timeSecond;
|
||||
if (timeSecond < 60) {
|
||||
theLastTime = [NSString stringWithFormat:@"00:%02zd", second];
|
||||
} else if(timeSecond >= 60 && timeSecond < 3600){
|
||||
theLastTime = [NSString stringWithFormat:@"%02zd:%02zd", second/60, second%60];
|
||||
} else if(timeSecond >= 3600){
|
||||
theLastTime = [NSString stringWithFormat:@"%02zd:%02zd:%02zd", second/3600, second%3600/60, second%60];
|
||||
}
|
||||
return theLastTime;
|
||||
}
|
||||
|
||||
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
|
||||
if (!color || size.width <= 0 || size.height <= 0) return nil;
|
||||
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
|
||||
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetFillColorWithColor(context, color.CGColor);
|
||||
CGContextFillRect(context, rect);
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (NSBundle *)bundle {
|
||||
static NSBundle *bundle = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
bundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"ZFPlayer" ofType:@"bundle"]];
|
||||
});
|
||||
return bundle;
|
||||
}
|
||||
|
||||
+ (UIImage *)imageNamed:(NSString *)name {
|
||||
if (name.length == 0) return nil;
|
||||
int scale = (int)UIScreen.mainScreen.scale;
|
||||
if (scale < 2) scale = 2;
|
||||
else if (scale > 3) scale = 3;
|
||||
NSString *n = [NSString stringWithFormat:@"%@@%dx", name, scale];
|
||||
UIImage *image = [UIImage imageWithContentsOfFile:[self.bundle pathForResource:n ofType:@"png"]];
|
||||
if (!image) image = [UIImage imageWithContentsOfFile:[self.bundle pathForResource:name ofType:@"png"]];
|
||||
return image;
|
||||
}
|
||||
|
||||
@end
|
||||
46
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFVolumeBrightnessView.h
generated
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// ZFVolumeBrightnessView.h
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, ZFVolumeBrightnessType) {
|
||||
ZFVolumeBrightnessTypeVolume, // volume
|
||||
ZFVolumeBrightnessTypeumeBrightness // brightness
|
||||
};
|
||||
|
||||
@interface ZFVolumeBrightnessView : UIView
|
||||
|
||||
@property (nonatomic, assign, readonly) ZFVolumeBrightnessType volumeBrightnessType;
|
||||
@property (nonatomic, strong, readonly) UIProgressView *progressView;
|
||||
@property (nonatomic, strong, readonly) UIImageView *iconImageView;
|
||||
|
||||
- (void)updateProgress:(CGFloat)progress withVolumeBrightnessType:(ZFVolumeBrightnessType)volumeBrightnessType;
|
||||
|
||||
/// 添加系统音量view
|
||||
- (void)addSystemVolumeView;
|
||||
|
||||
/// 移除系统音量view
|
||||
- (void)removeSystemVolumeView;
|
||||
|
||||
@end
|
||||
162
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ControlView/ZFVolumeBrightnessView.m
generated
Normal file
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// ZFVolumeBrightnessView.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 "ZFVolumeBrightnessView.h"
|
||||
#import <MediaPlayer/MediaPlayer.h>
|
||||
#import "ZFUtilities.h"
|
||||
|
||||
@interface ZFVolumeBrightnessView ()
|
||||
|
||||
@property (nonatomic, strong) UIProgressView *progressView;
|
||||
@property (nonatomic, strong) UIImageView *iconImageView;
|
||||
@property (nonatomic, assign) ZFVolumeBrightnessType volumeBrightnessType;
|
||||
@property (nonatomic, strong) MPVolumeView *volumeView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFVolumeBrightnessView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self addSubview:self.iconImageView];
|
||||
[self addSubview:self.progressView];
|
||||
[self hideTipView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self addSystemVolumeView];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGFloat min_x = 0;
|
||||
CGFloat min_y = 0;
|
||||
CGFloat min_w = 0;
|
||||
CGFloat min_h = 0;
|
||||
CGFloat min_view_w = self.frame.size.width;
|
||||
CGFloat min_view_h = self.frame.size.height;
|
||||
CGFloat margin = 10;
|
||||
|
||||
min_x = margin;
|
||||
min_w = 20;
|
||||
min_h = min_w;
|
||||
min_y = (min_view_h-min_h)/2;
|
||||
self.iconImageView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
min_x = CGRectGetMaxX(self.iconImageView.frame) + margin;
|
||||
min_h = 2;
|
||||
min_y = (min_view_h-min_h)/2;
|
||||
min_w = min_view_w - min_x - margin;
|
||||
self.progressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
|
||||
|
||||
self.layer.cornerRadius = min_view_h/2;
|
||||
self.layer.masksToBounds = YES;
|
||||
}
|
||||
|
||||
- (void)hideTipView {
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
self.alpha = 0;
|
||||
} completion:^(BOOL finished) {
|
||||
self.hidden = YES;
|
||||
}];
|
||||
}
|
||||
|
||||
/// 添加系统音量view
|
||||
- (void)addSystemVolumeView {
|
||||
[self.volumeView removeFromSuperview];
|
||||
}
|
||||
|
||||
/// 移除系统音量view
|
||||
- (void)removeSystemVolumeView {
|
||||
[[UIApplication sharedApplication].keyWindow addSubview:self.volumeView];
|
||||
}
|
||||
|
||||
- (void)updateProgress:(CGFloat)progress withVolumeBrightnessType:(ZFVolumeBrightnessType)volumeBrightnessType {
|
||||
if (progress >= 1) {
|
||||
progress = 1;
|
||||
} else if (progress <= 0) {
|
||||
progress = 0;
|
||||
}
|
||||
self.progressView.progress = progress;
|
||||
self.volumeBrightnessType = volumeBrightnessType;
|
||||
UIImage *playerImage = nil;
|
||||
if (volumeBrightnessType == ZFVolumeBrightnessTypeVolume) {
|
||||
if (progress == 0) {
|
||||
playerImage = ZFPlayer_Image(@"ZFPlayer_muted");
|
||||
} else if (progress > 0 && progress < 0.5) {
|
||||
playerImage = ZFPlayer_Image(@"ZFPlayer_volume_low");
|
||||
} else {
|
||||
playerImage = ZFPlayer_Image(@"ZFPlayer_volume_high");
|
||||
}
|
||||
} else if (volumeBrightnessType == ZFVolumeBrightnessTypeumeBrightness) {
|
||||
if (progress >= 0 && progress < 0.5) {
|
||||
playerImage = ZFPlayer_Image(@"ZFPlayer_brightness_low");
|
||||
} else {
|
||||
playerImage = ZFPlayer_Image(@"ZFPlayer_brightness_high");
|
||||
}
|
||||
}
|
||||
self.iconImageView.image = playerImage;
|
||||
self.hidden = NO;
|
||||
self.alpha = 1;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideTipView) object:nil];
|
||||
[self performSelector:@selector(hideTipView) withObject:nil afterDelay:1.5];
|
||||
}
|
||||
|
||||
- (void)setVolumeBrightnessType:(ZFVolumeBrightnessType)volumeBrightnessType {
|
||||
_volumeBrightnessType = volumeBrightnessType;
|
||||
if (volumeBrightnessType == ZFVolumeBrightnessTypeVolume) {
|
||||
self.iconImageView.image = ZFPlayer_Image(@"ZFPlayer_volume");
|
||||
} else {
|
||||
self.iconImageView.image = ZFPlayer_Image(@"ZFPlayer_brightness");
|
||||
}
|
||||
}
|
||||
|
||||
- (UIProgressView *)progressView {
|
||||
if (!_progressView) {
|
||||
_progressView = [[UIProgressView alloc] init];
|
||||
_progressView.progressTintColor = [UIColor whiteColor];
|
||||
_progressView.trackTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.4];;
|
||||
}
|
||||
return _progressView;
|
||||
}
|
||||
|
||||
- (UIImageView *)iconImageView {
|
||||
if (!_iconImageView) {
|
||||
_iconImageView = [UIImageView new];
|
||||
}
|
||||
return _iconImageView;
|
||||
}
|
||||
|
||||
- (MPVolumeView *)volumeView {
|
||||
if (!_volumeView) {
|
||||
_volumeView = [[MPVolumeView alloc] init];
|
||||
_volumeView.frame = CGRectMake(-1000, -1000, 100, 100);
|
||||
}
|
||||
return _volumeView;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* IJKAVMoviePlayerController.h
|
||||
*
|
||||
* Copyright (c) 2014 Bilibili
|
||||
* Copyright (c) 2014 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
File: AVPlayerDemoPlaybackViewController.h
|
||||
Abstract: UIViewController managing a playback view, thumbnail view, and associated playback UI.
|
||||
Version: 1.3
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#import "IJKMediaPlayback.h"
|
||||
|
||||
@interface IJKAVMoviePlayerController : NSObject <IJKMediaPlayback>
|
||||
|
||||
- (id)initWithContentURL:(NSURL *)aUrl;
|
||||
- (id)initWithContentURLString:(NSString *)aUrl;
|
||||
+ (id)getInstance:(NSString *)aUrl;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Bilibili
|
||||
* Copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface IJKFFMonitor : NSObject
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
@property(nonatomic) NSDictionary *mediaMeta;
|
||||
@property(nonatomic) NSDictionary *videoMeta;
|
||||
@property(nonatomic) NSDictionary *audioMeta;
|
||||
|
||||
@property(nonatomic, readonly) int64_t duration; // milliseconds
|
||||
@property(nonatomic, readonly) int64_t bitrate; // bit / sec
|
||||
@property(nonatomic, readonly) float fps; // frame / sec
|
||||
@property(nonatomic, readonly) int width; // width
|
||||
@property(nonatomic, readonly) int height; // height
|
||||
@property(nonatomic, readonly) NSString *vcodec; // video codec
|
||||
@property(nonatomic, readonly) NSString *acodec; // audio codec
|
||||
@property(nonatomic, readonly) int sampleRate;
|
||||
@property(nonatomic, readonly) int64_t channelLayout;
|
||||
|
||||
@property(nonatomic) NSString *vdecoder;
|
||||
|
||||
@property(nonatomic) int tcpError;
|
||||
@property(nonatomic) NSString *remoteIp;
|
||||
|
||||
@property(nonatomic) int httpError;
|
||||
@property(nonatomic) NSString *httpUrl;
|
||||
@property(nonatomic) NSString *httpHost;
|
||||
@property(nonatomic) int httpCode;
|
||||
@property(nonatomic) int64_t httpOpenTick;
|
||||
@property(nonatomic) int64_t httpSeekTick;
|
||||
@property(nonatomic) int httpOpenCount;
|
||||
@property(nonatomic) int httpSeekCount;
|
||||
@property(nonatomic) int64_t lastHttpOpenDuration;
|
||||
@property(nonatomic) int64_t lastHttpSeekDuration;
|
||||
@property(nonatomic) int64_t filesize;
|
||||
|
||||
@property(nonatomic) int64_t prepareStartTick;
|
||||
@property(nonatomic) int64_t prepareDuration;
|
||||
@property(nonatomic) int64_t firstVideoFrameLatency;
|
||||
@property(nonatomic) int64_t lastPrerollStartTick;
|
||||
@property(nonatomic) int64_t lastPrerollDuration;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* IJKFFMoviePlayerController.h
|
||||
*
|
||||
* Copyright (c) 2013 Bilibili
|
||||
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "IJKMediaPlayback.h"
|
||||
#import "IJKFFMonitor.h"
|
||||
#import "IJKFFOptions.h"
|
||||
#import "IJKSDLGLViewProtocol.h"
|
||||
|
||||
// media meta
|
||||
#define k_IJKM_KEY_FORMAT @"format"
|
||||
#define k_IJKM_KEY_DURATION_US @"duration_us"
|
||||
#define k_IJKM_KEY_START_US @"start_us"
|
||||
#define k_IJKM_KEY_BITRATE @"bitrate"
|
||||
|
||||
// stream meta
|
||||
#define k_IJKM_KEY_TYPE @"type"
|
||||
#define k_IJKM_VAL_TYPE__VIDEO @"video"
|
||||
#define k_IJKM_VAL_TYPE__AUDIO @"audio"
|
||||
#define k_IJKM_VAL_TYPE__UNKNOWN @"unknown"
|
||||
|
||||
#define k_IJKM_KEY_CODEC_NAME @"codec_name"
|
||||
#define k_IJKM_KEY_CODEC_PROFILE @"codec_profile"
|
||||
#define k_IJKM_KEY_CODEC_LONG_NAME @"codec_long_name"
|
||||
|
||||
// stream: video
|
||||
#define k_IJKM_KEY_WIDTH @"width"
|
||||
#define k_IJKM_KEY_HEIGHT @"height"
|
||||
#define k_IJKM_KEY_FPS_NUM @"fps_num"
|
||||
#define k_IJKM_KEY_FPS_DEN @"fps_den"
|
||||
#define k_IJKM_KEY_TBR_NUM @"tbr_num"
|
||||
#define k_IJKM_KEY_TBR_DEN @"tbr_den"
|
||||
#define k_IJKM_KEY_SAR_NUM @"sar_num"
|
||||
#define k_IJKM_KEY_SAR_DEN @"sar_den"
|
||||
// stream: audio
|
||||
#define k_IJKM_KEY_SAMPLE_RATE @"sample_rate"
|
||||
#define k_IJKM_KEY_CHANNEL_LAYOUT @"channel_layout"
|
||||
|
||||
#define kk_IJKM_KEY_STREAMS @"streams"
|
||||
|
||||
typedef enum IJKLogLevel {
|
||||
k_IJK_LOG_UNKNOWN = 0,
|
||||
k_IJK_LOG_DEFAULT = 1,
|
||||
|
||||
k_IJK_LOG_VERBOSE = 2,
|
||||
k_IJK_LOG_DEBUG = 3,
|
||||
k_IJK_LOG_INFO = 4,
|
||||
k_IJK_LOG_WARN = 5,
|
||||
k_IJK_LOG_ERROR = 6,
|
||||
k_IJK_LOG_FATAL = 7,
|
||||
k_IJK_LOG_SILENT = 8,
|
||||
} IJKLogLevel;
|
||||
|
||||
@interface IJKFFMoviePlayerController : NSObject <IJKMediaPlayback>
|
||||
|
||||
- (id)initWithContentURL:(NSURL *)aUrl
|
||||
withOptions:(IJKFFOptions *)options;
|
||||
|
||||
- (id)initWithContentURLString:(NSString *)aUrlString
|
||||
withOptions:(IJKFFOptions *)options;
|
||||
|
||||
- (id)initWithMoreContent:(NSURL *)aUrl
|
||||
withOptions:(IJKFFOptions *)options
|
||||
withGLView:(UIView<IJKSDLGLViewProtocol> *)glView;
|
||||
|
||||
- (id)initWithMoreContentString:(NSString *)aUrlString
|
||||
withOptions:(IJKFFOptions *)options
|
||||
withGLView:(UIView<IJKSDLGLViewProtocol> *)glView;
|
||||
|
||||
- (void)prepareToPlay;
|
||||
- (void)play;
|
||||
- (void)pause;
|
||||
- (void)stop;
|
||||
- (BOOL)isPlaying;
|
||||
- (int64_t)trafficStatistic;
|
||||
- (float)dropFrameRate;
|
||||
|
||||
- (void)setPauseInBackground:(BOOL)pause;
|
||||
- (BOOL)isVideoToolboxOpen;
|
||||
|
||||
- (void)setHudValue:(NSString *)value forKey:(NSString *)key;
|
||||
|
||||
+ (void)setLogReport:(BOOL)preferLogReport;
|
||||
+ (void)setLogLevel:(IJKLogLevel)logLevel;
|
||||
+ (BOOL)checkIfFFmpegVersionMatch:(BOOL)showAlert;
|
||||
+ (BOOL)checkIfPlayerVersionMatch:(BOOL)showAlert
|
||||
version:(NSString *)version;
|
||||
|
||||
@property(nonatomic, readonly) CGFloat fpsInMeta;
|
||||
@property(nonatomic, readonly) CGFloat fpsAtOutput;
|
||||
@property(nonatomic) BOOL shouldShowHudView;
|
||||
|
||||
- (void)setOptionValue:(NSString *)value
|
||||
forKey:(NSString *)key
|
||||
ofCategory:(IJKFFOptionCategory)category;
|
||||
|
||||
- (void)setOptionIntValue:(int64_t)value
|
||||
forKey:(NSString *)key
|
||||
ofCategory:(IJKFFOptionCategory)category;
|
||||
|
||||
|
||||
|
||||
- (void)setFormatOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
- (void)setCodecOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
- (void)setSwsOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
- (void)setPlayerOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
|
||||
- (void)setFormatOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
- (void)setCodecOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
- (void)setSwsOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
- (void)setPlayerOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
|
||||
@property (nonatomic, retain) id<IJKMediaUrlOpenDelegate> segmentOpenDelegate;
|
||||
@property (nonatomic, retain) id<IJKMediaUrlOpenDelegate> tcpOpenDelegate;
|
||||
@property (nonatomic, retain) id<IJKMediaUrlOpenDelegate> httpOpenDelegate;
|
||||
@property (nonatomic, retain) id<IJKMediaUrlOpenDelegate> liveOpenDelegate;
|
||||
|
||||
@property (nonatomic, retain) id<IJKMediaNativeInvokeDelegate> nativeInvokeDelegate;
|
||||
|
||||
- (void)didShutdown;
|
||||
|
||||
#pragma mark KVO properties
|
||||
@property (nonatomic, readonly) IJKFFMonitor *monitor;
|
||||
|
||||
@end
|
||||
|
||||
#define IJK_FF_IO_TYPE_READ (1)
|
||||
void IJKFFIOStatDebugCallback(const char *url, int type, int bytes);
|
||||
void IJKFFIOStatRegister(void (*cb)(const char *url, int type, int bytes));
|
||||
|
||||
void IJKFFIOStatCompleteDebugCallback(const char *url,
|
||||
int64_t read_bytes, int64_t total_size,
|
||||
int64_t elpased_time, int64_t total_duration);
|
||||
void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
|
||||
int64_t read_bytes, int64_t total_size,
|
||||
int64_t elpased_time, int64_t total_duration));
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* IJKFFOptions.h
|
||||
*
|
||||
* Copyright (c) 2013-2015 Bilibili
|
||||
* Copyright (c) 2013-2015 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef enum IJKFFOptionCategory {
|
||||
kIJKFFOptionCategoryFormat = 1,
|
||||
kIJKFFOptionCategoryCodec = 2,
|
||||
kIJKFFOptionCategorySws = 3,
|
||||
kIJKFFOptionCategoryPlayer = 4,
|
||||
kIJKFFOptionCategorySwr = 5,
|
||||
} IJKFFOptionCategory;
|
||||
|
||||
// for codec option 'skip_loop_filter' and 'skip_frame'
|
||||
typedef enum IJKAVDiscard {
|
||||
/* We leave some space between them for extensions (drop some
|
||||
* keyframes for intra-only or drop just some bidir frames). */
|
||||
IJK_AVDISCARD_NONE =-16, ///< discard nothing
|
||||
IJK_AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi
|
||||
IJK_AVDISCARD_NONREF = 8, ///< discard all non reference
|
||||
IJK_AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames
|
||||
IJK_AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes
|
||||
IJK_AVDISCARD_ALL = 48, ///< discard all
|
||||
} IJKAVDiscard;
|
||||
|
||||
struct IjkMediaPlayer;
|
||||
|
||||
@interface IJKFFOptions : NSObject
|
||||
|
||||
+(IJKFFOptions *)optionsByDefault;
|
||||
|
||||
-(void)applyTo:(struct IjkMediaPlayer *)mediaPlayer;
|
||||
|
||||
- (void)setOptionValue:(NSString *)value
|
||||
forKey:(NSString *)key
|
||||
ofCategory:(IJKFFOptionCategory)category;
|
||||
|
||||
- (void)setOptionIntValue:(int64_t)value
|
||||
forKey:(NSString *)key
|
||||
ofCategory:(IJKFFOptionCategory)category;
|
||||
|
||||
|
||||
-(void)setFormatOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
-(void)setCodecOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
-(void)setSwsOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
-(void)setPlayerOptionValue: (NSString *)value forKey:(NSString *)key;
|
||||
|
||||
-(void)setFormatOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
-(void)setCodecOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
-(void)setSwsOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
-(void)setPlayerOptionIntValue: (int64_t)value forKey:(NSString *)key;
|
||||
|
||||
@property(nonatomic) BOOL showHudView;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* IJKKVOController.h
|
||||
*
|
||||
* Copyright (c) 2014 Bilibili
|
||||
* Copyright (c) 2014 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface IJKKVOController : NSObject
|
||||
|
||||
- (id)initWithTarget:(NSObject *)target;
|
||||
|
||||
- (void)safelyAddObserver:(NSObject *)observer
|
||||
forKeyPath:(NSString *)keyPath
|
||||
options:(NSKeyValueObservingOptions)options
|
||||
context:(void *)context;
|
||||
- (void)safelyRemoveObserver:(NSObject *)observer
|
||||
forKeyPath:(NSString *)keyPath;
|
||||
|
||||
- (void)safelyRemoveAllObservers;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* IJKMPMoviePlayerController.h
|
||||
*
|
||||
* Copyright (c) 2013 Bilibili
|
||||
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "IJKMediaPlayback.h"
|
||||
#import <MediaPlayer/MediaPlayer.h>
|
||||
|
||||
@interface IJKMPMoviePlayerController : MPMoviePlayerController <IJKMediaPlayback>
|
||||
|
||||
- (id)initWithContentURL:(NSURL *)aUrl;
|
||||
- (id)initWithContentURLString:(NSString *)aUrl;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* IJKMediaFramework.h
|
||||
*
|
||||
* Copyright (c) 2013 Bilibili
|
||||
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
//! Project version number for IJKMediaFramework.
|
||||
FOUNDATION_EXPORT double IJKMediaFrameworkVersionNumber;
|
||||
|
||||
//! Project version string for IJKMediaFramework.
|
||||
FOUNDATION_EXPORT const unsigned char IJKMediaFrameworkVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <IJKMediaFrameworkWithSSL/PublicHeader.h>
|
||||
#import <IJKMediaFramework/IJKMediaPlayback.h>
|
||||
#import <IJKMediaFramework/IJKMPMoviePlayerController.h>
|
||||
#import <IJKMediaFramework/IJKFFOptions.h>
|
||||
#import <IJKMediaFramework/IJKFFMoviePlayerController.h>
|
||||
#import <IJKMediaFramework/IJKAVMoviePlayerController.h>
|
||||
#import <IJKMediaFramework/IJKMediaModule.h>
|
||||
#import <IJKMediaFramework/IJKMediaPlayer.h>
|
||||
#import <IJKMediaFramework/IJKNotificationManager.h>
|
||||
#import <IJKMediaFramework/IJKKVOController.h>
|
||||
#import <IJKMediaFramework/IJKSDLGLViewProtocol.h>
|
||||
|
||||
// backward compatible for old names
|
||||
#define IJKMediaPlaybackIsPreparedToPlayDidChangeNotification IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification
|
||||
#define IJKMoviePlayerLoadStateDidChangeNotification IJKMPMoviePlayerLoadStateDidChangeNotification
|
||||
#define IJKMoviePlayerPlaybackDidFinishNotification IJKMPMoviePlayerPlaybackDidFinishNotification
|
||||
#define IJKMoviePlayerPlaybackDidFinishReasonUserInfoKey IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey
|
||||
#define IJKMoviePlayerPlaybackStateDidChangeNotification IJKMPMoviePlayerPlaybackStateDidChangeNotification
|
||||
#define IJKMoviePlayerIsAirPlayVideoActiveDidChangeNotification IJKMPMoviePlayerIsAirPlayVideoActiveDidChangeNotification
|
||||
#define IJKMoviePlayerVideoDecoderOpenNotification IJKMPMoviePlayerVideoDecoderOpenNotification
|
||||
#define IJKMoviePlayerFirstVideoFrameRenderedNotification IJKMPMoviePlayerFirstVideoFrameRenderedNotification
|
||||
#define IJKMoviePlayerFirstAudioFrameRenderedNotification IJKMPMoviePlayerFirstAudioFrameRenderedNotification
|
||||
#define IJKMoviePlayerFirstAudioFrameDecodedNotification IJKMPMoviePlayerFirstAudioFrameDecodedNotification
|
||||
#define IJKMoviePlayerFirstVideoFrameDecodedNotification IJKMPMoviePlayerFirstVideoFrameDecodedNotification
|
||||
#define IJKMoviePlayerOpenInputNotification IJKMPMoviePlayerOpenInputNotification
|
||||
#define IJKMoviePlayerFindStreamInfoNotification IJKMPMoviePlayerFindStreamInfoNotification
|
||||
#define IJKMoviePlayerComponentOpenNotification IJKMPMoviePlayerComponentOpenNotification
|
||||
|
||||
#define IJKMPMoviePlayerAccurateSeekCompleteNotification IJKMPMoviePlayerAccurateSeekCompleteNotification
|
||||
#define IJKMoviePlayerSeekAudioStartNotification IJKMPMoviePlayerSeekAudioStartNotification
|
||||
#define IJKMoviePlayerSeekVideoStartNotification IJKMPMoviePlayerSeekVideoStartNotification
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* IJKMediaModule.h
|
||||
*
|
||||
* Copyright (c) 2013 Bilibili
|
||||
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface IJKMediaModule : NSObject
|
||||
|
||||
+ (IJKMediaModule *)sharedModule;
|
||||
|
||||
@property(atomic, getter=isAppIdleTimerDisabled) BOOL appIdleTimerDisabled;
|
||||
@property(atomic, getter=isMediaModuleIdleTimerDisabled) BOOL mediaModuleIdleTimerDisabled;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* IJKMediaPlayback.h
|
||||
*
|
||||
* Copyright (c) 2013 Bilibili
|
||||
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, IJKMPMovieScalingMode) {
|
||||
IJKMPMovieScalingModeNone, // No scaling
|
||||
IJKMPMovieScalingModeAspectFit, // Uniform scale until one dimension fits
|
||||
IJKMPMovieScalingModeAspectFill, // Uniform scale until the movie fills the visible bounds. One dimension may have clipped contents
|
||||
IJKMPMovieScalingModeFill // Non-uniform scale. Both render dimensions will exactly match the visible bounds
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, IJKMPMoviePlaybackState) {
|
||||
IJKMPMoviePlaybackStateStopped,
|
||||
IJKMPMoviePlaybackStatePlaying,
|
||||
IJKMPMoviePlaybackStatePaused,
|
||||
IJKMPMoviePlaybackStateInterrupted,
|
||||
IJKMPMoviePlaybackStateSeekingForward,
|
||||
IJKMPMoviePlaybackStateSeekingBackward
|
||||
};
|
||||
|
||||
typedef NS_OPTIONS(NSUInteger, IJKMPMovieLoadState) {
|
||||
IJKMPMovieLoadStateUnknown = 0,
|
||||
IJKMPMovieLoadStatePlayable = 1 << 0,
|
||||
IJKMPMovieLoadStatePlaythroughOK = 1 << 1, // Playback will be automatically started in this state when shouldAutoplay is YES
|
||||
IJKMPMovieLoadStateStalled = 1 << 2, // Playback will be automatically paused in this state, if started
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, IJKMPMovieFinishReason) {
|
||||
IJKMPMovieFinishReasonPlaybackEnded,
|
||||
IJKMPMovieFinishReasonPlaybackError,
|
||||
IJKMPMovieFinishReasonUserExited
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Thumbnails
|
||||
|
||||
typedef NS_ENUM(NSInteger, IJKMPMovieTimeOption) {
|
||||
IJKMPMovieTimeOptionNearestKeyFrame,
|
||||
IJKMPMovieTimeOptionExact
|
||||
};
|
||||
|
||||
@protocol IJKMediaPlayback;
|
||||
|
||||
#pragma mark IJKMediaPlayback
|
||||
|
||||
@protocol IJKMediaPlayback <NSObject>
|
||||
|
||||
- (void)prepareToPlay;
|
||||
- (void)play;
|
||||
- (void)pause;
|
||||
- (void)stop;
|
||||
- (BOOL)isPlaying;
|
||||
- (void)shutdown;
|
||||
- (void)setPauseInBackground:(BOOL)pause;
|
||||
|
||||
@property(nonatomic, readonly) UIView *view;
|
||||
@property(nonatomic) NSTimeInterval currentPlaybackTime;
|
||||
@property(nonatomic, readonly) NSTimeInterval duration;
|
||||
@property(nonatomic, readonly) NSTimeInterval playableDuration;
|
||||
@property(nonatomic, readonly) NSInteger bufferingProgress;
|
||||
|
||||
@property(nonatomic, readonly) BOOL isPreparedToPlay;
|
||||
@property(nonatomic, readonly) IJKMPMoviePlaybackState playbackState;
|
||||
@property(nonatomic, readonly) IJKMPMovieLoadState loadState;
|
||||
@property(nonatomic, readonly) int isSeekBuffering;
|
||||
@property(nonatomic, readonly) int isAudioSync;
|
||||
@property(nonatomic, readonly) int isVideoSync;
|
||||
|
||||
@property(nonatomic, readonly) int64_t numberOfBytesTransferred;
|
||||
|
||||
@property(nonatomic, readonly) CGSize naturalSize;
|
||||
@property(nonatomic) IJKMPMovieScalingMode scalingMode;
|
||||
@property(nonatomic) BOOL shouldAutoplay;
|
||||
|
||||
@property (nonatomic) BOOL allowsMediaAirPlay;
|
||||
@property (nonatomic) BOOL isDanmakuMediaAirPlay;
|
||||
@property (nonatomic, readonly) BOOL airPlayMediaActive;
|
||||
|
||||
@property (nonatomic) float playbackRate;
|
||||
@property (nonatomic) float playbackVolume;
|
||||
|
||||
- (UIImage *)thumbnailImageAtCurrentTime;
|
||||
|
||||
#pragma mark Notifications
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define IJK_EXTERN extern "C" __attribute__((visibility ("default")))
|
||||
#else
|
||||
#define IJK_EXTERN extern __attribute__((visibility ("default")))
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MPMediaPlayback.h
|
||||
|
||||
// Posted when the prepared state changes of an object conforming to the MPMediaPlayback protocol changes.
|
||||
// This supersedes MPMoviePlayerContentPreloadDidFinishNotification.
|
||||
IJK_EXTERN NSString *const IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MPMoviePlayerController.h
|
||||
// Movie Player Notifications
|
||||
|
||||
// Posted when the scaling mode changes.
|
||||
IJK_EXTERN NSString* const IJKMPMoviePlayerScalingModeDidChangeNotification;
|
||||
|
||||
// Posted when movie playback ends or a user exits playback.
|
||||
IJK_EXTERN NSString* const IJKMPMoviePlayerPlaybackDidFinishNotification;
|
||||
IJK_EXTERN NSString* const IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey; // NSNumber (IJKMPMovieFinishReason)
|
||||
|
||||
// Posted when the playback state changes, either programatically or by the user.
|
||||
IJK_EXTERN NSString* const IJKMPMoviePlayerPlaybackStateDidChangeNotification;
|
||||
|
||||
// Posted when the network load state changes.
|
||||
IJK_EXTERN NSString* const IJKMPMoviePlayerLoadStateDidChangeNotification;
|
||||
|
||||
// Posted when the movie player begins or ends playing video via AirPlay.
|
||||
IJK_EXTERN NSString* const IJKMPMoviePlayerIsAirPlayVideoActiveDidChangeNotification;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Movie Property Notifications
|
||||
|
||||
// Calling -prepareToPlay on the movie player will begin determining movie properties asynchronously.
|
||||
// These notifications are posted when the associated movie property becomes available.
|
||||
IJK_EXTERN NSString* const IJKMPMovieNaturalSizeAvailableNotification;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Extend Notifications
|
||||
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerVideoDecoderOpenNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerFirstVideoFrameRenderedNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerFirstAudioFrameRenderedNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerFirstAudioFrameDecodedNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerFirstVideoFrameDecodedNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerOpenInputNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerFindStreamInfoNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerComponentOpenNotification;
|
||||
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerDidSeekCompleteNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerDidSeekCompleteTargetKey;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerDidSeekCompleteErrorKey;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerDidAccurateSeekCompleteCurPos;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerAccurateSeekCompleteNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerSeekAudioStartNotification;
|
||||
IJK_EXTERN NSString *const IJKMPMoviePlayerSeekVideoStartNotification;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark IJKMediaUrlOpenDelegate
|
||||
|
||||
// Must equal to the defination in ijkavformat/ijkavformat.h
|
||||
typedef NS_ENUM(NSInteger, IJKMediaEvent) {
|
||||
|
||||
// Notify Events
|
||||
IJKMediaEvent_WillHttpOpen = 1, // attr: url
|
||||
IJKMediaEvent_DidHttpOpen = 2, // attr: url, error, http_code
|
||||
IJKMediaEvent_WillHttpSeek = 3, // attr: url, offset
|
||||
IJKMediaEvent_DidHttpSeek = 4, // attr: url, offset, error, http_code
|
||||
// Control Message
|
||||
IJKMediaCtrl_WillTcpOpen = 0x20001, // IJKMediaUrlOpenData: no args
|
||||
IJKMediaCtrl_DidTcpOpen = 0x20002, // IJKMediaUrlOpenData: error, family, ip, port, fd
|
||||
IJKMediaCtrl_WillHttpOpen = 0x20003, // IJKMediaUrlOpenData: url, segmentIndex, retryCounter
|
||||
IJKMediaCtrl_WillLiveOpen = 0x20005, // IJKMediaUrlOpenData: url, retryCounter
|
||||
IJKMediaCtrl_WillConcatSegmentOpen = 0x20007, // IJKMediaUrlOpenData: url, segmentIndex, retryCounter
|
||||
};
|
||||
|
||||
#define IJKMediaEventAttrKey_url @"url"
|
||||
#define IJKMediaEventAttrKey_host @"host"
|
||||
#define IJKMediaEventAttrKey_error @"error"
|
||||
#define IJKMediaEventAttrKey_time_of_event @"time_of_event"
|
||||
#define IJKMediaEventAttrKey_http_code @"http_code"
|
||||
#define IJKMediaEventAttrKey_offset @"offset"
|
||||
#define IJKMediaEventAttrKey_file_size @"file_size"
|
||||
|
||||
// event of IJKMediaUrlOpenEvent_xxx
|
||||
@interface IJKMediaUrlOpenData: NSObject
|
||||
|
||||
- (id)initWithUrl:(NSString *)url
|
||||
event:(IJKMediaEvent)event
|
||||
segmentIndex:(int)segmentIndex
|
||||
retryCounter:(int)retryCounter;
|
||||
|
||||
@property(nonatomic, readonly) IJKMediaEvent event;
|
||||
@property(nonatomic, readonly) int segmentIndex;
|
||||
@property(nonatomic, readonly) int retryCounter;
|
||||
|
||||
@property(nonatomic, retain) NSString *url;
|
||||
@property(nonatomic, assign) int fd;
|
||||
@property(nonatomic, strong) NSString *msg;
|
||||
@property(nonatomic) int error; // set a negative value to indicate an error has occured.
|
||||
@property(nonatomic, getter=isHandled) BOOL handled; // auto set to YES if url changed
|
||||
@property(nonatomic, getter=isUrlChanged) BOOL urlChanged; // auto set to YES by url changed
|
||||
|
||||
@end
|
||||
|
||||
@protocol IJKMediaUrlOpenDelegate <NSObject>
|
||||
|
||||
- (void)willOpenUrl:(IJKMediaUrlOpenData*) urlOpenData;
|
||||
|
||||
@end
|
||||
|
||||
@protocol IJKMediaNativeInvokeDelegate <NSObject>
|
||||
|
||||
- (int)invoke:(IJKMediaEvent)event attributes:(NSDictionary *)attributes;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* IJKMediaPlayer.h
|
||||
*
|
||||
* Copyright (c) 2013 Bilibili
|
||||
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "IJKMediaPlayback.h"
|
||||
#import "IJKMPMoviePlayerController.h"
|
||||
|
||||
#import "IJKFFOptions.h"
|
||||
#import "IJKFFMoviePlayerController.h"
|
||||
|
||||
#import "IJKAVMoviePlayerController.h"
|
||||
|
||||
#import "IJKMediaModule.h"
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* IJKNotificationManager.h
|
||||
*
|
||||
* Copyright (c) 2016 Bilibili
|
||||
* Copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface IJKNotificationManager : NSObject
|
||||
|
||||
- (nullable instancetype)init;
|
||||
|
||||
- (void)addObserver:(nonnull id)observer
|
||||
selector:(nonnull SEL)aSelector
|
||||
name:(nullable NSString *)aName
|
||||
object:(nullable id)anObject;
|
||||
|
||||
- (void)removeAllObservers:(nonnull id)observer;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* IJKSDLGLViewProtocol.h
|
||||
*
|
||||
* Copyright (c) 2017 Bilibili
|
||||
* Copyright (c) 2017 raymond <raymondzheng1412@gmail.com>
|
||||
*
|
||||
* This file is part of ijkPlayer.
|
||||
*
|
||||
* ijkPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ijkPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with ijkPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef IJKSDLGLViewProtocol_h
|
||||
#define IJKSDLGLViewProtocol_h
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef struct IJKOverlay IJKOverlay;
|
||||
struct IJKOverlay {
|
||||
int w;
|
||||
int h;
|
||||
UInt32 format;
|
||||
int planes;
|
||||
UInt16 *pitches;
|
||||
UInt8 **pixels;
|
||||
int sar_num;
|
||||
int sar_den;
|
||||
CVPixelBufferRef pixel_buffer;
|
||||
};
|
||||
|
||||
@protocol IJKSDLGLViewProtocol <NSObject>
|
||||
- (UIImage*) snapshot;
|
||||
@property(nonatomic, readonly) CGFloat fps;
|
||||
@property(nonatomic) CGFloat scaleFactor;
|
||||
@property(nonatomic) BOOL isThirdGLView;
|
||||
- (void) display_pixels: (IJKOverlay *) overlay;
|
||||
@end
|
||||
|
||||
#endif /* IJKSDLGLViewProtocol_h */
|
||||
@@ -0,0 +1,6 @@
|
||||
framework module IJKMediaFramework {
|
||||
umbrella header "IJKMediaFramework.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
45
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ijkplayer/ZFIJKPlayerManager.h
generated
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// ZFIJKPlayerManager.h
|
||||
// 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 <Foundation/Foundation.h>
|
||||
#if __has_include(<ZFPlayer/ZFPlayerMediaPlayback.h>)
|
||||
#import <ZFPlayer/ZFPlayerMediaPlayback.h>
|
||||
#else
|
||||
#import "ZFPlayerMediaPlayback.h"
|
||||
#endif
|
||||
|
||||
#if __has_include(<IJKMediaFramework/IJKMediaFramework.h>)
|
||||
#import <IJKMediaFramework/IJKMediaFramework.h>
|
||||
|
||||
@interface ZFIJKPlayerManager : NSObject <ZFPlayerMediaPlayback>
|
||||
|
||||
@property (nonatomic, strong, readonly) IJKFFMoviePlayerController *player;
|
||||
|
||||
@property (nonatomic, strong, readonly) IJKFFOptions *options;
|
||||
|
||||
@property (nonatomic, assign) NSTimeInterval timeRefreshInterval;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
458
Pods/DDZFPlayerKit_Private/DDZFPlayerKit_Private/Classes/ijkplayer/ZFIJKPlayerManager.m
generated
Normal file
@@ -0,0 +1,458 @@
|
||||
//
|
||||
// ZFIJKPlayerManager.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 "ZFIJKPlayerManager.h"
|
||||
#if __has_include(<ZFPlayer/ZFPlayer.h>)
|
||||
#import <ZFPlayer/ZFPlayer.h>
|
||||
#import <ZFPlayer/ZFPlayerConst.h>
|
||||
#else
|
||||
#import "ZFPlayer.h"
|
||||
#import "ZFPlayerConst.h"
|
||||
#endif
|
||||
#if __has_include(<IJKMediaFramework/IJKMediaFramework.h>)
|
||||
|
||||
@interface ZFIJKPlayerManager ()
|
||||
|
||||
@property (nonatomic, strong) IJKFFMoviePlayerController *player;
|
||||
@property (nonatomic, strong) IJKFFOptions *options;
|
||||
@property (nonatomic, assign) CGFloat lastVolume;
|
||||
@property (nonatomic, strong) NSTimer *timer;
|
||||
@property (nonatomic, assign) BOOL isReadyToPlay;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ZFIJKPlayerManager
|
||||
@synthesize view = _view;
|
||||
@synthesize currentTime = _currentTime;
|
||||
@synthesize totalTime = _totalTime;
|
||||
@synthesize playerPlayTimeChanged = _playerPlayTimeChanged;
|
||||
@synthesize playerBufferTimeChanged = _playerBufferTimeChanged;
|
||||
@synthesize playerDidToEnd = _playerDidToEnd;
|
||||
@synthesize bufferTime = _bufferTime;
|
||||
@synthesize playState = _playState;
|
||||
@synthesize loadState = _loadState;
|
||||
@synthesize assetURL = _assetURL;
|
||||
@synthesize playerPrepareToPlay = _playerPrepareToPlay;
|
||||
@synthesize playerReadyToPlay = _playerReadyToPlay;
|
||||
@synthesize playerPlayStateChanged = _playerPlayStateChanged;
|
||||
@synthesize playerLoadStateChanged = _playerLoadStateChanged;
|
||||
@synthesize seekTime = _seekTime;
|
||||
@synthesize muted = _muted;
|
||||
@synthesize volume = _volume;
|
||||
@synthesize presentationSize = _presentationSize;
|
||||
@synthesize isPlaying = _isPlaying;
|
||||
@synthesize rate = _rate;
|
||||
@synthesize isPreparedToPlay = _isPreparedToPlay;
|
||||
@synthesize shouldAutoPlay = _shouldAutoPlay;
|
||||
@synthesize scalingMode = _scalingMode;
|
||||
@synthesize playerPlayFailed = _playerPlayFailed;
|
||||
@synthesize presentationSizeChanged = _presentationSizeChanged;
|
||||
|
||||
- (void)dealloc {
|
||||
[self stop];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_scalingMode = ZFPlayerScalingModeAspectFit;
|
||||
_shouldAutoPlay = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)prepareToPlay {
|
||||
if (!_assetURL) return;
|
||||
_isPreparedToPlay = YES;
|
||||
[self initializePlayer];
|
||||
if (self.shouldAutoPlay) {
|
||||
[self play];
|
||||
}
|
||||
self.loadState = ZFPlayerLoadStatePrepare;
|
||||
if (self.playerPrepareToPlay) self.playerPrepareToPlay(self, self.assetURL);
|
||||
}
|
||||
|
||||
- (void)reloadPlayer {
|
||||
[self prepareToPlay];
|
||||
}
|
||||
|
||||
- (void)play {
|
||||
if (!_isPreparedToPlay) {
|
||||
[self prepareToPlay];
|
||||
} else {
|
||||
[self.player play];
|
||||
if (self.timer) [self.timer setFireDate:[NSDate date]];
|
||||
self.player.playbackRate = self.rate;
|
||||
_isPlaying = YES;
|
||||
self.playState = ZFPlayerPlayStatePlaying;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pause {
|
||||
if (self.timer) [self.timer setFireDate:[NSDate distantFuture]];
|
||||
[self.player pause];
|
||||
_isPlaying = NO;
|
||||
self.playState = ZFPlayerPlayStatePaused;
|
||||
}
|
||||
|
||||
- (void)stop {
|
||||
[self removeMovieNotificationObservers];
|
||||
[self.player shutdown];
|
||||
[self.player.view removeFromSuperview];
|
||||
self.player = nil;
|
||||
_assetURL = nil;
|
||||
[self.timer invalidate];
|
||||
self.presentationSize = CGSizeZero;
|
||||
self.timer = nil;
|
||||
_isPlaying = NO;
|
||||
_isPreparedToPlay = NO;
|
||||
self->_currentTime = 0;
|
||||
self->_totalTime = 0;
|
||||
self->_bufferTime = 0;
|
||||
self.isReadyToPlay = NO;
|
||||
self.playState = ZFPlayerPlayStatePlayStopped;
|
||||
}
|
||||
|
||||
- (void)replay {
|
||||
@zf_weakify(self)
|
||||
[self seekToTime:0 completionHandler:^(BOOL finished) {
|
||||
@zf_strongify(self)
|
||||
if (finished) {
|
||||
[self play];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)seekToTime:(NSTimeInterval)time completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||
if (self.player.duration > 0) {
|
||||
self.player.currentPlaybackTime = time;
|
||||
if (completionHandler) completionHandler(YES);
|
||||
} else {
|
||||
self.seekTime = time;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImage *)thumbnailImageAtCurrentTime {
|
||||
return [self.player thumbnailImageAtCurrentTime];
|
||||
}
|
||||
|
||||
#pragma mark - private method
|
||||
|
||||
- (void)initializePlayer {
|
||||
// IJKFFMoviePlayerController 初始化后,必须手动进行释放,否则会依然存在内存中对资源进行播放。
|
||||
if (self.player) {
|
||||
[self removeMovieNotificationObservers];
|
||||
[self.player shutdown];
|
||||
[self.player.view removeFromSuperview];
|
||||
self.player = nil;
|
||||
}
|
||||
|
||||
self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:self.assetURL withOptions:self.options];
|
||||
self.player.shouldAutoplay = self.shouldAutoPlay;
|
||||
[self.player prepareToPlay];
|
||||
self.view.playerView = self.player.view;
|
||||
self.scalingMode = self->_scalingMode;
|
||||
[self addPlayerNotificationObservers];
|
||||
}
|
||||
|
||||
- (void)addPlayerNotificationObservers {
|
||||
/// 准备播放
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(loadStateDidChange:)
|
||||
name:IJKMPMoviePlayerLoadStateDidChangeNotification
|
||||
object:_player];
|
||||
/// 播放完成或者用户退出
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(moviePlayBackFinish:)
|
||||
name:IJKMPMoviePlayerPlaybackDidFinishNotification
|
||||
object:_player];
|
||||
/// 准备开始播放了
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(mediaIsPreparedToPlayDidChange:)
|
||||
name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification
|
||||
object:_player];
|
||||
/// 播放状态改变了
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(moviePlayBackStateDidChange:)
|
||||
name:IJKMPMoviePlayerPlaybackStateDidChangeNotification
|
||||
object:_player];
|
||||
|
||||
/// 视频的尺寸变化了
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(sizeAvailableChange:)
|
||||
name:IJKMPMovieNaturalSizeAvailableNotification
|
||||
object:self.player];
|
||||
}
|
||||
|
||||
- (void)removeMovieNotificationObservers {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:IJKMPMoviePlayerLoadStateDidChangeNotification
|
||||
object:_player];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:IJKMPMoviePlayerPlaybackDidFinishNotification
|
||||
object:_player];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification
|
||||
object:_player];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:IJKMPMoviePlayerPlaybackStateDidChangeNotification
|
||||
object:_player];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:IJKMPMovieNaturalSizeAvailableNotification
|
||||
object:_player];
|
||||
}
|
||||
|
||||
- (void)timerUpdate {
|
||||
if (self.player.currentPlaybackTime > 0 && !self.isReadyToPlay) {
|
||||
self.isReadyToPlay = YES;
|
||||
self.loadState = ZFPlayerLoadStatePlaythroughOK;
|
||||
}
|
||||
self->_currentTime = self.player.currentPlaybackTime > 0 ? self.player.currentPlaybackTime : 0;
|
||||
self->_totalTime = self.player.duration;
|
||||
self->_bufferTime = self.player.playableDuration;
|
||||
if (self.playerPlayTimeChanged) self.playerPlayTimeChanged(self, self.currentTime, self.totalTime);
|
||||
if (self.playerBufferTimeChanged) self.playerBufferTimeChanged(self, self.bufferTime);
|
||||
}
|
||||
|
||||
#pragma - notification
|
||||
|
||||
/// 播放完成
|
||||
- (void)moviePlayBackFinish:(NSNotification *)notification {
|
||||
int reason = [[[notification userInfo] valueForKey:IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
|
||||
switch (reason) {
|
||||
case IJKMPMovieFinishReasonPlaybackEnded: {
|
||||
ZFPlayerLog(@"playbackStateDidChange: 播放完毕: %d\n", reason);
|
||||
self.playState = ZFPlayerPlayStatePlayStopped;
|
||||
if (self.playerDidToEnd) self.playerDidToEnd(self);
|
||||
}
|
||||
break;
|
||||
|
||||
case IJKMPMovieFinishReasonUserExited: {
|
||||
ZFPlayerLog(@"playbackStateDidChange: 用户退出播放: %d\n", reason);
|
||||
}
|
||||
break;
|
||||
|
||||
case IJKMPMovieFinishReasonPlaybackError: {
|
||||
ZFPlayerLog(@"playbackStateDidChange: 播放出现错误: %d\n", reason);
|
||||
self.playState = ZFPlayerPlayStatePlayFailed;
|
||||
if (self.playerPlayFailed) self.playerPlayFailed(self, @(reason));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ZFPlayerLog(@"playbackPlayBackDidFinish: ???: %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 准备开始播放了
|
||||
- (void)mediaIsPreparedToPlayDidChange:(NSNotification *)notification {
|
||||
ZFPlayerLog(@"加载状态变成了已经缓存完成,如果设置了自动播放, 会自动播放");
|
||||
// 视频开始播放的时候开启计时器
|
||||
if (!self.timer) {
|
||||
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeRefreshInterval > 0 ? self.timeRefreshInterval : 0.1 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES];
|
||||
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
|
||||
if (self.isPlaying) {
|
||||
[self play];
|
||||
self.muted = self.muted;
|
||||
if (self.seekTime > 0) {
|
||||
[self seekToTime:self.seekTime completionHandler:nil];
|
||||
self.seekTime = 0; // 滞空, 防止下次播放出错
|
||||
[self play];
|
||||
}
|
||||
}
|
||||
if (self.playerReadyToPlay) self.playerReadyToPlay(self, self.assetURL);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - 加载状态改变
|
||||
/**
|
||||
视频加载状态改变了
|
||||
IJKMPMovieLoadStateUnknown == 0
|
||||
IJKMPMovieLoadStatePlayable == 1
|
||||
IJKMPMovieLoadStatePlaythroughOK == 2
|
||||
IJKMPMovieLoadStateStalled == 4
|
||||
*/
|
||||
- (void)loadStateDidChange:(NSNotification*)notification {
|
||||
IJKMPMovieLoadState loadState = self.player.loadState;
|
||||
if ((loadState & IJKMPMovieLoadStatePlayable)) {
|
||||
ZFPlayerLog(@"加载状态变成了缓存数据足够开始播放,但是视频并没有缓存完全");
|
||||
if (self.player.currentPlaybackTime > 0) {
|
||||
self.loadState = ZFPlayerLoadStatePlayable;
|
||||
}
|
||||
} else if ((loadState & IJKMPMovieLoadStatePlaythroughOK)) {
|
||||
// 加载完成,即将播放,停止加载的动画,并将其移除
|
||||
ZFPlayerLog(@"加载状态变成了已经缓存完成,如果设置了自动播放, 会自动播放");
|
||||
} else if ((loadState & IJKMPMovieLoadStateStalled)) {
|
||||
// 可能由于网速不好等因素导致了暂停,重新添加加载的动画
|
||||
ZFPlayerLog(@"网速不好等因素导致了暂停");
|
||||
self.loadState = ZFPlayerLoadStateStalled;
|
||||
} else {
|
||||
ZFPlayerLog(@"加载状态变成了未知状态");
|
||||
self.loadState = ZFPlayerLoadStateUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
// 播放状态改变
|
||||
- (void)moviePlayBackStateDidChange:(NSNotification *)notification {
|
||||
switch (self.player.playbackState) {
|
||||
case IJKMPMoviePlaybackStateStopped: {
|
||||
ZFPlayerLog(@"播放器的播放状态变了,现在是停止状态 %d: stoped", (int)_player.playbackState);
|
||||
// 这里的回调也会来多次(一次播放完成, 会回调三次), 所以, 这里不设置
|
||||
self.playState = ZFPlayerPlayStatePlayStopped;
|
||||
}
|
||||
break;
|
||||
|
||||
case IJKMPMoviePlaybackStatePlaying: {
|
||||
ZFPlayerLog(@"播放器的播放状态变了,现在是播放状态 %d: playing", (int)_player.playbackState);
|
||||
}
|
||||
break;
|
||||
|
||||
case IJKMPMoviePlaybackStatePaused: {
|
||||
ZFPlayerLog(@"播放器的播放状态变了,现在是暂停状态 %d: paused", (int)_player.playbackState);
|
||||
}
|
||||
break;
|
||||
|
||||
case IJKMPMoviePlaybackStateInterrupted: {
|
||||
ZFPlayerLog(@"播放器的播放状态变了,现在是中断状态 %d: interrupted", (int)_player.playbackState);
|
||||
}
|
||||
break;
|
||||
|
||||
case IJKMPMoviePlaybackStateSeekingForward: {
|
||||
ZFPlayerLog(@"播放器的播放状态变了,现在是向前拖动状态:%d forward",(int)self.player.playbackState);
|
||||
}
|
||||
break;
|
||||
case IJKMPMoviePlaybackStateSeekingBackward: {
|
||||
ZFPlayerLog(@"放器的播放状态变了,现在是向后拖动状态 %d: backward", (int)_player.playbackState);
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
ZFPlayerLog(@"播放器的播放状态变了,现在是未知状态 %d: unknown", (int)_player.playbackState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// 视频的尺寸变化了
|
||||
- (void)sizeAvailableChange:(NSNotification *)notify {
|
||||
self.presentationSize = self.player.naturalSize;
|
||||
self.view.presentationSize = self.presentationSize;
|
||||
if (self.presentationSizeChanged) {
|
||||
self.presentationSizeChanged(self, self->_presentationSize);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - getter
|
||||
|
||||
- (ZFPlayerView *)view {
|
||||
if (!_view) {
|
||||
_view = [[ZFPlayerView alloc] init];
|
||||
}
|
||||
return _view;
|
||||
}
|
||||
|
||||
- (float)rate {
|
||||
return _rate == 0 ?1:_rate;
|
||||
}
|
||||
|
||||
- (IJKFFOptions *)options {
|
||||
if (!_options) {
|
||||
_options = [IJKFFOptions optionsByDefault];
|
||||
/// 精准seek
|
||||
[_options setPlayerOptionIntValue:1 forKey:@"enable-accurate-seek"];
|
||||
/// 解决http播放不了
|
||||
[_options setOptionIntValue:1 forKey:@"dns_cache_clear" ofCategory:kIJKFFOptionCategoryFormat];
|
||||
}
|
||||
return _options;
|
||||
}
|
||||
|
||||
#pragma mark - setter
|
||||
|
||||
- (void)setPlayState:(ZFPlayerPlaybackState)playState {
|
||||
_playState = playState;
|
||||
if (self.playerPlayStateChanged) self.playerPlayStateChanged(self, playState);
|
||||
}
|
||||
|
||||
- (void)setLoadState:(ZFPlayerLoadState)loadState {
|
||||
_loadState = loadState;
|
||||
if (self.playerLoadStateChanged) self.playerLoadStateChanged(self, loadState);
|
||||
}
|
||||
|
||||
- (void)setAssetURL:(NSURL *)assetURL {
|
||||
if (self.player) [self stop];
|
||||
_assetURL = assetURL;
|
||||
[self prepareToPlay];
|
||||
}
|
||||
|
||||
- (void)setRate:(float)rate {
|
||||
_rate = rate;
|
||||
if (self.player && fabsf(_player.playbackRate) > 0.00001f) {
|
||||
self.player.playbackRate = rate;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMuted:(BOOL)muted {
|
||||
_muted = muted;
|
||||
if (muted) {
|
||||
self.lastVolume = self.player.playbackVolume;
|
||||
self.player.playbackVolume = 0;
|
||||
} else {
|
||||
/// Fix first called the lastVolume is 0.
|
||||
if (self.lastVolume == 0) self.lastVolume = self.player.playbackVolume;
|
||||
self.player.playbackVolume = self.lastVolume;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setScalingMode:(ZFPlayerScalingMode)scalingMode {
|
||||
_scalingMode = scalingMode;
|
||||
self.view.scalingMode = scalingMode;
|
||||
switch (scalingMode) {
|
||||
case ZFPlayerScalingModeNone:
|
||||
self.player.scalingMode = IJKMPMovieScalingModeNone;
|
||||
break;
|
||||
case ZFPlayerScalingModeAspectFit:
|
||||
self.player.scalingMode = IJKMPMovieScalingModeAspectFit;
|
||||
break;
|
||||
case ZFPlayerScalingModeAspectFill:
|
||||
self.player.scalingMode = IJKMPMovieScalingModeAspectFill;
|
||||
break;
|
||||
case ZFPlayerScalingModeFill:
|
||||
self.player.scalingMode = IJKMPMovieScalingModeFill;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setVolume:(float)volume {
|
||||
_volume = MIN(MAX(0, volume), 1);
|
||||
self.player.playbackVolume = volume;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
19
Pods/DDZFPlayerKit_Private/LICENSE
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2023 DDIsFriend <DDIsFriend@163.com>
|
||||
|
||||
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.
|
||||
29
Pods/DDZFPlayerKit_Private/README.md
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
# DDZFPlayerKit_Private
|
||||
|
||||
[](https://travis-ci.org/DDIsFriend/DDZFPlayerKit_Private)
|
||||
[](https://cocoapods.org/pods/DDZFPlayerKit_Private)
|
||||
[](https://cocoapods.org/pods/DDZFPlayerKit_Private)
|
||||
[](https://cocoapods.org/pods/DDZFPlayerKit_Private)
|
||||
|
||||
## Example
|
||||
|
||||
To run the example project, clone the repo, and run `pod install` from the Example directory first.
|
||||
|
||||
## Requirements
|
||||
|
||||
## Installation
|
||||
|
||||
DDZFPlayerKit_Private is available through [CocoaPods](https://cocoapods.org). To install
|
||||
it, simply add the following line to your Podfile:
|
||||
|
||||
```ruby
|
||||
pod 'DDZFPlayerKit_Private'
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
DDIsFriend, DDIsFriend@163.com
|
||||
|
||||
## License
|
||||
|
||||
DDZFPlayerKit_Private is available under the MIT license. See the LICENSE file for more info.
|
||||