Skip to content

Commit

Permalink
Merge branch 'release/2.12.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
SoneeJohn committed Feb 24, 2020
2 parents edb6ed6 + 72a2a42 commit bbf5ee8
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 25 deletions.
4 changes: 2 additions & 2 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ source_directory: XCDYouTubeKit
framework_root: .
umbrella_header: XCDYouTubeKit/XCDYouTubeKit.h
module: XCDYouTubeKit
module_version: 2.11.0
module_version: 2.12.0

author: Cédric Luthi
author_url: https://twitter.com/0xced

readme: README.md
github_url: https://github.com/0xced/XCDYouTubeKit
github_file_prefix: https://github.com/0xced/XCDYouTubeKit/tree/2.11.0/XCDYouTubeKit
github_file_prefix: https://github.com/0xced/XCDYouTubeKit/tree/2.12.0/XCDYouTubeKit
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#### Version 2.12.0

* Add the ability to specify which `streamURLs` to query via `-[XCDYouTubeClient queryVideo:video:streamURLsToQuery:options:cookies:completionHandler:]` & `XCDYouTubeVideoQueryOperation` class.
* `initWithVideo:streamURLsToQuery:options:cookies:` is now the designated initializer for `XCDYouTubeVideoQueryOperation`.
* Correctly annotate the `streamURLs` & `streamErrors` properties as `nullable`.

#### Version 2.11.0

* `-[XCDYouTubeClient queryVideo:video:cookies:completionHandler:]` completion handler is now correctly called on the main thread.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ XCDYouTubeKit is available through [CocoaPods](https://cocoapods.org/), [Carthag
CocoaPods:

```ruby
pod "XCDYouTubeKit", "~> 2.11"
pod "XCDYouTubeKit", "~> 2.12"
```

Carthage:

```objc
github "0xced/XCDYouTubeKit" ~> 2.11
github "0xced/XCDYouTubeKit" ~> 2.12
```

Swift Package Manager:
Expand All @@ -48,7 +48,7 @@ Add `XCDYouTubeKit` to the dependencies value of your `Package.swift`

```swift
dependencies: [
.package(url: "https://github.com/0xced/XCDYouTubeKit.git", from: "2.11.0")
.package(url: "https://github.com/0xced/XCDYouTubeKit.git", from: "2.12.0")
]
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2.11.0;
CURRENT_PROJECT_VERSION = 2.12.0;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
Expand Down Expand Up @@ -804,7 +804,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 2.11.0;
CURRENT_PROJECT_VERSION = 2.12.0;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
Expand Down
2 changes: 1 addition & 1 deletion XCDYouTubeKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "XCDYouTubeKit"
s.version = "2.11.0"
s.version = "2.12.0"
s.summary = "YouTube video player for iOS and OS X."
s.homepage = "https://github.com/0xced/XCDYouTubeKit"
s.screenshot = "https://raw.github.com/0xced/XCDYouTubeKit/#{s.version}/Screenshots/XCDYouTubeVideoPlayerViewController.png"
Expand Down
8 changes: 4 additions & 4 deletions XCDYouTubeKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -649,10 +649,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 45;
CURRENT_PROJECT_VERSION = 46;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 2.0.0;
DYLIB_CURRENT_VERSION = 2.11.0;
DYLIB_CURRENT_VERSION = 2.12.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -727,10 +727,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 45;
CURRENT_PROJECT_VERSION = 46;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 2.0.0;
DYLIB_CURRENT_VERSION = 2.11.0;
DYLIB_CURRENT_VERSION = 2.12.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand Down
19 changes: 18 additions & 1 deletion XCDYouTubeKit/XCDYouTubeClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,24 @@ NS_ASSUME_NONNULL_BEGIN
*
* @return A newly initialized`<XCDYouTubeVideoQueryOperation>` object for canceling the asynchronous query operation. If you call the `cancel` method before the operation is finished, the completion handler will not be called.
*/
- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray <NSHTTPCookie *>*)cookies completionHandler:(void (^)(NSDictionary *streamURLs, NSError * __nullable error, NSDictionary<id, NSError *> *streamErrors))completionHandler;
- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray <NSHTTPCookie *>*)cookies completionHandler:(void (^)(NSDictionary * __nullable streamURLs, NSError * __nullable error, NSDictionary<id, NSError *> * __nullable streamErrors))completionHandler;
/**
* Starts an asynchronous operation for the specified `XCDYouTubeVide` object`, stream URLs to query and cookies, then calls a handler upon completion.
*
* @param video The `<XCDYouTubeVideo>` object that this operation will query. Passing a `nil` video will throw an `NSInvalidArgumentException` exception.
* @param streamURLsToQuery The specific stream URLs to query, can be nil. These URLs and keys must be contained in the `streamURLs` property of the `video` object, if none of the values in `streamURLsToQuery` match then all of the `streamURLs` will be queried.
* @param options Options that are reserved for future use.
* @param cookies An array of `NSHTTPCookie` objects, can be nil. These cookies can be used for certain videos that require a login.
* @param completionHandler A block to execute when the client finishes the operation. The completion handler is executed on the main thread. If the completion handler is nil, this method throws an exception.
* @discussion If the query operation completes successfully (i.e. at least one URL stream is reachable), the `streamURLs` parameter of the completion handler block contains a `NSDictionary` object, and the error parameter is nil. If the operation fails, the `streamURLs` parameter is nil and the error parameter contains information about the failure. The error's domain is always `XCDYouTubeVideoErrorDomain`. The `streamErrors` does not indicate that the operation failed but can contain detailed information on why a specific stream failed.In addition, this parameter is dictionary of `NSError` objects. The keys are the YouTube [itag](https://en.wikipedia.org/wiki/YouTube#Quality_and_formats) values as `NSNumber` objects. In some cases the errors within this dictionary may contain `NSError` objects with the code `NSURLErrorNetworkConnectionLost`—this may indicate that the file stored on YouTube's server is incomplete—furthermore, the error will make this suggestion via the`NSLocalizedRecoverySuggestionErrorKey` key of the error's `userInfo`.
*
* @see XCDYouTubeVideoQueryOperation
*
*
* @return A newly initialized`<XCDYouTubeVideoQueryOperation>` object for canceling the asynchronous query operation. If you call the `cancel` method before the operation is finished, the completion handler will not be called.
*/
- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(NSDictionary<id, NSURL *> * __nullable)streamURLsToQuery options:(NSDictionary * __nullable)options cookies:(nullable NSArray <NSHTTPCookie *>*)cookies completionHandler:(void (^)(NSDictionary *__nullable streamURLs, NSError * __nullable error, NSDictionary<id, NSError *> *__nullable streamErrors))completionHandler;


@end

Expand Down
9 changes: 7 additions & 2 deletions XCDYouTubeKit/XCDYouTubeClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,17 @@ - (instancetype) initWithLanguageIdentifier:(NSString *)languageIdentifier
return [self getVideoWithIdentifier:videoIdentifier cookies:cookies customPatterns:nil completionHandler:completionHandler];
}

- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video cookies:(NSArray<NSHTTPCookie *> *)cookies completionHandler:(void (^)(NSDictionary * _Nonnull, NSError * _Nullable, NSDictionary<id, NSError *> *streamErrors))completionHandler
- (XCDYouTubeVideoQueryOperation *)queryVideo:(XCDYouTubeVideo *)video cookies:(NSArray<NSHTTPCookie *> *)cookies completionHandler:(void (^)(NSDictionary * _Nonnull, NSError * _Nullable, NSDictionary<id,NSError *> * _Nonnull))completionHandler
{
return [self queryVideo:video streamURLsToQuery:nil options:nil cookies:cookies completionHandler:completionHandler];
}

- (XCDYouTubeVideoQueryOperation *)queryVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(NSDictionary<id,NSURL *> *)streamURLsToQuery options:(NSDictionary *)options cookies:(NSArray<NSHTTPCookie *> *)cookies completionHandler:(void (^)(NSDictionary * _Nullable, NSError * _Nullable, NSDictionary<id,NSError *> * _Nullable))completionHandler
{
if (!completionHandler)
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"The `completionHandler` argument must not be nil." userInfo:nil];

XCDYouTubeVideoQueryOperation *operation = [[XCDYouTubeVideoQueryOperation alloc]initWithVideo:video cookies:cookies];
XCDYouTubeVideoQueryOperation *operation = [[XCDYouTubeVideoQueryOperation alloc]initWithVideo:video streamURLsToQuery:streamURLsToQuery options:options cookies:cookies];
operation.completionBlock = ^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
#pragma clang diagnostic push
Expand Down
15 changes: 12 additions & 3 deletions XCDYouTubeKit/XCDYouTubeVideoQueryOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,28 @@ NS_ASSUME_NONNULL_BEGIN
/// Initializes a video query operation with the specified video and cookies.
/// @param video The `<XCDYouTubeVideo>` object that this operation will query. Passing a `nil` video will throw an `NSInvalidArgumentException` exception.
/// @param cookies An array of `NSHTTPCookie` objects, can be nil. These cookies can be used for certain videos that require a login.
- (instancetype) initWithVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray<NSHTTPCookie *> *)cookies NS_DESIGNATED_INITIALIZER;
- (instancetype) initWithVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray<NSHTTPCookie *> *)cookies;

/// Initializes a video query operation with the specified video, stream URLs to query and cookies.
/// @param video The `<XCDYouTubeVideo>` object that this operation will query. Passing a `nil` video will throw an `NSInvalidArgumentException` exception.
/// @param streamURLsToQuery The specific stream URLs to query, can be nil. These URLs and keys must be contained in the `streamURLs` property of the `video` object, if none of the values in `streamURLsToQuery` match then all of the `streamURLs` will be queried.
/// @param options Options that are reserved for future use.
/// @param cookies An array of `NSHTTPCookie` objects, can be nil. These cookies can be used for certain videos that require a login.
- (instancetype) initWithVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(nullable NSDictionary<id, NSURL *>*)streamURLsToQuery options:(nullable NSDictionary *)options cookies:(nullable NSArray<NSHTTPCookie *> *)cookies NS_DESIGNATED_INITIALIZER;

/// The `video` object that the operation initialized initialized with.
@property (atomic, strong, readonly) XCDYouTubeVideo *video;

@property (atomic, strong, readonly, nullable) NSDictionary<id, NSURL *> *streamURLsToQuery;

/// The array of `NSHTTPCookie` objects passed during initialization.
@property (atomic, copy, readonly, nullable) NSArray<NSHTTPCookie *>*cookies;

/// A dictionary of video stream URLs that are reachable. The keys are the YouTube [itag](https://en.wikipedia.org/wiki/YouTube#Quality_and_formats) values as `NSNumber` objects. The values are the video URLs as `NSURL` objects. There is also the special `XCDYouTubeVideoQualityHTTPLiveStreaming` key for live videos.
#if __has_feature(objc_generics)
@property (atomic, readonly) NSDictionary<id, NSURL *> *streamURLs;
@property (atomic, readonly, nullable) NSDictionary<id, NSURL *> *streamURLs;
#else
@property (atomic, readonly) NSDictionary *streamURLs;
@property (atomic, readonly, nullable) NSDictionary *streamURLs;
#endif

/// Returns an error of the `XCDYouTubeVideoErrorDomain` domain if the operation failed or nil if it succeeded. The operation will only return an error if no stream URL is reachable (error code: `XCDYouTubeErrorNoStreamAvailable`). Also, this returns `nil` if the operation is not yet finished or if it was canceled.
Expand Down
44 changes: 37 additions & 7 deletions XCDYouTubeKit/XCDYouTubeVideoQueryOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ @interface XCDYouTubeVideoQueryOperation ()
@property (atomic, readwrite, nullable) NSError *error;
@property (atomic, readwrite, nullable) NSDictionary<id, NSError *> *streamErrors;

@property (atomic, strong, readwrite, nullable) NSDictionary<id, NSURL *> *streamURLsToQuery;
@property (atomic, strong) NSOperationQueue *queryQueue;
@property (atomic, readonly) dispatch_semaphore_t operationStartSemaphore;
@end
Expand All @@ -31,29 +32,57 @@ @implementation XCDYouTubeVideoQueryOperation
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)init
{
@throw [NSException exceptionWithName:NSGenericException reason:@"Use the `initWithVideo:cookies:` method instead." userInfo:nil];
@throw [NSException exceptionWithName:NSGenericException reason:@"Use the `initWithVideo:streamURLsToQuery:options:cookies:` method instead." userInfo:nil];
}
#pragma clang diagnostic pop

- (instancetype) initWithVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray<NSHTTPCookie *> *)cookies
- (instancetype)initWithVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(NSDictionary<id,NSURL *> *)streamURLsToQuery options:(NSDictionary *)options cookies:(NSArray<NSHTTPCookie *> *)cookies
{
if (video == nil)
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"`video` must not be nil" userInfo:nil];

if (!(self = [super init]))
return nil;

_video = video;

NSMutableDictionary *streamURLsToQueryMutable = [NSMutableDictionary new];

for (id key in streamURLsToQuery)
{
//If the `video` object `streamURLs` does not contain this key we skip.
//Or, if value of the key isn't in the `video` object `streamURLs` we also skip.
if (_video.streamURLs[key] == nil || [(NSURL *)_video.streamURLs[key] isEqual:(NSURL *)streamURLsToQuery[key]] == NO)
{
continue;
}
streamURLsToQueryMutable[key] = _video.streamURLs[key];
}

if (streamURLsToQueryMutable.count == 0)
{
//No key and value matched so we disregard `streamURLs` and simply use the `streamURLs` from the `video` object
_streamURLsToQuery = _video.streamURLs;
}
else
{
_streamURLsToQuery = streamURLsToQueryMutable.copy;
}
_cookies = [cookies copy];

_queryQueue = [NSOperationQueue new];
_queryQueue.name = [NSString stringWithFormat:@"%@ Query Queue", NSStringFromClass(self.class)];
_queryQueue.maxConcurrentOperationCount = 6; // paul_irish: Chrome re-confirmed that the 6 connections-per-host limit is the right magic number: https://code.google.com/p/chromium/issues/detail?id=285567#c14 [https://twitter.com/paul_irish/status/422808635698212864]

_operationStartSemaphore = dispatch_semaphore_create(0);
return self;
}

- (instancetype) initWithVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray<NSHTTPCookie *> *)cookies
{
return [self initWithVideo:video streamURLsToQuery:nil options:nil cookies:cookies];
}

#pragma mark - NSOperation

+ (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key
Expand Down Expand Up @@ -104,9 +133,10 @@ - (void) startQuery
XCDYouTubeLogDebug(@"Starting query request for video: %@", self.video);

NSMutableArray <XCDURLHEADOperation *>*HEADOperations = [NSMutableArray new];
//Always use the `video` to check if it's a live stream (clients might not include `XCDYouTubeVideoQualityHTTPLiveStreaming` in `streamURLsToQuery`)
BOOL isHTTPLiveStream = self.video.streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] != nil;

[self.video.streamURLs enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, NSURL * _Nonnull obj, BOOL * _Nonnull stop)
[self.streamURLsToQuery enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, NSURL * _Nonnull obj, BOOL * _Nonnull stop)
{

XCDURLHEADOperation *operation = [[XCDURLHEADOperation alloc]initWithURL:obj info:@{key : obj} cookes:self.cookies];
Expand Down

0 comments on commit bbf5ee8

Please sign in to comment.