unified-video-framework 1.0.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.
Files changed (129) hide show
  1. package/.github/workflows/ci.yml +253 -0
  2. package/ANDROID_TV_IMPLEMENTATION.md +313 -0
  3. package/COMPLETION_STATUS.md +165 -0
  4. package/CONTRIBUTING.md +376 -0
  5. package/FINAL_STATUS_REPORT.md +170 -0
  6. package/FRAMEWORK_REVIEW.md +247 -0
  7. package/IMPROVEMENTS_SUMMARY.md +168 -0
  8. package/LICENSE +21 -0
  9. package/NATIVE_APP_INTEGRATION_GUIDE.md +903 -0
  10. package/PAYWALL_RENTAL_FLOW.md +499 -0
  11. package/PLATFORM_SETUP_GUIDE.md +1636 -0
  12. package/README.md +315 -0
  13. package/RUN_LOCALLY.md +151 -0
  14. package/apps/demo/cast-sender-min.html +173 -0
  15. package/apps/demo/custom-player.html +883 -0
  16. package/apps/demo/demo.html +990 -0
  17. package/apps/demo/enhanced-player.html +3556 -0
  18. package/apps/demo/index.html +159 -0
  19. package/apps/rental-api/.env.example +24 -0
  20. package/apps/rental-api/README.md +23 -0
  21. package/apps/rental-api/migrations/001_init.sql +35 -0
  22. package/apps/rental-api/migrations/002_videos.sql +10 -0
  23. package/apps/rental-api/migrations/003_add_gateway_subref.sql +4 -0
  24. package/apps/rental-api/migrations/004_update_gateways.sql +4 -0
  25. package/apps/rental-api/migrations/005_seed_demo_video.sql +5 -0
  26. package/apps/rental-api/package-lock.json +2045 -0
  27. package/apps/rental-api/package.json +33 -0
  28. package/apps/rental-api/scripts/run-migration.js +42 -0
  29. package/apps/rental-api/scripts/update-video-currency.js +21 -0
  30. package/apps/rental-api/scripts/update-video-price.js +19 -0
  31. package/apps/rental-api/src/config.ts +14 -0
  32. package/apps/rental-api/src/db.ts +10 -0
  33. package/apps/rental-api/src/routes/cashfree.ts +167 -0
  34. package/apps/rental-api/src/routes/pesapal.ts +92 -0
  35. package/apps/rental-api/src/routes/rentals.ts +242 -0
  36. package/apps/rental-api/src/routes/webhooks.ts +73 -0
  37. package/apps/rental-api/src/server.ts +41 -0
  38. package/apps/rental-api/src/services/entitlements.ts +45 -0
  39. package/apps/rental-api/src/services/payments.ts +22 -0
  40. package/apps/rental-api/tsconfig.json +17 -0
  41. package/check-urls.ps1 +74 -0
  42. package/comparison-report.md +181 -0
  43. package/docs/PAYWALL.md +95 -0
  44. package/docs/PLAYER_UI_VISIBILITY.md +431 -0
  45. package/docs/README.md +7 -0
  46. package/docs/SYSTEM_ARCHITECTURE.md +612 -0
  47. package/docs/VDOCIPHER_CLONE_REQUIREMENTS.md +403 -0
  48. package/examples/android/JavaSampleApp/MainActivity.java +641 -0
  49. package/examples/android/JavaSampleApp/activity_main.xml +226 -0
  50. package/examples/android/SampleApp/MainActivity.kt +430 -0
  51. package/examples/ios/SampleApp/ViewController.swift +337 -0
  52. package/examples/ios/SwiftUISampleApp/ContentView.swift +304 -0
  53. package/iOS_IMPLEMENTATION_OPTIONS.md +470 -0
  54. package/ios/UnifiedVideoPlayer/UnifiedVideoPlayer.podspec +33 -0
  55. package/jest.config.js +33 -0
  56. package/jitpack.yml +5 -0
  57. package/lerna.json +35 -0
  58. package/package.json +69 -0
  59. package/packages/PLATFORM_STATUS.md +163 -0
  60. package/packages/android/build.gradle +135 -0
  61. package/packages/android/src/main/AndroidManifest.xml +36 -0
  62. package/packages/android/src/main/java/com/unifiedvideo/player/PlayerConfiguration.java +221 -0
  63. package/packages/android/src/main/java/com/unifiedvideo/player/UnifiedVideoPlayer.java +1037 -0
  64. package/packages/android/src/main/java/com/unifiedvideo/player/UnifiedVideoPlayer.kt +707 -0
  65. package/packages/android/src/main/java/com/unifiedvideo/player/analytics/AnalyticsProvider.java +9 -0
  66. package/packages/android/src/main/java/com/unifiedvideo/player/cast/CastManager.java +141 -0
  67. package/packages/android/src/main/java/com/unifiedvideo/player/cast/CastOptionsProvider.java +29 -0
  68. package/packages/android/src/main/java/com/unifiedvideo/player/overlay/WatermarkOverlayView.java +88 -0
  69. package/packages/android/src/main/java/com/unifiedvideo/player/pip/PipActionReceiver.java +33 -0
  70. package/packages/android/src/main/java/com/unifiedvideo/player/services/PlaybackService.java +110 -0
  71. package/packages/android/src/main/java/com/unifiedvideo/player/services/PlayerHolder.java +19 -0
  72. package/packages/core/package.json +34 -0
  73. package/packages/core/src/BasePlayer.ts +250 -0
  74. package/packages/core/src/VideoPlayer.ts +237 -0
  75. package/packages/core/src/VideoPlayerFactory.ts +145 -0
  76. package/packages/core/src/index.ts +20 -0
  77. package/packages/core/src/interfaces/IVideoPlayer.ts +184 -0
  78. package/packages/core/src/interfaces.ts +240 -0
  79. package/packages/core/src/utils/EventEmitter.ts +66 -0
  80. package/packages/core/src/utils/PlatformDetector.ts +300 -0
  81. package/packages/core/tsconfig.json +20 -0
  82. package/packages/enact/package.json +51 -0
  83. package/packages/enact/src/VideoPlayer.js +365 -0
  84. package/packages/enact/src/adapters/TizenAdapter.js +354 -0
  85. package/packages/enact/src/index.js +82 -0
  86. package/packages/ios/BUILD_INSTRUCTIONS.md +108 -0
  87. package/packages/ios/FIX_EMBED_ISSUE.md +142 -0
  88. package/packages/ios/GETTING_STARTED.md +100 -0
  89. package/packages/ios/Package.swift +35 -0
  90. package/packages/ios/README.md +84 -0
  91. package/packages/ios/Sources/UnifiedVideoPlayer/Analytics/AnalyticsEmitter.swift +26 -0
  92. package/packages/ios/Sources/UnifiedVideoPlayer/DRM/FairPlayDRMManager.swift +102 -0
  93. package/packages/ios/Sources/UnifiedVideoPlayer/Info.plist +24 -0
  94. package/packages/ios/Sources/UnifiedVideoPlayer/Remote/RemoteCommandCenter.swift +109 -0
  95. package/packages/ios/Sources/UnifiedVideoPlayer/UnifiedVideoPlayer.swift +811 -0
  96. package/packages/ios/Sources/UnifiedVideoPlayer/UnifiedVideoPlayerView.swift +640 -0
  97. package/packages/ios/Sources/UnifiedVideoPlayer/Utilities/Color+Hex.swift +36 -0
  98. package/packages/ios/UnifiedVideoPlayer.podspec +27 -0
  99. package/packages/ios/UnifiedVideoPlayer.xcodeproj/project.pbxproj +385 -0
  100. package/packages/ios/build_framework.sh +55 -0
  101. package/packages/react-native/android/src/main/java/com/unifiedvideo/UnifiedVideoPlayerModule.kt +482 -0
  102. package/packages/react-native/ios/UnifiedVideoPlayer.swift +436 -0
  103. package/packages/react-native/package.json +51 -0
  104. package/packages/react-native/src/ReactNativePlayer.tsx +423 -0
  105. package/packages/react-native/src/VideoPlayer.tsx +224 -0
  106. package/packages/react-native/src/index.ts +28 -0
  107. package/packages/react-native/src/utils/EventEmitter.ts +66 -0
  108. package/packages/react-native/tsconfig.json +31 -0
  109. package/packages/roku/components/UnifiedVideoPlayer.brs +400 -0
  110. package/packages/roku/package.json +44 -0
  111. package/packages/roku/source/VideoPlayer.brs +231 -0
  112. package/packages/roku/source/main.brs +28 -0
  113. package/packages/web/GETTING_STARTED.md +292 -0
  114. package/packages/web/jest.config.js +28 -0
  115. package/packages/web/jest.setup.ts +110 -0
  116. package/packages/web/package.json +50 -0
  117. package/packages/web/src/SecureVideoPlayer.ts +1164 -0
  118. package/packages/web/src/WebPlayer.ts +3110 -0
  119. package/packages/web/src/__tests__/WebPlayer.test.ts +314 -0
  120. package/packages/web/src/index.ts +14 -0
  121. package/packages/web/src/paywall/PaywallController.ts +215 -0
  122. package/packages/web/src/react/WebPlayerView.tsx +177 -0
  123. package/packages/web/tsconfig.json +23 -0
  124. package/packages/web/webpack.config.js +45 -0
  125. package/server.js +131 -0
  126. package/server.py +84 -0
  127. package/test-urls.ps1 +97 -0
  128. package/test-video-urls.ps1 +87 -0
  129. package/tsconfig.json +39 -0
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>1.0</string>
19
+ <key>CFBundleVersion</key>
20
+ <string>$(CURRENT_PROJECT_VERSION)</string>
21
+ <key>NSPrincipalClass</key>
22
+ <string></string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,109 @@
1
+ import Foundation
2
+ import MediaPlayer
3
+ import AVFoundation
4
+ import UIKit
5
+
6
+ final class RemoteCommandCenter {
7
+ private weak var player: AVPlayer?
8
+ private var nowPlaying: [String: Any] = [:]
9
+
10
+ func enable(for player: AVPlayer, title: String?, duration: Double?, artworkURL: URL?) {
11
+ self.player = player
12
+ configureAudioSession()
13
+ setupRemoteCommands()
14
+ updateNowPlaying(title: title, duration: duration, elapsed: currentTime(), isPlaying: player.timeControlStatus == .playing, artworkURL: artworkURL)
15
+ }
16
+
17
+ func disable() {
18
+ let center = MPRemoteCommandCenter.shared()
19
+ center.playCommand.isEnabled = false
20
+ center.pauseCommand.isEnabled = false
21
+ center.togglePlayPauseCommand.isEnabled = false
22
+ center.changePlaybackPositionCommand.isEnabled = false
23
+ MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
24
+ nowPlaying = [:]
25
+ }
26
+
27
+ func updateProgress(elapsed: Double, duration: Double?, isPlaying: Bool) {
28
+ updateNowPlaying(title: nowPlaying[MPMediaItemPropertyTitle] as? String, duration: duration, elapsed: elapsed, isPlaying: isPlaying, artworkURL: nil)
29
+ }
30
+
31
+ private func configureAudioSession() {
32
+ do {
33
+ try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: [])
34
+ try AVAudioSession.sharedInstance().setActive(true)
35
+ } catch {
36
+ // Swallow; caller may be setting this too
37
+ }
38
+ }
39
+
40
+ private func setupRemoteCommands() {
41
+ let center = MPRemoteCommandCenter.shared()
42
+
43
+ center.playCommand.isEnabled = true
44
+ center.playCommand.addTarget { [weak self] _ in
45
+ self?.player?.play()
46
+ self?.syncState()
47
+ return .success
48
+ }
49
+
50
+ center.pauseCommand.isEnabled = true
51
+ center.pauseCommand.addTarget { [weak self] _ in
52
+ self?.player?.pause()
53
+ self?.syncState()
54
+ return .success
55
+ }
56
+
57
+ center.togglePlayPauseCommand.isEnabled = true
58
+ center.togglePlayPauseCommand.addTarget { [weak self] _ in
59
+ guard let p = self?.player else { return .commandFailed }
60
+ p.timeControlStatus == .playing ? p.pause() : p.play()
61
+ self?.syncState()
62
+ return .success
63
+ }
64
+
65
+ center.changePlaybackPositionCommand.isEnabled = true
66
+ center.changePlaybackPositionCommand.addTarget { [weak self] e in
67
+ guard let evt = e as? MPChangePlaybackPositionCommandEvent else { return .commandFailed }
68
+ let t = CMTime(seconds: evt.positionTime, preferredTimescale: 600)
69
+ self?.player?.seek(to: t)
70
+ self?.syncState()
71
+ return .success
72
+ }
73
+ }
74
+
75
+ private func updateNowPlaying(title: String?, duration: Double?, elapsed: Double, isPlaying: Bool, artworkURL: URL?) {
76
+ var info: [String: Any] = nowPlaying
77
+ if let title = title { info[MPMediaItemPropertyTitle] = title }
78
+ if let duration = duration { info[MPMediaItemPropertyPlaybackDuration] = duration }
79
+ info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = elapsed
80
+ info[MPNowPlayingInfoPropertyPlaybackRate] = isPlaying ? 1.0 : 0.0
81
+
82
+ if let artworkURL = artworkURL {
83
+ URLSession.shared.dataTask(with: artworkURL) { data, _, _ in
84
+ var edited = info
85
+ if let d = data, let img = UIImage(data: d) {
86
+ let art = MPMediaItemArtwork(boundsSize: img.size) { _ in img }
87
+ edited[MPMediaItemPropertyArtwork] = art
88
+ }
89
+ DispatchQueue.main.async { MPNowPlayingInfoCenter.default().nowPlayingInfo = edited }
90
+ }.resume()
91
+ } else {
92
+ MPNowPlayingInfoCenter.default().nowPlayingInfo = info
93
+ }
94
+
95
+ nowPlaying = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? info
96
+ }
97
+
98
+ private func syncState() {
99
+ guard let p = player else { return }
100
+ updateNowPlaying(title: nowPlaying[MPMediaItemPropertyTitle] as? String,
101
+ duration: nowPlaying[MPMediaItemPropertyPlaybackDuration] as? Double,
102
+ elapsed: currentTime(),
103
+ isPlaying: p.timeControlStatus == .playing,
104
+ artworkURL: nil)
105
+ }
106
+
107
+ private func currentTime() -> Double { player?.currentTime().seconds ?? 0 }
108
+ }
109
+