Skip to content

Commit

Permalink
Merge branch 'release/2.0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
0xced committed Jul 20, 2014
2 parents dfe8a90 + 51e85ae commit cedd927
Show file tree
Hide file tree
Showing 49 changed files with 943 additions and 97 deletions.
8 changes: 6 additions & 2 deletions .travis.yml
@@ -1,8 +1,12 @@
language: objective-c
install: gem install xcpretty --no-rdoc --no-ri --no-document --quiet
install:
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
- sudo easy_install cpp-coveralls
script:
- export LC_CTYPE=en_US.UTF-8
- set -o pipefail
- xcodebuild test -project XCDYouTubeKit.xcodeproj -scheme 'XCDYouTubeKit iOS' -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch)' | xcpretty -c
- xcodebuild test -project XCDYouTubeKit.xcodeproj -scheme 'XCDYouTubeKit iOS' -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' | xcpretty -c
- xcodebuild test -project XCDYouTubeKit.xcodeproj -scheme 'XCDYouTubeKit iOS' -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' OBJROOT=XCDYouTubeKit/build | xcpretty -c
- xcodebuild test -project XCDYouTubeKit.xcodeproj -scheme 'XCDYouTubeKit OS X' | xcpretty -c
after_success:
- ./Scripts/coveralls.sh
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,9 @@
#### Version 2.0.2

* Fixed errors on protected videos. (#52)
* Better error reporting if a protected video is not available.
* Updated README about YouTube Terms of Service.

#### Version 2.0.1

* Fixed crash on protected videos. (#46)
Expand Down
28 changes: 17 additions & 11 deletions README.md
@@ -1,19 +1,15 @@
## About

[![build status](https://travis-ci.org/0xced/XCDYouTubeKit.svg)](https://travis-ci.org/0xced/XCDYouTubeKit)
[![Build Status](https://img.shields.io/travis/0xced/XCDYouTubeKit/master.svg?style=flat)](https://travis-ci.org/0xced/XCDYouTubeKit)
[![Coverage Status](https://img.shields.io/coveralls/0xced/XCDYouTubeKit/master.svg?style=flat)](https://coveralls.io/r/0xced/XCDYouTubeKit?branch=master)
![Platform](https://img.shields.io/cocoapods/p/XCDYouTubeKit.svg?style=flat)
[![Pod Version](https://img.shields.io/cocoapods/v/XCDYouTubeKit.svg?style=flat)](http://cocoadocs.org/docsets/XCDYouTubeKit/)
[![License](https://img.shields.io/cocoapods/l/XCDYouTubeKit.svg?style=flat)](LICENSE)

**XCDYouTubeKit** is a YouTube video player for iOS and OS X.

<img src="Screenshots/XCDYouTubeVideoPlayerViewController.png" width="480" height="320">

To the best of my knowledge, the only *official* way of playing a YouTube video on iOS is with a UIWebView and the [iframe player API](https://developers.google.com/youtube/iframe_api_reference). Unfortunately, this is very slow and quite ugly, so I wrote this player to give users a better viewing experience.

Except for live videos, the player uses progressive download. Remember that some restrictions apply if you submit your app to the App Store, as stated in
[HTTP Live Streaming — Requirements for Apps](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/UsingHTTPLiveStreaming/UsingHTTPLiveStreaming.html#//apple_ref/doc/uid/TP40008332-CH102-SW5):
> **Warning**: iOS apps submitted for distribution in the App Store must conform to these requirements.
>
> If your app delivers video over cellular networks, and the video exceeds either 10 minutes duration or 5 MB of data in a five minute period, you are required to use HTTP Live Streaming. (Progressive download may be used for smaller clips.)
Are you enjoying XCDYouTubeKit? You can say thank you with [a tweet](https://twitter.com/intent/tweet?text=%400xced%20Thank%20you%20for%20XCDYouTubeKit%2E). I am also accepting donations. ;-)

[![Donate button](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MGEPRSNQFMV3W)
Expand All @@ -23,6 +19,16 @@ Are you enjoying XCDYouTubeKit? You can say thank you with [a tweet](https://twi
- Runs on iOS 5.0 and later
- Runs on OS X 10.7 and later

## Warnings

* XCDYouTubeKit is against the YouTube [Terms of Service](https://www.youtube.com/t/terms). The only *official* way of playing a YouTube video inside an app is with a web view and the [iframe player API](https://developers.google.com/youtube/iframe_api_reference). Unfortunately, this is very slow and quite ugly, so I wrote this player to give users a better viewing experience.

* Except for live videos, the player uses progressive download. Remember that some restrictions apply if you submit your app to the App Store, as stated in
[HTTP Live Streaming — Requirements for Apps](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/UsingHTTPLiveStreaming/UsingHTTPLiveStreaming.html#//apple_ref/doc/uid/TP40008332-CH102-SW5):
> **Warning**: iOS apps submitted for distribution in the App Store must conform to these requirements.
>
> If your app delivers video over cellular networks, and the video exceeds either 10 minutes duration or 5 MB of data in a five minute period, you are required to use HTTP Live Streaming. (Progressive download may be used for smaller clips.)
## Installation

XCDYouTubeKit is available through CocoaPods.
Expand All @@ -32,7 +38,7 @@ Alternatively, you can manually use the provided static library on iOS or dynami
If you use the iOS static library and you are targeting iOS 7, add the JavaScriptCore framework. If you are targeting iOS 5 or 6, you must add the following *Other Linker Flags* instead to your app:

```
-Wl,-U,_JSEvaluateScript -Wl,-U,_JSGlobalContextCreate -Wl,-U,_JSGlobalContextRelease -Wl,-U,_JSObjectCallAsFunction -Wl,-U,_JSObjectIsFunction -Wl,-U,_JSStringCopyCFString -Wl,-U,_JSStringCreateWithCFString -Wl,-U,_JSStringRelease -Wl,-U,_JSValueIsObject -Wl,-U,_JSValueIsString -Wl,-U,_JSValueMakeString -Wl,-U,_JSValueToStringCopy
-Wl,-U,_JSContextGetGlobalObject -Wl,-U,_JSEvaluateScript -Wl,-U,_JSGlobalContextCreate -Wl,-U,_JSGlobalContextRelease -Wl,-U,_JSObjectCallAsFunction -Wl,-U,_JSObjectIsFunction -Wl,-U,_JSObjectSetProperty -Wl,-U,_JSStringCopyCFString -Wl,-U,_JSStringCreateWithCFString -Wl,-U,_JSStringRelease -Wl,-U,_JSValueIsObject -Wl,-U,_JSValueIsString -Wl,-U,_JSValueMakeString -Wl,-U,_JSValueToStringCopy
```

See my [JavaScriptCore framework availability on iOS](http://stackoverflow.com/questions/23514579/javascriptcore-framework-availability-on-ios/23514580#23514580) answer on Stack Overflow for a complete explanation.
Expand Down Expand Up @@ -85,7 +91,7 @@ See the demo project for more sample code.
## Credits
The URL exctraction algorithms in *XCDYouTubeKit* are inspired by the [YouTube extractor](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/youtube.py) module of the *youtube-dl* project.
The URL extraction algorithms in *XCDYouTubeKit* are inspired by the [YouTube extractor](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/youtube.py) module of the *youtube-dl* project.
## Contact
Expand Down
19 changes: 19 additions & 0 deletions Scripts/create-coveralls-script.sh
@@ -0,0 +1,19 @@
#!/bin/bash -e

if [[ -z "${TRAVIS_JOB_ID}" ]]; then
exit 0
fi

COVERALLS_SCRIPT_PATH="${SRCROOT}/Scripts/coveralls.sh"
cat > "${COVERALLS_SCRIPT_PATH}" <<EOF
#!/bin/bash -e
cd "${OBJECT_FILE_DIR_normal}/${CURRENT_ARCH}"
for file in *.gcda; do
gcov "\${file}"
done
coveralls --root "${SRCROOT}/XCDYouTubeKit" --no-gcov --extension ".m"
EOF

chmod +x "${COVERALLS_SCRIPT_PATH}"
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>CFBundleVersion</key>
<string>2</string>
<string>3</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>LSMinimumSystemVersion</key>
Expand Down
Expand Up @@ -438,7 +438,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2.0.1;
CURRENT_PROJECT_VERSION = 2.0.2;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
Expand Down Expand Up @@ -476,7 +476,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 2.0.1;
CURRENT_PROJECT_VERSION = 2.0.2;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = "NS_BLOCK_ASSERTIONS=1";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
Expand All @@ -501,11 +501,13 @@
GCC_PREFIX_HEADER = "iOS Demo/Supporting Files/XCDYouTubeKit iOS Demo-Prefix.pch";
INFOPLIST_FILE = "iOS Demo/Supporting Files/XCDYouTubeKit iOS Demo-Info.plist";
OTHER_LDFLAGS = (
"-Wl,-U,_JSContextGetGlobalObject",
"-Wl,-U,_JSEvaluateScript",
"-Wl,-U,_JSGlobalContextCreate",
"-Wl,-U,_JSGlobalContextRelease",
"-Wl,-U,_JSObjectCallAsFunction",
"-Wl,-U,_JSObjectIsFunction",
"-Wl,-U,_JSObjectSetProperty",
"-Wl,-U,_JSStringCopyCFString",
"-Wl,-U,_JSStringCreateWithCFString",
"-Wl,-U,_JSStringRelease",
Expand All @@ -526,11 +528,13 @@
GCC_PREFIX_HEADER = "iOS Demo/Supporting Files/XCDYouTubeKit iOS Demo-Prefix.pch";
INFOPLIST_FILE = "iOS Demo/Supporting Files/XCDYouTubeKit iOS Demo-Info.plist";
OTHER_LDFLAGS = (
"-Wl,-U,_JSContextGetGlobalObject",
"-Wl,-U,_JSEvaluateScript",
"-Wl,-U,_JSGlobalContextCreate",
"-Wl,-U,_JSGlobalContextRelease",
"-Wl,-U,_JSObjectCallAsFunction",
"-Wl,-U,_JSObjectIsFunction",
"-Wl,-U,_JSObjectSetProperty",
"-Wl,-U,_JSStringCopyCFString",
"-Wl,-U,_JSStringCreateWithCFString",
"-Wl,-U,_JSStringRelease",
Expand Down
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>CFBundleVersion</key>
<string>2</string>
<string>3</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Expand Up @@ -68,6 +68,24 @@ - (BOOL)isEqual:(VCRRecording *)recording {
[self.body isEqualToString:recording.body];
}

static NSDictionary *SerializableUserInfo(NSDictionary *userInfo) {
NSMutableDictionary *serializableUserInfo = [NSMutableDictionary new];
for (id<NSCopying> key in userInfo) {
id value = userInfo[key];
if ([value isKindOfClass:[NSError class]]) {
NSError *error = (NSError *)value;
serializableUserInfo[key] = [NSError errorWithDomain:error.domain code:error.code userInfo:SerializableUserInfo(error.userInfo)];
} else if ([value conformsToProtocol:@protocol(NSCoding)]) {
serializableUserInfo[key] = value;
}
}
return [serializableUserInfo copy];
}

- (void)setError:(NSError *)error {
_error = [NSError errorWithDomain:error.domain code:error.code userInfo:SerializableUserInfo(error.userInfo)];
}

- (BOOL)isText {
NSString *type = [[self HTTPURLResponse] MIMEType] ?: @"text/plain";
if ([@[ @"application/x-www-form-urlencoded" ] containsObject:type]) {
Expand Down
38 changes: 0 additions & 38 deletions XCDYouTubeKit Tests/XCDYouTubeClientTestCase.m
Expand Up @@ -39,44 +39,6 @@ - (void) testThatVideoHasMetadata
XCTAssertTrue([monitor waitWithTimeout:10]);
}

- (void) testProtectedVEVOVideo
{
TRVSMonitor *monitor = [TRVSMonitor monitor];
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:@"rId6PKlDXeU" completionHandler:^(XCDYouTubeVideo *video, NSError *error) {
XCTAssertNil(error);
XCTAssertNotNil(video.title);
XCTAssertNotNil(video.smallThumbnailURL);
XCTAssertNotNil(video.mediumThumbnailURL);
XCTAssertNotNil(video.largeThumbnailURL);
XCTAssertTrue(video.streamURLs.count > 0);
XCTAssertTrue(video.duration > 0);
[video.streamURLs enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSURL *streamURL, BOOL *stop) {
XCTAssertTrue([streamURL.query rangeOfString:@"signature="].location != NSNotFound);
}];
[monitor signal];
}];
XCTAssertTrue([monitor waitWithTimeout:10]);
}

- (void) testProtectedVideoWithDollarSignature
{
TRVSMonitor *monitor = [TRVSMonitor monitor];
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:@"Pgum6OT_VH8" completionHandler:^(XCDYouTubeVideo *video, NSError *error) {
XCTAssertNil(error);
XCTAssertNotNil(video.title);
XCTAssertNotNil(video.smallThumbnailURL);
XCTAssertNotNil(video.mediumThumbnailURL);
XCTAssertNil(video.largeThumbnailURL);
XCTAssertTrue(video.streamURLs.count > 0);
XCTAssertTrue(video.duration > 0);
[video.streamURLs enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSURL *streamURL, BOOL *stop) {
XCTAssertTrue([streamURL.query rangeOfString:@"signature="].location != NSNotFound);
}];
[monitor signal];
}];
XCTAssertTrue([monitor waitWithTimeout:10]);
}

- (void) testMobileRestrictedVideo
{
TRVSMonitor *monitor = [TRVSMonitor monitor];
Expand Down
3 changes: 2 additions & 1 deletion XCDYouTubeKit Tests/XCDYouTubeKitTestCase.m
Expand Up @@ -19,6 +19,7 @@ - (void) setUpTestWithSelector:(SEL)selector
[super setUpTestWithSelector:selector];

NSString *cassettesDirectory = [[[NSProcessInfo processInfo] environment] objectForKey:@"VCR_CASSETTES_DIRECTORY"];
cassettesDirectory = [cassettesDirectory stringByAppendingPathComponent:NSStringFromClass(self.class)];
if ([[NSFileManager defaultManager] fileExistsAtPath:cassettesDirectory])
{
self.cassetteURL = [NSURL fileURLWithPath:[[cassettesDirectory stringByAppendingPathComponent:NSStringFromSelector(selector)] stringByAppendingPathExtension:@"json"]];
Expand All @@ -27,7 +28,7 @@ - (void) setUpTestWithSelector:(SEL)selector
}
else
{
self.cassetteURL = [[NSBundle bundleForClass:self.class] URLForResource:NSStringFromSelector(selector) withExtension:@"json" subdirectory:@"Cassettes"];
self.cassetteURL = [[NSBundle bundleForClass:self.class] URLForResource:NSStringFromSelector(selector) withExtension:@"json" subdirectory:[@"Cassettes" stringByAppendingPathComponent:NSStringFromClass(self.class)]];
XCTAssertNotNil(self.cassetteURL);
[VCR loadCassetteWithContentsOfURL:self.cassetteURL];
[VCR setReplaying:YES];
Expand Down

0 comments on commit cedd927

Please sign in to comment.