Skip to content

Commit 8c7740e

Browse files
committed
refactor: add helpers & clean code
1 parent 5c73faa commit 8c7740e

File tree

9 files changed

+131
-85
lines changed

9 files changed

+131
-85
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.brentvatne.exoplayer
2+
3+
import androidx.media3.exoplayer.ExoPlayer
4+
import com.brentvatne.react.RNVPlugin
5+
6+
/**
7+
* Interface for RNV plugins that have dependencies or logic that is specific to Exoplayer
8+
* It extends the RNVPlugin interface
9+
*/
10+
interface RNVExoplayerPlugin : RNVPlugin {
11+
/**
12+
* Optional function that allows plugin to provide custom DRM manager
13+
* Only one plugin can provide DRM manager at a time
14+
* @return DRMManagerSpec implementation if plugin wants to handle DRM, null otherwise
15+
*/
16+
fun getDRMManager(): DRMManagerSpec? = null
17+
18+
/**
19+
* Function called when a new player is created
20+
* @param id: a random string identifying the player
21+
* @param player: the instantiated player reference
22+
* @note: This is helper that ensure that player is non null ExoPlayer
23+
*/
24+
fun onInstanceCreated(id: String, player: ExoPlayer)
25+
26+
/**
27+
* Function called when a player should be destroyed
28+
* when this callback is called, the plugin shall free all
29+
* resources and release all reference to Player object
30+
* @param id: a random string identifying the player
31+
* @param player: the player to release
32+
* @note: This is helper that ensure that player is non null ExoPlayer
33+
*/
34+
fun onInstanceRemoved(id: String, player: ExoPlayer)
35+
36+
override fun onInstanceCreated(id: String, player: Any) {
37+
if (player is ExoPlayer) {
38+
onInstanceCreated(id, player)
39+
}
40+
}
41+
42+
override fun onInstanceRemoved(id: String, player: Any) {
43+
if (player is ExoPlayer) {
44+
onInstanceRemoved(id, player)
45+
}
46+
}
47+
}

android/src/main/java/com/brentvatne/react/RNVExoplayerPlugin.kt

Lines changed: 0 additions & 16 deletions
This file was deleted.

android/src/main/java/com/brentvatne/react/ReactNativeVideoManager.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package com.brentvatne.react
22

3+
import androidx.media3.exoplayer.ExoPlayer
34
import com.brentvatne.common.toolbox.DebugLog
45
import com.brentvatne.exoplayer.DRMManagerSpec
6+
import com.brentvatne.exoplayer.RNVExoplayerPlugin
57

68
/**
79
* ReactNativeVideoManager is a singleton class which allows to manipulate / the global state of the app
810
* It handles the list of <Video/> view instanced and registration of plugins
911
*/
1012
class ReactNativeVideoManager :
11-
RNVPlugin,
12-
RNVExoplayerPlugin {
13+
RNVPlugin {
1314
companion object {
1415
private const val TAG = "ReactNativeVideoManager"
1516

@@ -74,7 +75,7 @@ class ReactNativeVideoManager :
7475
}
7576

7677
// ----------------------- RNV Exoplayer plugin specific methods -----------------------
77-
override fun getDRMManager(): DRMManagerSpec? = customDRMManager
78+
fun getDRMManager(): DRMManagerSpec? = customDRMManager
7879

7980
// ----------------------- Custom Plugins Helpers -----------------------
8081
private fun maybeRegisterExoplayerPlugin(plugin: RNVPlugin) {

examples/react-native-video-plugin-sample/android/src/main/java/com/videopluginsample/VideoPluginSampleModule.kt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import androidx.media3.common.Player
55
import androidx.media3.exoplayer.ExoPlayer
66
import androidx.media3.exoplayer.util.EventLogger
77
import com.brentvatne.common.toolbox.DebugLog
8-
import com.brentvatne.react.RNVPlugin
8+
import com.brentvatne.exoplayer.RNVExoplayerPlugin
99
import com.facebook.react.bridge.Promise
1010
import com.facebook.react.bridge.ReactApplicationContext
1111
import com.facebook.react.bridge.ReactContextBaseJavaModule
1212
import com.facebook.react.bridge.ReactMethod
1313

1414
class VideoPluginSampleModule(reactContext: ReactApplicationContext) :
15-
ReactContextBaseJavaModule(reactContext), RNVPlugin, Player.Listener {
15+
ReactContextBaseJavaModule(reactContext), RNVExoplayerPlugin, Player.Listener {
1616

1717
private val debugEventLogger = EventLogger("RNVPluginSample")
1818

@@ -35,16 +35,12 @@ class VideoPluginSampleModule(reactContext: ReactApplicationContext) :
3535
}
3636

3737

38-
override fun onInstanceCreated(id: String, player: Any) {
39-
if (player is ExoPlayer) {
40-
player.addAnalyticsListener(debugEventLogger)
41-
player.addListener(this)
42-
}
38+
override fun onInstanceCreated(id: String, player: ExoPlayer) {
39+
player.addAnalyticsListener(debugEventLogger)
40+
player.addListener(this)
4341
}
4442

45-
override fun onInstanceRemoved(id: String, player: Any) {
46-
if (player is ExoPlayer) {
47-
player.removeAnalyticsListener(debugEventLogger)
48-
}
43+
override fun onInstanceRemoved(id: String, player: ExoPlayer) {
44+
player.removeAnalyticsListener(debugEventLogger)
4945
}
5046
}

examples/react-native-video-plugin-sample/ios/VideoPluginSample.swift

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import AVFoundation
33
import AVKit
44

55
@objc(VideoPluginSample)
6-
class VideoPluginSample: NSObject, RNVPlugin {
6+
class VideoPluginSample: RNVAVPlayerPlugin {
77
private var _playerRateChangeObserver: NSKeyValueObservation?
88
private var _playerCurrentItemChangeObserver: NSKeyValueObservation?
99
private var _playerItemStatusObserver: NSKeyValueObservation?
@@ -16,6 +16,10 @@ class VideoPluginSample: NSObject, RNVPlugin {
1616
ReactNativeVideoManager.shared.registerPlugin(plugin: self)
1717
}
1818

19+
deinit {
20+
ReactNativeVideoManager.shared.unregisterPlugin(plugin: self)
21+
}
22+
1923

2024
@objc(withResolver:withRejecter:)
2125
func setMetadata(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
@@ -25,23 +29,16 @@ class VideoPluginSample: NSObject, RNVPlugin {
2529
/*
2630
* Handlers called on player creation and destructon
2731
*/
28-
func onInstanceCreated(id: String, player: Any) {
29-
if player is AVPlayer {
30-
let avPlayer = player as! AVPlayer
31-
NSLog("plug onInstanceCreated")
32-
_playerRateChangeObserver = avPlayer.observe(\.rate, options: [.old], changeHandler: handlePlaybackRateChange)
33-
_playerCurrentItemChangeObserver = avPlayer.observe(\.currentItem, options: [.old], changeHandler: handleCurrentItemChange)
34-
35-
}
32+
override func onInstanceCreated(id: String, player: AVPlayer) {
33+
NSLog("plug onInstanceCreated")
34+
_playerRateChangeObserver = player.observe(\.rate, options: [.old], changeHandler: handlePlaybackRateChange)
35+
_playerCurrentItemChangeObserver = player.observe(\.currentItem, options: [.old], changeHandler: handleCurrentItemChange)
3636
}
3737

38-
func onInstanceRemoved(id: String, player: Any) {
39-
if player is AVPlayer {
40-
let avPlayer = player as! AVPlayer
41-
NSLog("plug onInstanceRemoved")
42-
_playerRateChangeObserver?.invalidate()
43-
_playerCurrentItemChangeObserver?.invalidate()
44-
}
38+
override func onInstanceRemoved(id: String, player: AVPlayer) {
39+
NSLog("plug onInstanceRemoved")
40+
_playerRateChangeObserver?.invalidate()
41+
_playerCurrentItemChangeObserver?.invalidate()
4542
}
4643

4744
/**

ios/Video/RCTVideo.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
9797
private var _didRequestAds = false
9898
private var _adPlaying = false
9999

100-
private lazy var _drmManager: DRMManagerSpec? = ReactNativeVideoManager.shared.createDRMManager()
100+
private lazy var _drmManager: DRMManagerSpec? = ReactNativeVideoManager.shared.getDRMManager()
101101
private var _playerObserver: RCTPlayerObserver = .init()
102102

103103
#if USE_VIDEO_CACHING
@@ -521,7 +521,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
521521

522522
if source.drm.json != nil {
523523
if _drmManager == nil {
524-
_drmManager = ReactNativeVideoManager.shared.createDRMManager()
524+
_drmManager = ReactNativeVideoManager.shared.getDRMManager()
525525
}
526526

527527
_drmManager?.createContentKeyRequest(

ios/Video/RNVAVPlayerPlugin.swift

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,48 @@
44
//
55

66
import Foundation
7+
import AVFoundation
78

89
/**
9-
* Protocol for RNV plugins that have dependencies or logic that is specific to AVPlayer
10+
* class for RNV plugins that have dependencies or logic that is specific to AVPlayer
1011
* It extends the RNVPlugin interface
1112
*/
12-
public protocol RNVAVPlayerPlugin: RNVPlugin {
13+
open class RNVAVPlayerPlugin: RNVPlugin {
14+
// MARK: - Definitions
1315
/**
1416
* Optional function that allows plugin to provide custom DRM manager
1517
* Only one plugin can provide DRM manager at a time
1618
* @return: DRMManagerSpec type if plugin wants to handle DRM, nil otherwise
1719
*/
18-
func getDRMManager() -> DRMManagerSpec.Type?
20+
open func getDRMManager() -> DRMManagerSpec? { nil }
21+
22+
/**
23+
* Function called when a new AVPlayer instance is created
24+
* @param id: a random string identifying the player
25+
* @param player: the instantiated AVPlayer
26+
* @note: This is helper that ensure that player is non null AVPlayer
27+
*/
28+
open func onInstanceCreated(id: String, player: AVPlayer) { /* no-op */ }
29+
30+
/**
31+
* Function called when a AVPlayer instance is being removed
32+
* @param id: a random string identifying the player
33+
* @param player: the AVPlayer to release
34+
* @note: This is helper that ensure that player is non null AVPlayer
35+
*/
36+
open func onInstanceRemoved(id: String, player: AVPlayer) { /* no-op */ }
37+
38+
// MARK: - RNVPlugin methods
39+
40+
override public func onInstanceCreated(id: String, player: Any) {
41+
if let avPlayer = player as? AVPlayer {
42+
onInstanceCreated(id: id, player: avPlayer)
43+
}
44+
}
45+
46+
override public func onInstanceRemoved(id: String, player: Any) {
47+
if let avPlayer = player as? AVPlayer {
48+
onInstanceRemoved(id: id, player: avPlayer)
49+
}
50+
}
1951
}

ios/Video/RNVPlugin.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@
66
import Foundation
77

88
/**
9-
* Protocol for RNV plugins that does not have dependencies or logic specific to any player
9+
* class for RNV plugins that does not have dependencies or logic specific to any player
1010
* It is the base interface for all RNV plugins
1111
*
1212
* If you need to have dependencies or logic specific to a player, use the RNVAVPlayerPlugin
1313
*/
14-
public protocol RNVPlugin {
14+
open class RNVPlugin: NSObject {
1515
/**
1616
* Function called when a new player is created
1717
* @param id: a random string identifying the player
1818
* @param player: the instantiated player reference
1919
*/
20-
func onInstanceCreated(id: String, player: Any)
20+
open func onInstanceCreated(id: String, player: Any) { /* no-op */ }
21+
2122
/**
2223
* Function called when a player should be destroyed
2324
* when this callback is called, the plugin shall free all
2425
* resources and release all reference to Player object
2526
* @param id: a random string identifying the player
2627
* @param player: the player to release
2728
*/
28-
func onInstanceRemoved(id: String, player: Any)
29+
open func onInstanceRemoved(id: String, player: Any) { /* no-op */ }
2930
}

ios/Video/ReactNativeVideoManager.swift

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ import Foundation
88
public class ReactNativeVideoManager: RNVPlugin {
99
private let expectedMaxVideoCount = 2
1010

11-
// create a private initializer
12-
private init() {}
13-
1411
public static let shared: ReactNativeVideoManager = .init()
12+
public var pluginName: String = "ReactNativeVideoManager"
1513

1614
private var instanceCount = 0
17-
private var pluginList: [RNVPlugin] = Array()
18-
private var customDRMManager: DRMManagerSpec.Type?
15+
private var pluginList: Set<RNVPlugin> = Set()
16+
private var customDRMManager: (RNVPlugin, DRMManagerSpec)? = nil
1917

2018
/**
2119
* register a new view
@@ -38,60 +36,52 @@ public class ReactNativeVideoManager: RNVPlugin {
3836
* register a new plugin in the managed list
3937
*/
4038
public func registerPlugin(plugin: RNVPlugin) {
41-
pluginList.append(plugin)
39+
pluginList.insert(plugin)
4240

43-
maybeRegisterAVPlayerPlugin(plugin)
41+
maybeRegisterAVPlayerPlugin(plugin: plugin)
4442
}
4543

4644
public func unregisterPlugin(plugin: RNVPlugin) {
4745
pluginList.remove(plugin)
4846

49-
maybeUnregisterAVPlayerPlugin(plugin)
47+
maybeUnregisterAVPlayerPlugin(plugin: plugin)
5048
}
5149

5250
// MARK: - RNVPlugin methods
5351

54-
public func onInstanceCreated(id: String, player: Any) {
52+
public override func onInstanceCreated(id: String, player: Any) {
5553
pluginList.forEach { it in it.onInstanceCreated(id: id, player: player) }
5654
}
5755

58-
public func onInstanceRemoved(id: String, player: Any) {
56+
public override func onInstanceRemoved(id: String, player: Any) {
5957
pluginList.forEach { it in it.onInstanceRemoved(id: id, player: player) }
6058
}
6159

6260
// MARK: - RNV AVPlayer plugin specific methods
6361

64-
public func getDRMManager() -> DRMManagerSpec.Type? {
65-
return nil
66-
}
67-
68-
// MARK: - Helper methods
69-
7062
/**
71-
* Creates a DRM manager instance
7263
* If a custom DRM manager is registered through a plugin, it will be used
7364
* Otherwise, the default DRMManager will be used
7465
*/
75-
func createDRMManager() -> DRMManagerSpec {
76-
if let customManager = customDRMManager {
77-
return customManager.init()
78-
}
79-
return DRMManager()
66+
public func getDRMManager() -> DRMManagerSpec? {
67+
return customDRMManager?.1 ?? DRMManager()
8068
}
8169

70+
// MARK: - Helper methods
8271
func maybeRegisterAVPlayerPlugin(plugin: RNVPlugin) {
8372
guard let avpPlugin = plugin as? RNVAVPlayerPlugin else {
8473
return
8574
}
86-
87-
avpPlugin.getDRMManager()?.let {
88-
drmManager -> if customDRMManager != nil {
75+
76+
if let drmManager = avpPlugin.getDRMManager() {
77+
if(customDRMManager != nil) {
8978
DebugLog(
9079
"Multiple DRM managers registered. This is not supported. Using first registered manager."
9180
)
9281
return
9382
}
94-
customDRMManager = drmManager
83+
84+
customDRMManager = (plugin, drmManager)
9585
}
9686
}
9787

@@ -100,10 +90,8 @@ public class ReactNativeVideoManager: RNVPlugin {
10090
return
10191
}
10292

103-
avpPlugin.getDRMManager()?.let {
104-
drmManager -> if customDRMManager == drmManager {
105-
customDRMManager = nil
106-
}
93+
if customDRMManager?.0 == plugin {
94+
customDRMManager = nil
10795
}
10896
}
10997
}

0 commit comments

Comments
 (0)