@picsa/capacitor-video-player 7.1.0 → 7.2.2
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/CapacitorVideoPlayer.podspec +17 -17
- package/LICENSE +21 -21
- package/android/build.gradle +71 -71
- package/android/src/main/AndroidManifest.xml +3 -3
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/CapacitorVideoPlayer.java +71 -71
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/CapacitorVideoPlayerPlugin.java +1256 -1256
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/FullscreenExoPlayerFragment.java +1595 -1595
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/Notifications/MyRunnable.java +21 -21
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/Notifications/NotificationCenter.java +61 -61
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/PickerVideo/AdapterVideoList.java +47 -47
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/PickerVideo/ModelVideo.java +49 -49
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/PickerVideo/PickerVideoFragment.java +119 -119
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/PickerVideo/VideoRecyclerViewHolder.java +65 -65
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/Utilities/FilesUtils.java +101 -101
- package/android/src/main/java/com/jeep/plugin/capacitor/capacitorvideoplayer/Utilities/FragmentUtils.java +32 -32
- package/android/src/main/res/drawable/bg_round_rect_white_50.xml +9 -9
- package/android/src/main/res/drawable/bg_rounded_rectangle_white_corner_rounded.xml +10 -10
- package/android/src/main/res/drawable/exo_close_btn.xml +11 -11
- package/android/src/main/res/drawable/gradient_transparent_middle.xml +12 -12
- package/android/src/main/res/drawable/ic_arrow_left.xml +5 -5
- package/android/src/main/res/drawable/ic_baseline_lq.xml +7 -7
- package/android/src/main/res/drawable/ic_exo_icon_fastforward.xml +35 -35
- package/android/src/main/res/drawable/ic_exo_icon_pause.xml +26 -26
- package/android/src/main/res/drawable/ic_exo_icon_play.xml +36 -36
- package/android/src/main/res/drawable/ic_exo_icon_rewind.xml +35 -35
- package/android/src/main/res/drawable/ic_expand.xml +5 -5
- package/android/src/main/res/drawable/ic_fit.xml +5 -5
- package/android/src/main/res/drawable/ic_image_background.xml +12 -12
- package/android/src/main/res/drawable/ic_img_16_9_background.xml +10 -10
- package/android/src/main/res/drawable/ic_img_9_16_background.xml +10 -10
- package/android/src/main/res/drawable/ic_outline_lock.xml +5 -5
- package/android/src/main/res/drawable/ic_outline_lock_open.xml +5 -5
- package/android/src/main/res/drawable/ic_pip_white.xml +5 -5
- package/android/src/main/res/drawable/ic_views.xml +18 -18
- package/android/src/main/res/drawable/ic_zoom.xml +5 -5
- package/android/src/main/res/layout/bridge_layout_main.xml +15 -15
- package/android/src/main/res/layout/exo_playback_control_view.xml +289 -289
- package/android/src/main/res/layout/exoplayer_layout_youtube.xml +361 -361
- package/android/src/main/res/layout/fragment_fs_exoplayer.xml +50 -50
- package/android/src/main/res/layout/fragment_picker_video.xml +21 -21
- package/android/src/main/res/layout/row_video.xml +76 -76
- package/android/src/main/res/values/colors.xml +14 -14
- package/android/src/main/res/values/strings.xml +3 -3
- package/android/src/main/res/values/styles.xml +3 -3
- package/dist/docs.json +14 -14
- package/ios/Plugin/CapacitorVideoPlayer.swift +63 -63
- package/ios/Plugin/CapacitorVideoPlayerPlugin.h +10 -10
- package/ios/Plugin/CapacitorVideoPlayerPlugin.m +22 -22
- package/ios/Plugin/CapacitorVideoPlayerPlugin.swift +631 -631
- package/ios/Plugin/Extensions/CapacitorVideoPlayerPlugin.AVPlayerViewController.swift +59 -59
- package/ios/Plugin/Extensions/CapacitorVideoPlayerPlugin.File.swift +126 -126
- package/ios/Plugin/Extensions/CapacitorVideoPlayerPlugin.Fullscreen.swift +94 -94
- package/ios/Plugin/Extensions/CapacitorVideoPlayerPlugin.Notifications.swift +140 -140
- package/ios/Plugin/Extensions/CapacitorVideoPlayerPlugin.Observers.swift +180 -180
- package/ios/Plugin/Info.plist +24 -24
- package/ios/Plugin/VideoPicker/VideoHelper.swift +127 -127
- package/ios/Plugin/VideoPicker/VideoPickerViewController.swift +144 -144
- package/ios/Plugin/VideoPlayer/Extensions/AVURLAsset.swift +18 -18
- package/ios/Plugin/VideoPlayer/Extensions/AllOrientationAVPlayerController.swift +12 -12
- package/ios/Plugin/VideoPlayer/Extensions/CMTime.swift +23 -23
- package/ios/Plugin/VideoPlayer/Extensions/LandscapeAVPlayerController.swift +12 -12
- package/ios/Plugin/VideoPlayer/Extensions/Notification.Name.swift +18 -18
- package/ios/Plugin/VideoPlayer/Extensions/PortraitAVPlayerController.swift +12 -12
- package/ios/Plugin/VideoPlayer/Extensions/View.swift +54 -54
- package/ios/Plugin/VideoPlayer/FullScreenVideoPlayerView.swift +601 -601
- package/ios/Plugin/VideoPlayer/Models/Video.swift +28 -28
- package/ios/Plugin/VideoPlayer/Models/VideoModel.swift +42 -42
- package/package.json +92 -92
- package/readme.md +196 -190
|
@@ -1,632 +1,632 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import Capacitor
|
|
3
|
-
import AVKit
|
|
4
|
-
import UIKit
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Please read the Capacitor iOS Plugin Development Guide
|
|
8
|
-
* here: https://capacitorjs.com/docs/plugins/ios
|
|
9
|
-
*/
|
|
10
|
-
@objc(CapacitorVideoPlayerPlugin)
|
|
11
|
-
// swiftlint:disable file_length
|
|
12
|
-
// swiftlint:disable type_body_length
|
|
13
|
-
public class CapacitorVideoPlayerPlugin: CAPPlugin {
|
|
14
|
-
public var call: CAPPluginCall?
|
|
15
|
-
public var videoPlayer: AVPlayerViewController?
|
|
16
|
-
public var bgPlayer: AVPlayer?
|
|
17
|
-
public let implementation = CapacitorVideoPlayer()
|
|
18
|
-
var videoPlayerFullScreenView: FullScreenVideoPlayerView?
|
|
19
|
-
var audioSession: AVAudioSession?
|
|
20
|
-
var mode: String?
|
|
21
|
-
var exitOnEnd: Bool = true
|
|
22
|
-
var loopOnEnd: Bool = false
|
|
23
|
-
var pipEnabled: Bool = true
|
|
24
|
-
var backModeEnabled: Bool = true
|
|
25
|
-
var showControls: Bool = true
|
|
26
|
-
var displayMode: String = "all"
|
|
27
|
-
var headers: [String: String]?
|
|
28
|
-
var title: String?
|
|
29
|
-
var smallTitle: String?
|
|
30
|
-
var artwork: String?
|
|
31
|
-
var fsPlayerId: String = "fullscreen"
|
|
32
|
-
var videoRate: Float = 1.0
|
|
33
|
-
var playObserver: Any?
|
|
34
|
-
var pauseObserver: Any?
|
|
35
|
-
var endObserver: Any?
|
|
36
|
-
var readyObserver: Any?
|
|
37
|
-
var fsDismissObserver: Any?
|
|
38
|
-
var backgroundObserver: Any?
|
|
39
|
-
var foregroundObserver: Any?
|
|
40
|
-
var vpInternalObserver: Any?
|
|
41
|
-
let rateList: [Float] = [0.25, 0.5, 0.75, 1.0, 2.0, 4.0]
|
|
42
|
-
|
|
43
|
-
override public func load() {
|
|
44
|
-
self.addObserversToNotificationCenter()
|
|
45
|
-
if (UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad),
|
|
46
|
-
#available(iOS 13.0, *) {
|
|
47
|
-
isPIPModeAvailable = true
|
|
48
|
-
} else if #available(iOS 14.0, *) {
|
|
49
|
-
isPIPModeAvailable = true
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
deinit {
|
|
53
|
-
NotificationCenter.default.removeObserver(playObserver as Any)
|
|
54
|
-
NotificationCenter.default.removeObserver(pauseObserver as Any)
|
|
55
|
-
NotificationCenter.default.removeObserver(endObserver as Any)
|
|
56
|
-
NotificationCenter.default.removeObserver(readyObserver as Any)
|
|
57
|
-
NotificationCenter.default.removeObserver(fsDismissObserver as Any)
|
|
58
|
-
NotificationCenter.default.removeObserver(backgroundObserver as Any)
|
|
59
|
-
NotificationCenter.default.removeObserver(foregroundObserver as Any)
|
|
60
|
-
NotificationCenter.default.removeObserver(vpInternalObserver as Any)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
@objc func echo(_ call: CAPPluginCall) {
|
|
64
|
-
let value = call.getString("value") ?? ""
|
|
65
|
-
call.resolve([
|
|
66
|
-
"value": implementation.echo(value)
|
|
67
|
-
])
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// MARK: - Init player(s)
|
|
71
|
-
|
|
72
|
-
// swiftlint:disable function_body_length
|
|
73
|
-
// swiftlint:disable cyclomatic_complexity
|
|
74
|
-
@objc func initPlayer(_ call: CAPPluginCall) {
|
|
75
|
-
self.call = call
|
|
76
|
-
guard let mode = call.options["mode"] as? String else {
|
|
77
|
-
let error: String = "Must provide a Mode " +
|
|
78
|
-
"(fullscreen/embedded)"
|
|
79
|
-
call.resolve([ "result": false, "method": "initPlayer",
|
|
80
|
-
"message": error])
|
|
81
|
-
|
|
82
|
-
return
|
|
83
|
-
}
|
|
84
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
85
|
-
let error: String = "Must provide a PlayerId"
|
|
86
|
-
call.resolve([ "result": false, "method": "initPlayer",
|
|
87
|
-
"message": error])
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
var mRate: Float = 1.0
|
|
91
|
-
if let sRate = call.options["rate"] as? Float {
|
|
92
|
-
if rateList.contains(sRate) {
|
|
93
|
-
mRate = sRate
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
var exitOnEnd: Bool = true
|
|
97
|
-
if let sexitOnEnd = call.options["exitOnEnd"] as? Bool {
|
|
98
|
-
exitOnEnd = sexitOnEnd
|
|
99
|
-
}
|
|
100
|
-
var loopOnEnd: Bool = false
|
|
101
|
-
if let sloopOnEnd = call.options["loopOnEnd"] as? Bool {
|
|
102
|
-
if !exitOnEnd {
|
|
103
|
-
loopOnEnd = sloopOnEnd
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
var headers: [String: String]?
|
|
107
|
-
if let sheaders = call.options["headers"] as? [String: String] {
|
|
108
|
-
headers = sheaders
|
|
109
|
-
}
|
|
110
|
-
var pipEnabled: Bool = true
|
|
111
|
-
if let spipEnabled = call.options["pipEnabled"] as? Bool {
|
|
112
|
-
pipEnabled = spipEnabled
|
|
113
|
-
}
|
|
114
|
-
var bkModeEnabled: Bool = true
|
|
115
|
-
if let sbkModeEnabled = call.options["bkmodeEnabled"] as? Bool {
|
|
116
|
-
bkModeEnabled = sbkModeEnabled
|
|
117
|
-
}
|
|
118
|
-
var shControls: Bool = true
|
|
119
|
-
if let shoControls = call.options["showControls"] as? Bool {
|
|
120
|
-
shControls = shoControls
|
|
121
|
-
}
|
|
122
|
-
var disMode: String = "all"
|
|
123
|
-
if let dispMode = call.options["displayMode"] as? String {
|
|
124
|
-
disMode = dispMode
|
|
125
|
-
}
|
|
126
|
-
var title: String?
|
|
127
|
-
if let stitle = call.options["title"] as? String {
|
|
128
|
-
title = stitle
|
|
129
|
-
}
|
|
130
|
-
var smallTitle: String?
|
|
131
|
-
if let ssmallTitle = call.options["smallTitle"] as? String {
|
|
132
|
-
smallTitle = ssmallTitle
|
|
133
|
-
}
|
|
134
|
-
var artwork: String?
|
|
135
|
-
if let sartwork = call.options["artwork"] as? String {
|
|
136
|
-
artwork = sartwork
|
|
137
|
-
}
|
|
138
|
-
self.fsPlayerId = playerId
|
|
139
|
-
self.mode = mode
|
|
140
|
-
self.videoRate = mRate
|
|
141
|
-
self.exitOnEnd = exitOnEnd
|
|
142
|
-
self.loopOnEnd = loopOnEnd
|
|
143
|
-
self.pipEnabled = pipEnabled
|
|
144
|
-
self.headers = headers
|
|
145
|
-
if !self.pipEnabled {isPIPModeAvailable = false}
|
|
146
|
-
self.backModeEnabled = bkModeEnabled
|
|
147
|
-
self.showControls = shControls
|
|
148
|
-
self.displayMode = disMode
|
|
149
|
-
self.title = title
|
|
150
|
-
self.smallTitle = smallTitle
|
|
151
|
-
self.artwork = artwork
|
|
152
|
-
if mode == "fullscreen" {
|
|
153
|
-
guard let videoPath = call.options["url"] as? String else {
|
|
154
|
-
let error: String = "Must provide a video url"
|
|
155
|
-
print(error)
|
|
156
|
-
call.resolve([ "result": false, "method": "initPlayer", "message": error])
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
var subTitlePath: String = ""
|
|
160
|
-
if let stPath = call.options["subtitle"] as? String {
|
|
161
|
-
subTitlePath = stPath
|
|
162
|
-
}
|
|
163
|
-
var subTitleLanguage: String = ""
|
|
164
|
-
if let stLanguage = call.options["language"] as? String {
|
|
165
|
-
subTitleLanguage = stLanguage
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
let subTitleOptions: [String: Any] = call.getObject("subtitleOptions") ?? [:]
|
|
169
|
-
|
|
170
|
-
if videoPath == "internal" {
|
|
171
|
-
DispatchQueue.main.async { [weak self] in
|
|
172
|
-
if let videoPickerViewController =
|
|
173
|
-
self?.implementation.pickVideoFromInternal(
|
|
174
|
-
rate: self?.videoRate ?? 1.0,
|
|
175
|
-
exitOnEnd: self?.exitOnEnd ?? true,
|
|
176
|
-
loopOnEnd: self?.loopOnEnd ?? false,
|
|
177
|
-
pipEnabled: self?.pipEnabled ?? true,
|
|
178
|
-
backModeEnabled: self?.backModeEnabled ?? true,
|
|
179
|
-
showControls: self?.showControls ?? true,
|
|
180
|
-
displayMode: self?.displayMode ?? "all") {
|
|
181
|
-
self?.bridge?.viewController?.present(
|
|
182
|
-
videoPickerViewController,
|
|
183
|
-
animated: true, completion: {return})
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
} else {
|
|
188
|
-
let dictUrl: [String: Any] =
|
|
189
|
-
getURLFromFilePath(filePath: videoPath)
|
|
190
|
-
if let message = dictUrl["message"] as? String {
|
|
191
|
-
if message.count > 0 {
|
|
192
|
-
call.resolve([ "result": false, "method": "initPlayer",
|
|
193
|
-
"message": message])
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
guard let url = dictUrl["url"] as? URL else {
|
|
198
|
-
call.resolve([ "result": false, "method": "initPlayer",
|
|
199
|
-
"message": "url not defined"])
|
|
200
|
-
return
|
|
201
|
-
}
|
|
202
|
-
var subTitle: URL?
|
|
203
|
-
if subTitlePath.count > 0 {
|
|
204
|
-
|
|
205
|
-
let dictSubTitle: [String: Any] =
|
|
206
|
-
getURLFromFilePath(filePath: subTitlePath)
|
|
207
|
-
if let message = dictSubTitle["message"] as? String {
|
|
208
|
-
if message.count > 0 {
|
|
209
|
-
call.resolve([ "result": false, "method": "initPlayer",
|
|
210
|
-
"message": message])
|
|
211
|
-
return
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
guard let sturl = dictSubTitle["url"] as? URL else {
|
|
215
|
-
call.resolve([ "result": false, "method": "initPlayer",
|
|
216
|
-
"message": "subtitle url not defined"])
|
|
217
|
-
return
|
|
218
|
-
}
|
|
219
|
-
subTitle = sturl
|
|
220
|
-
}
|
|
221
|
-
guard let call = self.call else { return }
|
|
222
|
-
self.createVideoPlayerFullscreenView(
|
|
223
|
-
call: call, videoUrl: url, rate: videoRate,
|
|
224
|
-
exitOnEnd: exitOnEnd, loopOnEnd: loopOnEnd,
|
|
225
|
-
pipEnabled: pipEnabled,
|
|
226
|
-
backModeEnabled: backModeEnabled,
|
|
227
|
-
showControls: showControls,
|
|
228
|
-
displayMode: displayMode,
|
|
229
|
-
subTitleUrl: subTitle,
|
|
230
|
-
subTitleLanguage: subTitleLanguage,
|
|
231
|
-
subTitleOptions: subTitleOptions,
|
|
232
|
-
headers: headers,
|
|
233
|
-
title: title,
|
|
234
|
-
smallTitle: smallTitle,
|
|
235
|
-
artwork: artwork)
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
call.resolve([ "result": false,
|
|
240
|
-
"method": "initPlayer",
|
|
241
|
-
"message": "Not implemented"])
|
|
242
|
-
return
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
// swiftlint:enable function_body_length
|
|
246
|
-
// swiftlint:enable cyclomatic_complexity
|
|
247
|
-
|
|
248
|
-
// MARK: - Play the given player
|
|
249
|
-
|
|
250
|
-
@objc func isPlaying(_ call: CAPPluginCall) {
|
|
251
|
-
self.call = call
|
|
252
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
253
|
-
let error: String = "Must provide a playerId"
|
|
254
|
-
print(error)
|
|
255
|
-
call.resolve([ "result": false, "method": "isPlaying", "message": error])
|
|
256
|
-
return
|
|
257
|
-
}
|
|
258
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
259
|
-
|
|
260
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
261
|
-
DispatchQueue.main.async {
|
|
262
|
-
let isPlaying: Bool = playerView.isPlaying
|
|
263
|
-
call.resolve([ "result": true, "method": "isPlaying", "value": isPlaying])
|
|
264
|
-
return
|
|
265
|
-
}
|
|
266
|
-
} else {
|
|
267
|
-
let error: String = "Fullscreen player not found"
|
|
268
|
-
print(error)
|
|
269
|
-
call.resolve([ "result": false, "method": "isPlaying", "message": error])
|
|
270
|
-
return
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
// MARK: - Play the given player
|
|
275
|
-
|
|
276
|
-
@objc func play(_ call: CAPPluginCall) {
|
|
277
|
-
self.call = call
|
|
278
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
279
|
-
let error: String = "Must provide a playerId"
|
|
280
|
-
print(error)
|
|
281
|
-
call.resolve([ "result": false, "method": "play", "message": error])
|
|
282
|
-
return
|
|
283
|
-
}
|
|
284
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
285
|
-
|
|
286
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
287
|
-
DispatchQueue.main.async {
|
|
288
|
-
playerView.play()
|
|
289
|
-
call.resolve([ "result": true, "method": "play", "value": true])
|
|
290
|
-
return
|
|
291
|
-
}
|
|
292
|
-
} else {
|
|
293
|
-
let error: String = "Fullscreen player not found"
|
|
294
|
-
print(error)
|
|
295
|
-
call.resolve([ "result": false, "method": "play", "message": error])
|
|
296
|
-
return
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// MARK: - Pause the given player
|
|
302
|
-
|
|
303
|
-
@objc func pause(_ call: CAPPluginCall) {
|
|
304
|
-
self.call = call
|
|
305
|
-
|
|
306
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
307
|
-
let error: String = "Must provide a playerId"
|
|
308
|
-
print(error)
|
|
309
|
-
call.resolve([ "result": false, "method": "pause", "message": error])
|
|
310
|
-
return
|
|
311
|
-
}
|
|
312
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
313
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
314
|
-
DispatchQueue.main.async {
|
|
315
|
-
playerView.pause()
|
|
316
|
-
call.resolve([ "result": true, "method": "pause", "value": true])
|
|
317
|
-
return
|
|
318
|
-
}
|
|
319
|
-
} else {
|
|
320
|
-
let error: String = "Fullscreen player not found"
|
|
321
|
-
print(error)
|
|
322
|
-
call.resolve([ "result": false, "method": "pause", "message": error])
|
|
323
|
-
return
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// MARK: - get Duration for the given player
|
|
329
|
-
|
|
330
|
-
@objc func getDuration(_ call: CAPPluginCall) {
|
|
331
|
-
self.call = call
|
|
332
|
-
|
|
333
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
334
|
-
let error: String = "Must provide a playerId"
|
|
335
|
-
print(error)
|
|
336
|
-
call.resolve([ "result": false, "method": "getDuration", "message": error])
|
|
337
|
-
return
|
|
338
|
-
}
|
|
339
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
340
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
341
|
-
DispatchQueue.main.async {
|
|
342
|
-
let duration: Double = playerView.getDuration()
|
|
343
|
-
call.resolve([ "result": true, "method": "getDuration", "value": duration])
|
|
344
|
-
return
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
let error: String = "Fullscreen playerId not found"
|
|
348
|
-
print(error)
|
|
349
|
-
call.resolve([ "result": false, "method": "getDuration", "message": error])
|
|
350
|
-
return
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// MARK: - get CurrentTime for the given player
|
|
356
|
-
|
|
357
|
-
@objc func getCurrentTime(_ call: CAPPluginCall) {
|
|
358
|
-
self.call = call
|
|
359
|
-
|
|
360
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
361
|
-
let error: String = "Must provide a playerId"
|
|
362
|
-
print(error)
|
|
363
|
-
call.resolve([ "result": false, "method": "getCurrentTime", "message": error])
|
|
364
|
-
return
|
|
365
|
-
}
|
|
366
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
367
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
368
|
-
DispatchQueue.main.async {
|
|
369
|
-
let currentTime: Double = playerView.getCurrentTime()
|
|
370
|
-
call.resolve([ "result": true, "method": "getCurrentTime",
|
|
371
|
-
"value": currentTime])
|
|
372
|
-
return
|
|
373
|
-
}
|
|
374
|
-
} else {
|
|
375
|
-
let error: String = "Fullscreen playerId not found"
|
|
376
|
-
print(error)
|
|
377
|
-
call.resolve([ "result": false, "method": "getCurrentTime", "message": error])
|
|
378
|
-
return
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// MARK: - set CurrentTime for the given player
|
|
385
|
-
|
|
386
|
-
@objc func setCurrentTime(_ call: CAPPluginCall) {
|
|
387
|
-
self.call = call
|
|
388
|
-
|
|
389
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
390
|
-
let error: String = "Must provide a playerId"
|
|
391
|
-
print(error)
|
|
392
|
-
call.resolve([ "result": false, "method": "setCurrentTime", "message": error])
|
|
393
|
-
return
|
|
394
|
-
}
|
|
395
|
-
guard let seekTime = call.options["seektime"] as? Double else {
|
|
396
|
-
let error: String = "Must provide a time in second"
|
|
397
|
-
print(error)
|
|
398
|
-
call.resolve([ "result": false, "method": "setCurrentTime", "message": error])
|
|
399
|
-
return
|
|
400
|
-
}
|
|
401
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
402
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
403
|
-
DispatchQueue.main.async {
|
|
404
|
-
playerView.setCurrentTime(time: seekTime)
|
|
405
|
-
call.resolve([ "result": true, "method": "setCurrentTime",
|
|
406
|
-
"value": seekTime])
|
|
407
|
-
return
|
|
408
|
-
}
|
|
409
|
-
} else {
|
|
410
|
-
let error: String = "Fullscreen playerId not found"
|
|
411
|
-
print(error)
|
|
412
|
-
call.resolve([ "result": false, "method": "setCurrentTime", "message": error])
|
|
413
|
-
return
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// MARK: - get Volume for the given player
|
|
419
|
-
|
|
420
|
-
@objc func getVolume(_ call: CAPPluginCall) {
|
|
421
|
-
self.call = call
|
|
422
|
-
|
|
423
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
424
|
-
let error: String = "Must provide a playerId"
|
|
425
|
-
print(error)
|
|
426
|
-
call.resolve([ "result": false, "method": "getVolume", "message": error])
|
|
427
|
-
return
|
|
428
|
-
}
|
|
429
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
430
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
431
|
-
DispatchQueue.main.async {
|
|
432
|
-
let volume: Float = playerView.getVolume()
|
|
433
|
-
call.resolve([ "result": true, "method": "getVolume", "value": volume])
|
|
434
|
-
return
|
|
435
|
-
}
|
|
436
|
-
} else {
|
|
437
|
-
let error: String = "Fullscreen playerId not found"
|
|
438
|
-
print(error)
|
|
439
|
-
call.resolve([ "result": false, "method": "getVolume", "message": error])
|
|
440
|
-
return
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// MARK: - set Volume for the given player
|
|
446
|
-
|
|
447
|
-
@objc func setVolume(_ call: CAPPluginCall) {
|
|
448
|
-
self.call = call
|
|
449
|
-
|
|
450
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
451
|
-
let error: String = "Must provide a playerId"
|
|
452
|
-
print(error)
|
|
453
|
-
call.resolve([ "result": false, "method": "setVolume", "message": error])
|
|
454
|
-
return
|
|
455
|
-
}
|
|
456
|
-
guard let volume = call.options["volume"] as? Float else {
|
|
457
|
-
let error: String = "Must provide a volume value"
|
|
458
|
-
print(error)
|
|
459
|
-
call.resolve([ "result": false, "method": "setVolume", "message": error])
|
|
460
|
-
|
|
461
|
-
return
|
|
462
|
-
}
|
|
463
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
464
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
465
|
-
DispatchQueue.main.async {
|
|
466
|
-
playerView.setVolume(volume: volume)
|
|
467
|
-
call.resolve([ "result": true, "method": "setVolume", "value": volume])
|
|
468
|
-
return
|
|
469
|
-
}
|
|
470
|
-
} else {
|
|
471
|
-
let error: String = "Fullscreen playerId not found"
|
|
472
|
-
print(error)
|
|
473
|
-
call.resolve([ "result": false, "method": "setVolume", "message": error])
|
|
474
|
-
return
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// MARK: - get Muted for the given player
|
|
481
|
-
|
|
482
|
-
@objc func getMuted(_ call: CAPPluginCall) {
|
|
483
|
-
self.call = call
|
|
484
|
-
|
|
485
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
486
|
-
let error: String = "Must provide a playerId"
|
|
487
|
-
print(error)
|
|
488
|
-
call.resolve([ "result": false, "method": "getMuted", "message": error])
|
|
489
|
-
return
|
|
490
|
-
}
|
|
491
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
492
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
493
|
-
DispatchQueue.main.async {
|
|
494
|
-
let muted: Bool = playerView.getMuted()
|
|
495
|
-
call.resolve([ "result": true, "method": "getMuted", "value": muted])
|
|
496
|
-
return
|
|
497
|
-
}
|
|
498
|
-
} else {
|
|
499
|
-
let error: String = "Fullscreen playerId not found"
|
|
500
|
-
print(error)
|
|
501
|
-
call.resolve([ "result": false, "method": "getMuted", "message": error])
|
|
502
|
-
return
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// MARK: - set Muted for the given player
|
|
508
|
-
|
|
509
|
-
@objc func setMuted(_ call: CAPPluginCall) {
|
|
510
|
-
self.call = call
|
|
511
|
-
|
|
512
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
513
|
-
let error: String = "Must provide a playerId"
|
|
514
|
-
print(error)
|
|
515
|
-
call.resolve([ "result": false, "method": "setMuted", "message": error])
|
|
516
|
-
return
|
|
517
|
-
}
|
|
518
|
-
guard let muted = call.options["muted"] as? Bool else {
|
|
519
|
-
let error: String = "Must provide a boolean true/false"
|
|
520
|
-
print(error)
|
|
521
|
-
call.resolve([ "result": false, "method": "setMuted", "message": error])
|
|
522
|
-
return
|
|
523
|
-
}
|
|
524
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
525
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
526
|
-
DispatchQueue.main.async {
|
|
527
|
-
playerView.setMuted(muted: muted)
|
|
528
|
-
call.resolve([ "result": true, "method": "setMuted", "value": muted])
|
|
529
|
-
return
|
|
530
|
-
}
|
|
531
|
-
} else {
|
|
532
|
-
let error: String = "Fullscreen playerId not found"
|
|
533
|
-
print(error)
|
|
534
|
-
call.resolve([ "result": false, "method": "setMuted", "message": error])
|
|
535
|
-
return
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// MARK: - Stop all player(s) playing
|
|
541
|
-
|
|
542
|
-
@objc func stopAllPlayers(_ call: CAPPluginCall) {
|
|
543
|
-
self.call = call
|
|
544
|
-
if self.mode == "fullscreen" {
|
|
545
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
546
|
-
DispatchQueue.main.async {
|
|
547
|
-
if playerView.isPlaying {
|
|
548
|
-
playerView.pause()
|
|
549
|
-
}
|
|
550
|
-
call.resolve([ "result": true, "method": "stopAllPlayers", "value": true])
|
|
551
|
-
return
|
|
552
|
-
}
|
|
553
|
-
} else {
|
|
554
|
-
let error: String = "Fullscreen player not found"
|
|
555
|
-
print(error)
|
|
556
|
-
call.resolve([ "result": false, "method": "stopAllPlayers", "message": error])
|
|
557
|
-
return
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// MARK: - get Rate for the given player
|
|
564
|
-
|
|
565
|
-
@objc func getRate(_ call: CAPPluginCall) {
|
|
566
|
-
self.call = call
|
|
567
|
-
|
|
568
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
569
|
-
let error: String = "Must provide a playerId"
|
|
570
|
-
print(error)
|
|
571
|
-
call.resolve([ "result": false, "method": "getRate", "message": error])
|
|
572
|
-
return
|
|
573
|
-
}
|
|
574
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
575
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
576
|
-
DispatchQueue.main.async {
|
|
577
|
-
let rate: Float = playerView.getRate()
|
|
578
|
-
call.resolve([ "result": true, "method": "getRate", "value": rate])
|
|
579
|
-
return
|
|
580
|
-
}
|
|
581
|
-
} else {
|
|
582
|
-
let error: String = "Fullscreen playerId not found"
|
|
583
|
-
print(error)
|
|
584
|
-
call.resolve([ "result": false, "method": "getRate", "message": error])
|
|
585
|
-
return
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
// MARK: - set Rate for the given player
|
|
591
|
-
|
|
592
|
-
@objc func setRate(_ call: CAPPluginCall) {
|
|
593
|
-
self.call = call
|
|
594
|
-
|
|
595
|
-
guard let playerId = call.options["playerId"] as? String else {
|
|
596
|
-
let error: String = "Must provide a playerId"
|
|
597
|
-
print(error)
|
|
598
|
-
call.resolve([ "result": false, "method": "setRate", "message": error])
|
|
599
|
-
return
|
|
600
|
-
}
|
|
601
|
-
guard let rate = call.options["rate"] as? Float else {
|
|
602
|
-
let error: String = "Must provide a rate value"
|
|
603
|
-
print(error)
|
|
604
|
-
call.resolve([ "result": false, "method": "setRate", "message": error])
|
|
605
|
-
|
|
606
|
-
return
|
|
607
|
-
}
|
|
608
|
-
self.videoRate = rateList.contains(rate) ? rate : 1.0
|
|
609
|
-
|
|
610
|
-
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
611
|
-
if let playerView = self.videoPlayerFullScreenView {
|
|
612
|
-
//34567890123456789012345678901234567890
|
|
613
|
-
DispatchQueue.main.async {
|
|
614
|
-
playerView.setRate(rate: self.videoRate)
|
|
615
|
-
call.resolve([ "result": true, "method": "setRate",
|
|
616
|
-
"value": self.videoRate])
|
|
617
|
-
return
|
|
618
|
-
}
|
|
619
|
-
} else {
|
|
620
|
-
let error: String = "Fullscreen playerId not found"
|
|
621
|
-
print(error)
|
|
622
|
-
call.resolve([ "result": false, "method": "setRate", "message": error])
|
|
623
|
-
return
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// swiftlint:enable type_body_length
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
import AVKit
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Please read the Capacitor iOS Plugin Development Guide
|
|
8
|
+
* here: https://capacitorjs.com/docs/plugins/ios
|
|
9
|
+
*/
|
|
10
|
+
@objc(CapacitorVideoPlayerPlugin)
|
|
11
|
+
// swiftlint:disable file_length
|
|
12
|
+
// swiftlint:disable type_body_length
|
|
13
|
+
public class CapacitorVideoPlayerPlugin: CAPPlugin {
|
|
14
|
+
public var call: CAPPluginCall?
|
|
15
|
+
public var videoPlayer: AVPlayerViewController?
|
|
16
|
+
public var bgPlayer: AVPlayer?
|
|
17
|
+
public let implementation = CapacitorVideoPlayer()
|
|
18
|
+
var videoPlayerFullScreenView: FullScreenVideoPlayerView?
|
|
19
|
+
var audioSession: AVAudioSession?
|
|
20
|
+
var mode: String?
|
|
21
|
+
var exitOnEnd: Bool = true
|
|
22
|
+
var loopOnEnd: Bool = false
|
|
23
|
+
var pipEnabled: Bool = true
|
|
24
|
+
var backModeEnabled: Bool = true
|
|
25
|
+
var showControls: Bool = true
|
|
26
|
+
var displayMode: String = "all"
|
|
27
|
+
var headers: [String: String]?
|
|
28
|
+
var title: String?
|
|
29
|
+
var smallTitle: String?
|
|
30
|
+
var artwork: String?
|
|
31
|
+
var fsPlayerId: String = "fullscreen"
|
|
32
|
+
var videoRate: Float = 1.0
|
|
33
|
+
var playObserver: Any?
|
|
34
|
+
var pauseObserver: Any?
|
|
35
|
+
var endObserver: Any?
|
|
36
|
+
var readyObserver: Any?
|
|
37
|
+
var fsDismissObserver: Any?
|
|
38
|
+
var backgroundObserver: Any?
|
|
39
|
+
var foregroundObserver: Any?
|
|
40
|
+
var vpInternalObserver: Any?
|
|
41
|
+
let rateList: [Float] = [0.25, 0.5, 0.75, 1.0, 2.0, 4.0]
|
|
42
|
+
|
|
43
|
+
override public func load() {
|
|
44
|
+
self.addObserversToNotificationCenter()
|
|
45
|
+
if (UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad),
|
|
46
|
+
#available(iOS 13.0, *) {
|
|
47
|
+
isPIPModeAvailable = true
|
|
48
|
+
} else if #available(iOS 14.0, *) {
|
|
49
|
+
isPIPModeAvailable = true
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
deinit {
|
|
53
|
+
NotificationCenter.default.removeObserver(playObserver as Any)
|
|
54
|
+
NotificationCenter.default.removeObserver(pauseObserver as Any)
|
|
55
|
+
NotificationCenter.default.removeObserver(endObserver as Any)
|
|
56
|
+
NotificationCenter.default.removeObserver(readyObserver as Any)
|
|
57
|
+
NotificationCenter.default.removeObserver(fsDismissObserver as Any)
|
|
58
|
+
NotificationCenter.default.removeObserver(backgroundObserver as Any)
|
|
59
|
+
NotificationCenter.default.removeObserver(foregroundObserver as Any)
|
|
60
|
+
NotificationCenter.default.removeObserver(vpInternalObserver as Any)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@objc func echo(_ call: CAPPluginCall) {
|
|
64
|
+
let value = call.getString("value") ?? ""
|
|
65
|
+
call.resolve([
|
|
66
|
+
"value": implementation.echo(value)
|
|
67
|
+
])
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// MARK: - Init player(s)
|
|
71
|
+
|
|
72
|
+
// swiftlint:disable function_body_length
|
|
73
|
+
// swiftlint:disable cyclomatic_complexity
|
|
74
|
+
@objc func initPlayer(_ call: CAPPluginCall) {
|
|
75
|
+
self.call = call
|
|
76
|
+
guard let mode = call.options["mode"] as? String else {
|
|
77
|
+
let error: String = "Must provide a Mode " +
|
|
78
|
+
"(fullscreen/embedded)"
|
|
79
|
+
call.resolve([ "result": false, "method": "initPlayer",
|
|
80
|
+
"message": error])
|
|
81
|
+
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
85
|
+
let error: String = "Must provide a PlayerId"
|
|
86
|
+
call.resolve([ "result": false, "method": "initPlayer",
|
|
87
|
+
"message": error])
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
var mRate: Float = 1.0
|
|
91
|
+
if let sRate = call.options["rate"] as? Float {
|
|
92
|
+
if rateList.contains(sRate) {
|
|
93
|
+
mRate = sRate
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
var exitOnEnd: Bool = true
|
|
97
|
+
if let sexitOnEnd = call.options["exitOnEnd"] as? Bool {
|
|
98
|
+
exitOnEnd = sexitOnEnd
|
|
99
|
+
}
|
|
100
|
+
var loopOnEnd: Bool = false
|
|
101
|
+
if let sloopOnEnd = call.options["loopOnEnd"] as? Bool {
|
|
102
|
+
if !exitOnEnd {
|
|
103
|
+
loopOnEnd = sloopOnEnd
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
var headers: [String: String]?
|
|
107
|
+
if let sheaders = call.options["headers"] as? [String: String] {
|
|
108
|
+
headers = sheaders
|
|
109
|
+
}
|
|
110
|
+
var pipEnabled: Bool = true
|
|
111
|
+
if let spipEnabled = call.options["pipEnabled"] as? Bool {
|
|
112
|
+
pipEnabled = spipEnabled
|
|
113
|
+
}
|
|
114
|
+
var bkModeEnabled: Bool = true
|
|
115
|
+
if let sbkModeEnabled = call.options["bkmodeEnabled"] as? Bool {
|
|
116
|
+
bkModeEnabled = sbkModeEnabled
|
|
117
|
+
}
|
|
118
|
+
var shControls: Bool = true
|
|
119
|
+
if let shoControls = call.options["showControls"] as? Bool {
|
|
120
|
+
shControls = shoControls
|
|
121
|
+
}
|
|
122
|
+
var disMode: String = "all"
|
|
123
|
+
if let dispMode = call.options["displayMode"] as? String {
|
|
124
|
+
disMode = dispMode
|
|
125
|
+
}
|
|
126
|
+
var title: String?
|
|
127
|
+
if let stitle = call.options["title"] as? String {
|
|
128
|
+
title = stitle
|
|
129
|
+
}
|
|
130
|
+
var smallTitle: String?
|
|
131
|
+
if let ssmallTitle = call.options["smallTitle"] as? String {
|
|
132
|
+
smallTitle = ssmallTitle
|
|
133
|
+
}
|
|
134
|
+
var artwork: String?
|
|
135
|
+
if let sartwork = call.options["artwork"] as? String {
|
|
136
|
+
artwork = sartwork
|
|
137
|
+
}
|
|
138
|
+
self.fsPlayerId = playerId
|
|
139
|
+
self.mode = mode
|
|
140
|
+
self.videoRate = mRate
|
|
141
|
+
self.exitOnEnd = exitOnEnd
|
|
142
|
+
self.loopOnEnd = loopOnEnd
|
|
143
|
+
self.pipEnabled = pipEnabled
|
|
144
|
+
self.headers = headers
|
|
145
|
+
if !self.pipEnabled {isPIPModeAvailable = false}
|
|
146
|
+
self.backModeEnabled = bkModeEnabled
|
|
147
|
+
self.showControls = shControls
|
|
148
|
+
self.displayMode = disMode
|
|
149
|
+
self.title = title
|
|
150
|
+
self.smallTitle = smallTitle
|
|
151
|
+
self.artwork = artwork
|
|
152
|
+
if mode == "fullscreen" {
|
|
153
|
+
guard let videoPath = call.options["url"] as? String else {
|
|
154
|
+
let error: String = "Must provide a video url"
|
|
155
|
+
print(error)
|
|
156
|
+
call.resolve([ "result": false, "method": "initPlayer", "message": error])
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
var subTitlePath: String = ""
|
|
160
|
+
if let stPath = call.options["subtitle"] as? String {
|
|
161
|
+
subTitlePath = stPath
|
|
162
|
+
}
|
|
163
|
+
var subTitleLanguage: String = ""
|
|
164
|
+
if let stLanguage = call.options["language"] as? String {
|
|
165
|
+
subTitleLanguage = stLanguage
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let subTitleOptions: [String: Any] = call.getObject("subtitleOptions") ?? [:]
|
|
169
|
+
|
|
170
|
+
if videoPath == "internal" {
|
|
171
|
+
DispatchQueue.main.async { [weak self] in
|
|
172
|
+
if let videoPickerViewController =
|
|
173
|
+
self?.implementation.pickVideoFromInternal(
|
|
174
|
+
rate: self?.videoRate ?? 1.0,
|
|
175
|
+
exitOnEnd: self?.exitOnEnd ?? true,
|
|
176
|
+
loopOnEnd: self?.loopOnEnd ?? false,
|
|
177
|
+
pipEnabled: self?.pipEnabled ?? true,
|
|
178
|
+
backModeEnabled: self?.backModeEnabled ?? true,
|
|
179
|
+
showControls: self?.showControls ?? true,
|
|
180
|
+
displayMode: self?.displayMode ?? "all") {
|
|
181
|
+
self?.bridge?.viewController?.present(
|
|
182
|
+
videoPickerViewController,
|
|
183
|
+
animated: true, completion: {return})
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
} else {
|
|
188
|
+
let dictUrl: [String: Any] =
|
|
189
|
+
getURLFromFilePath(filePath: videoPath)
|
|
190
|
+
if let message = dictUrl["message"] as? String {
|
|
191
|
+
if message.count > 0 {
|
|
192
|
+
call.resolve([ "result": false, "method": "initPlayer",
|
|
193
|
+
"message": message])
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
guard let url = dictUrl["url"] as? URL else {
|
|
198
|
+
call.resolve([ "result": false, "method": "initPlayer",
|
|
199
|
+
"message": "url not defined"])
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
var subTitle: URL?
|
|
203
|
+
if subTitlePath.count > 0 {
|
|
204
|
+
|
|
205
|
+
let dictSubTitle: [String: Any] =
|
|
206
|
+
getURLFromFilePath(filePath: subTitlePath)
|
|
207
|
+
if let message = dictSubTitle["message"] as? String {
|
|
208
|
+
if message.count > 0 {
|
|
209
|
+
call.resolve([ "result": false, "method": "initPlayer",
|
|
210
|
+
"message": message])
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
guard let sturl = dictSubTitle["url"] as? URL else {
|
|
215
|
+
call.resolve([ "result": false, "method": "initPlayer",
|
|
216
|
+
"message": "subtitle url not defined"])
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
subTitle = sturl
|
|
220
|
+
}
|
|
221
|
+
guard let call = self.call else { return }
|
|
222
|
+
self.createVideoPlayerFullscreenView(
|
|
223
|
+
call: call, videoUrl: url, rate: videoRate,
|
|
224
|
+
exitOnEnd: exitOnEnd, loopOnEnd: loopOnEnd,
|
|
225
|
+
pipEnabled: pipEnabled,
|
|
226
|
+
backModeEnabled: backModeEnabled,
|
|
227
|
+
showControls: showControls,
|
|
228
|
+
displayMode: displayMode,
|
|
229
|
+
subTitleUrl: subTitle,
|
|
230
|
+
subTitleLanguage: subTitleLanguage,
|
|
231
|
+
subTitleOptions: subTitleOptions,
|
|
232
|
+
headers: headers,
|
|
233
|
+
title: title,
|
|
234
|
+
smallTitle: smallTitle,
|
|
235
|
+
artwork: artwork)
|
|
236
|
+
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
call.resolve([ "result": false,
|
|
240
|
+
"method": "initPlayer",
|
|
241
|
+
"message": "Not implemented"])
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// swiftlint:enable function_body_length
|
|
246
|
+
// swiftlint:enable cyclomatic_complexity
|
|
247
|
+
|
|
248
|
+
// MARK: - Play the given player
|
|
249
|
+
|
|
250
|
+
@objc func isPlaying(_ call: CAPPluginCall) {
|
|
251
|
+
self.call = call
|
|
252
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
253
|
+
let error: String = "Must provide a playerId"
|
|
254
|
+
print(error)
|
|
255
|
+
call.resolve([ "result": false, "method": "isPlaying", "message": error])
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
259
|
+
|
|
260
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
261
|
+
DispatchQueue.main.async {
|
|
262
|
+
let isPlaying: Bool = playerView.isPlaying
|
|
263
|
+
call.resolve([ "result": true, "method": "isPlaying", "value": isPlaying])
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
let error: String = "Fullscreen player not found"
|
|
268
|
+
print(error)
|
|
269
|
+
call.resolve([ "result": false, "method": "isPlaying", "message": error])
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// MARK: - Play the given player
|
|
275
|
+
|
|
276
|
+
@objc func play(_ call: CAPPluginCall) {
|
|
277
|
+
self.call = call
|
|
278
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
279
|
+
let error: String = "Must provide a playerId"
|
|
280
|
+
print(error)
|
|
281
|
+
call.resolve([ "result": false, "method": "play", "message": error])
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
285
|
+
|
|
286
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
287
|
+
DispatchQueue.main.async {
|
|
288
|
+
playerView.play()
|
|
289
|
+
call.resolve([ "result": true, "method": "play", "value": true])
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
let error: String = "Fullscreen player not found"
|
|
294
|
+
print(error)
|
|
295
|
+
call.resolve([ "result": false, "method": "play", "message": error])
|
|
296
|
+
return
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// MARK: - Pause the given player
|
|
302
|
+
|
|
303
|
+
@objc func pause(_ call: CAPPluginCall) {
|
|
304
|
+
self.call = call
|
|
305
|
+
|
|
306
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
307
|
+
let error: String = "Must provide a playerId"
|
|
308
|
+
print(error)
|
|
309
|
+
call.resolve([ "result": false, "method": "pause", "message": error])
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
313
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
314
|
+
DispatchQueue.main.async {
|
|
315
|
+
playerView.pause()
|
|
316
|
+
call.resolve([ "result": true, "method": "pause", "value": true])
|
|
317
|
+
return
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
let error: String = "Fullscreen player not found"
|
|
321
|
+
print(error)
|
|
322
|
+
call.resolve([ "result": false, "method": "pause", "message": error])
|
|
323
|
+
return
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// MARK: - get Duration for the given player
|
|
329
|
+
|
|
330
|
+
@objc func getDuration(_ call: CAPPluginCall) {
|
|
331
|
+
self.call = call
|
|
332
|
+
|
|
333
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
334
|
+
let error: String = "Must provide a playerId"
|
|
335
|
+
print(error)
|
|
336
|
+
call.resolve([ "result": false, "method": "getDuration", "message": error])
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
340
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
341
|
+
DispatchQueue.main.async {
|
|
342
|
+
let duration: Double = playerView.getDuration()
|
|
343
|
+
call.resolve([ "result": true, "method": "getDuration", "value": duration])
|
|
344
|
+
return
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
let error: String = "Fullscreen playerId not found"
|
|
348
|
+
print(error)
|
|
349
|
+
call.resolve([ "result": false, "method": "getDuration", "message": error])
|
|
350
|
+
return
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// MARK: - get CurrentTime for the given player
|
|
356
|
+
|
|
357
|
+
@objc func getCurrentTime(_ call: CAPPluginCall) {
|
|
358
|
+
self.call = call
|
|
359
|
+
|
|
360
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
361
|
+
let error: String = "Must provide a playerId"
|
|
362
|
+
print(error)
|
|
363
|
+
call.resolve([ "result": false, "method": "getCurrentTime", "message": error])
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
367
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
368
|
+
DispatchQueue.main.async {
|
|
369
|
+
let currentTime: Double = playerView.getCurrentTime()
|
|
370
|
+
call.resolve([ "result": true, "method": "getCurrentTime",
|
|
371
|
+
"value": currentTime])
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
let error: String = "Fullscreen playerId not found"
|
|
376
|
+
print(error)
|
|
377
|
+
call.resolve([ "result": false, "method": "getCurrentTime", "message": error])
|
|
378
|
+
return
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// MARK: - set CurrentTime for the given player
|
|
385
|
+
|
|
386
|
+
@objc func setCurrentTime(_ call: CAPPluginCall) {
|
|
387
|
+
self.call = call
|
|
388
|
+
|
|
389
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
390
|
+
let error: String = "Must provide a playerId"
|
|
391
|
+
print(error)
|
|
392
|
+
call.resolve([ "result": false, "method": "setCurrentTime", "message": error])
|
|
393
|
+
return
|
|
394
|
+
}
|
|
395
|
+
guard let seekTime = call.options["seektime"] as? Double else {
|
|
396
|
+
let error: String = "Must provide a time in second"
|
|
397
|
+
print(error)
|
|
398
|
+
call.resolve([ "result": false, "method": "setCurrentTime", "message": error])
|
|
399
|
+
return
|
|
400
|
+
}
|
|
401
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
402
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
403
|
+
DispatchQueue.main.async {
|
|
404
|
+
playerView.setCurrentTime(time: seekTime)
|
|
405
|
+
call.resolve([ "result": true, "method": "setCurrentTime",
|
|
406
|
+
"value": seekTime])
|
|
407
|
+
return
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
let error: String = "Fullscreen playerId not found"
|
|
411
|
+
print(error)
|
|
412
|
+
call.resolve([ "result": false, "method": "setCurrentTime", "message": error])
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// MARK: - get Volume for the given player
|
|
419
|
+
|
|
420
|
+
@objc func getVolume(_ call: CAPPluginCall) {
|
|
421
|
+
self.call = call
|
|
422
|
+
|
|
423
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
424
|
+
let error: String = "Must provide a playerId"
|
|
425
|
+
print(error)
|
|
426
|
+
call.resolve([ "result": false, "method": "getVolume", "message": error])
|
|
427
|
+
return
|
|
428
|
+
}
|
|
429
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
430
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
431
|
+
DispatchQueue.main.async {
|
|
432
|
+
let volume: Float = playerView.getVolume()
|
|
433
|
+
call.resolve([ "result": true, "method": "getVolume", "value": volume])
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
} else {
|
|
437
|
+
let error: String = "Fullscreen playerId not found"
|
|
438
|
+
print(error)
|
|
439
|
+
call.resolve([ "result": false, "method": "getVolume", "message": error])
|
|
440
|
+
return
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// MARK: - set Volume for the given player
|
|
446
|
+
|
|
447
|
+
@objc func setVolume(_ call: CAPPluginCall) {
|
|
448
|
+
self.call = call
|
|
449
|
+
|
|
450
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
451
|
+
let error: String = "Must provide a playerId"
|
|
452
|
+
print(error)
|
|
453
|
+
call.resolve([ "result": false, "method": "setVolume", "message": error])
|
|
454
|
+
return
|
|
455
|
+
}
|
|
456
|
+
guard let volume = call.options["volume"] as? Float else {
|
|
457
|
+
let error: String = "Must provide a volume value"
|
|
458
|
+
print(error)
|
|
459
|
+
call.resolve([ "result": false, "method": "setVolume", "message": error])
|
|
460
|
+
|
|
461
|
+
return
|
|
462
|
+
}
|
|
463
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
464
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
465
|
+
DispatchQueue.main.async {
|
|
466
|
+
playerView.setVolume(volume: volume)
|
|
467
|
+
call.resolve([ "result": true, "method": "setVolume", "value": volume])
|
|
468
|
+
return
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
let error: String = "Fullscreen playerId not found"
|
|
472
|
+
print(error)
|
|
473
|
+
call.resolve([ "result": false, "method": "setVolume", "message": error])
|
|
474
|
+
return
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// MARK: - get Muted for the given player
|
|
481
|
+
|
|
482
|
+
@objc func getMuted(_ call: CAPPluginCall) {
|
|
483
|
+
self.call = call
|
|
484
|
+
|
|
485
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
486
|
+
let error: String = "Must provide a playerId"
|
|
487
|
+
print(error)
|
|
488
|
+
call.resolve([ "result": false, "method": "getMuted", "message": error])
|
|
489
|
+
return
|
|
490
|
+
}
|
|
491
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
492
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
493
|
+
DispatchQueue.main.async {
|
|
494
|
+
let muted: Bool = playerView.getMuted()
|
|
495
|
+
call.resolve([ "result": true, "method": "getMuted", "value": muted])
|
|
496
|
+
return
|
|
497
|
+
}
|
|
498
|
+
} else {
|
|
499
|
+
let error: String = "Fullscreen playerId not found"
|
|
500
|
+
print(error)
|
|
501
|
+
call.resolve([ "result": false, "method": "getMuted", "message": error])
|
|
502
|
+
return
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// MARK: - set Muted for the given player
|
|
508
|
+
|
|
509
|
+
@objc func setMuted(_ call: CAPPluginCall) {
|
|
510
|
+
self.call = call
|
|
511
|
+
|
|
512
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
513
|
+
let error: String = "Must provide a playerId"
|
|
514
|
+
print(error)
|
|
515
|
+
call.resolve([ "result": false, "method": "setMuted", "message": error])
|
|
516
|
+
return
|
|
517
|
+
}
|
|
518
|
+
guard let muted = call.options["muted"] as? Bool else {
|
|
519
|
+
let error: String = "Must provide a boolean true/false"
|
|
520
|
+
print(error)
|
|
521
|
+
call.resolve([ "result": false, "method": "setMuted", "message": error])
|
|
522
|
+
return
|
|
523
|
+
}
|
|
524
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
525
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
526
|
+
DispatchQueue.main.async {
|
|
527
|
+
playerView.setMuted(muted: muted)
|
|
528
|
+
call.resolve([ "result": true, "method": "setMuted", "value": muted])
|
|
529
|
+
return
|
|
530
|
+
}
|
|
531
|
+
} else {
|
|
532
|
+
let error: String = "Fullscreen playerId not found"
|
|
533
|
+
print(error)
|
|
534
|
+
call.resolve([ "result": false, "method": "setMuted", "message": error])
|
|
535
|
+
return
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// MARK: - Stop all player(s) playing
|
|
541
|
+
|
|
542
|
+
@objc func stopAllPlayers(_ call: CAPPluginCall) {
|
|
543
|
+
self.call = call
|
|
544
|
+
if self.mode == "fullscreen" {
|
|
545
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
546
|
+
DispatchQueue.main.async {
|
|
547
|
+
if playerView.isPlaying {
|
|
548
|
+
playerView.pause()
|
|
549
|
+
}
|
|
550
|
+
call.resolve([ "result": true, "method": "stopAllPlayers", "value": true])
|
|
551
|
+
return
|
|
552
|
+
}
|
|
553
|
+
} else {
|
|
554
|
+
let error: String = "Fullscreen player not found"
|
|
555
|
+
print(error)
|
|
556
|
+
call.resolve([ "result": false, "method": "stopAllPlayers", "message": error])
|
|
557
|
+
return
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// MARK: - get Rate for the given player
|
|
564
|
+
|
|
565
|
+
@objc func getRate(_ call: CAPPluginCall) {
|
|
566
|
+
self.call = call
|
|
567
|
+
|
|
568
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
569
|
+
let error: String = "Must provide a playerId"
|
|
570
|
+
print(error)
|
|
571
|
+
call.resolve([ "result": false, "method": "getRate", "message": error])
|
|
572
|
+
return
|
|
573
|
+
}
|
|
574
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
575
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
576
|
+
DispatchQueue.main.async {
|
|
577
|
+
let rate: Float = playerView.getRate()
|
|
578
|
+
call.resolve([ "result": true, "method": "getRate", "value": rate])
|
|
579
|
+
return
|
|
580
|
+
}
|
|
581
|
+
} else {
|
|
582
|
+
let error: String = "Fullscreen playerId not found"
|
|
583
|
+
print(error)
|
|
584
|
+
call.resolve([ "result": false, "method": "getRate", "message": error])
|
|
585
|
+
return
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// MARK: - set Rate for the given player
|
|
591
|
+
|
|
592
|
+
@objc func setRate(_ call: CAPPluginCall) {
|
|
593
|
+
self.call = call
|
|
594
|
+
|
|
595
|
+
guard let playerId = call.options["playerId"] as? String else {
|
|
596
|
+
let error: String = "Must provide a playerId"
|
|
597
|
+
print(error)
|
|
598
|
+
call.resolve([ "result": false, "method": "setRate", "message": error])
|
|
599
|
+
return
|
|
600
|
+
}
|
|
601
|
+
guard let rate = call.options["rate"] as? Float else {
|
|
602
|
+
let error: String = "Must provide a rate value"
|
|
603
|
+
print(error)
|
|
604
|
+
call.resolve([ "result": false, "method": "setRate", "message": error])
|
|
605
|
+
|
|
606
|
+
return
|
|
607
|
+
}
|
|
608
|
+
self.videoRate = rateList.contains(rate) ? rate : 1.0
|
|
609
|
+
|
|
610
|
+
if self.mode == "fullscreen" && self.fsPlayerId == playerId {
|
|
611
|
+
if let playerView = self.videoPlayerFullScreenView {
|
|
612
|
+
//34567890123456789012345678901234567890
|
|
613
|
+
DispatchQueue.main.async {
|
|
614
|
+
playerView.setRate(rate: self.videoRate)
|
|
615
|
+
call.resolve([ "result": true, "method": "setRate",
|
|
616
|
+
"value": self.videoRate])
|
|
617
|
+
return
|
|
618
|
+
}
|
|
619
|
+
} else {
|
|
620
|
+
let error: String = "Fullscreen playerId not found"
|
|
621
|
+
print(error)
|
|
622
|
+
call.resolve([ "result": false, "method": "setRate", "message": error])
|
|
623
|
+
return
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// swiftlint:enable type_body_length
|
|
632
632
|
// swiftlint:enable file_length
|