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

Media public api and tracker #4

Merged
merged 19 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from 4 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
57 changes: 48 additions & 9 deletions AEPMedia/Sources/Media+PublicAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,23 @@ import AEPServices
private static let LOG_TAG = "Media"

@objc(createTracker)
static func createTracker() -> MediaTracker {
//TODO
return MediaTracker()
static func createTracker() -> MediaTracker? {
return createTrackerWith(config: nil)
}

@objc(createTrackerWithConfig:)
static func createTrackerWith(config: [String: Any]?) -> MediaTracker {
//TODO
return MediaTracker()
static func createTrackerWith(config: [String: Any]?) -> MediaTracker? {
return MediaTracker.create(dispatch: MobileCore.dispatch(event:), config: config)
}

@objc(createMediaObjectWith:id:length:streamType:mediaType:)
static func createMediaObjectWith(name: String, id: String, length: Double, streamType: String, mediaType: (String)) -> [String: Any]? {
//TODO
return [:]
static func createMediaObjectWith(name: String, id: String, length: Double, streamType: String, mediaType: MediaType) -> [String: Any]? {
guard let mediaInfo = MediaInfo.create(id: id, name: name, streamType: streamType, mediaType: mediaType, length: length) else {
Log.error(label: LOG_TAG, "\(#function) Error creating media Object")
return nil
}

return mediaInfo.toMap()
}

@objc(createAdBreakObjectWith:position:startTime:)
Expand Down Expand Up @@ -64,5 +66,42 @@ import AEPServices
//TODO
return [:]
}
}

@objc public enum AEPMediaEvent: Int {
case AEPMediaEventAdBreakStart
case AEPMediaEventAdBreakComplete
case AEPMediaEventAdStart
case AEPMediaEventAdComplete
case AEPMediaEventAdSkip
case AEPMediaEventChapterStart
case AEPMediaEventChapterComplete
case AEPMediaEventChapterSkip
case AEPMediaEventSeekStart
case AEPMediaEventSeekComplete
case AEPMediaEventBufferStart
case AEPMediaEventBufferComplete
case AEPMediaEventBitrateChange
case AEPMediaEventStateStart
case AEPMediaEventStateEnd

func stringValue() -> String {
switch self {
case .AEPMediaEventAdBreakStart: return MediaConstants.EventName.ADBREAK_START
case .AEPMediaEventAdBreakComplete: return MediaConstants.EventName.ADBREAK_COMPLETE
case .AEPMediaEventAdStart: return MediaConstants.EventName.AD_START
case .AEPMediaEventAdComplete: return MediaConstants.EventName.AD_COMPLETE
case .AEPMediaEventAdSkip: return MediaConstants.EventName.AD_SKIP
case .AEPMediaEventChapterStart: return MediaConstants.EventName.CHAPTER_START
case .AEPMediaEventChapterComplete: return MediaConstants.EventName.CHAPTER_COMPLETE
case .AEPMediaEventChapterSkip: return MediaConstants.EventName.CHAPTER_SKIP
case .AEPMediaEventSeekStart: return MediaConstants.EventName.SEEK_START
case .AEPMediaEventSeekComplete: return MediaConstants.EventName.SEEK_COMPLETE
case .AEPMediaEventBufferStart: return MediaConstants.EventName.BUFFER_START
case .AEPMediaEventBufferComplete: return MediaConstants.EventName.BUFFER_COMPLETE
case .AEPMediaEventBitrateChange: return MediaConstants.EventName.BITRATE_CHANGE
case .AEPMediaEventStateStart: return MediaConstants.EventName.STATE_START
case .AEPMediaEventStateEnd: return MediaConstants.EventName.STATE_END
}
}
}
19 changes: 19 additions & 0 deletions AEPMedia/Sources/MediaConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ enum MediaConstants {
static let ANALYTICS_VISITOR_ID = "aid"
}

enum Media {
static let EVENT_TYPE = "com.adobe.eventtype.media"
static let EVENT_SOURCE_TRACKER_REQUEST = "com.adobe.eventsource.media.requesttracker"
static let EVENT_SOURCE_TRACKER_RESPONSE = "com.adobe.eventsource.media.responsetracker"
static let EVENT_SOURCE_TRACK_MEDIA = "com.adobe.eventsource.media.trackmedia"
}

enum EventName {
static let SESSION_START = "sessionstart"
static let SESSION_END = "sessionend"
Expand Down Expand Up @@ -154,4 +161,16 @@ enum MediaConstants {
static let SITE_ID = "a.media.ad.site"
static let CREATIVE_URL = "a.media.ad.creativeURL"
}

enum Tracker {
static let ID = "trackerid"
static let SESSION_ID = "sessionid"
static let CREATED = "trackercreated"
static let EVENT_NAME = "event.name"
static let EVENT_PARAM = "event.param"
static let EVENT_METADATA = "event.metadata"
static let EVENT_TIMESTAMP = "event.timestamp"
static let EVENT_INTERNAL = "event.internal"
static let PLAYHEAD = "time.playhead"
}
}
209 changes: 209 additions & 0 deletions AEPMedia/Sources/MediaObject.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*
Copyright 2021 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

import AEPServices

@objc public enum MediaType: Int {
addb marked this conversation as resolved.
Show resolved Hide resolved
case Audio
case Video

func stringValue() -> String {
switch self {
case .Audio: return "audio"
case .Video: return "video"
}
}
}

class MediaInfo: Equatable {
static let LOG_TAG = "MediaInfo"
static let MEDIA_TYPE_AUDIO = "audio"
addb marked this conversation as resolved.
Show resolved Hide resolved
static let MEDIA_TYPE_VIDEO = "video"
static let DEFAULT_PREROLL_WAITING_TIME_IN_MS: Double = 250.0 //250 milliseconds
private var id: String
addb marked this conversation as resolved.
Show resolved Hide resolved
private var name: String
private var streamType: String
private var mediaType: MediaType
private var length: Double
private var resumed: Bool
private var prerollWaitingTime: TimeInterval
private var granularAdTracking: Bool

static func == (lhs: MediaInfo, rhs: MediaInfo) -> Bool {
return lhs.id == rhs.id &&
lhs.name == rhs.name &&
lhs.streamType == rhs.streamType &&
lhs.mediaType == rhs.mediaType &&
lhs.length == rhs.length &&
lhs.resumed == rhs.resumed &&
lhs.prerollWaitingTime == rhs.prerollWaitingTime &&
lhs.granularAdTracking == rhs.granularAdTracking
}

private init(id: String, name: String, streamType: String, mediaType: MediaType, length: Double, resumed: Bool, prerollWaitingTime: TimeInterval, granularAdTracking: Bool) {
self.id = id
self.name = name
self.streamType = streamType
self.mediaType = mediaType
self.length = length
self.resumed = resumed
self.prerollWaitingTime = prerollWaitingTime
self.granularAdTracking = granularAdTracking
}

static func createFrom(info: [String: Any]?) -> MediaInfo? {
addb marked this conversation as resolved.
Show resolved Hide resolved
guard info != nil else {
return nil
}

guard let id = info?[MediaConstants.MediaInfo.ID] as? String else {
Log.debug(label: LOG_TAG, "\(#function) - Error parsing MediaInfo, invalid id")
return nil
}

guard let name = info?[MediaConstants.MediaInfo.NAME] as? String else {
Log.debug(label: LOG_TAG, "\(#function) - Error parsing MediaInfo, invalid name")
return nil
}

guard let streamType = info?[MediaConstants.MediaInfo.STREAM_TYPE] as? String else {
Log.debug(label: LOG_TAG, "\(#function) - Error parsing MediaInfo, invalid stream type. Sample values -> {\"VOD\", \"LIVE\" ...}")
return nil
}

guard let mediaTypeString = info?[MediaConstants.MediaInfo.MEDIA_TYPE] as? String else {
Log.debug(label: LOG_TAG, "\(#function) - Error parsing MediaInfo, invalid media type. Valid values -> {\"video\", \"audio\"}")
return nil
}

var mediaType: MediaType
if mediaTypeString == MediaType.Audio.stringValue() {
mediaType = MediaType.Audio
} else if mediaTypeString == MediaType.Video.stringValue() {
mediaType = MediaType.Video
} else {
Log.debug(label: LOG_TAG, "\(#function) - Error parsing MediaInfo, invalid media type")
return nil
}

guard let length = info?[MediaConstants.MediaInfo.LENGTH] as? Double else {
Log.debug(label: LOG_TAG, "\(#function) - Error parsing MediaInfo, invalid length")
return nil
}

let resumed = info?[MediaConstants.MediaInfo.RESUMED] as? Bool ?? false

let prerollWaitTimeVal: Double = info?[MediaConstants.MediaInfo.PREROLL_TRACKING_WAITING_TIME] as? Double ?? DEFAULT_PREROLL_WAITING_TIME_IN_MS

let prerollWaitingTime: TimeInterval = TimeInterval(prerollWaitTimeVal)

let granularAdTracking = info?[MediaConstants.MediaInfo.GRANULAR_AD_TRACKING] as? Bool ?? false

let mediaInfo = create(id: id, name: name, streamType: streamType, mediaType: mediaType, length: length, resumed: resumed, prerollWaitingTime: prerollWaitingTime, granularAdTracking: granularAdTracking)

return mediaInfo
}

static func create(id: String, name: String, streamType: String, mediaType: MediaType = MediaType.Video, length: Double, resumed: Bool = false, prerollWaitingTime: TimeInterval = DEFAULT_PREROLL_WAITING_TIME_IN_MS, granularAdTracking: Bool = false) -> MediaInfo? {

guard !id.isEmpty else {
addb marked this conversation as resolved.
Show resolved Hide resolved
Log.debug(label: LOG_TAG, "\(#function) - Error creating MediaInfo, id must not be Empty")
addb marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

guard !name.isEmpty else {
Log.debug(label: LOG_TAG, "\(#function) - Error creating MediaInfo, name must not be Empty")
return nil
}

guard !streamType.isEmpty else {
Log.debug(label: LOG_TAG, "\(#function) - Error creating MediaInfo, stream type must not be Empty")
return nil
}

guard length > 0 else {
Log.debug(label: LOG_TAG, "\(#function) - Error creating MediaInfo, length must not be less than zero")
return nil
}

let prerollWaitingTimeInSeconds = prerollWaitingTime/1000 //convert to seconds

let mediaInfo = MediaInfo.init(id: id, name: name, streamType: streamType, mediaType: mediaType, length: length, resumed: resumed, prerollWaitingTime: prerollWaitingTimeInSeconds, granularAdTracking: granularAdTracking)

return mediaInfo
}

func toMap() -> [String: Any] {
var mediaInfoMap: [String: Any] = [:]
mediaInfoMap[MediaConstants.MediaInfo.ID] = getId()
mediaInfoMap[MediaConstants.MediaInfo.NAME] = getName()
mediaInfoMap[MediaConstants.MediaInfo.LENGTH] = getLength()
mediaInfoMap[MediaConstants.MediaInfo.STREAM_TYPE] = getStreamType()
mediaInfoMap[MediaConstants.MediaInfo.MEDIA_TYPE] = getMediaType().stringValue()
mediaInfoMap[MediaConstants.MediaInfo.RESUMED] = isResumed()
mediaInfoMap[MediaConstants.MediaInfo.PREROLL_TRACKING_WAITING_TIME] = getPrerollWaitingTime()
mediaInfoMap[MediaConstants.MediaInfo.GRANULAR_AD_TRACKING] = isGranularAdTrackingEnabled()

return mediaInfoMap
}

func getId() -> String {
return id
}

func getName() -> String {
return name
}

func getStreamType() -> String {
return streamType
}

func getMediaType() -> MediaType {
return mediaType
}

func getLength() -> Double {
return length
}

func isResumed() -> Bool {
return resumed
}

func getPrerollWaitingTime() -> TimeInterval {
return prerollWaitingTime
}

func isGranularAdTrackingEnabled() -> Bool {
return granularAdTracking
}
}

class AdBreakInfo {

}

class AdInfo {

}

class ChapterInfo {

}

class QoEInfo {

}

class StateInfo {

}
Loading