Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Airplay Support #166

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions MobilePlayer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
049568191E733437006E4937 /* Airplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049568181E733437006E4937 /* Airplay.swift */; };
0495681B1E733563006E4937 /* AirplayConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0495681A1E733563006E4937 /* AirplayConfig.swift */; };
0495681D1E733904006E4937 /* Airplay.json in Resources */ = {isa = PBXBuildFile; fileRef = 0495681C1E733904006E4937 /* Airplay.json */; };
0495681F1E73484A006E4937 /* AdvancedConfigAirplayExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0495681E1E73484A006E4937 /* AdvancedConfigAirplayExampleViewController.swift */; };
5F31B7B91BBAE39900EF50C4 /* MobilePlayerNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31B7B81BBAE39900EF50C4 /* MobilePlayerNotification.swift */; };
5F3F03C31C18E73200EF50C4 /* PrerollExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3F03C21C18E73200EF50C4 /* PrerollExampleViewController.swift */; };
5F3F03C51C18E74000EF50C4 /* PauseOverlayExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3F03C41C18E74000EF50C4 /* PauseOverlayExampleViewController.swift */; };
Expand Down Expand Up @@ -136,6 +140,10 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
049568181E733437006E4937 /* Airplay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Airplay.swift; path = Views/Airplay.swift; sourceTree = "<group>"; };
0495681A1E733563006E4937 /* AirplayConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AirplayConfig.swift; sourceTree = "<group>"; };
0495681C1E733904006E4937 /* Airplay.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = Airplay.json; path = Resources/Airplay.json; sourceTree = "<group>"; };
0495681E1E73484A006E4937 /* AdvancedConfigAirplayExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedConfigAirplayExampleViewController.swift; sourceTree = "<group>"; };
0A3D625F8D46F7B3823A9927 /* Pods-MobilePlayerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MobilePlayerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MobilePlayerTests/Pods-MobilePlayerTests.debug.xcconfig"; sourceTree = "<group>"; };
460022C3A2D4FC80A1D57D18 /* Pods-MobilePlayerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MobilePlayerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-MobilePlayerTests/Pods-MobilePlayerTests.release.xcconfig"; sourceTree = "<group>"; };
505CCD80FF878F8F17EC4627 /* Pods_MobilePlayerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MobilePlayerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -281,6 +289,7 @@
children = (
5F4CED421C054A5200EF50C4 /* WatermarkedPlayer.json */,
5FF829681C16924400EF50C4 /* MovielalaPlayer.json */,
0495681C1E733904006E4937 /* Airplay.json */,
);
name = Resources;
sourceTree = "<group>";
Expand All @@ -298,6 +307,7 @@
5F3F03C21C18E73200EF50C4 /* PrerollExampleViewController.swift */,
5F3F03C41C18E74000EF50C4 /* PauseOverlayExampleViewController.swift */,
5F3F03C61C18E75300EF50C4 /* PostrollExampleViewController.swift */,
0495681E1E73484A006E4937 /* AdvancedConfigAirplayExampleViewController.swift */,
);
name = Examples;
sourceTree = "<group>";
Expand Down Expand Up @@ -362,6 +372,7 @@
5FA92EA21BA9896300EF50C4 /* ToggleButton.swift */,
5FA92EA61BA9919D00EF50C4 /* Slider.swift */,
5F7CDF4A1BBEB6F900EF50C4 /* VolumeView.swift */,
049568181E733437006E4937 /* Airplay.swift */,
);
name = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -413,6 +424,7 @@
5FA92EA01BA9839300EF50C4 /* ButtonConfig.swift */,
5FBFEA331BA8ACDE00EF50C4 /* ToggleButtonConfig.swift */,
5FBFEA351BA8AD0200EF50C4 /* SliderConfig.swift */,
0495681A1E733563006E4937 /* AirplayConfig.swift */,
);
path = Config;
sourceTree = "<group>";
Expand Down Expand Up @@ -721,6 +733,7 @@
5F56CB901C040E8D00EF50C4 /* LaunchScreen.storyboard in Resources */,
5F3F03D51C1903EF00EF50C4 /* PostrollOverlayViewController.xib in Resources */,
5FF829691C16924400EF50C4 /* MovielalaPlayer.json in Resources */,
0495681D1E733904006E4937 /* Airplay.json in Resources */,
5F56CB8D1C040E8D00EF50C4 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -788,6 +801,7 @@
5F79747C1C17ED7800EF50C4 /* TimedOverlayExampleViewController.swift in Sources */,
5F3F03CF1C18F3DA00EF50C4 /* PauseOverlayViewController.swift in Sources */,
5FF829671C168E4700EF50C4 /* ProgConfigExampleViewController.swift in Sources */,
0495681F1E73484A006E4937 /* AdvancedConfigAirplayExampleViewController.swift in Sources */,
5F3F03D31C1903E200EF50C4 /* PostrollOverlayViewController.swift in Sources */,
5F7974781C17B02200EF50C4 /* OverlayExampleViewController.swift in Sources */,
5F56CBB71C041DAE00EF50C4 /* RemoteConfigExampleViewController.swift in Sources */,
Expand Down Expand Up @@ -817,11 +831,13 @@
5FA92EA51BA98BE700EF50C4 /* Bar.swift in Sources */,
5FBFEA361BA8AD0200EF50C4 /* SliderConfig.swift in Sources */,
5FBFEA2E1BA8AC1B00EF50C4 /* BarConfig.swift in Sources */,
0495681B1E733563006E4937 /* AirplayConfig.swift in Sources */,
C308B3C01B150F7600CB1515 /* MobilePlayerConfig.swift in Sources */,
5F8272741BFA9F0600EF50C4 /* UIImage+CocoaPods.swift in Sources */,
5F7CDF471BBEB6C400EF50C4 /* YoutubeParser.swift in Sources */,
5FD756961BAC4AE700EF50C4 /* WatermarkViewController.swift in Sources */,
5FBFEA321BA8ACC500EF50C4 /* LabelConfig.swift in Sources */,
049568191E733437006E4937 /* Airplay.swift in Sources */,
5F6AF3701BA96EF000EF50C4 /* Button.swift in Sources */,
5FBFEA341BA8ACDE00EF50C4 /* ToggleButtonConfig.swift in Sources */,
CE554D731AFE6EBB00DAC7E9 /* MobilePlayerOverlayViewController.swift in Sources */,
Expand Down Expand Up @@ -935,6 +951,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = MobilePlayerExamples/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
Expand All @@ -950,6 +967,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = MobilePlayerExamples/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
Expand All @@ -963,6 +981,7 @@
isa = XCBuildConfiguration;
buildSettings = {
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = MobilePlayerExamplesUITests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
Expand All @@ -978,6 +997,7 @@
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = MobilePlayerExamplesUITests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
Expand Down Expand Up @@ -1129,6 +1149,7 @@
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
Expand All @@ -1150,6 +1171,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
"BUNDLE_LOADER[arch=*]" = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
Expand Down
50 changes: 50 additions & 0 deletions MobilePlayer/Config/AirplayConfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// AirplayConfig.swift
// MobilePlayer
//
// Created by Maca on 3/10/17.
// Copyright © 2017 MovieLaLa. All rights reserved.
//

import UIKit

/// Holds button configuration values.
public class AirplayConfig: ElementConfig {

/// Airplay background color
public let backgroundColor: UIColor

/// Airplay tint color. Default value is white.
public let tintColor: UIColor

/// Initializes using default values.
public convenience init() {
self.init(dictionary: [String: Any]())
}

/// Initializes using a dictionary.
///
/// * Key for `backgroundColor` is `"backgroundColor"` and its value should be a color hex string.
/// * Key for `tintColor` is `"tintColor"` and its value should be a color hex string.
///
/// - parameters:
/// - dictionary: Button configuration dictionary.
public override init(dictionary: [String: Any]) {
// Values need to be AnyObject for type conversions to work correctly.
let dictionary = dictionary as [String: AnyObject]

if let backgroundColorHex = dictionary["backgroundColor"] as? String {
backgroundColor = UIColor(hex: backgroundColorHex)
} else {
backgroundColor = UIColor.clear
}

if let tintColorHex = dictionary["tintColor"] as? String {
tintColor = UIColor(hex: tintColorHex)
} else {
tintColor = UIColor.white
}

super.init(dictionary: dictionary)
}
}
2 changes: 2 additions & 0 deletions MobilePlayer/Config/BarConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public class BarConfig {
validElements.append(LabelConfig(dictionary: elementDictionary))
case "slider":
validElements.append(SliderConfig(dictionary: elementDictionary))
case "airplay":
validElements.append(AirplayConfig(dictionary: elementDictionary))
default:
break
}
Expand Down
5 changes: 5 additions & 0 deletions MobilePlayer/Config/ElementConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public enum ElementType: String {

/// Element is a slider.
case Slider = "slider"

/// Element is airplay button
case Airplay = "airplay"
}

/// Determines how an element's width will be calculated.
Expand Down Expand Up @@ -61,6 +64,8 @@ public class ElementConfig {
/// * "play"
/// * Sliders
/// * "playback"
/// * Airplay
/// * "router"
public let identifier: String?

/// How the width of the element will be calculated. Default value is `.Fill` for title label and playback slider,
Expand Down
1 change: 1 addition & 0 deletions MobilePlayer/MobilePlayerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ open class MobilePlayerViewController: MPMoviePlayerViewController {
edgesForExtendedLayout = []
moviePlayer.scalingMode = .aspectFit
moviePlayer.controlStyle = .none
moviePlayer.allowsAirPlay = true
initializeNotificationObservers()
initializeControlsView()
parseContentURLIfNeeded()
Expand Down
48 changes: 48 additions & 0 deletions MobilePlayer/Views/Airplay.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Airplay.swift
// MobilePlayer
//
// Created by Maca on 3/10/17.
// Copyright © 2017 MovieLaLa. All rights reserved.
//

import UIKit
import MediaPlayer

class Airplay: MPVolumeView {
let config: AirplayConfig

init(config: AirplayConfig = AirplayConfig()) {
self.config = config
super.init(frame: .zero)
accessibilityLabel = accessibilityLabel ?? config.identifier
tintColor = config.tintColor
backgroundColor = config.backgroundColor
showsRouteButton = true
showsVolumeSlider = false
translatesAutoresizingMaskIntoConstraints = false
self.sizeToFit()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// override func sizeThatFits(_ size: CGSize) -> CGSize {
// let superSize = super.sizeThatFits(size)
// return CGSize(
// width: 40.0,
// height: superSize.height)
// }
}

// MARK: - Element
extension Airplay: Element {
var type: ElementType { return config.type }
var identifier: String? { return config.identifier }
var widthCalculation: ElementWidthCalculation { return config.widthCalculation }
var width: CGFloat { return config.width }
var marginLeft: CGFloat { return config.marginLeft }
var marginRight: CGFloat { return config.marginRight }
var view: UIView { return self }
}
3 changes: 3 additions & 0 deletions MobilePlayer/Views/Bar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class Bar: UIView {
case .Slider:
guard let sliderConfig = config as? SliderConfig else { return }
elementView = Slider(config: sliderConfig)
case .Airplay:
guard let airplayConfig = config as? AirplayConfig else { return }
elementView = Airplay(config: airplayConfig)
case .Unknown:
elementView = nil
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// AdvancedConfigAirplayExampleViewController.swift
// MobilePlayer
//
// Created by Maca on 3/10/17.
// Copyright © 2017 MovieLaLa. All rights reserved.
//

import UIKit
import MobilePlayer

class AdvancedConfigAirplayExampleViewController: ExampleViewController {

override init() {
super.init()
title = "Advanced w/Airplay Configuration"
codeImageView.image = UIImage(named: "AdvancedConfigExampleCode")
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func showButtonDidGetTapped() {
let bundle = Bundle.main
let config = MobilePlayerConfig(fileURL: bundle.url(
forResource: "Airplay",
withExtension: "json")!)
let playerVC = MobilePlayerViewController(
contentURL: videoURL,
config: config)
playerVC.title = videoTitle
playerVC.activityItems = [videoURL]
presentMoviePlayerViewControllerAnimated(playerVC)
}
}

1 change: 1 addition & 0 deletions MobilePlayerExamples/ExamplesTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ExamplesTableViewController: UITableViewController {
RemoteConfigExampleViewController(),
ProgConfigExampleViewController(),
AdvancedConfigExampleViewController(),
AdvancedConfigAirplayExampleViewController(),
OverlayExampleViewController(),
TimedOverlayExampleViewController(),
PrerollExampleViewController(),
Expand Down
54 changes: 54 additions & 0 deletions MobilePlayerExamples/Resources/Airplay.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"topBar": {
"backgroundColor": ["#a60500b0", "#a60500a0"],
"elements": [
{
"type": "button",
"identifier": "close"
},
{
"type": "slider",
"identifier": "playback",
"trackHeight": 6,
"trackCornerRadius": 3,
"minimumTrackTintColor": "#eee",
"availableTrackTintColor": "#9e9b9a",
"maximumTrackTintColor": "#cccccc",
"thumbTintColor": "#f9f9f9",
"thumbBorderWidth": 1,
"thumbBorderColor": "#fff",
"marginRight": 4
}
]
},
"bottomBar": {
"backgroundColor": ["#a60500a0", "#a60500b0"],
"elements": [
{
"type": "label",
"text": "Now Watching",
"font": "Baskerville",
"size": 12,
"marginLeft": 8,
"marginRight": 8
},
{
"type": "label",
"identifier": "title",
"size": 14
},
{
"type": "button",
"identifier": "action"
},
{
"type": "toggleButton",
"identifier": "play"
},
{
"type": "airplay",
"identifier": "router"
}
]
}
}