react-native-unified-player 0.3.3 → 0.3.4

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.
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
10
10
  s.license = package["license"]
11
11
  s.authors = package["author"]
12
12
 
13
- s.platforms = { :ios => "12.0" }
13
+ s.platforms = { :ios => "13.0" }
14
14
  s.source = { :git => "https://github.com/blueromans/react-native-unified-player.git", :tag => "#{s.version}" }
15
15
 
16
16
  s.source_files = "ios/**/*.{h,m,mm}"
@@ -1,172 +1,187 @@
1
1
  package com.unifiedplayer
2
2
 
3
- import com.facebook.react.bridge.ReactApplicationContext
4
- import com.facebook.react.bridge.ReactContextBaseJavaModule
5
- import com.facebook.react.bridge.ReactMethod
6
- import com.facebook.react.bridge.Promise
7
- import com.facebook.react.uimanager.UIManagerModule
3
+ import android.graphics.Bitmap
4
+ import android.util.Base64
8
5
  import android.util.Log
9
- import com.facebook.react.bridge.UiThreadUtil
10
- import android.view.View
6
+ import com.facebook.react.bridge.*
7
+ import com.facebook.react.uimanager.UIManagerModule
8
+ import com.facebook.react.uimanager.UIBlock
9
+ import com.facebook.react.uimanager.NativeViewHierarchyManager
10
+ import java.io.ByteArrayOutputStream
11
11
 
12
12
  class UnifiedPlayerModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
13
- companion object {
14
- private const val TAG = "UnifiedPlayerModule"
15
- }
16
-
17
- init {
18
- Log.d(TAG, "UnifiedPlayerModule initialized")
19
- }
20
-
21
- override fun getName(): String {
22
- Log.d(TAG, "getName() called, returning 'UnifiedPlayer'")
23
- return "UnifiedPlayer"
24
- }
25
-
26
- private fun getPlayerViewByTag(viewTag: Int): UnifiedPlayerView? {
13
+ private var isModuleReady = false
14
+
15
+ override fun initialize() {
16
+ super.initialize()
27
17
  try {
28
- val view = reactApplicationContext.currentActivity?.findViewById<View>(viewTag)
29
- Log.d(TAG, "Looking for view with tag: $viewTag, found: ${view != null}")
30
-
31
- if (view is UnifiedPlayerView) {
32
- return view
33
- } else if (view != null) {
34
- Log.e(TAG, "View with tag $viewTag is not a UnifiedPlayerView, it's a ${view.javaClass.simpleName}")
18
+ reactContext.getNativeModule(UIManagerModule::class.java)?.let {
19
+ isModuleReady = true
20
+ Log.d(TAG, "Module successfully initialized")
35
21
  }
36
22
  } catch (e: Exception) {
37
- Log.e(TAG, "Error finding view with tag $viewTag: ${e.message}", e)
23
+ Log.e(TAG, "Initialization failed", e)
38
24
  }
39
- return null
40
25
  }
41
-
26
+ companion object {
27
+ private const val TAG = "UnifiedPlayerModule"
28
+ }
29
+
30
+ override fun getName(): String = "UnifiedPlayer"
31
+
42
32
  @ReactMethod
43
33
  fun play(viewTag: Int, promise: Promise) {
44
- Log.d(TAG, "Native play method called with viewTag: $viewTag")
45
34
  try {
46
- val playerView = getPlayerViewByTag(viewTag)
47
- if (playerView != null) {
48
- UiThreadUtil.runOnUiThread {
49
- try {
50
- playerView.play()
51
- Log.d(TAG, "Play command executed successfully")
35
+ val uiManager = reactApplicationContext.getNativeModule(UIManagerModule::class.java)
36
+ ?: throw IllegalStateException("UIManagerModule not available")
37
+
38
+ uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager ->
39
+ try {
40
+ val view = nativeViewHierarchyManager.resolveView(viewTag) as? UnifiedPlayerView
41
+ if (view != null) {
42
+ view.play()
52
43
  promise.resolve(true)
53
- } catch (e: Exception) {
54
- Log.e(TAG, "Error during play: ${e.message}", e)
55
- promise.reject("PLAY_ERROR", "Error during play: ${e.message}", e)
44
+ } else {
45
+ promise.reject("INVALID_VIEW", "View with tag $viewTag not found")
56
46
  }
47
+ } catch (e: Exception) {
48
+ Log.e(TAG, "Error in play method", e)
49
+ promise.reject("PLAY_ERROR", "Error in play method", e)
57
50
  }
58
- } else {
59
- Log.e(TAG, "Player view not found for tag: $viewTag")
60
- promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
61
- }
51
+ })
62
52
  } catch (e: Exception) {
63
- Log.e(TAG, "Error in play method: ${e.message}", e)
64
- promise.reject("PLAY_ERROR", "Error in play method: ${e.message}", e)
53
+ Log.e(TAG, "Error in play method", e)
54
+ promise.reject("UIMANAGER_ERROR", "UIManagerModule not available", e)
65
55
  }
66
56
  }
67
57
 
68
58
  @ReactMethod
69
59
  fun pause(viewTag: Int, promise: Promise) {
70
- Log.d(TAG, "Native pause method called with viewTag: $viewTag")
71
60
  try {
72
- val playerView = getPlayerViewByTag(viewTag)
73
- if (playerView != null) {
74
- UiThreadUtil.runOnUiThread {
75
- try {
76
- playerView.pause()
77
- Log.d(TAG, "Pause command executed successfully")
61
+ val uiManager = reactApplicationContext.getNativeModule(UIManagerModule::class.java)
62
+ ?: throw IllegalStateException("UIManagerModule not available")
63
+
64
+ uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager ->
65
+ try {
66
+ val view = nativeViewHierarchyManager.resolveView(viewTag) as? UnifiedPlayerView
67
+ if (view != null) {
68
+ view.pause()
78
69
  promise.resolve(true)
79
- } catch (e: Exception) {
80
- Log.e(TAG, "Error during pause: ${e.message}", e)
81
- promise.reject("PAUSE_ERROR", "Error during pause: ${e.message}", e)
70
+ } else {
71
+ promise.reject("INVALID_VIEW", "View with tag $viewTag not found")
82
72
  }
73
+ } catch (e: Exception) {
74
+ Log.e(TAG, "Error in pause method", e)
75
+ promise.reject("PAUSE_ERROR", "Error in pause method", e)
83
76
  }
84
- } else {
85
- Log.e(TAG, "Player view not found for tag: $viewTag")
86
- promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
87
- }
77
+ })
88
78
  } catch (e: Exception) {
89
- Log.e(TAG, "Error in pause method: ${e.message}", e)
90
- promise.reject("PAUSE_ERROR", "Error in pause method: ${e.message}", e)
79
+ Log.e(TAG, "Error in pause method", e)
80
+ promise.reject("UIMANAGER_ERROR", "UIManagerModule not available", e)
91
81
  }
92
82
  }
93
83
 
94
84
  @ReactMethod
95
85
  fun seekTo(viewTag: Int, seconds: Float, promise: Promise) {
96
- Log.d(TAG, "Native seekTo method called with viewTag: $viewTag, seconds: $seconds")
97
86
  try {
98
- val playerView = getPlayerViewByTag(viewTag)
99
- if (playerView != null) {
100
- UiThreadUtil.runOnUiThread {
101
- try {
102
- playerView.seekTo(seconds)
103
- Log.d(TAG, "SeekTo command executed successfully to $seconds seconds")
87
+ val uiManager = reactApplicationContext.getNativeModule(UIManagerModule::class.java)
88
+ ?: throw IllegalStateException("UIManagerModule not available")
89
+
90
+ uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager ->
91
+ try {
92
+ val view = nativeViewHierarchyManager.resolveView(viewTag) as? UnifiedPlayerView
93
+ if (view != null) {
94
+ view.seekTo(seconds)
104
95
  promise.resolve(true)
105
- } catch (e: Exception) {
106
- Log.e(TAG, "Error during seekTo: ${e.message}", e)
107
- promise.reject("SEEK_ERROR", "Error during seekTo: ${e.message}", e)
96
+ } else {
97
+ promise.reject("INVALID_VIEW", "View with tag $viewTag not found")
108
98
  }
99
+ } catch (e: Exception) {
100
+ Log.e(TAG, "Error in seekTo method", e)
101
+ promise.reject("SEEK_ERROR", "Error in seekTo method", e)
109
102
  }
110
- } else {
111
- Log.e(TAG, "Player view not found for tag: $viewTag")
112
- promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
113
- }
103
+ })
114
104
  } catch (e: Exception) {
115
- Log.e(TAG, "Error in seekTo method: ${e.message}", e)
116
- promise.reject("SEEK_ERROR", "Error in seekTo method: ${e.message}", e)
105
+ Log.e(TAG, "Error in seekTo method", e)
106
+ promise.reject("UIMANAGER_ERROR", "UIManagerModule not available", e)
117
107
  }
118
108
  }
119
109
 
120
110
  @ReactMethod
121
111
  fun getCurrentTime(viewTag: Int, promise: Promise) {
122
- Log.d(TAG, "Native getCurrentTime method called with viewTag: $viewTag")
123
- try {
124
- val playerView = getPlayerViewByTag(viewTag)
125
- if (playerView != null) {
126
- UiThreadUtil.runOnUiThread {
127
- try {
128
- val currentTime = playerView.getCurrentTime()
129
- Log.d(TAG, "getCurrentTime executed successfully, current time: $currentTime")
130
- promise.resolve(currentTime)
131
- } catch (e: Exception) {
132
- Log.e(TAG, "Error getting current time: ${e.message}", e)
133
- promise.reject("GET_TIME_ERROR", "Error getting current time: ${e.message}", e)
112
+ reactApplicationContext.getNativeModule(UIManagerModule::class.java)?.let { uiManager ->
113
+ uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager ->
114
+ try {
115
+ val view = nativeViewHierarchyManager.resolveView(viewTag) as? UnifiedPlayerView
116
+ if (view != null) {
117
+ promise.resolve(view.getCurrentTime())
118
+ } else {
119
+ promise.reject("INVALID_VIEW", "View with tag $viewTag not found")
134
120
  }
121
+ } catch (e: Exception) {
122
+ Log.e(TAG, "Error in getCurrentTime method", e)
123
+ promise.reject("GET_TIME_ERROR", "Error in getCurrentTime method", e)
135
124
  }
136
- } else {
137
- Log.e(TAG, "Player view not found for tag: $viewTag")
138
- promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
139
- }
140
- } catch (e: Exception) {
141
- Log.e(TAG, "Error in getCurrentTime method: ${e.message}", e)
142
- promise.reject("GET_TIME_ERROR", "Error in getCurrentTime method: ${e.message}", e)
125
+ })
126
+ } ?: run {
127
+ promise.reject("ERROR", "UIManagerModule not available")
143
128
  }
144
129
  }
145
130
 
146
131
  @ReactMethod
147
132
  fun getDuration(viewTag: Int, promise: Promise) {
148
- Log.d(TAG, "Native getDuration method called with viewTag: $viewTag")
149
- try {
150
- val playerView = getPlayerViewByTag(viewTag)
151
- if (playerView != null) {
152
- UiThreadUtil.runOnUiThread {
153
- try {
154
- val duration = playerView.getDuration()
155
- Log.d(TAG, "getDuration executed successfully, duration: $duration")
156
- promise.resolve(duration)
157
- } catch (e: Exception) {
158
- Log.e(TAG, "Error getting duration: ${e.message}", e)
159
- promise.reject("GET_DURATION_ERROR", "Error getting duration: ${e.message}", e)
133
+ reactApplicationContext.getNativeModule(UIManagerModule::class.java)?.let { uiManager ->
134
+ uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager ->
135
+ try {
136
+ val view = nativeViewHierarchyManager.resolveView(viewTag) as? UnifiedPlayerView
137
+ if (view != null) {
138
+ promise.resolve(view.getDuration())
139
+ } else {
140
+ promise.reject("INVALID_VIEW", "View with tag $viewTag not found")
160
141
  }
142
+ } catch (e: Exception) {
143
+ Log.e(TAG, "Error in getDuration method", e)
144
+ promise.reject("GET_DURATION_ERROR", "Error in getDuration method", e)
161
145
  }
162
- } else {
163
- Log.e(TAG, "Player view not found for tag: $viewTag")
164
- promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
146
+ })
147
+ } ?: run {
148
+ promise.reject("ERROR", "UIManagerModule not available")
149
+ }
150
+ }
151
+
152
+ @ReactMethod
153
+ fun capture(viewTag: Int, promise: Promise) {
154
+ try {
155
+ if (!isModuleReady) {
156
+ throw IllegalStateException("Module not ready. Ensure React Native bridge is initialized.")
165
157
  }
158
+ val uiManager = reactApplicationContext.getNativeModule(UIManagerModule::class.java)
159
+ ?: throw IllegalStateException("UIManagerModule not available. Is the bridge active?")
160
+
161
+ uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager ->
162
+ try {
163
+ val view = nativeViewHierarchyManager.resolveView(viewTag) as? UnifiedPlayerView
164
+ if (view != null) {
165
+ val bitmap = view.captureFrame()
166
+ if (bitmap != null) {
167
+ val outputStream = ByteArrayOutputStream()
168
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
169
+ val base64 = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT)
170
+ promise.resolve(base64)
171
+ } else {
172
+ promise.reject("CAPTURE_ERROR", "Failed to capture frame")
173
+ }
174
+ } else {
175
+ promise.reject("INVALID_VIEW", "View with tag $viewTag not found")
176
+ }
177
+ } catch (e: Exception) {
178
+ Log.e(TAG, "Error in capture method", e)
179
+ promise.reject("CAPTURE_ERROR", "Error in capture method", e)
180
+ }
181
+ })
166
182
  } catch (e: Exception) {
167
- Log.e(TAG, "Error in getDuration method: ${e.message}", e)
168
- promise.reject("GET_DURATION_ERROR", "Error in getDuration method: ${e.message}", e)
183
+ Log.e(TAG, "Error in capture method", e)
184
+ promise.reject("UIMANAGER_ERROR", "UIManagerModule not available", e)
169
185
  }
170
186
  }
171
-
172
187
  }
@@ -12,7 +12,12 @@ class UnifiedPlayerPackage : ReactPackage {
12
12
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
13
13
  Log.d(TAG, "Creating native modules")
14
14
  return listOf(
15
- UnifiedPlayerModule(reactContext)
15
+ UnifiedPlayerModule(reactContext).apply {
16
+ reactContext.runOnUiQueueThread {
17
+ // Initialize module on UI thread
18
+ Log.d(TAG, "Module initialized on UI thread")
19
+ }
20
+ }
16
21
  )
17
22
  }
18
23
 
@@ -4,9 +4,13 @@ import android.annotation.SuppressLint
4
4
  import android.content.Context
5
5
  import android.graphics.Color
6
6
  import android.util.Log
7
+ import android.graphics.Bitmap
8
+ import android.graphics.Canvas
7
9
  import android.os.Handler
8
10
  import android.os.Looper
9
11
  import android.view.Gravity
12
+ import android.view.TextureView
13
+ import android.view.View
10
14
  import android.widget.FrameLayout
11
15
  import com.facebook.react.bridge.Arguments
12
16
  import com.google.android.exoplayer2.ExoPlayer
@@ -312,17 +316,41 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
312
316
  }
313
317
  }
314
318
 
315
- fun getDuration(): Float {
316
- Log.d(TAG, "GetDuration method called")
317
- return player?.let {
318
- val duration = it.duration.toFloat() / 1000f
319
- Log.d(TAG, "Duration: $duration seconds (raw: ${it.duration})")
320
- if (it.duration > 0) duration else 0f
321
- } ?: run {
322
- Log.e(TAG, "Cannot get duration: player is null")
323
- 0f
324
- }
319
+ fun getDuration(): Float {
320
+ Log.d(TAG, "GetDuration method called")
321
+ return player?.let {
322
+ val duration = it.duration.toFloat() / 1000f
323
+ Log.d(TAG, "Duration: $duration seconds (raw: ${it.duration})")
324
+ if (it.duration > 0) duration else 0f
325
+ } ?: run {
326
+ Log.e(TAG, "Cannot get duration: player is null")
327
+ 0f
325
328
  }
329
+ }
330
+
331
+ fun captureFrame(): Bitmap? {
332
+ Log.d(TAG, "CaptureFrame method called")
333
+ try {
334
+ // Create a bitmap with the same dimensions as the player view
335
+ val bitmap = Bitmap.createBitmap(
336
+ playerView.width,
337
+ playerView.height,
338
+ Bitmap.Config.ARGB_8888
339
+ )
340
+
341
+ // Create a canvas with the bitmap
342
+ val canvas = Canvas(bitmap)
343
+
344
+ // Draw the player view onto the canvas
345
+ playerView.draw(canvas)
346
+
347
+ Log.d(TAG, "Successfully captured frame from PlayerView")
348
+ return bitmap
349
+ } catch (e: Exception) {
350
+ Log.e(TAG, "Error capturing frame: ${e.message}", e)
351
+ return null
352
+ }
353
+ }
326
354
 
327
355
  // Add a getter for the ExoPlayer instance
328
356
  val exoPlayer: ExoPlayer?
@@ -1,5 +1,9 @@
1
1
  #import <React/RCTEventEmitter.h>
2
2
  #import <React/RCTBridgeModule.h>
3
+ #import <MobileVLCKit/MobileVLCKit.h> // Import MobileVLCKit
4
+
5
+ // Forward declaration for UnifiedPlayerUIView
6
+ @class UnifiedPlayerUIView;
3
7
 
4
8
  @interface UnifiedPlayerModule : RCTEventEmitter <RCTBridgeModule>
5
- @end
9
+ @end
@@ -1,4 +1,5 @@
1
1
  #import "UnifiedPlayerModule.h"
2
+ #import "UnifiedPlayerUIView.h"
2
3
  #import <React/RCTLog.h>
3
4
  #import <React/RCTBridgeModule.h>
4
5
  #import <React/RCTEventEmitter.h>
@@ -175,35 +176,43 @@ RCT_EXPORT_METHOD(getCurrentTime:(nonnull NSNumber *)reactTag
175
176
  // Get video duration
176
177
  RCT_EXPORT_METHOD(getDuration:(nonnull NSNumber *)reactTag
177
178
  resolver:(RCTPromiseResolveBlock)resolve
178
- rejecter:(RCTPromiseRejectBlock)reject) {
179
- [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
179
+ rejecter:(RCTPromiseRejectBlock)reject)
180
+ {
181
+ [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
180
182
  UIView *view = viewRegistry[reactTag];
181
- if (!view) {
182
- reject(@"error", @"Invalid view for tag", nil);
183
- return;
183
+ if (![view isKindOfClass:[UnifiedPlayerUIView class]]) {
184
+ RCTLogError(@"Invalid view returned from registry, expecting UnifiedPlayerUIView, got: %@", view);
185
+ reject(@"E_INVALID_VIEW", @"Expected UnifiedPlayerUIView", nil);
186
+ } else {
187
+ UnifiedPlayerUIView *playerView = (UnifiedPlayerUIView *)view;
188
+ float duration = [playerView getDuration];
189
+ resolve(@(duration));
184
190
  }
185
-
186
- // Cast to UnifiedPlayerUIView class
187
- Class UnifiedPlayerUIViewClass = NSClassFromString(@"UnifiedPlayerUIView");
188
- if (![view isKindOfClass:UnifiedPlayerUIViewClass]) {
189
- reject(@"error", @"View is not a UnifiedPlayerUIView", nil);
191
+ }];
192
+ }
193
+
194
+ RCT_EXPORT_METHOD(capture:(nonnull NSNumber *)reactTag
195
+ resolver:(RCTPromiseResolveBlock)resolve
196
+ rejecter:(RCTPromiseRejectBlock)reject)
197
+ {
198
+ [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
199
+ UIView *view = viewRegistry[reactTag];
200
+ if (![view isKindOfClass:[UnifiedPlayerUIView class]]) {
201
+ RCTLogError(@"Invalid view returned from registry, expecting UnifiedPlayerUIView, got: %@", view);
202
+ reject(@"E_INVALID_VIEW", @"Expected UnifiedPlayerUIView", nil);
190
203
  return;
191
204
  }
192
205
 
193
- // Use direct method call with proper type safety
194
- float duration = 0;
195
- @try {
196
- // Use direct ivar access for safety
197
- VLCMediaPlayer *player = [view valueForKey:@"player"];
198
- if (player && player.media) {
199
- duration = player.media.length.intValue / 1000.0f;
200
- resolve(@(duration));
206
+ UnifiedPlayerUIView *playerView = (UnifiedPlayerUIView *)view;
207
+ [playerView captureFrameWithCompletion:^(NSString * _Nullable base64String, NSError * _Nullable error) {
208
+ if (error) {
209
+ reject(@"E_CAPTURE_FAILED", error.localizedDescription, error);
210
+ } else if (base64String) {
211
+ resolve(base64String);
201
212
  } else {
202
- reject(@"error", @"Player or media not initialized", nil);
213
+ reject(@"E_CAPTURE_FAILED", @"Unknown capture error", nil);
203
214
  }
204
- } @catch (NSException *exception) {
205
- reject(@"error", [NSString stringWithFormat:@"Error getting duration: %@", exception.reason], nil);
206
- }
215
+ }];
207
216
  }];
208
217
  }
209
218
 
@@ -0,0 +1,42 @@
1
+ #import <UIKit/UIKit.h>
2
+ #import <React/RCTView.h>
3
+ #import <React/RCTComponent.h>
4
+ #import <MobileVLCKit/MobileVLCKit.h>
5
+
6
+ NS_ASSUME_NONNULL_BEGIN
7
+
8
+ @interface UnifiedPlayerUIView : UIView <VLCMediaPlayerDelegate>
9
+
10
+ @property (nonatomic, strong) VLCMediaPlayer *player;
11
+ @property (nonatomic, copy) NSString *videoUrlString;
12
+ @property (nonatomic, assign) BOOL autoplay;
13
+ @property (nonatomic, assign) BOOL loop;
14
+ @property (nonatomic, assign) BOOL isPaused;
15
+ @property (nonatomic, strong) NSArray *mediaOptions;
16
+ @property (nonatomic, weak) RCTBridge *bridge;
17
+ @property (nonatomic, assign) VLCMediaPlayerState previousState;
18
+ @property (nonatomic, assign) BOOL hasRenderedVideo;
19
+
20
+ // Event callbacks
21
+ @property (nonatomic, copy) RCTDirectEventBlock onLoadStart;
22
+ @property (nonatomic, copy) RCTDirectEventBlock onReadyToPlay;
23
+ @property (nonatomic, copy) RCTDirectEventBlock onError;
24
+ @property (nonatomic, copy) RCTDirectEventBlock onProgress;
25
+ @property (nonatomic, copy) RCTDirectEventBlock onPlaybackComplete;
26
+ @property (nonatomic, copy) RCTDirectEventBlock onPlaybackStalled;
27
+ @property (nonatomic, copy) RCTDirectEventBlock onPlaybackResumed;
28
+ @property (nonatomic, copy) RCTDirectEventBlock onPlaying;
29
+ @property (nonatomic, copy) RCTDirectEventBlock onPaused;
30
+
31
+ // Method declarations
32
+ - (void)setupWithVideoUrlString:(NSString *)videoUrlString;
33
+ - (void)play;
34
+ - (void)pause;
35
+ - (void)seekToTime:(NSNumber *)timeNumber;
36
+ - (float)getCurrentTime;
37
+ - (float)getDuration;
38
+ - (void)captureFrameWithCompletion:(void (^)(NSString * _Nullable base64String, NSError * _Nullable error))completion;
39
+
40
+ @end
41
+
42
+ NS_ASSUME_NONNULL_END
@@ -8,37 +8,7 @@
8
8
  #import <React/RCTComponent.h>
9
9
  #import <MobileVLCKit/MobileVLCKit.h>
10
10
  #import "UnifiedPlayerModule.h"
11
-
12
- // Forward declarations
13
- @interface UnifiedPlayerUIView : UIView <VLCMediaPlayerDelegate>
14
- @property (nonatomic, strong) VLCMediaPlayer *player;
15
- @property (nonatomic, copy) NSString *videoUrlString;
16
- @property (nonatomic, assign) BOOL autoplay;
17
- @property (nonatomic, assign) BOOL loop;
18
- @property (nonatomic, assign) BOOL isPaused;
19
- @property (nonatomic, strong) NSArray *mediaOptions;
20
- @property (nonatomic, weak) RCTBridge *bridge;
21
- @property (nonatomic, assign) VLCMediaPlayerState previousState;
22
- @property (nonatomic, assign) BOOL hasRenderedVideo;
23
-
24
- // Event callbacks
25
- @property (nonatomic, copy) RCTDirectEventBlock onLoadStart;
26
- @property (nonatomic, copy) RCTDirectEventBlock onReadyToPlay;
27
- @property (nonatomic, copy) RCTDirectEventBlock onError;
28
- @property (nonatomic, copy) RCTDirectEventBlock onProgress;
29
- @property (nonatomic, copy) RCTDirectEventBlock onPlaybackComplete;
30
- @property (nonatomic, copy) RCTDirectEventBlock onPlaybackStalled;
31
- @property (nonatomic, copy) RCTDirectEventBlock onPlaybackResumed;
32
- @property (nonatomic, copy) RCTDirectEventBlock onPlaying;
33
- @property (nonatomic, copy) RCTDirectEventBlock onPaused;
34
-
35
- - (void)setupWithVideoUrlString:(NSString *)videoUrlString;
36
- - (void)play;
37
- - (void)pause;
38
- - (void)seekToTime:(NSNumber *)timeNumber;
39
- - (float)getCurrentTime;
40
- - (float)getDuration;
41
- @end
11
+ #import "UnifiedPlayerUIView.h"
42
12
 
43
13
  // Main player view implementation
44
14
  @implementation UnifiedPlayerUIView
@@ -179,13 +149,15 @@
179
149
  self.onPlaying(body);
180
150
  } else if ([eventName isEqualToString:@"onPaused"] && self.onPaused) {
181
151
  self.onPaused(body);
152
+ } else {
153
+ RCTLogInfo(@"[UnifiedPlayerViewManager] No direct event block found for event: %@", eventName);
182
154
  }
183
155
 
184
- // Also send events through the module for backward compatibility
185
- UnifiedPlayerModule *eventEmitter = [self.bridge moduleForClass:[UnifiedPlayerModule class]];
186
- if (eventEmitter != nil) {
187
- [eventEmitter sendEventWithName:eventName body:body];
188
- }
156
+ // Removed the redundant event sending via UnifiedPlayerModule emitter
157
+ // UnifiedPlayerModule *eventEmitter = [self.bridge moduleForClass:[UnifiedPlayerModule class]];
158
+ // if (eventEmitter != nil) {
159
+ // [eventEmitter sendEventWithName:eventName body:body];
160
+ // }
189
161
  }
190
162
 
191
163
  - (void)setupWithVideoUrlString:(NSString *)videoUrlString {
@@ -369,11 +341,49 @@
369
341
  }
370
342
 
371
343
  - (float)getCurrentTime {
372
- return _player.time.intValue / 1000.0f; // Convert from milliseconds to seconds
344
+ if (_player) {
345
+ return _player.time.intValue / 1000.0f;
346
+ }
347
+ return 0.0f;
373
348
  }
374
349
 
375
350
  - (float)getDuration {
376
- return _player.media.length.intValue / 1000.0f; // Convert from milliseconds to seconds
351
+ if (_player && _player.media) {
352
+ return _player.media.length.intValue / 1000.0f;
353
+ }
354
+ return 0.0f;
355
+ }
356
+
357
+ - (void)captureFrameWithCompletion:(void (^)(NSString * _Nullable base64String, NSError * _Nullable error))completion {
358
+ if (!_player || !_player.drawable) {
359
+ NSError *error = [NSError errorWithDomain:@"UnifiedPlayerUIView" code:100 userInfo:@{NSLocalizedDescriptionKey: @"Player not initialized"}];
360
+ if (completion) {
361
+ completion(nil, error);
362
+ }
363
+ return;
364
+ }
365
+
366
+ // Create a snapshot of the current view
367
+ UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
368
+ [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
369
+ UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
370
+ UIGraphicsEndImageContext();
371
+
372
+ if (!image) {
373
+ NSError *error = [NSError errorWithDomain:@"UnifiedPlayerUIView" code:101 userInfo:@{NSLocalizedDescriptionKey: @"Failed to capture frame"}];
374
+ if (completion) {
375
+ completion(nil, error);
376
+ }
377
+ return;
378
+ }
379
+
380
+ // Convert to base64
381
+ NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
382
+ NSString *base64String = [imageData base64EncodedStringWithOptions:0];
383
+
384
+ if (completion) {
385
+ completion(base64String, nil);
386
+ }
377
387
  }
378
388
 
379
389
  - (void)setAutoplay:(BOOL)autoplay {
@@ -406,6 +416,12 @@
406
416
  float currentTime = [self getCurrentTime];
407
417
  float duration = [self getDuration];
408
418
 
419
+ // Avoid sending progress events for invalid durations
420
+ if (duration > 0 && !isnan(duration)) {
421
+ [self sendProgressEvent:currentTime duration:duration];
422
+ }
423
+ RCTLogInfo(@"[UnifiedPlayerViewManager] mediaPlayerTimeChanged - CurrentTime: %f, Duration: %f", currentTime, duration); // Added Log
424
+
409
425
  // Avoid sending progress events for invalid durations
410
426
  if (duration > 0 && !isnan(duration)) {
411
427
  [self sendProgressEvent:currentTime duration:duration];
@@ -414,6 +430,7 @@
414
430
 
415
431
  - (void)mediaPlayerStateChanged:(NSNotification *)notification {
416
432
  VLCMediaPlayerState state = _player.state;
433
+ RCTLogInfo(@"[UnifiedPlayerViewManager] mediaPlayerStateChanged - New State: %d", state); // Added Log
417
434
 
418
435
  // Debug information for video output
419
436
  if (state == VLCMediaPlayerStatePlaying) {
@@ -143,6 +143,26 @@ export const UnifiedPlayer = {
143
143
  console.log('Error calling getDuration:', error instanceof Error ? error.message : String(error));
144
144
  return Promise.reject(error);
145
145
  }
146
+ },
147
+ /**
148
+ * Capture the current video frame as a base64 encoded image
149
+ * @param viewTag - The tag of the player view
150
+ * @returns Promise resolving to the base64 encoded image string
151
+ */
152
+ capture: viewTag => {
153
+ try {
154
+ console.log('UnifiedPlayer.capture called with viewTag:', viewTag);
155
+ return UnifiedPlayerModule.capture(viewTag).then(base64String => {
156
+ console.log('Native capture method called successfully');
157
+ return base64String;
158
+ }).catch(error => {
159
+ console.log('Error calling capture:', error instanceof Error ? error.message : String(error));
160
+ throw error;
161
+ });
162
+ } catch (error) {
163
+ console.log('Error calling capture:', error instanceof Error ? error.message : String(error));
164
+ return Promise.reject(error);
165
+ }
146
166
  }
147
167
  };
148
168
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","requireNativeComponent","UIManager","NativeModules","Platform","jsx","_jsx","LINKING_ERROR","select","ios","default","getViewManagerConfig","UnifiedPlayer","Error","NativeUnifiedPlayerView","UnifiedPlayerModule","UnifiedPlayerEventTypes","LOAD_START","READY","ERROR","PROGRESS","COMPLETE","STALLED","RESUMED","PLAYING","PAUSED","UnifiedPlayerEvents","UnifiedPlayerView","props","ref","play","viewTag","console","log","then","result","catch","error","message","String","Promise","reject","pause","seekTo","time","getCurrentTime","getDuration"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["forwardRef","requireNativeComponent","UIManager","NativeModules","Platform","jsx","_jsx","LINKING_ERROR","select","ios","default","getViewManagerConfig","UnifiedPlayer","Error","NativeUnifiedPlayerView","UnifiedPlayerModule","UnifiedPlayerEventTypes","LOAD_START","READY","ERROR","PROGRESS","COMPLETE","STALLED","RESUMED","PLAYING","PAUSED","UnifiedPlayerEvents","UnifiedPlayerView","props","ref","play","viewTag","console","log","then","result","catch","error","message","String","Promise","reject","pause","seekTo","time","getCurrentTime","getDuration","capture","base64String"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -69,5 +69,11 @@ export declare const UnifiedPlayer: {
69
69
  * @returns Promise resolving to duration in seconds
70
70
  */
71
71
  getDuration: (viewTag: number) => Promise<number>;
72
+ /**
73
+ * Capture the current video frame as a base64 encoded image
74
+ * @param viewTag - The tag of the player view
75
+ * @returns Promise resolving to the base64 encoded image string
76
+ */
77
+ capture: (viewTag: number) => Promise<string>;
72
78
  };
73
79
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAkBtB,MAAM,MAAM,kBAAkB,GAAG;IAE/B,QAAQ,EAAE,MAAM,CAAC;IAGjB,KAAK,EAAE,SAAS,CAAC;IAGjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,IAAI,CAAC,EAAE,OAAO,CAAC;IAGf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAGzB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAG3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAG/B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAGhC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAGvE,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAGtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAYF,eAAO,MAAM,uBAAuB;;;;;;;;;;CAUnC,CAAC;AAGF,eAAO,MAAM,mBAAmB,KAA8B,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,8LAK5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB;;;;OAIG;oBACa,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwBzC;;;;OAIG;qBACc,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwB1C;;;;;OAKG;sBACe,MAAM,QAAQ,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IA6BzD;;;;OAIG;8BACuB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAalD;;;;OAIG;2BACoB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;CAYhD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAkBtB,MAAM,MAAM,kBAAkB,GAAG;IAE/B,QAAQ,EAAE,MAAM,CAAC;IAGjB,KAAK,EAAE,SAAS,CAAC;IAGjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,IAAI,CAAC,EAAE,OAAO,CAAC;IAGf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAGzB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAG3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAG/B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAGhC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAGvE,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAGtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAYF,eAAO,MAAM,uBAAuB;;;;;;;;;;CAUnC,CAAC;AAGF,eAAO,MAAM,mBAAmB,KAA8B,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,8LAK5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB;;;;OAIG;oBACa,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwBzC;;;;OAIG;qBACc,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwB1C;;;;;OAKG;sBACe,MAAM,QAAQ,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IA6BzD;;;;OAIG;8BACuB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAalD;;;;OAIG;2BACoB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAa/C;;;;OAIG;uBACgB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;CAuB5C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-unified-player",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Unified Player",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
package/src/index.tsx CHANGED
@@ -234,4 +234,33 @@ export const UnifiedPlayer = {
234
234
  return Promise.reject(error);
235
235
  }
236
236
  },
237
+
238
+ /**
239
+ * Capture the current video frame as a base64 encoded image
240
+ * @param viewTag - The tag of the player view
241
+ * @returns Promise resolving to the base64 encoded image string
242
+ */
243
+ capture: (viewTag: number): Promise<string> => {
244
+ try {
245
+ console.log('UnifiedPlayer.capture called with viewTag:', viewTag);
246
+ return UnifiedPlayerModule.capture(viewTag)
247
+ .then((base64String: string) => {
248
+ console.log('Native capture method called successfully');
249
+ return base64String;
250
+ })
251
+ .catch((error: any) => {
252
+ console.log(
253
+ 'Error calling capture:',
254
+ error instanceof Error ? error.message : String(error)
255
+ );
256
+ throw error;
257
+ });
258
+ } catch (error) {
259
+ console.log(
260
+ 'Error calling capture:',
261
+ error instanceof Error ? error.message : String(error)
262
+ );
263
+ return Promise.reject(error);
264
+ }
265
+ },
237
266
  };