@jwplayer/jwplayer-react-native 1.0.0 → 1.0.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.
Files changed (43) hide show
  1. package/.github/CODEOWNERS +1 -1
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +12 -2
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +12 -2
  4. package/.github/ISSUE_TEMPLATE/implement.md +26 -0
  5. package/.github/ISSUE_TEMPLATE/question.md +12 -2
  6. package/README.md +25 -3
  7. package/RNJWPlayer.podspec +2 -2
  8. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  9. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  10. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  11. package/android/.gradle/buildOutputCleanup/cache.properties +2 -2
  12. package/android/build.gradle +2 -2
  13. package/android/src/main/AndroidManifest.xml +2 -0
  14. package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerView.java +259 -11
  15. package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerViewManager.java +4 -0
  16. package/android/src/main/java/com/jwplayer/rnjwplayer/Util.java +24 -3
  17. package/badges/version.svg +1 -1
  18. package/index.d.ts +14 -2
  19. package/index.js +8 -2
  20. package/ios/RNJWPlayer/RNJWPlayerView.swift +202 -196
  21. package/ios/RNJWPlayer/RNJWPlayerViewController.swift +27 -23
  22. package/ios/RNJWPlayer/RNJWPlayerViewManager.m +4 -0
  23. package/ios/RNJWPlayer/RNJWPlayerViewManager.swift +5 -3
  24. package/package.json +3 -3
  25. package/android/.gradle/8.1.1/checksums/checksums.lock +0 -0
  26. package/android/.gradle/8.1.1/dependencies-accessors/dependencies-accessors.lock +0 -0
  27. package/android/.gradle/8.1.1/fileHashes/fileHashes.lock +0 -0
  28. package/android/.gradle/8.2/checksums/checksums.lock +0 -0
  29. package/android/.gradle/8.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  30. package/android/.gradle/8.2/dependencies-accessors/gc.properties +0 -0
  31. package/android/.gradle/8.2/fileChanges/last-build.bin +0 -0
  32. package/android/.gradle/8.2/fileHashes/fileHashes.lock +0 -0
  33. package/android/.gradle/8.2/gc.properties +0 -0
  34. package/android/.gradle/config.properties +0 -2
  35. package/android/.idea/gradle.xml +0 -12
  36. package/android/.idea/migrations.xml +0 -10
  37. package/android/.idea/misc.xml +0 -10
  38. package/android/.idea/vcs.xml +0 -6
  39. package/android/.idea/workspace.xml +0 -54
  40. package/android/local.properties +0 -8
  41. /package/android/.gradle/{8.1.1 → 8.9}/dependencies-accessors/gc.properties +0 -0
  42. /package/android/.gradle/{8.1.1 → 8.9}/fileChanges/last-build.bin +0 -0
  43. /package/android/.gradle/{8.1.1 → 8.9}/gc.properties +0 -0
@@ -159,6 +159,10 @@ public class RNJWPlayerViewManager extends SimpleViewManager<RNJWPlayerView> {
159
159
  MapBuilder.of(
160
160
  "phasedRegistrationNames",
161
161
  MapBuilder.of("bubbled", "onCasting")))
162
+ .put("topFirstFrame",
163
+ MapBuilder.of(
164
+ "phasedRegistrationNames",
165
+ MapBuilder.of("bubbled", "onLoaded")))
162
166
  .build();
163
167
  }
164
168
 
@@ -21,6 +21,7 @@ import java.net.URL;
21
21
  import java.util.ArrayList;
22
22
  import java.util.List;
23
23
  import java.util.Map;
24
+ import java.util.Locale;
24
25
 
25
26
  public class Util {
26
27
 
@@ -98,7 +99,7 @@ public class Util {
98
99
  if (sourceProp.hasKey("file")) {
99
100
  String file = sourceProp.getString("file");
100
101
  String label = sourceProp.getString("label");
101
- boolean isDefault = sourceProp.getBoolean("default");
102
+ boolean isDefault = sourceProp.hasKey("default") ? sourceProp.getBoolean("default") : false;
102
103
  MediaSource source = new MediaSource.Builder().file(file).label(label).isDefault(isDefault).build();
103
104
  sources.add(source);
104
105
  }
@@ -147,8 +148,13 @@ public class Util {
147
148
  if (trackProp.hasKey("file")) {
148
149
  String file = trackProp.getString("file");
149
150
  String label = trackProp.getString("label");
150
- boolean isDefault = trackProp.getBoolean("default");
151
- Caption caption = new Caption.Builder().file(file).label(label).kind(CaptionType.CAPTIONS).isDefault(isDefault).build();
151
+ CaptionType kind = CaptionType.CAPTIONS;
152
+ // Being safe to old implementations though this should be required.
153
+ if (trackProp.hasKey("kind")) {
154
+ kind = getCaptionType(trackProp.getString("kind").toUpperCase(Locale.US));
155
+ }
156
+ boolean isDefault = trackProp.hasKey("default") ? trackProp.getBoolean("default") : false;
157
+ Caption caption = new Caption.Builder().file(file).label(label).kind(kind).isDefault(isDefault).build();
152
158
  tracks.add(caption);
153
159
  }
154
160
  }
@@ -186,6 +192,21 @@ public class Util {
186
192
  return itemBuilder.build();
187
193
  }
188
194
 
195
+ /**
196
+ * Internal helper for parsing a caption type from a known string
197
+ * @param type one of "CAPTIONS", "CHAPTERS", "THUMBNAILS"
198
+ * @return the correct Enum CaptionType
199
+ */
200
+ public static CaptionType getCaptionType(String type){
201
+ for (CaptionType captionType: CaptionType.values()) {
202
+ if (captionType.name().equals(type)) {
203
+ return CaptionType.valueOf(type);
204
+ }
205
+ }
206
+ // This should never happen. If a null is returned, expect a crash. Check `type` is specified type
207
+ return null;
208
+ }
209
+
189
210
  public enum AdEventType {
190
211
  JWAdEventTypeAdBreakEnd(0),
191
212
  JWAdEventTypeAdBreakStart(1),
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="version: 1.0.0"><title>version: 1.0.0</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="39" height="20" fill="#007ec6"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">version</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">1.0.0</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="290">1.0.0</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="version: 1.0.2"><title>version: 1.0.2</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="39" height="20" fill="#007ec6"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">version</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">1.0.2</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="290">1.0.2</text></g></svg>
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare module "jwplayer-react-native" {
1
+ declare module "@jwplayer/jwplayer-react-native" {
2
2
  import React from "react";
3
3
  import { ViewStyle } from "react-native";
4
4
 
@@ -216,7 +216,7 @@ declare module "jwplayer-react-native" {
216
216
  interface JwTrack {
217
217
  id?: string;
218
218
  file?: string;
219
- kind: string;
219
+ kind: TrackKind;
220
220
  label?: string;
221
221
  default?: boolean;
222
222
  }
@@ -251,9 +251,13 @@ declare module "jwplayer-react-native" {
251
251
  label: string;
252
252
  default?: boolean;
253
253
  }
254
+
255
+ type TrackKind = "captions" | "chapters" | "thumbnails";
256
+
254
257
  interface Track {
255
258
  file: string;
256
259
  label: string;
260
+ kind: TrackKind;
257
261
  default?: boolean;
258
262
  }
259
263
  interface JWAdSettings {
@@ -349,6 +353,9 @@ declare module "jwplayer-react-native" {
349
353
  size?: number;
350
354
  }
351
355
  type EdgeStyles = "none" | "dropshadow" | "raised" | "depressed" | "uniform";
356
+
357
+ // All `Styling` is only intended to be used with iOS. Android requires overloading
358
+ // of the JWP IDs seen here: https://docs.jwplayer.com/players/docs/android-styling-guide
352
359
  interface Styling {
353
360
  colors?: {
354
361
  buttons?: string;
@@ -441,6 +448,7 @@ declare module "jwplayer-react-native" {
441
448
  landscapeOnFullScreen?: boolean;
442
449
  portraitOnExitFullScreen?: boolean;
443
450
  exitFullScreenOnPortrait?: boolean;
451
+ playerInModal?: boolean;
444
452
  playlist?: PlaylistItem[];
445
453
  stretching?: string;
446
454
  related?: Related;
@@ -479,6 +487,9 @@ declare module "jwplayer-react-native" {
479
487
  interface PlaylistEventProps {
480
488
  playlist: PlaylistItem[]
481
489
  }
490
+ interface LoadEventProps {
491
+ loadTime: number;
492
+ }
482
493
  interface PlaylistItemEventProps {
483
494
  playlistItem: PlaylistItem
484
495
  }
@@ -504,6 +515,7 @@ declare module "jwplayer-react-native" {
504
515
  forceLegacyConfig?: boolean;
505
516
  onPlayerReady?: () => void;
506
517
  onPlaylist?: (event: BaseEvent<PlaylistEventProps>) => void;
518
+ onLoaded? : (event: BaseEvent<LoadEventProps>) => void;
507
519
  onBeforePlay?: () => void;
508
520
  onBeforeComplete?: () => void;
509
521
  onComplete?: () => void;
package/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  findNodeHandle,
7
7
  } from 'react-native';
8
8
  import PropTypes from 'prop-types';
9
- import _ from 'lodash';
9
+ import isEqualWith from 'lodash.isequalwith';
10
10
 
11
11
  const RNJWPlayerManager =
12
12
  Platform.OS === 'ios'
@@ -232,6 +232,8 @@ export default class JWPlayer extends Component {
232
232
  PropTypes.shape({
233
233
  file: PropTypes.string,
234
234
  label: PropTypes.string,
235
+ kind: PropTypes.oneOf(['captions', 'thumbnails', 'chapters']),
236
+ default: PropTypes.bool
235
237
  })
236
238
  ),
237
239
  adSchedule: PropTypes.arrayOf(
@@ -252,6 +254,8 @@ export default class JWPlayer extends Component {
252
254
  'hidden',
253
255
  'onscreen',
254
256
  ]),
257
+ // All `Styling` is only intended to be used with iOS. Android requires overloading
258
+ // of the JWP IDs seen here: https://docs.jwplayer.com/players/docs/android-styling-guide
255
259
  styling: PropTypes.shape({
256
260
  colors: PropTypes.shape({
257
261
  buttons: PropTypes.string,
@@ -302,6 +306,7 @@ export default class JWPlayer extends Component {
302
306
  offlineImage: PropTypes.string,
303
307
  forceFullScreenOnLandscape: PropTypes.bool,
304
308
  forceLandscapeOnFullScreen: PropTypes.bool,
309
+ playerInModal: PropTypes.bool,
305
310
  enableLockScreenControls: PropTypes.bool,
306
311
  stretching: PropTypes.oneOf([
307
312
  'uniform',
@@ -315,6 +320,7 @@ export default class JWPlayer extends Component {
315
320
  }),
316
321
  onPlayerReady: PropTypes.func,
317
322
  onPlaylist: PropTypes.func,
323
+ onLoaded: PropTypes.func,
318
324
  changePlaylist: PropTypes.func,
319
325
  play: PropTypes.func,
320
326
  pause: PropTypes.func,
@@ -385,7 +391,7 @@ export default class JWPlayer extends Component {
385
391
  var { config, controls } = nextProps;
386
392
  var thisConfig = this.props.config || {};
387
393
 
388
- var result = !_.isEqualWith(
394
+ var result = !isEqualWith(
389
395
  config,
390
396
  thisConfig,
391
397
  (value1, value2, key) => {
@@ -10,14 +10,17 @@ import AVFoundation
10
10
  import AVKit
11
11
  import MediaPlayer
12
12
  import React
13
- import GoogleCast
14
13
  import JWPlayerKit
15
14
 
16
- class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDelegate, JWCastDelegate, JWAVDelegate, JWPlayerViewDelegate, JWPlayerViewControllerDelegate, JWDRMContentKeyDataSource, AVPictureInPictureControllerDelegate {
15
+ #if USE_GOOGLE_CAST
16
+ import GoogleCast
17
+ #endif
18
+
19
+ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDelegate, JWAVDelegate, JWPlayerViewDelegate, JWPlayerViewControllerDelegate, JWDRMContentKeyDataSource, JWTimeEventListener, AVPictureInPictureControllerDelegate {
17
20
 
18
21
  // MARK: - RNJWPlayer allocation
19
22
 
20
- var playerViewController:RNJWPlayerViewController!
23
+ var playerViewController: RNJWPlayerViewController!
21
24
  var playerView: JWPlayerView!
22
25
  var audioSession: AVAudioSession!
23
26
  var pipEnabled: Bool = true
@@ -39,49 +42,49 @@ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDele
39
42
  var isCasting: Bool = false
40
43
  var availableDevices: [AnyObject]!
41
44
 
42
- @objc var onBuffer:RCTDirectEventBlock?
43
- @objc var onUpdateBuffer:RCTDirectEventBlock?
44
- @objc var onPlay:RCTDirectEventBlock?
45
- @objc var onBeforePlay:RCTDirectEventBlock?
46
- @objc var onAttemptPlay:RCTDirectEventBlock?
47
- @objc var onPause:RCTDirectEventBlock?
48
- @objc var onIdle:RCTDirectEventBlock?
49
- @objc var onPlaylistItem:RCTDirectEventBlock?
50
- @objc var onLoaded:RCTDirectEventBlock?
51
- @objc var onVisible:RCTDirectEventBlock?
52
- @objc var onTime:RCTDirectEventBlock?
53
- @objc var onSeek:RCTDirectEventBlock?
54
- @objc var onSeeked:RCTDirectEventBlock?
55
- @objc var onRateChanged:RCTDirectEventBlock?
56
- @objc var onPlaylist:RCTDirectEventBlock?
57
- @objc var onPlaylistComplete:RCTDirectEventBlock?
58
- @objc var onBeforeComplete:RCTDirectEventBlock?
59
- @objc var onComplete:RCTDirectEventBlock?
60
- @objc var onAudioTracks:RCTDirectEventBlock?
61
- @objc var onPlayerReady:RCTDirectEventBlock?
62
- @objc var onSetupPlayerError:RCTDirectEventBlock?
63
- @objc var onPlayerError:RCTDirectEventBlock?
64
- @objc var onPlayerWarning:RCTDirectEventBlock?
65
- @objc var onPlayerAdWarning:RCTDirectEventBlock?
66
- @objc var onPlayerAdError:RCTDirectEventBlock?
67
- @objc var onAdEvent:RCTDirectEventBlock?
68
- @objc var onAdTime:RCTDirectEventBlock?
69
- @objc var onScreenTapped:RCTDirectEventBlock?
70
- @objc var onControlBarVisible:RCTDirectEventBlock?
71
- @objc var onFullScreen:RCTDirectEventBlock?
72
- @objc var onFullScreenRequested:RCTDirectEventBlock?
73
- @objc var onFullScreenExit:RCTDirectEventBlock?
74
- @objc var onFullScreenExitRequested:RCTDirectEventBlock?
75
- @objc var onPlayerSizeChange:RCTDirectEventBlock?
76
- @objc var onCastingDevicesAvailable:RCTDirectEventBlock?
77
- @objc var onConnectedToCastingDevice:RCTDirectEventBlock?
78
- @objc var onDisconnectedFromCastingDevice:RCTDirectEventBlock?
79
- @objc var onConnectionTemporarilySuspended:RCTDirectEventBlock?
80
- @objc var onConnectionRecovered:RCTDirectEventBlock?
81
- @objc var onConnectionFailed:RCTDirectEventBlock?
82
- @objc var onCasting:RCTDirectEventBlock?
83
- @objc var onCastingEnded:RCTDirectEventBlock?
84
- @objc var onCastingFailed:RCTDirectEventBlock?
45
+ @objc var onBuffer: RCTDirectEventBlock?
46
+ @objc var onUpdateBuffer: RCTDirectEventBlock?
47
+ @objc var onPlay: RCTDirectEventBlock?
48
+ @objc var onBeforePlay: RCTDirectEventBlock?
49
+ @objc var onAttemptPlay: RCTDirectEventBlock?
50
+ @objc var onPause: RCTDirectEventBlock?
51
+ @objc var onIdle: RCTDirectEventBlock?
52
+ @objc var onPlaylistItem: RCTDirectEventBlock?
53
+ @objc var onLoaded: RCTDirectEventBlock?
54
+ @objc var onVisible: RCTDirectEventBlock?
55
+ @objc var onTime: RCTDirectEventBlock?
56
+ @objc var onSeek: RCTDirectEventBlock?
57
+ @objc var onSeeked: RCTDirectEventBlock?
58
+ @objc var onRateChanged: RCTDirectEventBlock?
59
+ @objc var onPlaylist: RCTDirectEventBlock?
60
+ @objc var onPlaylistComplete: RCTDirectEventBlock?
61
+ @objc var onBeforeComplete: RCTDirectEventBlock?
62
+ @objc var onComplete: RCTDirectEventBlock?
63
+ @objc var onAudioTracks: RCTDirectEventBlock?
64
+ @objc var onPlayerReady: RCTDirectEventBlock?
65
+ @objc var onSetupPlayerError: RCTDirectEventBlock?
66
+ @objc var onPlayerError: RCTDirectEventBlock?
67
+ @objc var onPlayerWarning: RCTDirectEventBlock?
68
+ @objc var onPlayerAdWarning: RCTDirectEventBlock?
69
+ @objc var onPlayerAdError: RCTDirectEventBlock?
70
+ @objc var onAdEvent: RCTDirectEventBlock?
71
+ @objc var onAdTime: RCTDirectEventBlock?
72
+ @objc var onScreenTapped: RCTDirectEventBlock?
73
+ @objc var onControlBarVisible: RCTDirectEventBlock?
74
+ @objc var onFullScreen: RCTDirectEventBlock?
75
+ @objc var onFullScreenRequested: RCTDirectEventBlock?
76
+ @objc var onFullScreenExit: RCTDirectEventBlock?
77
+ @objc var onFullScreenExitRequested: RCTDirectEventBlock?
78
+ @objc var onPlayerSizeChange: RCTDirectEventBlock?
79
+ @objc var onCastingDevicesAvailable: RCTDirectEventBlock?
80
+ @objc var onConnectedToCastingDevice: RCTDirectEventBlock?
81
+ @objc var onDisconnectedFromCastingDevice: RCTDirectEventBlock?
82
+ @objc var onConnectionTemporarilySuspended: RCTDirectEventBlock?
83
+ @objc var onConnectionRecovered: RCTDirectEventBlock?
84
+ @objc var onConnectionFailed: RCTDirectEventBlock?
85
+ @objc var onCasting: RCTDirectEventBlock?
86
+ @objc var onCastingEnded: RCTDirectEventBlock?
87
+ @objc var onCastingFailed: RCTDirectEventBlock?
85
88
 
86
89
  init() {
87
90
  super.init(frame: CGRect(x: 20, y: 0, width: UIScreen.main.bounds.width - 40, height: 300))
@@ -279,7 +282,7 @@ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDele
279
282
  func setNewConfig(config: [String : Any]) {
280
283
  let forceLegacyConfig = config["forceLegacyConfig"] as? Bool?
281
284
  let data:Data! = try? JSONSerialization.data(withJSONObject: config, options:.prettyPrinted)
282
- let jwConfig = try? JWJSONParser.configFromJSON(data)
285
+ let jwConfig = try? JWJSONParser.config(from:data)
283
286
 
284
287
  currentConfig = config
285
288
 
@@ -1071,11 +1074,11 @@ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDele
1071
1074
 
1072
1075
  // MARK: Time events
1073
1076
 
1074
- func onAdTimeEvent(time:JWTimeData) {
1077
+ func onAdTimeEvent(_ time:JWTimeData) {
1075
1078
  self.onAdTime?(["position": time.position, "duration": time.duration])
1076
1079
  }
1077
1080
 
1078
- func onMediaTimeEvent(time:JWTimeData) {
1081
+ func onMediaTimeEvent(_ time:JWTimeData) {
1079
1082
  self.onTime?(["position": time.position, "duration": time.duration])
1080
1083
  }
1081
1084
 
@@ -1189,7 +1192,7 @@ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDele
1189
1192
  }
1190
1193
 
1191
1194
  func jwplayer(_ player:JWPlayer, didFinishLoadingWithTime loadTime:TimeInterval) {
1192
- self.onLoaded?([:])
1195
+ self.onLoaded?(["loadTime":loadTime])
1193
1196
  }
1194
1197
 
1195
1198
  func jwplayer(_ player:JWPlayer, isAttemptingToPlay playlistItem:JWPlayerItem, reason:JWPlayReason) {
@@ -1382,152 +1385,6 @@ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDele
1382
1385
  self.onAdEvent?(["client": event.client, "type": event.type])
1383
1386
  }
1384
1387
 
1385
- // pragma Mark - Casting methods
1386
-
1387
- func setUpCastController() {
1388
- if (playerView != nil) && playerView.player as! Bool && (castController == nil) {
1389
- castController = JWCastController(player:playerView.player)
1390
- castController.delegate = self
1391
- }
1392
-
1393
- self.scanForDevices()
1394
- }
1395
-
1396
- func scanForDevices() {
1397
- if castController != nil {
1398
- castController.startDiscovery()
1399
- }
1400
- }
1401
-
1402
- func stopScanForDevices() {
1403
- if castController != nil {
1404
- castController.stopDiscovery()
1405
- }
1406
- }
1407
-
1408
- func presentCastDialog() {
1409
- GCKCastContext.sharedInstance().presentCastDialog()
1410
- }
1411
-
1412
- func startDiscovery() {
1413
- GCKCastContext.sharedInstance().discoveryManager.startDiscovery()
1414
- }
1415
-
1416
- func stopDiscovery() {
1417
- GCKCastContext.sharedInstance().discoveryManager.stopDiscovery()
1418
- }
1419
-
1420
- func discoveryActive() -> Bool {
1421
- return GCKCastContext.sharedInstance().discoveryManager.discoveryActive
1422
- }
1423
-
1424
- func hasDiscoveredDevices() -> Bool {
1425
- return GCKCastContext.sharedInstance().discoveryManager.hasDiscoveredDevices
1426
- }
1427
-
1428
- func discoveryState() -> GCKDiscoveryState {
1429
- return GCKCastContext.sharedInstance().discoveryManager.discoveryState
1430
- }
1431
-
1432
- func setPassiveScan(passive:Bool) {
1433
- GCKCastContext.sharedInstance().discoveryManager.passiveScan = passive
1434
- }
1435
-
1436
- func castState() -> GCKCastState {
1437
- return GCKCastContext.sharedInstance().castState
1438
- }
1439
-
1440
- func deviceCount() -> UInt {
1441
- return GCKCastContext.sharedInstance().discoveryManager.deviceCount
1442
- }
1443
-
1444
- func getAvailableDevices() -> [JWCastingDevice]! {
1445
- return castController.availableDevices
1446
- }
1447
-
1448
- func connectedDevice() -> JWCastingDevice! {
1449
- return castController.connectedDevice
1450
- }
1451
-
1452
- func connectToDevice(device:JWCastingDevice!) {
1453
- return castController.connectToDevice(device)
1454
- }
1455
-
1456
- func cast() {
1457
- return castController.cast()
1458
- }
1459
-
1460
- func stopCasting() {
1461
- return castController.stopCasting()
1462
- }
1463
-
1464
- // MARK: - JWPlayer Cast Delegate
1465
-
1466
- func castController(_ controller: JWCastController, castingBeganWithDevice device: JWCastingDevice) {
1467
- self.onCasting?([:])
1468
- }
1469
-
1470
- func castController(_ controller:JWCastController, castingEndedWithError error: Error?) {
1471
- self.onCastingEnded?(["error": error as Any])
1472
- }
1473
-
1474
- func castController(_ controller:JWCastController, castingFailedWithError error: Error) {
1475
- self.onCastingFailed?(["error": error as Any])
1476
- }
1477
-
1478
- func castController(_ controller:JWCastController, connectedTo device: JWCastingDevice) {
1479
- let dict:NSMutableDictionary! = NSMutableDictionary()
1480
-
1481
- dict.setObject(device.name, forKey:"name" as NSCopying)
1482
- dict.setObject(device.identifier, forKey:"identifier" as NSCopying)
1483
-
1484
- do {
1485
- let data:Data! = try JSONSerialization.data(withJSONObject: dict as Any, options:.prettyPrinted)
1486
-
1487
- self.onConnectedToCastingDevice?(["device": String(data:data as Data, encoding:String.Encoding.utf8) as Any])
1488
- } catch {
1489
- print("Error converting dictionary to JSON data: \(error)")
1490
- }
1491
- }
1492
-
1493
- func castController(_ controller:JWCastController, connectionFailedWithError error: Error) {
1494
- self.onConnectionFailed?(["error": error as Any])
1495
- }
1496
-
1497
- func castController(_ controller: JWCastController, connectionRecoveredWithDevice device:JWCastingDevice) {
1498
- self.onConnectionRecovered?([:])
1499
- }
1500
-
1501
- func castController(_ controller: JWCastController, connectionSuspendedWithDevice device: JWCastingDevice) {
1502
- self.onConnectionTemporarilySuspended?([:])
1503
- }
1504
-
1505
- func castController(_ controller: JWCastController, devicesAvailable devices:[JWCastingDevice]) {
1506
- self.availableDevices = devices
1507
-
1508
- var devicesInfo: [[String: Any]] = []
1509
- for device in devices {
1510
- var dict: [String: Any] = [:]
1511
-
1512
- dict["name"] = device.name
1513
- dict["identifier"] = device.identifier
1514
-
1515
- devicesInfo.append(dict)
1516
- }
1517
-
1518
- do {
1519
- let data:Data! = try JSONSerialization.data(withJSONObject: devicesInfo as Any, options:.prettyPrinted)
1520
-
1521
- self.onCastingDevicesAvailable?(["devices": String(data:data as Data, encoding:String.Encoding.utf8) as Any])
1522
- } catch {
1523
- print("Error converting dictionary to JSON data: \(error)")
1524
- }
1525
- }
1526
-
1527
- func castController(_ controller: JWCastController, disconnectedWithError error: (Error)?) {
1528
- self.onDisconnectedFromCastingDevice?(["error": error as Any])
1529
- }
1530
-
1531
1388
  // MARK: - JWPlayer AV Delegate
1532
1389
 
1533
1390
  func jwplayer(_ player:JWPlayer, audioTracksUpdated levels:[JWMediaSelectionOption]) {
@@ -1835,3 +1692,152 @@ class RNJWPlayerView : UIView, JWPlayerDelegate, JWPlayerStateDelegate, JWAdDele
1835
1692
  }
1836
1693
 
1837
1694
  }
1695
+
1696
+ #if USE_GOOGLE_CAST
1697
+ extension RNJWPlayerView: JWCastDelegate {
1698
+ // pragma Mark - Casting methods
1699
+ func setUpCastController() {
1700
+ if (playerView != nil) && playerView.player as! Bool && (castController == nil) {
1701
+ castController = JWCastController(player:playerView.player)
1702
+ castController.delegate = self
1703
+ }
1704
+
1705
+ self.scanForDevices()
1706
+ }
1707
+
1708
+ func scanForDevices() {
1709
+ if castController != nil {
1710
+ castController.startDiscovery()
1711
+ }
1712
+ }
1713
+
1714
+ func stopScanForDevices() {
1715
+ if castController != nil {
1716
+ castController.stopDiscovery()
1717
+ }
1718
+ }
1719
+
1720
+ func presentCastDialog() {
1721
+ GCKCastContext.sharedInstance().presentCastDialog()
1722
+ }
1723
+
1724
+ func startDiscovery() {
1725
+ GCKCastContext.sharedInstance().discoveryManager.startDiscovery()
1726
+ }
1727
+
1728
+ func stopDiscovery() {
1729
+ GCKCastContext.sharedInstance().discoveryManager.stopDiscovery()
1730
+ }
1731
+
1732
+ func discoveryActive() -> Bool {
1733
+ return GCKCastContext.sharedInstance().discoveryManager.discoveryActive
1734
+ }
1735
+
1736
+ func hasDiscoveredDevices() -> Bool {
1737
+ return GCKCastContext.sharedInstance().discoveryManager.hasDiscoveredDevices
1738
+ }
1739
+
1740
+ func discoveryState() -> GCKDiscoveryState {
1741
+ return GCKCastContext.sharedInstance().discoveryManager.discoveryState
1742
+ }
1743
+
1744
+ func setPassiveScan(passive:Bool) {
1745
+ GCKCastContext.sharedInstance().discoveryManager.passiveScan = passive
1746
+ }
1747
+
1748
+ func castState() -> GCKCastState {
1749
+ return GCKCastContext.sharedInstance().castState
1750
+ }
1751
+
1752
+ func deviceCount() -> UInt {
1753
+ return GCKCastContext.sharedInstance().discoveryManager.deviceCount
1754
+ }
1755
+
1756
+ func getAvailableDevices() -> [JWCastingDevice]! {
1757
+ return castController.availableDevices
1758
+ }
1759
+
1760
+ func connectedDevice() -> JWCastingDevice! {
1761
+ return castController.connectedDevice
1762
+ }
1763
+
1764
+ func connectToDevice(device:JWCastingDevice!) {
1765
+ return castController.connectToDevice(device)
1766
+ }
1767
+
1768
+ func cast() {
1769
+ return castController.cast()
1770
+ }
1771
+
1772
+ func stopCasting() {
1773
+ return castController.stopCasting()
1774
+ }
1775
+
1776
+ // MARK: - JWPlayer Cast Delegate
1777
+
1778
+ func castController(_ controller: JWCastController, castingBeganWithDevice device: JWCastingDevice) {
1779
+ self.onCasting?([:])
1780
+ }
1781
+
1782
+ func castController(_ controller:JWCastController, castingEndedWithError error: Error?) {
1783
+ self.onCastingEnded?(["error": error as Any])
1784
+ }
1785
+
1786
+ func castController(_ controller:JWCastController, castingFailedWithError error: Error) {
1787
+ self.onCastingFailed?(["error": error as Any])
1788
+ }
1789
+
1790
+ func castController(_ controller:JWCastController, connectedTo device: JWCastingDevice) {
1791
+ let dict:NSMutableDictionary! = NSMutableDictionary()
1792
+
1793
+ dict.setObject(device.name, forKey:"name" as NSCopying)
1794
+ dict.setObject(device.identifier, forKey:"identifier" as NSCopying)
1795
+
1796
+ do {
1797
+ let data:Data! = try JSONSerialization.data(withJSONObject: dict as Any, options:.prettyPrinted)
1798
+
1799
+ self.onConnectedToCastingDevice?(["device": String(data:data as Data, encoding:String.Encoding.utf8) as Any])
1800
+ } catch {
1801
+ print("Error converting dictionary to JSON data: \(error)")
1802
+ }
1803
+ }
1804
+
1805
+ func castController(_ controller:JWCastController, connectionFailedWithError error: Error) {
1806
+ self.onConnectionFailed?(["error": error as Any])
1807
+ }
1808
+
1809
+ func castController(_ controller: JWCastController, connectionRecoveredWithDevice device:JWCastingDevice) {
1810
+ self.onConnectionRecovered?([:])
1811
+ }
1812
+
1813
+ func castController(_ controller: JWCastController, connectionSuspendedWithDevice device: JWCastingDevice) {
1814
+ self.onConnectionTemporarilySuspended?([:])
1815
+ }
1816
+
1817
+ func castController(_ controller: JWCastController, devicesAvailable devices:[JWCastingDevice]) {
1818
+ self.availableDevices = devices
1819
+
1820
+ var devicesInfo: [[String: Any]] = []
1821
+ for device in devices {
1822
+ var dict: [String: Any] = [:]
1823
+
1824
+ dict["name"] = device.name
1825
+ dict["identifier"] = device.identifier
1826
+
1827
+ devicesInfo.append(dict)
1828
+ }
1829
+
1830
+ do {
1831
+ let data:Data! = try JSONSerialization.data(withJSONObject: devicesInfo as Any, options:.prettyPrinted)
1832
+
1833
+ self.onCastingDevicesAvailable?(["devices": String(data:data as Data, encoding:String.Encoding.utf8) as Any])
1834
+ } catch {
1835
+ print("Error converting dictionary to JSON data: \(error)")
1836
+ }
1837
+ }
1838
+
1839
+ func castController(_ controller: JWCastController, disconnectedWithError error: (Error)?) {
1840
+ self.onDisconnectedFromCastingDevice?(["error": error as Any])
1841
+ }
1842
+ }
1843
+ #endif