@takeoffmedia/react-native-penthera 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +203 -0
- package/android/build.gradle +105 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +51 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/AssetQueueObserver.kt +148 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/EventEmitter.kt +53 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/PentheraModule.kt +104 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/PentheraPackage.kt +16 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/YourPlayerActivity.kt +14 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/DemoLicenseManager.kt +50 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/OfflineVideoEngine.kt +227 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/PentheraContentProvider.kt +17 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/ServiceStarter.kt +65 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/data/Drm.kt +6 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/data/Item.kt +34 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/notification/NotificationFactory.kt +279 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/notification/NotificationType.kt +10 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/notification/ServiceForegroundNotificationProvider.kt +98 -0
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/util/Util.kt +22 -0
- package/android/src/main/res/drawable/ic_launcher_background.xml +170 -0
- package/android/src/main/res/drawable/small_logo.png +0 -0
- package/android/src/main/res/values/colors.xml +6 -0
- package/android/src/main/res/values/strings.xml +61 -0
- package/android/src/main/res/values/styles.xml +10 -0
- package/android/src/main/res/xml/network_security_config.xml +9 -0
- package/ios/Catalog.swift +30 -0
- package/ios/EventEmitter.swift +53 -0
- package/ios/Penthera-Bridging-Header.h +3 -0
- package/ios/Penthera.m +40 -0
- package/ios/Penthera.swift +384 -0
- package/ios/Penthera.xcodeproj/project.pbxproj +283 -0
- package/ios/Util.swift +16 -0
- package/ios/drm/FairPlayDrmSetup.swift +107 -0
- package/ios/drm/FairPlayLicenseProcessingDelegate.swift +42 -0
- package/lib/commonjs/data/data.json +58 -0
- package/lib/commonjs/hooks/index.js +13 -0
- package/lib/commonjs/hooks/index.js.map +1 -0
- package/lib/commonjs/hooks/usePenthera.js +146 -0
- package/lib/commonjs/hooks/usePenthera.js.map +1 -0
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/interface/HomeTypes.js +6 -0
- package/lib/commonjs/interface/HomeTypes.js.map +1 -0
- package/lib/commonjs/interface/Idata.js +2 -0
- package/lib/commonjs/interface/Idata.js.map +1 -0
- package/lib/commonjs/interface/PentheraTypes.js +2 -0
- package/lib/commonjs/interface/PentheraTypes.js.map +1 -0
- package/lib/commonjs/nativeModules/index.js +48 -0
- package/lib/commonjs/nativeModules/index.js.map +1 -0
- package/lib/commonjs/utils/Penthera.js +19 -0
- package/lib/commonjs/utils/Penthera.js.map +1 -0
- package/lib/module/data/data.json +58 -0
- package/lib/module/hooks/index.js +2 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/usePenthera.js +139 -0
- package/lib/module/hooks/usePenthera.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/interface/HomeTypes.js +2 -0
- package/lib/module/interface/HomeTypes.js.map +1 -0
- package/lib/module/interface/Idata.js +2 -0
- package/lib/module/interface/Idata.js.map +1 -0
- package/lib/module/interface/PentheraTypes.js +2 -0
- package/lib/module/interface/PentheraTypes.js.map +1 -0
- package/lib/module/nativeModules/index.js +35 -0
- package/lib/module/nativeModules/index.js.map +1 -0
- package/lib/module/utils/Penthera.js +12 -0
- package/lib/module/utils/Penthera.js.map +1 -0
- package/lib/typescript/hooks/index.d.ts +2 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -0
- package/lib/typescript/hooks/usePenthera.d.ts +19 -0
- package/lib/typescript/hooks/usePenthera.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +4 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/interface/HomeTypes.d.ts +15 -0
- package/lib/typescript/interface/HomeTypes.d.ts.map +1 -0
- package/lib/typescript/interface/Idata.d.ts +30 -0
- package/lib/typescript/interface/Idata.d.ts.map +1 -0
- package/lib/typescript/interface/PentheraTypes.d.ts +104 -0
- package/lib/typescript/interface/PentheraTypes.d.ts.map +1 -0
- package/lib/typescript/nativeModules/index.d.ts +9 -0
- package/lib/typescript/nativeModules/index.d.ts.map +1 -0
- package/lib/typescript/utils/Penthera.d.ts +11 -0
- package/lib/typescript/utils/Penthera.d.ts.map +1 -0
- package/package.json +166 -0
- package/src/data/data.json +58 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/usePenthera.ts +160 -0
- package/src/index.tsx +5 -0
- package/src/interface/HomeTypes.ts +16 -0
- package/src/interface/Idata.ts +34 -0
- package/src/interface/PentheraTypes.ts +104 -0
- package/src/nativeModules/index.ts +58 -0
- package/src/utils/Penthera.ts +10 -0
- package/takeoffmedia-react-native-penthera.podspec +36 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
struct Catalog: Codable {
|
|
2
|
+
var id: String = ""
|
|
3
|
+
var url: String = ""
|
|
4
|
+
var thumbnail: String = ""
|
|
5
|
+
|
|
6
|
+
var showId: String = ""
|
|
7
|
+
var showTitle: String = ""
|
|
8
|
+
|
|
9
|
+
var title: String = ""
|
|
10
|
+
var description: String = ""
|
|
11
|
+
var rate: String = ""
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
struct OfflineCatalog: Codable {
|
|
15
|
+
var id: String = ""
|
|
16
|
+
var thumbnail: String = ""
|
|
17
|
+
var wallpaper: String = ""
|
|
18
|
+
var subtitle: String = ""
|
|
19
|
+
var url: String = ""
|
|
20
|
+
var certificateUrl: String = ""
|
|
21
|
+
var licenseUrl: String = ""
|
|
22
|
+
var isCompleted: Bool
|
|
23
|
+
var isPaused: Bool
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
struct Event: Codable {
|
|
27
|
+
var code: String = ""
|
|
28
|
+
var assetId: String = ""
|
|
29
|
+
var body: String = ""
|
|
30
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
struct PentheraEvent {
|
|
2
|
+
static let DID_START_DOWNLOADING = "DID_START_DOWNLOADING"
|
|
3
|
+
static let PROGRESS_UPDATED = "PROGRESS_UPDATED"
|
|
4
|
+
static let DOWNLOAD_COMPLETE = "DOWNLOAD_COMPLETE"
|
|
5
|
+
static let CONFIG_ASSET_FAILED = "CONFIG_ASSET_FAILED"
|
|
6
|
+
static let ASSET_RESUME_DOWNLOAD_UPDATED = "ASSET_RESUME_DOWNLOAD_UPDATED"
|
|
7
|
+
static let ASSET_DELETED = "ASSET_DELETED"
|
|
8
|
+
static let FAIR_PLAY_FAILED_INIT_DELEGATE = "FAIR_PLAY_FAILED_INIT_DELEGATE"
|
|
9
|
+
static let FAIR_PLAY_EXTRACT_CID = "FAIR_PLAY_EXTRACT_CID"
|
|
10
|
+
static let FAIR_PLAY_PREPARE_SPC = "FAIR_PLAY_PREPARE_SPC"
|
|
11
|
+
static let FAIR_PLAY_EXTRACT_CKC = "FAIR_PLAY_EXTRACT_CKC"
|
|
12
|
+
static let FAIR_PLAY_LICENSE_DELEGATE_ERROR = "FAIR_PLAY_LICENSE_DELEGATE_ERROR"
|
|
13
|
+
static let PENDING_ASSET_FOUND = "PENDING_ASSET_FOUND"
|
|
14
|
+
static let ERROR_DOWNLOAD = "ERROR_DOWNLOAD"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class EventEmitter {
|
|
18
|
+
|
|
19
|
+
/// Shared Instance.
|
|
20
|
+
public static var sharedInstance = EventEmitter()
|
|
21
|
+
|
|
22
|
+
// ReactNativeEventEmitter is instantiated by React Native with the bridge.
|
|
23
|
+
private var eventEmitter: Penthera!
|
|
24
|
+
|
|
25
|
+
private init() {}
|
|
26
|
+
|
|
27
|
+
// When React Native instantiates the emitter it is registered here.
|
|
28
|
+
func registerEventEmitter(eventEmitter: Penthera) {
|
|
29
|
+
self.eventEmitter = eventEmitter
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func dispatch(name: String, code: String, assetId: String, body: String) {
|
|
33
|
+
let event = Event(code: code, assetId: assetId, body: body)
|
|
34
|
+
let decoder = JSONEncoder()
|
|
35
|
+
do {
|
|
36
|
+
let data = try decoder.encode(event)
|
|
37
|
+
let json = String(data: data, encoding: .utf8)!
|
|
38
|
+
eventEmitter.sendEvent(withName: name, body: json)
|
|
39
|
+
} catch {
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// All Events which must be support by React Native.
|
|
45
|
+
lazy var allEvents: [String] = {
|
|
46
|
+
var allEventNames: [String] = ["penthera"]
|
|
47
|
+
|
|
48
|
+
// Append all events here
|
|
49
|
+
|
|
50
|
+
return allEventNames
|
|
51
|
+
}()
|
|
52
|
+
|
|
53
|
+
}
|
package/ios/Penthera.m
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <VirtuosoClientDownloadEngine/VirtuosoClientDownloadEngine.h>
|
|
3
|
+
#import <React/RCTEventEmitter.h>
|
|
4
|
+
|
|
5
|
+
@interface RCT_EXTERN_MODULE(Penthera, RCTEventEmitter)
|
|
6
|
+
|
|
7
|
+
RCT_EXTERN_METHOD(multiply:(float)a withB:(float)b
|
|
8
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
10
|
+
|
|
11
|
+
RCT_EXTERN_METHOD(initializeSdk:(NSString*)user
|
|
12
|
+
withBackplaneUrl:(NSString*)backplaneUrl
|
|
13
|
+
withPublicKey:(NSString*)publicKey
|
|
14
|
+
withPrivateKey:(NSString*)privateKey
|
|
15
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
16
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
17
|
+
|
|
18
|
+
RCT_EXTERN_METHOD(getDownloads:(NSString*)blank
|
|
19
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
20
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
21
|
+
|
|
22
|
+
RCT_EXTERN_METHOD(download:(NSString*)catalog
|
|
23
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
24
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
25
|
+
|
|
26
|
+
RCT_EXTERN_METHOD(delete:(NSString*)assetID
|
|
27
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
28
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
RCT_EXTERN_METHOD(playAsset:(NSString*)assetID
|
|
32
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
33
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
34
|
+
|
|
35
|
+
+ (BOOL)requiresMainQueueSetup
|
|
36
|
+
{
|
|
37
|
+
return NO;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@end
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import VirtuosoClientDownloadEngine
|
|
2
|
+
|
|
3
|
+
@objc(Penthera)
|
|
4
|
+
class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
|
|
5
|
+
var downloadEngineNotifications: VirtuosoDownloadEngineNotificationManager!
|
|
6
|
+
|
|
7
|
+
public override init() {
|
|
8
|
+
super.init()
|
|
9
|
+
EventEmitter.sharedInstance.registerEventEmitter(eventEmitter: self)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@objc(multiply:withB:withResolver:withRejecter:)
|
|
13
|
+
func multiply(a: Float, b: Float, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
14
|
+
resolve(a*b)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@objc(initializeSdk:withBackplaneUrl:withPublicKey:withPrivateKey:withResolver:withRejecter:)
|
|
18
|
+
func initializeSdk(user: String, backplaneUrl: String, publicKey: String, privateKey: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
19
|
+
guard let engineConfig = VirtuosoEngineConfig(
|
|
20
|
+
user: user,
|
|
21
|
+
backplaneUrl: backplaneUrl,
|
|
22
|
+
publicKey: publicKey,
|
|
23
|
+
privateKey: privateKey) else {
|
|
24
|
+
return reject("Penthera", "engine Config", nil)
|
|
25
|
+
}
|
|
26
|
+
self.downloadEngineNotifications = VirtuosoDownloadEngineNotificationManager.init(delegate: self)
|
|
27
|
+
let virtuoso = VirtuosoDownloadEngine.instance()
|
|
28
|
+
virtuoso.startup(engineConfig) { status in
|
|
29
|
+
switch(status) {
|
|
30
|
+
case .vde_EngineStartupSuccess:
|
|
31
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: "Virtuoso Success", assetId: "test", body: "asset")
|
|
32
|
+
resolve("Success")
|
|
33
|
+
case .vde_EngineStartupAlreadyStarted:
|
|
34
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Aready Started")
|
|
35
|
+
resolve("Already Started")
|
|
36
|
+
case .vde_EngineStartupSuccessNoBackplane:
|
|
37
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Backplane")
|
|
38
|
+
resolve("No Backplane")
|
|
39
|
+
case .vde_EngineStartupInvalidOptions:
|
|
40
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Invalid")
|
|
41
|
+
resolve("Invalid Option")
|
|
42
|
+
case .vde_EngineStartupMethodIsDeprecated:
|
|
43
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Method Decraped")
|
|
44
|
+
resolve("Decraped")
|
|
45
|
+
case .vde_EngineStartupInternalException:
|
|
46
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Internal Exception")
|
|
47
|
+
resolve("Internal Exception")
|
|
48
|
+
case .vde_EngineDataMigrationError:
|
|
49
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Migrate Error")
|
|
50
|
+
resolve("Error")
|
|
51
|
+
@unknown default:
|
|
52
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Default")
|
|
53
|
+
resolve("Error Default")
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc(getDownloads:withResolver:withRejecter:)
|
|
59
|
+
func getDownloads(blank: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
60
|
+
let completedAssets = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
|
|
61
|
+
let pendingAssets = VirtuosoAsset.pendingAssets(withAvailabilityFilter: false)
|
|
62
|
+
var offlineCatalogs: [OfflineCatalog] = []
|
|
63
|
+
|
|
64
|
+
for case let va as VirtuosoAsset in completedAssets {
|
|
65
|
+
let thumbnail = va.findAllAncillaries(withTag: "thumbnail").first
|
|
66
|
+
let wallpaper = va.findAllAncillaries(withTag: "wallpaper").first
|
|
67
|
+
let catalog = OfflineCatalog(
|
|
68
|
+
id: va.assetID,
|
|
69
|
+
thumbnail: thumbnail?.localFilePath ?? "",
|
|
70
|
+
wallpaper: wallpaper?.localFilePath ?? "",
|
|
71
|
+
isCompleted: va.isPlayable,
|
|
72
|
+
isPaused: va.isPaused)
|
|
73
|
+
offlineCatalogs.append(catalog)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for case let va as VirtuosoAsset in pendingAssets {
|
|
77
|
+
let catalog = OfflineCatalog(
|
|
78
|
+
id: va.assetID,
|
|
79
|
+
isCompleted: false,
|
|
80
|
+
isPaused: va.isPaused)
|
|
81
|
+
offlineCatalogs.append(catalog)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let decoder = JSONEncoder()
|
|
85
|
+
do {
|
|
86
|
+
let data = try decoder.encode(offlineCatalogs)
|
|
87
|
+
let json = String(data: data, encoding: .utf8)!
|
|
88
|
+
resolve(json)
|
|
89
|
+
} catch {
|
|
90
|
+
reject("penthere", error.localizedDescription, error)
|
|
91
|
+
}
|
|
92
|
+
//resolve(downloadComplete.map{ ($0 as? VirtuosoAsset)?.assetID })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func getDownloadedAsset(assetID: String) -> VirtuosoAsset? {
|
|
96
|
+
print("Entra getDownloadedAsset>>>")
|
|
97
|
+
// assets that have finished downloading
|
|
98
|
+
let completedAssets = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
|
|
99
|
+
guard let asset = completedAssets.filter({ ($0 as! VirtuosoAsset).assetID == assetID }).first as? VirtuosoAsset else {
|
|
100
|
+
return nil
|
|
101
|
+
}
|
|
102
|
+
return asset
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public func downloadEngineDidStartDownloadingAsset(_ asset: VirtuosoAsset) {
|
|
106
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.DID_START_DOWNLOADING, assetId: asset.assetID, body: "")
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public func downloadEngineProgressUpdated(for asset: VirtuosoAsset) {
|
|
110
|
+
let percentage: Float = Float(asset.fractionComplete)/Float(asset.estimatedSize)
|
|
111
|
+
if(percentage.isFinite) {
|
|
112
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.PROGRESS_UPDATED, assetId: asset.assetID, body: "\(Int(asset.fractionComplete*100))")
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public func downloadEngineProgressUpdatedProcessing(for asset: VirtuosoAsset) {
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public func downloadEngineDidFinishDownloadingAsset(_ asset: VirtuosoAsset) {
|
|
121
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.DOWNLOAD_COMPLETE, assetId: asset.assetID, body: "")
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public func downloadEngineDidEncounterError(for asset: VirtuosoAsset, error: Error?, task: URLSessionTask?, data: Data?, statusCode: NSNumber?) {
|
|
125
|
+
asset.delete()
|
|
126
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.ERROR_DOWNLOAD, assetId: asset.assetID, body: error.debugDescription ?? "Error downloading")
|
|
127
|
+
/*EventEmitter.sharedInstance.dispatch(name: "penthera", body: "\(asset.assetID): Engine did encounter error \(error?.localizedDescription ?? "-")")*/
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public func downloadEngineInternalQueueUpdate(asset: VirtuosoAsset) {
|
|
131
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", code: "TEST downloadEngineInternalQueueUpdate", body: "Queue updated", assetId: asset.assetID)
|
|
132
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: "TEST downloadEngineInternalQueueUpdate", assetId: asset.assetID, body: "Queue updated")
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public func downloadEngineStartupComplete(_ succeeded: Bool, asset: VirtuosoAsset) {
|
|
136
|
+
//EventEmitter.sharedInstance.dispatch(name: "penthera", code: "Test downloadEngineStartupComplete", body: "SDK startup complete", assetId: asset.assetID)
|
|
137
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: "TEST downloadEngineStartupComplete", assetId: asset.assetID, body: "SDK startup complete")
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
func getPendingAsset(assetID: String) -> VirtuosoAsset? {
|
|
144
|
+
let pendingAssets = VirtuosoAsset.pendingAssets(withAvailabilityFilter: false)
|
|
145
|
+
guard let asset = pendingAssets.filter({ ($0 as! VirtuosoAsset).assetID == assetID }).first as? VirtuosoAsset else {
|
|
146
|
+
return nil
|
|
147
|
+
}
|
|
148
|
+
return asset
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
func getAncillaryFiles(files: [String: AnyObject]) -> [VirtuosoAncillaryFile] {
|
|
152
|
+
var ancillaryFiles: [VirtuosoAncillaryFile] = []
|
|
153
|
+
files.forEach { file in
|
|
154
|
+
guard let url = file.value as? String else {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
guard let ancillaryFile = VirtuosoAncillaryFile(downloadUrl: url, andTag: file.key) else {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
ancillaryFiles.append(ancillaryFile)
|
|
161
|
+
}
|
|
162
|
+
return ancillaryFiles
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@objc(download:withResolver:withRejecter:)
|
|
166
|
+
func download(catalogString: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
167
|
+
let virtuoso = VirtuosoDownloadEngine.instance()
|
|
168
|
+
var queue = virtuoso.assetsInQueue()
|
|
169
|
+
|
|
170
|
+
//let decoder = JSONDecoder()
|
|
171
|
+
|
|
172
|
+
do {
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
let data = catalogString.getDictionary()
|
|
176
|
+
|
|
177
|
+
guard let item = data!["item"] as! [String: AnyObject]? else {
|
|
178
|
+
reject("No item", nil, nil)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
guard let url = data!["url"] as? String else {
|
|
182
|
+
reject("No url", nil, nil)
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let assetID = item["id"] as! String? ?? ""
|
|
187
|
+
let hasDRM = item["drm"] as! Bool? ?? false
|
|
188
|
+
|
|
189
|
+
let downloadAsset = getDownloadedAsset(assetID: assetID)
|
|
190
|
+
let pendingAsset = getPendingAsset(assetID: assetID)
|
|
191
|
+
|
|
192
|
+
if (pendingAsset != nil) {
|
|
193
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.PENDING_ASSET_FOUND, assetId: assetID, body: "")
|
|
194
|
+
pendingAsset?.delete()
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if(downloadAsset == nil && pendingAsset == nil) {
|
|
199
|
+
|
|
200
|
+
DispatchQueue.global(qos: .background).async {
|
|
201
|
+
guard let config = VirtuosoAssetConfig(url: url,
|
|
202
|
+
assetID: assetID,
|
|
203
|
+
description: "\(assetID)",
|
|
204
|
+
type: .vde_AssetTypeHLS) else {
|
|
205
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.CONFIG_ASSET_FAILED, assetId: assetID, body: "-")
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Ancillary Files
|
|
210
|
+
let thumbnails = item["thumbnails"] as! [String: AnyObject]? ?? [:]
|
|
211
|
+
let subtitles = item["subtitles"] as! [String: AnyObject]? ?? [:]
|
|
212
|
+
config.ancillaries = self.getAncillaryFiles(files: thumbnails) + self.getAncillaryFiles(files: subtitles)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
//DRM
|
|
216
|
+
if(hasDRM) {
|
|
217
|
+
|
|
218
|
+
guard let drm = data!["drm"] as! [String: AnyObject]? else {
|
|
219
|
+
reject("No drm", nil, nil)
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let token = drm["token"] as! String? ?? ""
|
|
224
|
+
let licenceHttpHeader = drm["licence_server_http_header"] as! String? ?? ""
|
|
225
|
+
let licence = drm["licence_server"] as! String? ?? ""
|
|
226
|
+
let cert = drm["fairplay_cert"] as! String? ?? ""
|
|
227
|
+
|
|
228
|
+
guard let drmSetup = FairPlayDrmSetup(assetID: assetID, certificateUrl: cert, licenceUrl: licence, header: licenceHttpHeader, token: token) else {
|
|
229
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if !drmSetup.configure() {
|
|
234
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
config.protectionType = .vde_AssetProtectionTypeFairPlay
|
|
238
|
+
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let asset = VirtuosoAsset.init(config: config)
|
|
242
|
+
|
|
243
|
+
let data = item["data"] as! [String: AnyObject]? ?? [:]
|
|
244
|
+
|
|
245
|
+
asset?.userInfo = data
|
|
246
|
+
|
|
247
|
+
config.ancillaries?.forEach{ file in
|
|
248
|
+
asset?.add(file)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
//asset?.add(subtitle!)
|
|
253
|
+
|
|
254
|
+
//let calendar = Calendar.current
|
|
255
|
+
//guard let expiryDate = calendar.date(byAdding: .minute, value: 1, to: Date()) else {
|
|
256
|
+
// return
|
|
257
|
+
//}
|
|
258
|
+
|
|
259
|
+
//asset?.expiryAfterDownload = expiryDate.timeIntervalSinceNow
|
|
260
|
+
|
|
261
|
+
queue.append(asset!)
|
|
262
|
+
resolve(assetID)
|
|
263
|
+
//resolve(queue.count)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
} catch {
|
|
268
|
+
reject("penthera", error.localizedDescription, error)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@objc(delete:withResolver:withRejecter:)
|
|
273
|
+
func delete(assetID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
274
|
+
//DispatchQueue.global(qos: .background).async {
|
|
275
|
+
|
|
276
|
+
let downloadComplete = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
|
|
277
|
+
if(downloadComplete.count > 0) {
|
|
278
|
+
(downloadComplete.first as! VirtuosoAsset).delete()
|
|
279
|
+
}
|
|
280
|
+
resolve("Delete complete")
|
|
281
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
|
282
|
+
EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.ASSET_DELETED, assetId: assetID, body: "")
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@objc open override func supportedEvents() -> [String] {
|
|
287
|
+
return EventEmitter.sharedInstance.allEvents
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@objc(playAsset:withResolver:withRejecter:)
|
|
291
|
+
func playAsset(assetID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
292
|
+
|
|
293
|
+
let downloadComplete = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
|
|
294
|
+
guard let asset = downloadComplete.filter({ ($0 as! VirtuosoAsset).assetID == assetID }).first as? VirtuosoAsset else {
|
|
295
|
+
reject("Error streaming asset", "", nil)
|
|
296
|
+
return
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let decoder = JSONEncoder()
|
|
300
|
+
|
|
301
|
+
do {
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
// let subtitle = vcHttpServer?.ancillaryURLForAncillary(withTag: "subtitle", usingMime: "text/vtt")
|
|
305
|
+
// let thumbnailOffline = asset.findAllAncillaries(withTag: "thumbnailOffline").first
|
|
306
|
+
//let wallpaper = asset.findAllAncillaries(withTag: "wallpaper").first
|
|
307
|
+
|
|
308
|
+
let vcHttpServer = VirtuosoClientHTTPServer(asset: asset)
|
|
309
|
+
|
|
310
|
+
let licenseURL = vcHttpServer?.fairPlayLicenseServerURL
|
|
311
|
+
let certificateURL = vcHttpServer?.fairPlayCertificateDataURL(forSubType: nil)
|
|
312
|
+
|
|
313
|
+
//let avContentKeySession = VirtuosoLicenseManager.registeredAVContentKeySession()
|
|
314
|
+
|
|
315
|
+
//let userInfoData = try encoder.encode(asset.userInfo)
|
|
316
|
+
//let userInfo = String(data: userInfoData, encoding: .utf8)
|
|
317
|
+
|
|
318
|
+
let assetData = [
|
|
319
|
+
"id": asset.assetID,
|
|
320
|
+
"url": vcHttpServer?.playbackURL ?? "",
|
|
321
|
+
"certificate": certificateURL ,
|
|
322
|
+
"license": licenseURL
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
let data = try decoder.encode(assetData)
|
|
326
|
+
let json = String(data: data, encoding: .utf8)!
|
|
327
|
+
resolve(json)
|
|
328
|
+
|
|
329
|
+
// let config = PlayerConfig()
|
|
330
|
+
// config.styleConfig.userInterfaceType = .system
|
|
331
|
+
// config.key = "ASSSSSS"
|
|
332
|
+
|
|
333
|
+
// let player = PlayerFactory.create(playerConfig: config)
|
|
334
|
+
|
|
335
|
+
// guard let streamUrl = URL(string: vcHttpServer!.playbackURL) else {
|
|
336
|
+
// return
|
|
337
|
+
// }
|
|
338
|
+
|
|
339
|
+
// // Create a SourceConfig
|
|
340
|
+
// let sourceConfig = SourceConfig(url: streamUrl, type: .hls)
|
|
341
|
+
// print(streamUrl.absoluteString)
|
|
342
|
+
|
|
343
|
+
// // Optionally set additional properties
|
|
344
|
+
// sourceConfig.title = "Art of motion"
|
|
345
|
+
|
|
346
|
+
// DispatchQueue.main.async {
|
|
347
|
+
// let source = SourceFactory.create(from: sourceConfig)
|
|
348
|
+
|
|
349
|
+
// player.load(source: source)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
// let viewController = UIApplication.shared.windows.first?.rootViewController as? UIViewController
|
|
353
|
+
|
|
354
|
+
// let playerView = PlayerView(player: player, frame: (viewController?.view.bounds)!)
|
|
355
|
+
|
|
356
|
+
// // Adding the view to the a container View
|
|
357
|
+
// viewController?.view.addSubview(playerView)
|
|
358
|
+
// viewController?.view.bringSubviewToFront(playerView)
|
|
359
|
+
// }
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
/*
|
|
363
|
+
let demoPlayer = DemoPlayerViewController()
|
|
364
|
+
DispatchQueue.main.async {
|
|
365
|
+
asset.play(using: .vde_AssetPlaybackTypeLocal,
|
|
366
|
+
andPlayer: demoPlayer as VirtuosoPlayer,
|
|
367
|
+
onSuccess: {
|
|
368
|
+
// Present the player
|
|
369
|
+
|
|
370
|
+
let viewController = UIApplication.shared.windows.first?.rootViewController as? UIViewController
|
|
371
|
+
viewController?.present(demoPlayer, animated: true)
|
|
372
|
+
//self.present(demoPlayer, animated: true, completion: nil)
|
|
373
|
+
},
|
|
374
|
+
onFail: {
|
|
375
|
+
//self.error = nil
|
|
376
|
+
})
|
|
377
|
+
}*/
|
|
378
|
+
|
|
379
|
+
} catch {
|
|
380
|
+
reject("penthere", error.localizedDescription, error)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
}
|