extended-vlc-player 0.1.3 → 0.1.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.
- package/android/build.gradle +3 -15
- package/android/src/main/java/expo/modules/extendedvlcplayer/ExtendedVlcPlayerModule.kt +2 -2
- package/android/src/main/java/expo/modules/extendedvlcplayer/PlayerSession.kt +17 -13
- package/app.plugin.js +2 -2
- package/ios/ExtendedVlcPlayer.podspec +2 -0
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
// Top-level build file for the `extended-vlc-player` local Expo Module.
|
|
2
|
-
buildscript {
|
|
3
|
-
repositories {
|
|
4
|
-
google()
|
|
5
|
-
mavenCentral()
|
|
6
|
-
}
|
|
7
|
-
dependencies {
|
|
8
|
-
classpath 'com.android.tools.build:gradle'
|
|
9
|
-
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin'
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
1
|
apply plugin: 'com.android.library'
|
|
14
2
|
apply plugin: 'kotlin-android'
|
|
15
3
|
apply plugin: 'expo-module-gradle-plugin'
|
|
@@ -20,8 +8,8 @@ version = '0.1.0'
|
|
|
20
8
|
android {
|
|
21
9
|
namespace 'expo.modules.extendedvlcplayer'
|
|
22
10
|
defaultConfig {
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
versionCode 1
|
|
12
|
+
versionName '0.1.0'
|
|
25
13
|
}
|
|
26
14
|
// The libVLC .so files ship native code for four ABIs. The Expo app
|
|
27
15
|
// already filters to its own ABIs in android/app/build.gradle; the host
|
|
@@ -32,5 +20,5 @@ android {
|
|
|
32
20
|
}
|
|
33
21
|
|
|
34
22
|
dependencies {
|
|
35
|
-
implementation 'org.videolan.android:libvlc:3.6.0'
|
|
23
|
+
implementation 'org.videolan.android:libvlc-all:3.6.0'
|
|
36
24
|
}
|
|
@@ -24,7 +24,7 @@ class ExtendedVlcPlayerModule : Module() {
|
|
|
24
24
|
|
|
25
25
|
AsyncFunction("isPictureInPictureSupported") {
|
|
26
26
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
|
|
27
|
-
appContext.
|
|
27
|
+
appContext.currentActivity?.application?.packageManager?.hasSystemFeature(
|
|
28
28
|
android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE
|
|
29
29
|
) == true
|
|
30
30
|
}
|
|
@@ -76,7 +76,7 @@ class ExtendedVlcPlayerModule : Module() {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
AsyncFunction("startPictureInPicture") { instanceId: Int ->
|
|
79
|
-
val activity = appContext.
|
|
79
|
+
val activity = appContext.currentActivity ?: return@AsyncFunction false
|
|
80
80
|
val session = PlayerRegistry.session(instanceId) ?: return@AsyncFunction false
|
|
81
81
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return@AsyncFunction false
|
|
82
82
|
val params = PictureInPictureParams.Builder()
|
|
@@ -49,9 +49,10 @@ class PlayerSession(
|
|
|
49
49
|
init {
|
|
50
50
|
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
|
|
51
51
|
override fun surfaceCreated(holder: SurfaceHolder) {
|
|
52
|
-
mediaPlayer.
|
|
52
|
+
val vout = mediaPlayer.getVLCVout()
|
|
53
|
+
vout.setVideoView(surfaceView)
|
|
53
54
|
if (!isAttached) {
|
|
54
|
-
|
|
55
|
+
vout.attachViews()
|
|
55
56
|
isAttached = true
|
|
56
57
|
}
|
|
57
58
|
mediaPlayer.play()
|
|
@@ -60,36 +61,40 @@ class PlayerSession(
|
|
|
60
61
|
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
|
|
61
62
|
|
|
62
63
|
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
|
63
|
-
mediaPlayer.
|
|
64
|
+
val vout = mediaPlayer.getVLCVout()
|
|
65
|
+
if (vout.areViewsAttached()) {
|
|
66
|
+
vout.detachViews()
|
|
67
|
+
}
|
|
68
|
+
isAttached = false
|
|
64
69
|
}
|
|
65
70
|
})
|
|
66
71
|
|
|
67
72
|
mediaPlayer.setEventListener { event ->
|
|
68
73
|
when (event.type) {
|
|
69
|
-
MediaPlayer.Event.Playing -> onPlaying?.invoke(mapOf("duration" to (
|
|
74
|
+
MediaPlayer.Event.Playing -> onPlaying?.invoke(mapOf("duration" to durationSeconds()))
|
|
70
75
|
MediaPlayer.Event.Paused -> onPaused?.invoke(emptyMap())
|
|
71
76
|
MediaPlayer.Event.Stopped -> onEnded?.invoke()
|
|
72
77
|
MediaPlayer.Event.EndReached -> onEnded?.invoke()
|
|
73
78
|
MediaPlayer.Event.EncounteredError -> onError?.invoke(
|
|
74
79
|
mapOf(
|
|
75
|
-
"message" to
|
|
80
|
+
"message" to "libVLC error",
|
|
76
81
|
"code" to "VLC_ERROR",
|
|
77
82
|
"domain" to "libVLC"
|
|
78
83
|
)
|
|
79
84
|
)
|
|
80
|
-
MediaPlayer.Event.Buffering -> onBuffering?.invoke(mapOf("isBuffering" to event.
|
|
85
|
+
MediaPlayer.Event.Buffering -> onBuffering?.invoke(mapOf("isBuffering" to (event.getBuffering() < 100.0f)))
|
|
81
86
|
MediaPlayer.Event.Opening -> onLoad?.invoke(
|
|
82
87
|
mapOf(
|
|
83
|
-
"duration" to (
|
|
88
|
+
"duration" to durationSeconds(),
|
|
84
89
|
"audioTracks" to emptyList<Map<String, Any>>(),
|
|
85
90
|
"textTracks" to emptyList<Map<String, Any>>()
|
|
86
91
|
)
|
|
87
92
|
)
|
|
88
93
|
MediaPlayer.Event.TimeChanged -> onProgress?.invoke(
|
|
89
94
|
mapOf(
|
|
90
|
-
"currentTime" to (event.
|
|
91
|
-
"duration" to (
|
|
92
|
-
"position" to (if (
|
|
95
|
+
"currentTime" to (event.getTimeChanged() / 1000.0),
|
|
96
|
+
"duration" to durationSeconds(),
|
|
97
|
+
"position" to (if (mediaPlayer.getLength() > 0) event.getTimeChanged().toDouble() / mediaPlayer.getLength() else 0.0)
|
|
93
98
|
)
|
|
94
99
|
)
|
|
95
100
|
}
|
|
@@ -103,6 +108,8 @@ class PlayerSession(
|
|
|
103
108
|
mediaPlayer.media = media
|
|
104
109
|
}
|
|
105
110
|
|
|
111
|
+
private fun durationSeconds(): Double = mediaPlayer.getLength() / 1000.0
|
|
112
|
+
|
|
106
113
|
fun play() = mediaPlayer.play()
|
|
107
114
|
fun pause() = mediaPlayer.pause()
|
|
108
115
|
fun stop() = mediaPlayer.stop()
|
|
@@ -163,6 +170,3 @@ class PlayerSession(
|
|
|
163
170
|
libVlc.release()
|
|
164
171
|
}
|
|
165
172
|
}
|
|
166
|
-
|
|
167
|
-
// Helper to convert Kotlin Array to Java Array (libVLC's attachViews is Java).
|
|
168
|
-
private inline fun <reified T> Array<out T>.toJavaArray(): Array<T> = this as Array<T>
|
package/app.plugin.js
CHANGED
|
@@ -65,7 +65,7 @@ function withIosPods(config, options) {
|
|
|
65
65
|
// ---- iOS Info.plist -------------------------------------------------------
|
|
66
66
|
|
|
67
67
|
const INFOPLIST_TAG = 'extended-vlc-player-info-plist';
|
|
68
|
-
const INFOPLIST_AUDIO_SESSION = '
|
|
68
|
+
const INFOPLIST_AUDIO_SESSION = '// extended-vlc-player: keep audio session active for PiP and background playback';
|
|
69
69
|
|
|
70
70
|
function withIosInfoPlist(config) {
|
|
71
71
|
return withInfoPlist(config, (infoPlist) => {
|
|
@@ -80,7 +80,7 @@ function withIosInfoPlist(config) {
|
|
|
80
80
|
// ---- Android build.gradle ------------------------------------------------
|
|
81
81
|
|
|
82
82
|
const GRADLE_TAG = 'extended-vlc-player-gradle';
|
|
83
|
-
const GRADLE_VLC = (vlcVersion) => ` implementation "org.videolan.android:libvlc:${vlcVersion}"`;
|
|
83
|
+
const GRADLE_VLC = (vlcVersion) => ` implementation "org.videolan.android:libvlc-all:${vlcVersion}"`;
|
|
84
84
|
|
|
85
85
|
function withAndroidGradle(config, options) {
|
|
86
86
|
const vlcVersion = (options?.android?.libVlcVersion || '3.6.0').toString();
|
|
@@ -24,6 +24,8 @@ Pod::Spec.new do |s|
|
|
|
24
24
|
s.source_files = '**/*.{h,m,mm,swift}'
|
|
25
25
|
s.pod_target_xcconfig = {
|
|
26
26
|
'DEFINES_MODULE' => 'YES',
|
|
27
|
+
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++20',
|
|
28
|
+
'CLANG_CXX_LIBRARY' => 'libc++',
|
|
27
29
|
'SWIFT_OBJC_INTERFACE_HEADER_NAME' => 'ExtendedVlcPlayer-Swift.h',
|
|
28
30
|
'OTHER_SWIFT_FLAGS' => '$(inherited) -D COCOAPODS -Xfrontend -module-name -Xfrontend ExtendedVlcPlayer',
|
|
29
31
|
# The host app's Podfile already enables use_frameworks! :linkage => :static
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extended-vlc-player",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "React Native video player built on MobileVLCKit (iOS) and libVLC (Android) with true iOS Picture-in-Picture via AVSampleBufferDisplayLayer bridge.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "build/index.js",
|