diff --git a/Classes/Network/KalturaMultiRequestBuilder.swift b/Classes/Network/KalturaMultiRequestBuilder.swift
index 00339297..57d5fc00 100644
--- a/Classes/Network/KalturaMultiRequestBuilder.swift
+++ b/Classes/Network/KalturaMultiRequestBuilder.swift
@@ -26,7 +26,7 @@ class KalturaMultiRequestBuilder: KalturaRequestBuilder {
override public func build() -> Request {
let data = self.kalturaMultiRequestData()
- let request = RequestElement(requestId: self.requestId, method: self.method, url: self.url, dataBody: data, headers: self.headers, timeout: self.timeout, configuration: self.configuration, completion: self.completion)
+ let request = RequestElement(requestId: self.requestId, method: self.method, url: self.url, dataBody: data, headers: self.headers, timeout: self.timeout, configuration: self.configuration, responseSerializer: self.responseSerializer, completion: self.completion)
return request
}
diff --git a/Classes/Network/Request.swift b/Classes/Network/Request.swift
index 2e793aa0..c83f0daf 100644
--- a/Classes/Network/Request.swift
+++ b/Classes/Network/Request.swift
@@ -34,6 +34,7 @@ public protocol Request {
var timeout: Double { get }
var configuration: RequestConfiguration? { get }
var completion: completionClosures? { get }
+ var responseSerializer: ResponseSerializer { get }
}
public struct RequestElement: Request {
@@ -45,6 +46,7 @@ public struct RequestElement: Request {
public var headers: [String:String]?
public var timeout: Double
public var configuration: RequestConfiguration?
+ public var responseSerializer: ResponseSerializer
public var completion: completionClosures?
}
@@ -62,7 +64,7 @@ public struct RequestElement: Request {
public var configuration: RequestConfiguration? = nil
public var completion: completionClosures? = nil
public var urlParams: [String: String]? = nil
-
+ public var responseSerializer : ResponseSerializer = JSONSerializer()
public init?(url: String){
if let path = URL(string: url) {
self.url = path
@@ -101,6 +103,12 @@ public struct RequestElement: Request {
return self
}
+ @discardableResult
+ public func set(responseSerializer: ResponseSerializer) -> Self{
+ self.responseSerializer = responseSerializer
+ return self
+ }
+
@discardableResult
public func set(completion:completionClosures?) -> Self{
self.completion = completion
@@ -170,7 +178,7 @@ public struct RequestElement: Request {
}
- return RequestElement(requestId: self.requestId, method:self.method , url: self.url, dataBody: bodyData, headers: self.headers, timeout: self.timeout, configuration: self.configuration, completion: self.completion)
+ return RequestElement(requestId: self.requestId, method:self.method , url: self.url, dataBody: bodyData, headers: self.headers, timeout: self.timeout, configuration: self.configuration,responseSerializer: self.responseSerializer, completion: self.completion)
}
}
diff --git a/Classes/Network/ResponseSerializer.swift b/Classes/Network/ResponseSerializer.swift
new file mode 100644
index 00000000..c6b06567
--- /dev/null
+++ b/Classes/Network/ResponseSerializer.swift
@@ -0,0 +1,51 @@
+//
+// ResponseSerializer.swift
+// Pods
+//
+// Created by Rivka Peleg on 14/03/2017.
+//
+//
+
+import Foundation
+
+enum SerializerError: Error {
+ case serializationError
+}
+
+
+public protocol ResponseSerializer {
+ /**
+ This fuction will serialize the response data of certin request to the expected type according to the serializer type
+ */
+ func serialize(data: Data) throws -> Any
+}
+
+
+ class JSONSerializer: ResponseSerializer {
+
+ func serialize(data: Data) throws -> Any {
+ let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions())
+ return json
+ }
+}
+
+
+ class IntSerializer: ResponseSerializer {
+
+ func serialize(data: Data) throws -> Any {
+ guard let int8 = [UInt8](data).last else {
+ throw SerializerError.serializationError
+ }
+
+ let int: Int = Int(int8)
+ return int
+ }
+}
+
+ class StringSerializer: ResponseSerializer {
+
+ func serialize(data: Data) throws -> Any {
+ let string = String(data: data, encoding: .utf8)
+ return string
+ }
+}
diff --git a/Classes/Network/USRExecutor.swift b/Classes/Network/USRExecutor.swift
index ddd5ede6..4268deba 100644
--- a/Classes/Network/USRExecutor.swift
+++ b/Classes/Network/USRExecutor.swift
@@ -78,7 +78,7 @@ import UIKit
if let d = data {
do {
- let json = try JSONSerialization.jsonObject(with: d, options: JSONSerialization.ReadingOptions())
+ let json = try r.responseSerializer.serialize(data: d)
let result = Response(data: json, error:nil)
completion(result)
} catch {
diff --git a/Classes/Player/Player.swift b/Classes/Player/Player.swift
index 3c281ba8..57c1138a 100644
--- a/Classes/Player/Player.swift
+++ b/Classes/Player/Player.swift
@@ -16,7 +16,7 @@ import AVKit
@objc public protocol Player: NSObjectProtocol {
- @objc var delegate: PlayerDelegate? { get set }
+ @objc weak var delegate: PlayerDelegate? { get set }
/// The player's associated media entry.
weak var mediaEntry: MediaEntry? { get }
diff --git a/Classes/Player/PlayerController.swift b/Classes/Player/PlayerController.swift
index a2569cb0..2f71b5ae 100644
--- a/Classes/Player/PlayerController.swift
+++ b/Classes/Player/PlayerController.swift
@@ -14,7 +14,7 @@ class PlayerController: NSObject, Player {
var onEventBlock: ((PKEvent)->Void)?
- var delegate: PlayerDelegate?
+ weak var delegate: PlayerDelegate?
fileprivate var currentPlayer: AVPlayerEngine
fileprivate var assetBuilder: AssetBuilder?
diff --git a/Classes/Plugins/BasePlugin.swift b/Classes/Plugins/BasePlugin.swift
index 863440e3..67b77a04 100644
--- a/Classes/Plugins/BasePlugin.swift
+++ b/Classes/Plugins/BasePlugin.swift
@@ -16,8 +16,8 @@ import Foundation
fatalError("abstract property should be overriden in subclass")
}
- @objc public unowned var player: Player
- @objc public unowned var messageBus: MessageBus
+ @objc public weak var player: Player?
+ @objc public weak var messageBus: MessageBus?
@objc public required init(player: Player, pluginConfig: Any?, messageBus: MessageBus) throws {
PKLog.info("initializing plugin \(type(of:self))")
diff --git a/Classes/Plugins/PKPlugin.swift b/Classes/Plugins/PKPlugin.swift
index 1559afb8..0887e201 100644
--- a/Classes/Plugins/PKPlugin.swift
+++ b/Classes/Plugins/PKPlugin.swift
@@ -15,8 +15,9 @@ public protocol PKPlugin {
static var pluginName: String { get }
/// The player associated with the plugin
- unowned var player: Player { get }
- unowned var messageBus: MessageBus { get }
+ weak var player: Player? { get }
+ /// The messageBus associated with the plugin
+ weak var messageBus: MessageBus? { get }
init(player: Player, pluginConfig: Any?, messageBus: MessageBus) throws
diff --git a/Classes/WidevineClassicHelper.swift b/Classes/WidevineClassicHelper.swift
index e5cff835..377c5856 100644
--- a/Classes/WidevineClassicHelper.swift
+++ b/Classes/WidevineClassicHelper.swift
@@ -18,12 +18,12 @@ typealias LocalAssetStatusBlock = (Error?, TimeInterval, TimeInterval) -> Void
// MARK: - WidevineClassicError
/************************************************************/
- enum WidevineClassicError: PKError {
+ enum WidevineClassicError: PKError {
case invalidDRMData
case missingWidevineFile
- static let Domain = "com.kaltura.playkit.error.drm.widevine"
+ static let domain = "com.kaltura.playkit.error.drm.widevine"
var code: Int {
switch self {
@@ -48,7 +48,7 @@ typealias LocalAssetStatusBlock = (Error?, TimeInterval, TimeInterval) -> Void
}
extension PKErrorDomain {
- @objc public static let Widevine = WidevineClassicError.Domain
+ @objc public static let Widevine = WidevineClassicError.domain
}
extension PKErrorCode {
diff --git a/Example/PlayKit/Info.plist b/Example/PlayKit/Info.plist
index 5c1ca7e5..f7769bc4 100644
--- a/Example/PlayKit/Info.plist
+++ b/Example/PlayKit/Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.1.23
+ 0.1.25
CFBundleSignature
????
CFBundleVersion
diff --git a/PlayKit.podspec b/PlayKit.podspec
index 1aefa0d9..04c13c0e 100644
--- a/PlayKit.podspec
+++ b/PlayKit.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PlayKit'
-s.version = '0.1.23'
+s.version = '0.1.25'
s.summary = 'PlayKit: Kaltura Mobile Player SDK - iOS'
diff --git a/Plugins/AnalyticsCommon/AnalyticsPluginProtocol.swift b/Plugins/AnalyticsCommon/AnalyticsPluginProtocol.swift
index a48e98de..d0ab4d3d 100644
--- a/Plugins/AnalyticsCommon/AnalyticsPluginProtocol.swift
+++ b/Plugins/AnalyticsCommon/AnalyticsPluginProtocol.swift
@@ -10,8 +10,6 @@ import Foundation
protocol AnalyticsPluginProtocol: PKPlugin {
- unowned var player: Player { get set }
- unowned var messageBus: MessageBus { get set }
var config: AnalyticsConfig? { get set }
var isFirstPlay: Bool { get set }
var playerEventsToRegister: [PlayerEvent.Type] { get }
diff --git a/Plugins/AnalyticsCommon/BaseAnalyticsPlugin.swift b/Plugins/AnalyticsCommon/BaseAnalyticsPlugin.swift
index ea890bd2..baf696b1 100644
--- a/Plugins/AnalyticsCommon/BaseAnalyticsPlugin.swift
+++ b/Plugins/AnalyticsCommon/BaseAnalyticsPlugin.swift
@@ -73,8 +73,8 @@ extension PKErrorCode {
}
public override func destroy() {
+ self.messageBus?.removeObserver(self, events: playerEventsToRegister)
super.destroy()
- self.messageBus.removeObserver(self, events: playerEventsToRegister)
}
/************************************************************/
diff --git a/Plugins/IMA/IMAPlugin.swift b/Plugins/IMA/IMAPlugin.swift
index 8d2919b8..43b8c4dc 100644
--- a/Plugins/IMA/IMAPlugin.swift
+++ b/Plugins/IMA/IMAPlugin.swift
@@ -20,7 +20,6 @@ extension IMAAdsManager {
weak var dataSource: AdsPluginDataSource? {
didSet {
PKLog.debug("data source set")
- self.setupMainView()
}
}
weak var delegate: AdsPluginDelegate?
@@ -28,7 +27,6 @@ extension IMAAdsManager {
private var contentPlayhead: IMAAVPlayerContentPlayhead?
private var adsManager: IMAAdsManager?
- private var companionSlot: IMACompanionAdSlot?
private var renderingSettings: IMAAdsRenderingSettings! = IMAAdsRenderingSettings()
private static var loader: IMAAdsLoader!
@@ -94,9 +92,9 @@ extension IMAAdsManager {
throw PKPluginError.missingPluginConfig(pluginName: IMAPlugin.pluginName)
}
- self.messageBus.addObserver(self, events: [PlayerEvent.ended], block: { (data: Any) -> Void in
- self.contentComplete()
- })
+ self.messageBus?.addObserver(self, events: [PlayerEvent.ended]) { [weak self] event in
+ self?.contentComplete()
+ }
self.timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(IMAPlugin.update), userInfo: nil, repeats: true)
}
@@ -120,11 +118,23 @@ extension IMAAdsManager {
/************************************************************/
func requestAds() {
+ guard let playerView = player?.view else { return }
+
if self.adTagUrl != nil && self.adTagUrl != "" {
self.startAdCalled = false
+ // setup ad display container and companion if exists, needs to create a new ad container for each request.
+ var companionAdSlot: IMACompanionAdSlot? = nil
+ let adDisplayContainer: IMAAdDisplayContainer
+ if let companionView = self.config?.companionView {
+ companionAdSlot = IMACompanionAdSlot(view: companionView, width: Int32(companionView.frame.size.width), height: Int32(companionView.frame.size.height))
+ adDisplayContainer = IMAAdDisplayContainer(adContainer: playerView, companionSlots: [companionAdSlot])
+ } else {
+ adDisplayContainer = IMAAdDisplayContainer(adContainer: playerView, companionSlots: [])
+ }
+
var request: IMAAdsRequest
- request = IMAAdsRequest(adTagUrl: self.adTagUrl, adDisplayContainer: self.createAdDisplayContainer(), contentPlayhead: self, userContext: nil)
+ request = IMAAdsRequest(adTagUrl: self.adTagUrl, adDisplayContainer: adDisplayContainer, contentPlayhead: self, userContext: nil)
IMAPlugin.loader.requestAds(with: request)
PKLog.trace("request Ads")
@@ -176,16 +186,6 @@ extension IMAAdsManager {
imaSettings.autoPlayAdBreaks = config.autoPlayAdBreaks
IMAPlugin.loader = IMAAdsLoader(settings: imaSettings)
}
-
- private func setupMainView() {
-// if let _ = self.player.playerEngine {
-// self.pictureInPictureProxy = IMAPictureInPictureProxy(avPictureInPictureControllerDelegate: self)
-// }
-
- if let companionView = self.config?.companionView {
- self.companionSlot = IMACompanionAdSlot(view: companionView, width: Int32(companionView.frame.size.width), height: Int32(companionView.frame.size.height))
- }
- }
private func setupLoadingView() {
self.loadingView = UIView(frame: CGRect.zero)
@@ -202,16 +202,13 @@ extension IMAAdsManager {
self.loadingView!.addConstraint(NSLayoutConstraint(item: self.loadingView!, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: indicator, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0))
self.loadingView!.addConstraint(NSLayoutConstraint(item: self.loadingView!, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: indicator, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0))
- let videoView = self.player.view
- videoView?.addSubview(self.loadingView!)
- videoView?.addConstraint(NSLayoutConstraint(item: videoView!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0))
- videoView?.addConstraint(NSLayoutConstraint(item: videoView!, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0))
- videoView?.addConstraint(NSLayoutConstraint(item: videoView!, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0))
- videoView?.addConstraint(NSLayoutConstraint(item: videoView!, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.right, multiplier: 1, constant: 0))
- }
-
- private func createAdDisplayContainer() -> IMAAdDisplayContainer {
- return IMAAdDisplayContainer(adContainer: self.player.view, companionSlots: self.config?.companionView != nil ? [self.companionSlot!] : nil)
+ if let videoView = self.player?.view {
+ videoView.addSubview(self.loadingView!)
+ videoView.addConstraint(NSLayoutConstraint(item: videoView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0))
+ videoView.addConstraint(NSLayoutConstraint(item: videoView, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0))
+ videoView.addConstraint(NSLayoutConstraint(item: videoView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0))
+ videoView.addConstraint(NSLayoutConstraint(item: videoView, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self.loadingView!, attribute: NSLayoutAttribute.right, multiplier: 1, constant: 0))
+ }
}
private func loadAdsIfNeeded() {
@@ -251,10 +248,7 @@ extension IMAAdsManager {
@objc private func update() {
if !self.isAdPlayback {
- let currentTime = self.player.currentTime
- if currentTime.isNaN {
- return
- }
+ guard let currentTime = self.player?.currentTime, !currentTime.isNaN else { return }
self.currentPlaybackTime = currentTime
self.loadAdsIfNeeded()
}
@@ -281,12 +275,12 @@ extension IMAAdsManager {
self.loadingView!.alpha = alpha
self.loadingView!.isHidden = !show
- self.player.view?.bringSubview(toFront: self.loadingView!)
+ self.player?.view?.bringSubview(toFront: self.loadingView!)
}
private func notify(event: AdEvent) {
self.delegate?.adsPlugin(self, didReceive: event)
- self.messageBus.post(event)
+ self.messageBus?.post(event)
}
private func notifyAdCuePoints(fromAdsManager adsManager: IMAAdsManager) {
@@ -324,7 +318,7 @@ extension IMAAdsManager {
self.loaderFailed = true
self.showLoadingView(false, alpha: 0)
PKLog.error(adErrorData.adError.message)
- self.messageBus.post(AdEvent.Error(nsError: IMAPluginError(adError: adErrorData.adError).asNSError))
+ self.messageBus?.post(AdEvent.Error(nsError: IMAPluginError(adError: adErrorData.adError).asNSError))
self.delegate?.adsPlugin(self, loaderFailedWith: adErrorData.adError.message)
}
@@ -392,7 +386,7 @@ extension IMAAdsManager {
public func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) {
self.showLoadingView(false, alpha: 0)
PKLog.error(error.message)
- self.messageBus.post(AdEvent.Error(nsError: IMAPluginError(adError: error).asNSError))
+ self.messageBus?.post(AdEvent.Error(nsError: IMAPluginError(adError: error).asNSError))
self.delegate?.adsPlugin(self, managerFailedWith: error.message)
}
diff --git a/Plugins/KalturaLiveStats/KalturaLiveStatsPlugin.swift b/Plugins/KalturaLiveStats/KalturaLiveStatsPlugin.swift
index 0cfbe3e3..001a3045 100644
--- a/Plugins/KalturaLiveStats/KalturaLiveStatsPlugin.swift
+++ b/Plugins/KalturaLiveStats/KalturaLiveStatsPlugin.swift
@@ -63,38 +63,42 @@ public class KalturaLiveStatsPlugin: BaseAnalyticsPlugin {
switch event {
case let e where e.self == PlayerEvent.play:
- self.messageBus.addObserver(self, events: [e.self]){ [unowned self] event in
+ self.messageBus?.addObserver(self, events: [e.self]){ [weak self] event in
+ guard let strongSelf = self, let player = self?.player else { return }
PKLog.debug("play event: \(event)")
- self.lastReportedStartTime = self.player.currentTime.toInt32()
- self.startLiveEvents()
+ strongSelf.lastReportedStartTime = player.currentTime.toInt32()
+ strongSelf.startLiveEvents()
}
case let e where e.self == PlayerEvent.pause:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("pause event: \(event)")
- self.stopLiveEvents()
+ strongSelf.stopLiveEvents()
}
case let e where e.self == PlayerEvent.playbackParamsUpdated:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("playbackParamsUpdated event: \(event)")
if type(of: event) == PlayerEvent.playbackParamsUpdated {
- self.lastReportedBitrate = Int32(event.currentBitrate!)
+ strongSelf.lastReportedBitrate = Int32(event.currentBitrate!)
}
}
case let e where e.self == PlayerEvent.stateChanged:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("playbackParamsUpdated event: \(event)")
if type(of: event) == PlayerEvent.stateChanged {
switch event.newState {
case .ready:
- self.startTimer()
- if self.isBuffering {
- self.isBuffering = false
- self.sendLiveEvent(theBufferTime: self.calculateBuffer(isBuffering: false))
+ strongSelf.startTimer()
+ if strongSelf.isBuffering {
+ strongSelf.isBuffering = false
+ strongSelf.sendLiveEvent(theBufferTime: strongSelf.calculateBuffer(isBuffering: false))
}
case .buffering:
- self.isBuffering = true
- self.bufferStartTime = Date().timeIntervalSince1970.toInt32()
+ strongSelf.isBuffering = true
+ strongSelf.bufferStartTime = Date().timeIntervalSince1970.toInt32()
default: break
}
}
@@ -134,7 +138,6 @@ public class KalturaLiveStatsPlugin: BaseAnalyticsPlugin {
}
self.timer = Timer.scheduledTimer(timeInterval: TimeInterval(self.interval), target: self, selector: #selector(KalturaLiveStatsPlugin.timerHit), userInfo: nil, repeats: true)
-
}
@objc private func timerHit() {
@@ -176,7 +179,7 @@ public class KalturaLiveStatsPlugin: BaseAnalyticsPlugin {
private func sendLiveEvent(theBufferTime: Int32) {
PKLog.debug("sendLiveEvent - Buffer Time: \(bufferTime)")
- guard let mediaEntry = self.player.mediaEntry else { return }
+ guard let mediaEntry = self.player?.mediaEntry else { return }
var sessionId = ""
var baseUrl = "https://stats.kaltura.com/api_v3/index.php"
diff --git a/Plugins/KalturaStats/KalturaStatsPlugin.swift b/Plugins/KalturaStats/KalturaStatsPlugin.swift
index 3cbe9abc..afef85ae 100644
--- a/Plugins/KalturaStats/KalturaStatsPlugin.swift
+++ b/Plugins/KalturaStats/KalturaStatsPlugin.swift
@@ -97,65 +97,66 @@ public class KalturaStatsPlugin: BaseAnalyticsPlugin {
switch event {
case let e where e.self == PlayerEvent.canPlay:
- self.messageBus.addObserver(self, events: [e.self], block: { [unowned self] (event) in
+ self.messageBus?.addObserver(self, events: [e.self], block: { [weak self] (event) in
+ guard let strongSelf = self else { return }
PKLog.debug("canPlay event: \(event)")
- self.sendMediaLoaded()
+ strongSelf.sendMediaLoaded()
})
case let e where e.self == PlayerEvent.ended || e.self == PlayerEvent.pause || e.self == PlayerEvent.seeking:
- self.messageBus.addObserver(self, events: [e.self], block: { (event) in
+ self.messageBus?.addObserver(self, events: [e.self], block: { [weak self] (event) in
PKLog.debug("\(e.self) event: \(event)")
})
case let e where e.self == PlayerEvent.seeked:
- self.messageBus.addObserver(self, events: [e.self], block: { [unowned self] (event) in
+ self.messageBus?.addObserver(self, events: [e.self], block: { [weak self] (event) in
+ guard let strongSelf = self, let player = self?.player else { return }
PKLog.debug("seeked event: \(event)")
- self.hasSeeked = true
- self.seekPercent = Float(self.player.currentTime) / Float(self.player.duration)
- self.sendAnalyticsEvent(action: .SEEK)
+ strongSelf.hasSeeked = true
+ strongSelf.seekPercent = Float(player.currentTime) / Float(player.duration)
+ strongSelf.sendAnalyticsEvent(action: .SEEK)
})
case let e where e.self == PlayerEvent.playing:
- self.messageBus.addObserver(self, events: [e.self], block: { [unowned self] (event) in
+ self.messageBus?.addObserver(self, events: [e.self], block: { [weak self] (event) in
+ guard let strongSelf = self else { return }
PKLog.debug("play event: \(event)")
- if self.isFirstPlay {
- self.sendAnalyticsEvent(action: .PLAY)
- self.isFirstPlay = false
+ if strongSelf.isFirstPlay {
+ strongSelf.sendAnalyticsEvent(action: .PLAY)
+ strongSelf.isFirstPlay = false
}
})
case let e where e.self == PlayerEvent.error:
- self.messageBus.addObserver(self, events: [e.self], block: { [unowned self] (event) in
+ self.messageBus?.addObserver(self, events: [e.self], block: { [weak self] (event) in
+ guard let strongSelf = self else { return }
PKLog.debug("error event: \(event)")
- self.sendAnalyticsEvent(action: .ERROR)
+ strongSelf.sendAnalyticsEvent(action: .ERROR)
})
case let e where e.self == PlayerEvent.stateChanged:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("state changed event: \(event)")
if let stateChanged = event as? PlayerEvent.StateChanged {
switch stateChanged.newState {
case .idle:
- self.sendWidgetLoaded()
- break
+ strongSelf.sendWidgetLoaded()
case .loading:
- self.sendWidgetLoaded()
- if self.isBuffering {
- self.isBuffering = false
- self.sendAnalyticsEvent(action: .BUFFER_END)
+ strongSelf.sendWidgetLoaded()
+ if strongSelf.isBuffering {
+ strongSelf.isBuffering = false
+ strongSelf.sendAnalyticsEvent(action: .BUFFER_END)
}
- break
case .ready:
- if self.isBuffering {
- self.isBuffering = false
- self.sendAnalyticsEvent(action: .BUFFER_END)
+ if strongSelf.isBuffering {
+ strongSelf.isBuffering = false
+ strongSelf.sendAnalyticsEvent(action: .BUFFER_END)
}
- if !self.intervalOn {
- self.intervalOn = true
- self.createTimer()
+ if !strongSelf.intervalOn {
+ strongSelf.intervalOn = true
+ strongSelf.createTimer()
}
- self.sendMediaLoaded()
- break
+ strongSelf.sendMediaLoaded()
case .buffering:
- self.sendWidgetLoaded()
- self.isBuffering = true
- self.sendAnalyticsEvent(action: .BUFFER_START)
- break
+ strongSelf.sendWidgetLoaded()
+ strongSelf.isBuffering = true
+ strongSelf.sendAnalyticsEvent(action: .BUFFER_START)
case .error: break
case .unknown: break
}
@@ -223,7 +224,8 @@ public class KalturaStatsPlugin: BaseAnalyticsPlugin {
}
@objc private func timerHit() {
- let progress = Float(self.player.currentTime) / Float(self.player.duration)
+ guard let player = self.player else { return }
+ let progress = Float(player.currentTime) / Float(player.duration)
PKLog.debug("Progress is \(progress)")
if progress >= 0.25 && !playReached25 && seekPercent <= 0.25 {
@@ -239,7 +241,6 @@ public class KalturaStatsPlugin: BaseAnalyticsPlugin {
playReached100 = true
sendAnalyticsEvent(action: .PLAY_REACHED_100)
}
-
}
private func startTimer() {
@@ -260,7 +261,7 @@ public class KalturaStatsPlugin: BaseAnalyticsPlugin {
}
private func sendAnalyticsEvent(action: KStatsEventType) {
-
+ guard let player = self.player else { return }
PKLog.debug("Action: \(action)")
var sessionId = ""
@@ -284,7 +285,7 @@ public class KalturaStatsPlugin: BaseAnalyticsPlugin {
parterId = String(pId)
}
- guard let mediaEntry = self.player.mediaEntry else {
+ guard let mediaEntry = player.mediaEntry else {
PKLog.error("send analytics failed due to nil mediaEntry")
return
}
@@ -293,9 +294,9 @@ public class KalturaStatsPlugin: BaseAnalyticsPlugin {
partnerId: parterId,
eventType: action.rawValue,
clientVer: PlayKitManager.clientTag,
- duration: Float(self.player.duration),
+ duration: Float(player.duration),
sessionId: sessionId,
- position: self.player.currentTime.toInt32(),
+ position: player.currentTime.toInt32(),
uiConfId: confId,
entryId: mediaEntry.id,
widgetId: "_\(parterId)",
diff --git a/Plugins/Phoenix/BaseOTTAnalyticsPlugin.swift b/Plugins/Phoenix/BaseOTTAnalyticsPlugin.swift
index 84cf23c3..b83bf1ff 100644
--- a/Plugins/Phoenix/BaseOTTAnalyticsPlugin.swift
+++ b/Plugins/Phoenix/BaseOTTAnalyticsPlugin.swift
@@ -72,49 +72,53 @@ public class BaseOTTAnalyticsPlugin: BaseAnalyticsPlugin, OTTAnalyticsPluginProt
switch event {
case let e where e.self == PlayerEvent.ended:
- self.messageBus.addObserver(self, events: [e.self], block: { event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("ended event: \(event)")
- self.stopTimer()
- self.sendAnalyticsEvent(ofType: .finish)
- })
+ strongSelf.stopTimer()
+ strongSelf.sendAnalyticsEvent(ofType: .finish)
+ }
case let e where e.self == PlayerEvent.error:
- self.messageBus.addObserver(self, events: [e.self], block: { event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("error event: \(event)")
- self.sendAnalyticsEvent(ofType: .error)
- })
+ strongSelf.sendAnalyticsEvent(ofType: .error)
+ }
case let e where e.self == PlayerEvent.pause:
- self.messageBus.addObserver(self, events: [e.self], block: { event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("pause event: \(event)")
// invalidate timer when receiving pause event only after first play
// and set intervalOn to false in order to start timer again on play event.
- if !self.isFirstPlay {
- self.stopTimer()
- self.intervalOn = false
+ if !strongSelf.isFirstPlay {
+ strongSelf.stopTimer()
+ strongSelf.intervalOn = false
}
-
- self.sendAnalyticsEvent(ofType: .pause)
- })
+ strongSelf.sendAnalyticsEvent(ofType: .pause)
+ }
case let e where e.self == PlayerEvent.loadedMetadata:
- self.messageBus.addObserver(self, events: [e.self], block: { event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("loadedMetadata event: \(event)")
- self.sendAnalyticsEvent(ofType: .load)
- })
+ strongSelf.sendAnalyticsEvent(ofType: .load)
+ }
case let e where e.self == PlayerEvent.playing:
- self.messageBus.addObserver(self, events: [e.self], block: { event in
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
PKLog.debug("play event: \(event)")
- if !self.intervalOn {
- self.createTimer()
- self.intervalOn = true
+ if !strongSelf.intervalOn {
+ strongSelf.createTimer()
+ strongSelf.intervalOn = true
}
- if self.isFirstPlay {
- self.isFirstPlay = false
- self.sendAnalyticsEvent(ofType: .first_play);
+ if strongSelf.isFirstPlay {
+ strongSelf.isFirstPlay = false
+ strongSelf.sendAnalyticsEvent(ofType: .first_play);
} else {
- self.sendAnalyticsEvent(ofType: .play);
+ strongSelf.sendAnalyticsEvent(ofType: .play);
}
- })
+ }
default: assertionFailure("plugin \(type(of:self)) all events must be handled")
}
}
@@ -144,7 +148,7 @@ public class BaseOTTAnalyticsPlugin: BaseAnalyticsPlugin, OTTAnalyticsPluginProt
/************************************************************/
func reportConcurrencyEvent() {
- self.messageBus.post(OttEvent.Concurrency())
+ self.messageBus?.post(OttEvent.Concurrency())
}
}
@@ -179,9 +183,10 @@ extension BaseOTTAnalyticsPlugin {
}
fileprivate func sendProgressEvent() {
+ guard let player = self.player else { return }
self.sendAnalyticsEvent(ofType: .hit);
- let progress = Float(self.player.currentTime) / Float(self.player.duration)
+ let progress = Float(player.currentTime) / Float(player.duration)
PKLog.debug("Progress is \(progress)")
if progress > 0.98 {
diff --git a/Plugins/Phoenix/PhoenixAnalyticsPlugin.swift b/Plugins/Phoenix/PhoenixAnalyticsPlugin.swift
index 8e7cf55b..f968ad46 100644
--- a/Plugins/Phoenix/PhoenixAnalyticsPlugin.swift
+++ b/Plugins/Phoenix/PhoenixAnalyticsPlugin.swift
@@ -38,9 +38,14 @@ public class PhoenixAnalyticsPlugin: BaseOTTAnalyticsPlugin {
parterId = pId
}
- guard let mediaEntry = self.player.mediaEntry else {
+ guard let player = self.player else {
+ PKLog.error("send analytics failed due to nil associated player")
+ return nil
+ }
+
+ guard let mediaEntry = player.mediaEntry else {
PKLog.error("send analytics failed due to nil mediaEntry")
- self.messageBus.post(PlayerEvent.PluginError(error: AnalyticsPluginError.missingMediaEntry))
+ self.messageBus?.post(PlayerEvent.PluginError(error: AnalyticsPluginError.missingMediaEntry))
return nil
}
@@ -48,7 +53,7 @@ public class PhoenixAnalyticsPlugin: BaseOTTAnalyticsPlugin {
partnerId: parterId,
ks: ks,
eventType: type.rawValue.uppercased(),
- currentTime: self.player.currentTime.toInt32(),
+ currentTime: player.currentTime.toInt32(),
assetId: mediaEntry.id,
fileId: fileId) else {
return nil
diff --git a/Plugins/Phoenix/TVPAPIAnalyticsPlugin.swift b/Plugins/Phoenix/TVPAPIAnalyticsPlugin.swift
index c5a169f0..d8f72ac4 100644
--- a/Plugins/Phoenix/TVPAPIAnalyticsPlugin.swift
+++ b/Plugins/Phoenix/TVPAPIAnalyticsPlugin.swift
@@ -18,18 +18,20 @@ public class TVPAPIAnalyticsPlugin: BaseOTTAnalyticsPlugin {
/************************************************************/
override func buildRequest(ofType type: OTTAnalyticsEventType) -> Request? {
+ guard let player = self.player else { return nil }
+
var fileId = ""
var baseUrl = ""
guard let initObj = self.config?.params["initObj"] as? [String: Any] else {
PKLog.error("send analytics failed due to no initObj data")
- self.messageBus.post(PlayerEvent.PluginError(error: AnalyticsPluginError.missingInitObject))
+ self.messageBus?.post(PlayerEvent.PluginError(error: AnalyticsPluginError.missingInitObject))
return nil
}
- guard let mediaEntry = self.player.mediaEntry else {
+ guard let mediaEntry = player.mediaEntry else {
PKLog.error("send analytics failed due to nil mediaEntry")
- self.messageBus.post(PlayerEvent.PluginError(error: AnalyticsPluginError.missingMediaEntry))
+ self.messageBus?.post(PlayerEvent.PluginError(error: AnalyticsPluginError.missingMediaEntry))
return nil
}
@@ -47,17 +49,17 @@ public class TVPAPIAnalyticsPlugin: BaseOTTAnalyticsPlugin {
guard let requestBuilder: RequestBuilder = MediaMarkService.sendTVPAPIEVent(baseURL: baseUrl,
initObj: initObj,
eventType: type.rawValue,
- currentTime: self.player.currentTime.toInt32(),
+ currentTime: player.currentTime.toInt32(),
assetId: mediaEntry.id,
fileId: fileId) else {
return nil
}
-
+ requestBuilder.set(responseSerializer: StringSerializer())
requestBuilder.set { (response: Response) in
PKLog.trace("Response: \(response)")
if response.statusCode == 0 {
PKLog.trace("\(response.data)")
- guard let data = response.data as? String, data.lowercased() == "concurrent" else { return }
+ guard let data = response.data as? String, data.lowercased() == "\"concurrent\"" else { return }
self.reportConcurrencyEvent()
}
}
diff --git a/Plugins/Youbora/YouboraPlugin.swift b/Plugins/Youbora/YouboraPlugin.swift
index 0560e3a1..2c6c2d62 100644
--- a/Plugins/Youbora/YouboraPlugin.swift
+++ b/Plugins/Youbora/YouboraPlugin.swift
@@ -75,8 +75,8 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
public override func onLoad(mediaConfig: MediaConfig) {
super.onLoad(mediaConfig: mediaConfig)
self.setupYouboraManager() { succeeded in
- if succeeded {
- self.startMonitoring(player: self.player)
+ if let player = self.player, succeeded {
+ self.startMonitoring(player: player)
}
}
}
@@ -117,66 +117,75 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
switch event {
case let e where e.self == PlayerEvent.canPlay:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
- self.postEventLogWithMessage(message: "canPlay event: \(event)")
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ strongSelf.postEventLogWithMessage(message: "canPlay event: \(event)")
}
case let e where e.self == PlayerEvent.play:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
youboraManager.playHandler()
- self.postEventLogWithMessage(message: "play event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "play event: \(event)")
}
case let e where e.self == PlayerEvent.pause:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
youboraManager.pauseHandler()
- self.postEventLogWithMessage(message: "pause event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "pause event: \(event)")
}
case let e where e.self == PlayerEvent.playing:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
- self.postEventLogWithMessage(message: "playing event: \(event)")
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ strongSelf.postEventLogWithMessage(message: "playing event: \(event)")
- guard let youboraManager = self.youboraManager else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
- if self.isFirstPlay {
+ if strongSelf.isFirstPlay {
youboraManager.joinHandler()
youboraManager.bufferedHandler()
- self.isFirstPlay = false
+ strongSelf.isFirstPlay = false
} else {
youboraManager.resumeHandler()
}
}
case let e where e.self == PlayerEvent.seeking:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] event in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
youboraManager.seekingHandler()
- self.postEventLogWithMessage(message: "seeking event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "seeking event: \(event)")
}
case let e where e.self == PlayerEvent.seeked:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] (event) in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
youboraManager.seekedHandler()
- self.postEventLogWithMessage(message: "seeked event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "seeked event: \(event)")
}
case let e where e.self == PlayerEvent.ended:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] (event) in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
youboraManager.endedHandler()
- self.postEventLogWithMessage(message: "ended event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "ended event: \(event)")
}
case let e where e.self == PlayerEvent.playbackParamsUpdated:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] (event) in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
youboraManager.currentBitrate = event.currentBitrate?.doubleValue
- self.postEventLogWithMessage(message: "playbackParamsUpdated event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "playbackParamsUpdated event: \(event)")
}
case let e where e.self == PlayerEvent.stateChanged:
- self.messageBus.addObserver(self, events: [e.self]) { [unowned self] (event) in
- guard let youboraManager = self.youboraManager else { return }
+ self.messageBus?.addObserver(self, events: [e.self]) { [weak self] event in
+ guard let strongSelf = self else { return }
+ guard let youboraManager = strongSelf.youboraManager else { return }
switch event.newState {
case .buffering:
youboraManager.bufferingHandler()
- self.postEventLogWithMessage(message: "Buffering event: ֿ\(event)")
+ strongSelf.postEventLogWithMessage(message: "Buffering event: ֿ\(event)")
break
default: break
}
@@ -184,7 +193,7 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
switch event.oldState {
case .buffering:
youboraManager.bufferedHandler()
- self.postEventLogWithMessage(message: "Buffered event: \(event)")
+ strongSelf.postEventLogWithMessage(message: "Buffered event: \(event)")
break
default: break
}
@@ -194,8 +203,8 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
}
PKLog.debug("register ads events")
- self.messageBus.addObserver(self, events: AdEvent.allEventTypes) { [unowned self] (event) in
- self.postEventLogWithMessage(message: "Ads event event: \(event)")
+ self.messageBus?.addObserver(self, events: AdEvent.allEventTypes) { [weak self] event in
+ self?.postEventLogWithMessage(message: "Ads event event: \(event)")
}
}
@@ -204,17 +213,17 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
/************************************************************/
private func setupYouboraManager(completionHandler: ((_ succeeded: Bool) -> Void)? = nil) {
-
- guard let mediaEntry = self.player.mediaEntry else {
+ guard let player = self.player else { return }
+ guard let mediaEntry = player.mediaEntry else {
PKLog.error("missing MediaEntry, could not setup youbora manager")
- self.messageBus.post(PlayerEvent.PluginError(nsError: YouboraPluginError.failedToSetupYouboraManager.asNSError))
+ self.messageBus?.post(PlayerEvent.PluginError(nsError: YouboraPluginError.failedToSetupYouboraManager.asNSError))
completionHandler?(false)
return
}
guard let config = self.config else {
PKLog.error("config params doesn't exist, could not setup youbora manager")
- self.messageBus.post(PlayerEvent.PluginError(nsError: YouboraPluginError.failedToSetupYouboraManager.asNSError))
+ self.messageBus?.post(PlayerEvent.PluginError(nsError: YouboraPluginError.failedToSetupYouboraManager.asNSError))
completionHandler?(false)
return
}
@@ -225,7 +234,7 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
if var media = config.params["media"] as? [String: Any] {
media["resource"] = mediaEntry.id
media["title"] = mediaEntry.id
- media["duration"] = self.player.duration
+ media["duration"] = player.duration
config.params["media"] = media
} else {
config.params["media"] = [
@@ -260,7 +269,7 @@ public class YouboraPlugin: BaseAnalyticsPlugin {
private func postEventLogWithMessage(message: String) {
PKLog.debug(message)
let eventLog = YouboraEvent.YouboraReportSent(message: message as NSString)
- self.messageBus.post(eventLog)
+ self.messageBus?.post(eventLog)
}
}