Compare commits

..

1 Commits

Author SHA1 Message Date
Freddy Kellison-Linn 56bef1c115 Release 1.3.0 2018-07-18 15:39:05 -04:00
24 changed files with 356 additions and 409 deletions
-50
View File
@@ -1,50 +0,0 @@
version: 2
jobs:
build-and-test:
environment:
BUNDLE_PATH: vendor/bundle
FL_OUTPUT_DIR: output
macos:
xcode: "10.2.1"
working_directory: ~/PlayerKit
shell: /bin/bash --login -o pipefail
steps:
- checkout
- restore_cache:
key: v1-gems-{{ checksum "Gemfile.lock" }}
- run:
name: Set Ruby version
command: echo "ruby-2.4" > ~/.ruby-version
- run:
name: Install bundler dependencies
command: bundle install --path vendor/bundle
- run:
name: Build and run tests
command: bundle exec fastlane ios test
environment:
SCAN_DEVICE: iPhone 8
SCAN_SCHEME: PlayerKit-Example
- save_cache:
paths:
- vendor/bundle
key: v1-gems-{{ checksum "Gemfile.lock" }}
- store_artifacts:
path: output
- store_test_results:
path: output/scan
workflows:
version: 2
build:
jobs:
- build-and-test
+1
View File
@@ -0,0 +1 @@
4.0
-42
View File
@@ -1,42 +0,0 @@
# Copyright © 2018 Vimeo. All rights reserved.
#
# 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.
# Run `swiftlint rules` for a list of available rules.
# Only the rules specified here will be enabled.
whitelist_rules:
- trailing_newline
- trailing_whitespace
- opening_brace
# Paths to include during linting.
included:
- ../PlayerKit/Classes
- ../Example
# Paths to exclude during linting.
excluded:
- Pods
# Configurable rules can be customized from this configuration file,
# binary rules can set their severity level.
trailing_whitespace:
ignores_empty_lines: true
+15 -42
View File
@@ -172,7 +172,6 @@
39DBB93200760D1BB486C4CC /* [CP] Check Pods Manifest.lock */,
607FACCC1AFB9204008FA782 /* Sources */,
607FACCD1AFB9204008FA782 /* Frameworks */,
0C1455B6219DDFB7006442F3 /* ShellScript */,
607FACCE1AFB9204008FA782 /* Resources */,
AEEB7FDEAB18BB5B2C3B7E51 /* [CP] Embed Pods Frameworks */,
);
@@ -211,18 +210,18 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0720;
LastUpgradeCheck = 1020;
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = CocoaPods;
TargetAttributes = {
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 35R365FS4Q;
LastSwiftMigration = 1020;
LastSwiftMigration = 0900;
};
607FACE41AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 35R365FS4Q;
LastSwiftMigration = 1020;
LastSwiftMigration = 0900;
TestTargetID = 607FACCF1AFB9204008FA782;
};
};
@@ -232,7 +231,6 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
@@ -269,19 +267,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0C1455B6219DDFB7006442F3 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "WORKSPACE_ROOT=$( cd \"$(dirname \"${SRCROOT[0]}\")\" ; pwd -P )\n\nif which \"$PODS_ROOT\"/SwiftLint/swiftlint > /dev/null; then\n \"$PODS_ROOT\"/SwiftLint/swiftlint autocorrect --config \"$WORKSPACE_ROOT\"/.swiftlint.yml\nelse\n echo \"Warning: SwiftLint is not installed. Make sure you've run `bundle exec pod install`.\"\nfi\n";
};
39DBB93200760D1BB486C4CC /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -382,27 +367,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -431,7 +407,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -439,27 +415,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -480,7 +447,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 3.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -489,6 +456,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9D69DB7C6B7F626E6391E3FA /* Pods-PlayerKit_Example.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 35R365FS4Q;
INFOPLIST_FILE = PlayerKit/Info.plist;
@@ -496,7 +464,8 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -505,6 +474,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = CF08222175BD5B0E142D343A /* Pods-PlayerKit_Example.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 35R365FS4Q;
INFOPLIST_FILE = PlayerKit/Info.plist;
@@ -512,7 +482,8 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -531,7 +502,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -545,7 +517,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -69,6 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
+2 -1
View File
@@ -13,7 +13,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = PlayerViewController()
self.window?.makeKeyAndVisible()
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+28 -14
View File
@@ -10,8 +10,10 @@ import UIKit
import PlayerKit
import AVFoundation
class PlayerViewController: UIViewController, PlayerDelegate {
private struct Constants {
class PlayerViewController: UIViewController, PlayerDelegate
{
private struct Constants
{
static let VideoURL = URL(string: "https://github.com/vimeo/PlayerKit/blob/master/Example/PlayerKit/video.mp4?raw=true")!
}
@@ -22,7 +24,8 @@ class PlayerViewController: UIViewController, PlayerDelegate {
private let player = RegularPlayer()
override func viewDidLoad() {
override func viewDidLoad()
{
super.viewDidLoad()
player.delegate = self
@@ -34,7 +37,8 @@ class PlayerViewController: UIViewController, PlayerDelegate {
// MARK: Setup
private func addPlayerToView() {
private func addPlayerToView()
{
player.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
player.view.frame = self.view.bounds
self.view.insertSubview(player.view, at: 0)
@@ -42,11 +46,13 @@ class PlayerViewController: UIViewController, PlayerDelegate {
// MARK: Actions
@IBAction func didTapPlayButton() {
@IBAction func didTapPlayButton()
{
self.player.playing ? self.player.pause() : self.player.play()
}
@IBAction func didChangeSliderValue() {
@IBAction func didChangeSliderValue()
{
let value = Double(self.slider.value)
let time = value * self.player.duration
@@ -56,10 +62,12 @@ class PlayerViewController: UIViewController, PlayerDelegate {
// MARK: VideoPlayerDelegate
func playerDidUpdateState(player: Player, previousState: PlayerState) {
func playerDidUpdateState(player: Player, previousState: PlayerState)
{
self.activityIndicator.isHidden = true
switch player.state {
switch player.state
{
case .loading:
self.activityIndicator.isHidden = false
@@ -74,24 +82,30 @@ class PlayerViewController: UIViewController, PlayerDelegate {
}
}
func playerDidUpdatePlaying(player: Player) {
func playerDidUpdatePlaying(player: Player)
{
self.playButton.isSelected = player.playing
}
func playerDidUpdateTime(player: Player) {
guard player.duration > 0 else {
func playerDidUpdateTime(player: Player)
{
guard player.duration > 0 else
{
return
}
let ratio = player.time / player.duration
if self.slider.isHighlighted == false {
if self.slider.isHighlighted == false
{
self.slider.value = Float(ratio)
}
}
func playerDidUpdateBufferedTime(player: Player) {
guard player.duration > 0 else {
func playerDidUpdateBufferedTime(player: Player)
{
guard player.duration > 0 else
{
return
}
+6 -8
View File
@@ -1,12 +1,10 @@
use_frameworks!
platform :ios, '8.0'
target 'PlayerKit_Example' do
pod 'PlayerKit', :path => '../'
pod 'SwiftLint', '0.28.0'
target 'PlayerKit_Tests' do
inherit! :search_paths
end
pod 'PlayerKit', :path => '../'
target 'PlayerKit_Tests' do
inherit! :search_paths
end
end
+3 -10
View File
@@ -1,23 +1,16 @@
PODS:
- PlayerKit (2.0.0)
- SwiftLint (0.28.0)
- PlayerKit (1.2.0)
DEPENDENCIES:
- PlayerKit (from `../`)
- SwiftLint (= 0.28.0)
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- SwiftLint
EXTERNAL SOURCES:
PlayerKit:
:path: "../"
SPEC CHECKSUMS:
PlayerKit: 1830be30e87ca46708c93e7ef0a6cf6590936b14
SwiftLint: 088cfacb75b45970017e62b7524d506776d60148
PlayerKit: ff4e4cd4c216d60ebcfccf3a68772d6299373e5a
PODFILE CHECKSUM: 90f31c00641fb4d5e9453ba687a3a06a32cca83f
PODFILE CHECKSUM: 071d8819500a822237123321021901352f4d91a4
COCOAPODS: 1.5.2
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+2 -2
View File
@@ -1,10 +1,10 @@
source 'https://rubygems.org'
gem 'fastlane', '2.108.0'
gem 'fastlane', '2.42.0'
gem 'cocoapods', '1.5.2'
gem 'danger', '4.0.4'
gem 'xcode-install', '2.1.0'
gem 'xcpretty-json-formatter', '0.1.0'
gem 'danger-xcode_summary', '0.1.0'
gem 'nokogiri', '1.8.5'
gem 'nokogiri', '1.6.0'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval(File.read(plugins_path), binding) if File.exist?(plugins_path)
+55 -63
View File
@@ -1,7 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
CFPropertyList (2.3.6)
activesupport (4.2.10)
i18n (~> 0.7)
minitest (~> 5.1)
@@ -9,7 +9,7 @@ GEM
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3)
atomos (0.1.2)
babosa (1.0.2)
claide (1.0.2)
claide-plugins (0.9.2)
@@ -40,12 +40,12 @@ GEM
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.2)
cocoapods-downloader (1.2.2)
cocoapods-downloader (1.2.0)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.3.1)
cocoapods-trunk (1.3.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.1.0)
@@ -54,7 +54,7 @@ GEM
colorize (0.8.1)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
concurrent-ruby (1.1.3)
concurrent-ruby (1.0.5)
cork (0.3.0)
colored2 (~> 3.1)
danger (4.0.4)
@@ -76,11 +76,10 @@ GEM
declarative-option (0.1.0)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.5.0)
emoji_regex (0.1.1)
dotenv (2.4.0)
escape (0.0.4)
excon (0.62.0)
faraday (0.15.3)
faraday (0.15.2)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
@@ -89,23 +88,22 @@ GEM
faraday (~> 0.8)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.4)
fastlane (2.108.0)
CFPropertyList (>= 2.3, < 4.0.0)
fastimage (2.1.3)
fastlane (2.42.0)
CFPropertyList (>= 2.3, < 3.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 2.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
commander-fastlane (>= 4.4.0, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (~> 0.1)
excon (>= 0.45.0, < 1.0.0)
faraday (~> 0.9)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.9)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.21.2, < 0.24.0)
fastimage (>= 1.6)
gh_inspector (>= 1.0.1, < 2.0.0)
google-api-client (>= 0.12.0, < 0.13.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
mini_magick (~> 4.5.1)
@@ -113,18 +111,15 @@ GEM
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
public_suffix (~> 2.0.0)
rubyzip (>= 1.2.2, < 2.0.0)
rubyzip (>= 1.1.0, < 2.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
slack-notifier (>= 1.3, < 2.0.0)
terminal-notifier (>= 1.6.2, < 2.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
tty-screen (~> 0.5.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.6.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcodeproj (>= 1.4.4, < 2.0.0)
xcpretty (>= 0.2.4, < 1.0.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-pretty_junit (0.1.1)
colorize
@@ -133,21 +128,21 @@ GEM
fourflusher (2.0.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
git (1.5.0)
google-api-client (0.23.9)
git (1.4.0)
google-api-client (0.12.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
googleauth (~> 0.5)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
googleauth (0.6.7)
googleauth (0.6.2)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
os (~> 0.9)
signet (~> 0.7)
highline (1.7.10)
http-cookie (1.0.3)
@@ -157,77 +152,74 @@ GEM
concurrent-ruby (~> 1.0)
json (2.1.0)
jwt (2.1.0)
kramdown (1.17.0)
kramdown (1.16.2)
little-plugger (1.1.4)
logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
memoist (0.16.0)
mime-types (3.2.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mime-types-data (3.2016.0521)
mini_magick (4.5.1)
mini_portile2 (2.3.0)
mini_portile (0.5.3)
minitest (5.11.3)
molinillo (0.6.6)
molinillo (0.6.5)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
nanaimo (0.2.5)
nap (1.1.0)
naturally (2.2.0)
netrc (0.11.0)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
octokit (4.13.0)
nokogiri (1.6.0)
mini_portile (~> 0.5.0)
octokit (4.9.0)
sawyer (~> 0.8.0, >= 0.5.3)
open4 (1.3.4)
os (1.0.0)
os (0.9.6)
plist (3.4.0)
public_suffix (2.0.5)
public_suffix (3.0.2)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
retriable (3.1.1)
rouge (2.0.7)
ruby-macho (1.3.1)
rubyzip (1.2.2)
ruby-macho (1.1.0)
rubyzip (1.2.1)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
security (0.1.3)
signet (0.11.0)
signet (0.8.1)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.5)
CFPropertyList
naturally
slack-notifier (2.3.2)
slack-notifier (1.5.1)
terminal-notifier (1.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-cursor (0.6.0)
tty-screen (0.6.5)
tty-spinner (0.8.0)
tty-cursor (>= 0.5.0)
tty-screen (0.5.1)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.0)
unicode-display_width (1.3.2)
word_wrap (1.0.0)
xcode-install (2.1.0)
claide (>= 0.9.1, < 1.1.0)
fastlane (>= 2.1.1, < 3.0.0)
xcodeproj (1.7.0)
xcodeproj (1.5.9)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
atomos (~> 0.1.2)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.6)
xcpretty (0.3.0)
nanaimo (~> 0.2.5)
xcpretty (0.2.8)
rouge (~> 2.0.7)
xcpretty-json-formatter (0.1.0)
xcpretty (~> 0.2, >= 0.0.7)
@@ -241,11 +233,11 @@ DEPENDENCIES
cocoapods (= 1.5.2)
danger (= 4.0.4)
danger-xcode_summary (= 0.1.0)
fastlane (= 2.108.0)
fastlane (= 2.42.0)
fastlane-plugin-pretty_junit
nokogiri (= 1.8.5)
nokogiri (= 1.6.0)
xcode-install (= 2.1.0)
xcpretty-json-formatter (= 0.1.0)
BUNDLED WITH
1.17.1
1.15.3
+1 -3
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PlayerKit'
s.version = '2.0.0'
s.version = '1.3.0'
s.summary = 'A modular video player system.'
s.description = <<-DESC
@@ -15,8 +15,6 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '8.0'
s.tvos.deployment_target = '9.0'
s.swift_version = "4.2"
s.source_files = 'PlayerKit/Classes/**/*'
end
+12 -6
View File
@@ -9,24 +9,30 @@
import Foundation
import AVFoundation
extension AVPlayer {
var errorForPlayerOrItem: NSError? {
extension AVPlayer
{
var errorForPlayerOrItem: NSError?
{
// First try to return the current item's error
if let error = self.currentItem?.error {
if let error = self.currentItem?.error
{
// If current item's error has an underlying error, return that
if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError {
if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError
{
return underlyingError
}
else {
else
{
return error as NSError?
}
}
// Otherwise, try to return the player error
if let error = self.error {
if let error = self.error
{
return error as NSError?
}
+6 -3
View File
@@ -9,9 +9,12 @@
import Foundation
import AVFoundation
extension CMTime {
var timeInterval: TimeInterval? {
if CMTIME_IS_INVALID(self) || CMTIME_IS_INDEFINITE(self) {
extension CMTime
{
var timeInterval: TimeInterval?
{
if CMTIME_IS_INVALID(self) || CMTIME_IS_INDEFINITE(self)
{
return nil
}
+32 -16
View File
@@ -10,7 +10,8 @@ import UIKit
import AVKit
/// A player error
public enum PlayerError: Int {
public enum PlayerError: Int
{
case unknown
case loading
@@ -19,8 +20,10 @@ public enum PlayerError: Int {
/// The associated error
///
/// - Returns: The error
public func error() -> NSError {
switch self {
public func error() -> NSError
{
switch self
{
case .unknown:
return NSError(domain: type(of: self).Domain, code: self.rawValue, userInfo: [NSLocalizedDescriptionKey: "An unknown error occurred."])
@@ -37,14 +40,16 @@ public enum PlayerError: Int {
/// - loading: The player is loading or buffering
/// - ready: The player is ready for playback
/// - failed: The player has failed
@objc public enum PlayerState: Int {
@objc public enum PlayerState: Int
{
case loading
case ready
case failed
}
/// An object that adopts the PlayerDelegate protocol can receive updates from the player.
@objc public protocol PlayerDelegate: class {
@objc public protocol PlayerDelegate: class
{
func playerDidUpdateState(player: Player, previousState: PlayerState)
func playerDidUpdatePlaying(player: Player)
func playerDidUpdateTime(player: Player)
@@ -52,7 +57,8 @@ public enum PlayerError: Int {
}
/// An object that adopts the Player protocol is responsible for implementing the API and calling PlayerDelegate methods where appropriate.
@objc public protocol Player: class {
@objc public protocol Player: class
{
weak var delegate: PlayerDelegate? { get set }
var state: PlayerState { get }
@@ -82,34 +88,40 @@ public enum PlayerError: Int {
// MARK: Identity Protocols
/// A player that adopts the ProvidesView protocol is capable of providing a view to be added to a view hierarchy.
@objc public protocol ProvidesView {
@objc public protocol ProvidesView
{
var view: UIView { get }
}
// MARK: Capability Protocols
/// A player that adopts the ProvidesView protocol is capable of AirPlay playback.
@objc public protocol AirPlayCapable {
@objc public protocol AirPlayCapable
{
var isAirPlayEnabled: Bool { get set }
}
/// A player that adopts the ProvidesView protocol is capable of setting audio volume.
@objc public protocol VolumeCapable {
@objc public protocol VolumeCapable
{
var volume: Float { get set }
}
/// A player that adopts the ProvidesView protocol is capable of setting the video fill mode.
@objc public protocol FillModeCapable {
@objc public protocol FillModeCapable
{
var fillMode: FillMode { get set }
}
@objc public enum FillMode: Int {
@objc public enum FillMode: Int
{
case fit
case fill
}
/// The metadata that should be attached to any type of text track.
@objc public protocol TextTrackMetadata {
@objc public protocol TextTrackMetadata
{
var displayName: String { get }
var locale: Locale? { get }
// Indicates that the text track represents subtitles for the def and hard of hearing (SDH).
@@ -118,14 +130,17 @@ public enum PlayerError: Int {
@objc(displayNameWithLocale:) func displayName(with locale: Locale) -> String
}
extension TextTrackMetadata {
public func matches(_ other: TextTrackMetadata) -> Bool {
extension TextTrackMetadata
{
public func matches(_ other: TextTrackMetadata) -> Bool
{
return (self.locale == other.locale && self.isSDHTrack == other.isSDHTrack)
}
}
/// A player that conforms to the TextTrackCapable protocol is capable of advertising and displaying text tracks.
@objc public protocol TextTrackCapable {
@objc public protocol TextTrackCapable
{
var selectedTextTrack: TextTrackMetadata? { get }
var availableTextTracks: [TextTrackMetadata] { get }
@@ -135,7 +150,8 @@ extension TextTrackMetadata {
#if os(iOS)
/// A player that adopts the ProvidesView protocol is capable of Picture in Picture playback.
@objc public protocol PictureInPictureCapable {
@objc public protocol PictureInPictureCapable
{
@available(iOS 9.0, *)
var pictureInPictureController: AVPictureInPictureController? { get }
}
+162 -92
View File
@@ -11,15 +11,19 @@ import Foundation
import AVFoundation
import AVKit
extension AVMediaSelectionOption: TextTrackMetadata {
public var isSDHTrack: Bool {
extension AVMediaSelectionOption: TextTrackMetadata
{
public var isSDHTrack: Bool
{
return self.hasMediaCharacteristic(.describesMusicAndSoundForAccessibility) && self.hasMediaCharacteristic(.transcribesSpokenDialogForAccessibility)
}
}
/// A RegularPlayer is used to play regular videos.
@objc open class RegularPlayer: NSObject, Player, ProvidesView {
public struct Constants {
@objc open class RegularPlayer: NSObject, Player, ProvidesView
{
public struct Constants
{
public static let TimeUpdateInterval: TimeInterval = 0.1
}
@@ -32,10 +36,12 @@ extension AVMediaSelectionOption: TextTrackMetadata {
/// Sets an AVAsset on the player.
///
/// - Parameter asset: The AVAsset
@objc open func set(_ asset: AVAsset) {
@objc open func set(_ asset: AVAsset)
{
// Prepare the old item for removal
if let currentItem = self.player.currentItem {
if let currentItem = self.player.currentItem
{
self.removePlayerItemObservers(fromPlayerItem: currentItem)
}
@@ -50,27 +56,33 @@ extension AVMediaSelectionOption: TextTrackMetadata {
// MARK: ProvidesView
private class RegularPlayerView: UIView {
var playerLayer: AVPlayerLayer {
private class RegularPlayerView: UIView
{
var playerLayer: AVPlayerLayer
{
return self.layer as! AVPlayerLayer
}
override class var layerClass: AnyClass {
override class var layerClass: AnyClass
{
return AVPlayerLayer.self
}
func configureForPlayer(player: AVPlayer) {
func configureForPlayer(player: AVPlayer)
{
(self.layer as! AVPlayerLayer).player = player
}
}
public let view: UIView = RegularPlayerView(frame: .zero)
private var regularPlayerView: RegularPlayerView {
private var regularPlayerView: RegularPlayerView
{
return self.view as! RegularPlayerView
}
private var playerLayer: AVPlayerLayer {
private var playerLayer: AVPlayerLayer
{
return self.regularPlayerView.playerLayer
}
@@ -78,55 +90,68 @@ extension AVMediaSelectionOption: TextTrackMetadata {
weak public var delegate: PlayerDelegate?
public private(set) var state: PlayerState = .ready {
didSet {
public private(set) var state: PlayerState = .ready
{
didSet
{
self.delegate?.playerDidUpdateState(player: self, previousState: oldValue)
}
}
public var duration: TimeInterval {
public var duration: TimeInterval
{
return self.player.currentItem?.duration.timeInterval ?? 0
}
public private(set) var time: TimeInterval = 0 {
didSet {
public private(set) var time: TimeInterval = 0
{
didSet
{
self.delegate?.playerDidUpdateTime(player: self)
}
}
public private(set) var bufferedTime: TimeInterval = 0 {
didSet {
public private(set) var bufferedTime: TimeInterval = 0
{
didSet
{
self.delegate?.playerDidUpdateBufferedTime(player: self)
}
}
public var playing: Bool {
public var playing: Bool
{
return self.player.rate > 0
}
public var error: NSError? {
public var error: NSError?
{
return self.player.errorForPlayerOrItem
}
public func seek(to time: TimeInterval) {
let cmTime = CMTimeMakeWithSeconds(time, preferredTimescale: Int32(NSEC_PER_SEC))
public func seek(to time: TimeInterval)
{
let cmTime = CMTimeMakeWithSeconds(time, Int32(NSEC_PER_SEC))
self.player.seek(to: cmTime)
self.time = time
}
public func play() {
public func play()
{
self.player.play()
}
public func pause() {
public func pause()
{
self.player.pause()
}
// MARK: Lifecycle
public override init() {
public override init()
{
super.init()
self.addPlayerObservers()
@@ -136,8 +161,10 @@ extension AVMediaSelectionOption: TextTrackMetadata {
self.setupAirplay()
}
deinit {
if let playerItem = self.player.currentItem {
deinit
{
if let playerItem = self.player.currentItem
{
self.removePlayerItemObservers(fromPlayerItem: playerItem)
}
@@ -145,29 +172,23 @@ extension AVMediaSelectionOption: TextTrackMetadata {
}
// MARK: Setup
@available(iOS 10.0, *)
public var automaticallyWaitsToMinimizeStalling: Bool {
get {
return self.player.automaticallyWaitsToMinimizeStalling
}
set {
self.player.automaticallyWaitsToMinimizeStalling = newValue
}
}
private func setupAirplay() {
private func setupAirplay()
{
self.player.usesExternalPlaybackWhileExternalScreenIsActive = true
}
// MARK: Observers
private struct KeyPath {
struct Player {
private struct KeyPath
{
struct Player
{
static let Rate = "rate"
}
struct PlayerItem {
struct PlayerItem
{
static let Status = "status"
static let PlaybackLikelyToKeepUp = "playbackLikelyToKeepUp"
static let LoadedTimeRanges = "loadedTimeRanges"
@@ -176,35 +197,41 @@ extension AVMediaSelectionOption: TextTrackMetadata {
private var playerTimeObserver: Any?
private func addPlayerItemObservers(toPlayerItem playerItem: AVPlayerItem) {
private func addPlayerItemObservers(toPlayerItem playerItem: AVPlayerItem)
{
playerItem.addObserver(self, forKeyPath: KeyPath.PlayerItem.Status, options: [.initial, .new], context: nil)
playerItem.addObserver(self, forKeyPath: KeyPath.PlayerItem.PlaybackLikelyToKeepUp, options: [.initial, .new], context: nil)
playerItem.addObserver(self, forKeyPath: KeyPath.PlayerItem.LoadedTimeRanges, options: [.initial, .new], context: nil)
}
private func removePlayerItemObservers(fromPlayerItem playerItem: AVPlayerItem) {
private func removePlayerItemObservers(fromPlayerItem playerItem: AVPlayerItem)
{
playerItem.removeObserver(self, forKeyPath: KeyPath.PlayerItem.Status, context: nil)
playerItem.removeObserver(self, forKeyPath: KeyPath.PlayerItem.PlaybackLikelyToKeepUp, context: nil)
playerItem.removeObserver(self, forKeyPath: KeyPath.PlayerItem.LoadedTimeRanges, context: nil)
}
private func addPlayerObservers() {
private func addPlayerObservers()
{
self.player.addObserver(self, forKeyPath: KeyPath.Player.Rate, options: [.initial, .new], context: nil)
let interval = CMTimeMakeWithSeconds(Constants.TimeUpdateInterval, preferredTimescale: Int32(NSEC_PER_SEC))
let interval = CMTimeMakeWithSeconds(Constants.TimeUpdateInterval, Int32(NSEC_PER_SEC))
self.playerTimeObserver = self.player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { [weak self] (cmTime) in
if let strongSelf = self, let time = cmTime.timeInterval {
if let strongSelf = self, let time = cmTime.timeInterval
{
strongSelf.time = time
}
})
}
private func removePlayerObservers() {
private func removePlayerObservers()
{
self.player.removeObserver(self, forKeyPath: KeyPath.Player.Rate, context: nil)
if let playerTimeObserver = self.playerTimeObserver {
if let playerTimeObserver = self.playerTimeObserver
{
self.player.removeTimeObserver(playerTimeObserver)
self.playerTimeObserver = nil
@@ -213,44 +240,56 @@ extension AVMediaSelectionOption: TextTrackMetadata {
// MARK: Observation
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
// Player Item Observers
if keyPath == KeyPath.PlayerItem.Status {
if let statusInt = change?[.newKey] as? Int, let status = AVPlayerItem.Status(rawValue: statusInt) {
if keyPath == KeyPath.PlayerItem.Status
{
if let statusInt = change?[.newKey] as? Int, let status = AVPlayerItemStatus(rawValue: statusInt)
{
self.playerItemStatusDidChange(status: status)
}
}
else if keyPath == KeyPath.PlayerItem.PlaybackLikelyToKeepUp {
if let playbackLikelyToKeepUp = change?[.newKey] as? Bool {
else if keyPath == KeyPath.PlayerItem.PlaybackLikelyToKeepUp
{
if let playbackLikelyToKeepUp = change?[.newKey] as? Bool
{
self.playerItemPlaybackLikelyToKeepUpDidChange(playbackLikelyToKeepUp: playbackLikelyToKeepUp)
}
}
else if keyPath == KeyPath.PlayerItem.LoadedTimeRanges {
if let loadedTimeRanges = change?[.newKey] as? [NSValue] {
else if keyPath == KeyPath.PlayerItem.LoadedTimeRanges
{
if let loadedTimeRanges = change?[.newKey] as? [NSValue]
{
self.playerItemLoadedTimeRangesDidChange(loadedTimeRanges: loadedTimeRanges)
}
}
// Player Observers
else if keyPath == KeyPath.Player.Rate {
if let rate = change?[.newKey] as? Float {
else if keyPath == KeyPath.Player.Rate
{
if let rate = change?[.newKey] as? Float
{
self.playerRateDidChange(rate: rate)
}
}
// Fall Through Observers
else {
else
{
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
// MARK: Observation Helpers
private func playerItemStatusDidChange(status: AVPlayerItem.Status) {
switch status {
private func playerItemStatusDidChange(status: AVPlayerItemStatus)
{
switch status
{
case .unknown:
self.state = .loading
@@ -265,18 +304,22 @@ extension AVMediaSelectionOption: TextTrackMetadata {
}
}
private func playerRateDidChange(rate: Float) {
private func playerRateDidChange(rate: Float)
{
self.delegate?.playerDidUpdatePlaying(player: self)
}
private func playerItemPlaybackLikelyToKeepUpDidChange(playbackLikelyToKeepUp: Bool) {
private func playerItemPlaybackLikelyToKeepUpDidChange(playbackLikelyToKeepUp: Bool)
{
let state: PlayerState = playbackLikelyToKeepUp ? .ready : .loading
self.state = state
}
private func playerItemLoadedTimeRangesDidChange(loadedTimeRanges: [NSValue]) {
guard let bufferedCMTime = loadedTimeRanges.first?.timeRangeValue.end, let bufferedTime = bufferedCMTime.timeInterval else {
private func playerItemLoadedTimeRangesDidChange(loadedTimeRanges: [NSValue])
{
guard let bufferedCMTime = loadedTimeRanges.first?.timeRangeValue.end, let bufferedTime = bufferedCMTime.timeInterval else
{
return
}
@@ -297,20 +340,25 @@ extension AVMediaSelectionOption: TextTrackMetadata {
extension RegularPlayer: AirPlayCapable
{
public var isAirPlayEnabled: Bool {
get {
public var isAirPlayEnabled: Bool
{
get
{
return self.player.allowsExternalPlayback
}
set {
set
{
return self.player.allowsExternalPlayback = newValue
}
}
}
#if os(iOS)
extension RegularPlayer: PictureInPictureCapable {
extension RegularPlayer: PictureInPictureCapable
{
@available(iOS 9.0, *)
public var pictureInPictureController: AVPictureInPictureController? {
public var pictureInPictureController: AVPictureInPictureController?
{
return self._pictureInPictureController
}
}
@@ -318,27 +366,35 @@ extension RegularPlayer: PictureInPictureCapable {
extension RegularPlayer: VolumeCapable
{
public var volume: Float {
get {
public var volume: Float
{
get
{
return self.player.volume
}
set {
set
{
self.player.volume = newValue
}
}
}
extension RegularPlayer: FillModeCapable {
public var fillMode: FillMode {
get {
extension RegularPlayer: FillModeCapable
{
public var fillMode: FillMode
{
get
{
let gravity = (self.view.layer as! AVPlayerLayer).videoGravity
return gravity == .resizeAspect ? .fit : .fill
}
set {
set
{
let gravity: AVLayerVideoGravity
switch newValue {
switch newValue
{
case .fit:
gravity = .resizeAspect
@@ -353,48 +409,62 @@ extension RegularPlayer: FillModeCapable {
}
}
extension RegularPlayer: TextTrackCapable {
public var selectedTextTrack: TextTrackMetadata? {
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
extension RegularPlayer: TextTrackCapable
{
public var selectedTextTrack: TextTrackMetadata?
{
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else
{
return nil
}
if #available(iOS 9.0, *) {
if #available(iOS 9.0, *)
{
return self.player.currentItem?.currentMediaSelection.selectedMediaOption(in: group)
}
else {
else
{
return self.player.currentItem?.selectedMediaOption(in: group)
}
}
public var availableTextTracks: [TextTrackMetadata] {
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
public var availableTextTracks: [TextTrackMetadata]
{
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else
{
return []
}
return group.options
}
public func fetchTextTracks(completion: @escaping ([TextTrackMetadata], TextTrackMetadata?) -> Void) {
public func fetchTextTracks(completion: @escaping ([TextTrackMetadata], TextTrackMetadata?) -> Void)
{
self.player.currentItem?.asset.loadValuesAsynchronously(forKeys: [#keyPath(AVAsset.availableMediaCharacteristicsWithMediaSelectionOptions)]) { [weak self] in
guard let strongSelf = self, let group = strongSelf.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
guard let strongSelf = self, let group = strongSelf.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else
{
completion([], nil)
return
}
if #available(iOS 9.0, *) {
if #available(iOS 9.0, *)
{
completion(group.options, strongSelf.player.currentItem?.currentMediaSelection.selectedMediaOption(in: group))
}
else {
else
{
completion(group.options, strongSelf.player.currentItem?.selectedMediaOption(in: group))
}
}
}
public func select(_ textTrack: TextTrackMetadata?) {
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
public func select(_ textTrack: TextTrackMetadata?)
{
guard let group = self.player.currentItem?.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else
{
return
}
guard let track = textTrack else {
guard let track = textTrack else
{
self.player.currentItem?.select(nil, in: group)
return
}
+3 -3
View File
@@ -23,7 +23,7 @@ To run the example project, clone the repo, and run `pod install` from the Examp
## Minimum Requirements
- iOS 8.0 / tvOS 9.0
- Swift 4.2
- Swift 3.2
## Installation
@@ -62,9 +62,9 @@ player.delegate = delegate
You can create your own players by creating objects that conform to the Player protocol and call the delegate methods when appropriate.
## Questions?
## Author
Post on [Stackoverflow](http://stackoverflow.com/questions/tagged/vimeo-ios) with the tag `vimeo-ios`. Get in touch [here](https://vimeo.com/help/contact). Interested in working at Vimeo? We're [hiring](https://vimeo.com/jobs)!
Gavin King, gavin@vimeo.com
## License
+1
View File
@@ -0,0 +1 @@
Example/Pods/Pods.xcodeproj
+19
View File
@@ -0,0 +1,19 @@
general:
artifacts:
- "build/Logs"
- "PlayerKit_Example-PlayerKit-Example.log"
machine:
xcode:
version: 9.0
dependencies:
override:
- bundle install --deployment
cache_directories:
- "~/.cocoapods"
- "Example/Pods"
- "vendor/bundle"
test:
override:
- bundle exec fastlane test
+2 -23
View File
@@ -17,10 +17,10 @@ default_platform :ios
platform :ios do
before_all do
ensure_xcode_version(version: "10.2.1")
ensure_xcode_version(version: "9.0.1")
end
desc "Run tests"
desc "run tests"
lane :test do |options|
cocoapods(
@@ -43,27 +43,6 @@ platform :ios do
end
end
desc "bumps the project and podspec version"
lane :version_bump do |options|
bump_type = options[:bump_type]
version_number = options[:version_number]
if bump_type.nil? && version_number.nil?
UI.user_error!("version_bump requires you to provide a bump_type [patch|minor|major] or specific version_number. Please try again.")
end
increment_version_number(
bump_type: bump_type,
version_number: version_number,
xcodeproj: "Example/PlayerKit.xcodeproj"
)
version_bump_podspec(
bump_type: bump_type,
version_number: version_number
)
end
after_all do |lane|
end
+1 -7
View File
@@ -27,19 +27,13 @@ xcode-select --install
<td width="33%"><code>sudo gem install fastlane -NV</code></td>
</tr>
</table>
# Available Actions
## iOS
### ios test
```
fastlane ios test
```
Run tests
### ios version_bump
```
fastlane ios version_bump
```
bumps the project and podspec version
run tests
----
-21
View File
@@ -1,21 +0,0 @@
name: VimeoPlayerKit
targets:
PlayerKit:
type: framework
platform: iOS
settings:
PRODUCT_BUNDLE_IDENTIFIER: com.vimeo.playerkit
INFOPLIST_FILE: Example/PlayerKit/Info.plist
sources:
- path: PlayerKit
scheme:
testTargets:
- PlayerKitTests
PlayerKitTests:
dependencies:
- target: PlayerKit
type: bundle.unit-test
platform: iOS
sources:
- path: Example/Tests