expo-libvlc-player 3.4.19 → 3.4.20
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 +2 -2
- package/android/src/main/java/expo/modules/libvlcplayer/LibVlcPlayerView.kt +6 -6
- package/android/src/main/java/expo/modules/libvlcplayer/managers/AudioFocusManager.kt +17 -23
- package/android/src/main/java/expo/modules/libvlcplayer/managers/KeepAwakeManager.kt +6 -6
- package/android/src/main/java/expo/modules/libvlcplayer/managers/MediaPlayerManager.kt +15 -20
- package/ios/Managers/LocalNetworkManager.swift +33 -33
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'expo.modules.libvlcplayer'
|
|
4
|
-
version = '3.4.
|
|
4
|
+
version = '3.4.20'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(':expo-modules-core').projectDir.absolutePath, 'ExpoModulesCorePlugin.gradle')
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -25,7 +25,7 @@ android {
|
|
|
25
25
|
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
26
26
|
|
|
27
27
|
versionCode 1
|
|
28
|
-
versionName '3.4.
|
|
28
|
+
versionName '3.4.20'
|
|
29
29
|
|
|
30
30
|
consumerProguardFiles('proguard-rules.pro')
|
|
31
31
|
}
|
|
@@ -47,8 +47,8 @@ class LibVlcPlayerView(
|
|
|
47
47
|
appContext: AppContext,
|
|
48
48
|
) : ExpoView(context, appContext) {
|
|
49
49
|
private val playerView: VLCVideoLayout =
|
|
50
|
-
VLCVideoLayout(context).also {
|
|
51
|
-
addView(
|
|
50
|
+
VLCVideoLayout(context).also { textureView ->
|
|
51
|
+
addView(textureView)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
var libVLC: LibVLC? = null
|
|
@@ -682,9 +682,9 @@ fun LibVlcPlayerView.setMediaPlayerListener() {
|
|
|
682
682
|
}
|
|
683
683
|
|
|
684
684
|
fun LibVlcPlayerView.setDialogCallbacks() {
|
|
685
|
-
libVLC?.let {
|
|
685
|
+
libVLC?.let { ILibVLC ->
|
|
686
686
|
VLCDialog.setCallbacks(
|
|
687
|
-
|
|
687
|
+
ILibVLC,
|
|
688
688
|
object : VLCDialog.Callbacks {
|
|
689
689
|
override fun onDisplay(dialog: VLCDialog.ErrorMessage) {
|
|
690
690
|
vlcDialog = dialog
|
|
@@ -743,7 +743,7 @@ private fun MutableList<String>.hasStartPausedOption(): Boolean {
|
|
|
743
743
|
":start-paused",
|
|
744
744
|
)
|
|
745
745
|
|
|
746
|
-
return any {
|
|
746
|
+
return any { option -> option in options }
|
|
747
747
|
}
|
|
748
748
|
|
|
749
749
|
private fun MutableList<String>.toggleStartPausedOption(autoplay: Boolean) {
|
|
@@ -754,7 +754,7 @@ private fun MutableList<String>.toggleStartPausedOption(autoplay: Boolean) {
|
|
|
754
754
|
":start-paused",
|
|
755
755
|
)
|
|
756
756
|
|
|
757
|
-
removeAll {
|
|
757
|
+
removeAll { option -> option in options }
|
|
758
758
|
|
|
759
759
|
if (!autoplay) {
|
|
760
760
|
add("--start-paused")
|
|
@@ -28,8 +28,8 @@ class AudioFocusManager(
|
|
|
28
28
|
|
|
29
29
|
private val anyPlayerRequiresFocus: Boolean
|
|
30
30
|
get() =
|
|
31
|
-
MediaPlayerManager.playerViews.
|
|
32
|
-
playerRequiresFocus(view.
|
|
31
|
+
MediaPlayerManager.playerViews.any { view ->
|
|
32
|
+
playerRequiresFocus(view.mediaPlayer)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
var currentMixingMode: AudioMixingMode = AudioMixingMode.AUTO
|
|
@@ -46,20 +46,16 @@ class AudioFocusManager(
|
|
|
46
46
|
|
|
47
47
|
private fun findAudioMixingMode(): AudioMixingMode {
|
|
48
48
|
val mixingModes =
|
|
49
|
-
MediaPlayerManager.playerViews
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
?.takeIf { view ->
|
|
53
|
-
view.mediaPlayer?.isPlaying() == true
|
|
54
|
-
}?.audioMixingMode
|
|
55
|
-
}
|
|
49
|
+
MediaPlayerManager.playerViews
|
|
50
|
+
.filter { view -> view.mediaPlayer?.isPlaying() == true }
|
|
51
|
+
.map { view -> view.audioMixingMode }
|
|
56
52
|
|
|
57
53
|
if (mixingModes.isEmpty()) {
|
|
58
54
|
return AudioMixingMode.AUTO
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
return mixingModes.reduce { currentAudioMixingMode, next ->
|
|
62
|
-
next.takeIf {
|
|
58
|
+
next.takeIf { nextAudioMixingMode -> nextAudioMixingMode.priority > currentAudioMixingMode.priority } ?: currentAudioMixingMode
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
|
|
@@ -81,8 +77,8 @@ class AudioFocusManager(
|
|
|
81
77
|
}
|
|
82
78
|
|
|
83
79
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
84
|
-
currentFocusRequest?.let {
|
|
85
|
-
if (
|
|
80
|
+
currentFocusRequest?.let { focusRequest ->
|
|
81
|
+
if (focusRequest.focusGain == audioFocusType) {
|
|
86
82
|
return
|
|
87
83
|
}
|
|
88
84
|
}
|
|
@@ -110,9 +106,9 @@ class AudioFocusManager(
|
|
|
110
106
|
}
|
|
111
107
|
|
|
112
108
|
private fun abandonAudioFocus() {
|
|
113
|
-
currentFocusRequest?.let {
|
|
109
|
+
currentFocusRequest?.let { focusRequest ->
|
|
114
110
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
115
|
-
audioManager.abandonAudioFocusRequest(
|
|
111
|
+
audioManager.abandonAudioFocusRequest(focusRequest)
|
|
116
112
|
} else {
|
|
117
113
|
@Suppress("DEPRECATION")
|
|
118
114
|
audioManager.abandonAudioFocus(this)
|
|
@@ -159,7 +155,7 @@ class AudioFocusManager(
|
|
|
159
155
|
AudioManager.AUDIOFOCUS_LOSS -> {
|
|
160
156
|
appContext.mainQueue.launch {
|
|
161
157
|
MediaPlayerManager.playerViews.forEach { view ->
|
|
162
|
-
pausePlayerIfUnmuted(view.
|
|
158
|
+
pausePlayerIfUnmuted(view.mediaPlayer)
|
|
163
159
|
}
|
|
164
160
|
|
|
165
161
|
currentFocusRequest = null
|
|
@@ -175,7 +171,7 @@ class AudioFocusManager(
|
|
|
175
171
|
|
|
176
172
|
appContext.mainQueue.launch {
|
|
177
173
|
MediaPlayerManager.playerViews.forEach { view ->
|
|
178
|
-
pausePlayerIfUnmuted(view.
|
|
174
|
+
pausePlayerIfUnmuted(view.mediaPlayer)
|
|
179
175
|
}
|
|
180
176
|
|
|
181
177
|
currentFocusRequest = null
|
|
@@ -187,12 +183,10 @@ class AudioFocusManager(
|
|
|
187
183
|
|
|
188
184
|
appContext.mainQueue.launch {
|
|
189
185
|
MediaPlayerManager.playerViews.forEach { view ->
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
duckPlayer(player)
|
|
195
|
-
}
|
|
186
|
+
if (audioMixingMode == AudioMixingMode.DO_NOT_MIX) {
|
|
187
|
+
pausePlayerIfUnmuted(view.mediaPlayer)
|
|
188
|
+
} else {
|
|
189
|
+
duckPlayer(view.mediaPlayer)
|
|
196
190
|
}
|
|
197
191
|
}
|
|
198
192
|
}
|
|
@@ -201,7 +195,7 @@ class AudioFocusManager(
|
|
|
201
195
|
AudioManager.AUDIOFOCUS_GAIN -> {
|
|
202
196
|
appContext.mainQueue.launch {
|
|
203
197
|
MediaPlayerManager.playerViews.forEach { view ->
|
|
204
|
-
unduckPlayer(view.
|
|
198
|
+
unduckPlayer(view.mediaPlayer)
|
|
205
199
|
}
|
|
206
200
|
}
|
|
207
201
|
}
|
|
@@ -12,17 +12,17 @@ class KeepAwakeManager(
|
|
|
12
12
|
get() = appContext?.currentActivity ?: throw CurrentActivityNotFoundException()
|
|
13
13
|
|
|
14
14
|
fun activateKeepAwake() {
|
|
15
|
-
currentActivity.let {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
currentActivity.let { activity ->
|
|
16
|
+
activity.runOnUiThread {
|
|
17
|
+
activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
fun deactivateKeepAwake() {
|
|
23
|
-
currentActivity.let {
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
currentActivity.let { activity ->
|
|
24
|
+
activity.runOnUiThread {
|
|
25
|
+
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -2,20 +2,21 @@ package expo.modules.libvlcplayer.managers
|
|
|
2
2
|
|
|
3
3
|
import expo.modules.kotlin.AppContext
|
|
4
4
|
import expo.modules.libvlcplayer.LibVlcPlayerView
|
|
5
|
-
import java.
|
|
5
|
+
import java.util.Collections
|
|
6
|
+
import java.util.WeakHashMap
|
|
6
7
|
|
|
7
8
|
object MediaPlayerManager {
|
|
8
9
|
lateinit var audioFocusManager: AudioFocusManager
|
|
9
10
|
lateinit var keepAwakeManager: KeepAwakeManager
|
|
10
11
|
|
|
11
|
-
val playerViews:
|
|
12
|
+
val playerViews: MutableSet<LibVlcPlayerView> = Collections.newSetFromMap(WeakHashMap())
|
|
12
13
|
|
|
13
14
|
fun registerPlayerView(view: LibVlcPlayerView) {
|
|
14
|
-
playerViews.
|
|
15
|
+
playerViews.add(view)
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
fun unregisterPlayerView(view: LibVlcPlayerView) {
|
|
18
|
-
playerViews.
|
|
19
|
+
playerViews.remove(view)
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
fun onModuleCreate(appContext: AppContext) {
|
|
@@ -29,32 +30,26 @@ object MediaPlayerManager {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
fun onModuleDestroy() {
|
|
32
|
-
playerViews.forEach {
|
|
33
|
-
|
|
34
|
-
view.destroyPlayer()
|
|
35
|
-
}
|
|
33
|
+
playerViews.forEach { view ->
|
|
34
|
+
view.destroyPlayer()
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
fun onModuleForeground() {
|
|
40
|
-
playerViews.forEach {
|
|
41
|
-
|
|
42
|
-
view.onForeground(Unit)
|
|
43
|
-
}
|
|
39
|
+
playerViews.forEach { view ->
|
|
40
|
+
view.onForeground(Unit)
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
fun onModuleBackground() {
|
|
48
|
-
playerViews.forEach {
|
|
49
|
-
|
|
50
|
-
view.onBackground(Unit)
|
|
45
|
+
playerViews.forEach { view ->
|
|
46
|
+
view.onBackground(Unit)
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
view.mediaPlayer?.let { player ->
|
|
49
|
+
val shouldPause = !view.playInBackground && player.isPlaying()
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
51
|
+
if (shouldPause) {
|
|
52
|
+
player.pause()
|
|
58
53
|
}
|
|
59
54
|
}
|
|
60
55
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
class LocalNetworkManager {
|
|
2
2
|
static let shared = LocalNetworkManager()
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
// Attempts to trigger the local network privacy alert.
|
|
5
|
+
//
|
|
6
|
+
// This builds a list of link-local IPv6 addresses and then creates a connected
|
|
7
|
+
// UDP socket to each in turn. Connecting a UDP socket triggers the local
|
|
8
|
+
// network alert without actually sending any traffic.
|
|
9
|
+
//
|
|
10
|
+
// This is a ‘best effort’ approach, and it handles errors by ignoring them.
|
|
11
|
+
// There’s no guarantee that it’ll actually trigger the alert (FB8711182).
|
|
12
12
|
|
|
13
13
|
func triggerNetworkAlert() {
|
|
14
14
|
let addresses = selectedLinkLocalIPv6Addresses()
|
|
@@ -25,20 +25,20 @@ class LocalNetworkManager {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
// Returns a selection of IPv6 addresses to connect to.
|
|
29
|
+
//
|
|
30
|
+
// To build this list it:
|
|
31
|
+
//
|
|
32
|
+
// 1. Finds the IPv6 address of every broadcast-capable interface.
|
|
33
|
+
//
|
|
34
|
+
// 2. Filters out all the ones that aren’t link-local.
|
|
35
|
+
//
|
|
36
|
+
// 3. Sets the port number to port 9, that is, the discard service. Even
|
|
37
|
+
// though the caller won’t actually send any traffic, this ensures that it
|
|
38
|
+
// would be discarded if it were sent.
|
|
39
|
+
//
|
|
40
|
+
// 4. Creates two copies of each address, and replaces the host part with a
|
|
41
|
+
// random number.
|
|
42
42
|
|
|
43
43
|
private func selectedLinkLocalIPv6Addresses() -> [sockaddr_in6] {
|
|
44
44
|
let r1 = (0 ..< 8).map { _ in UInt8.random(in: 0 ... 255) }
|
|
@@ -50,13 +50,13 @@ class LocalNetworkManager {
|
|
|
50
50
|
.joined())
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
// Replaces the host part of an IPv6 link-local address with the supplied
|
|
54
|
+
// value.
|
|
55
|
+
//
|
|
56
|
+
// In this context, _host part_ refers to the bottom 64-bits of the address,
|
|
57
|
+
// that is, the `interface ID` as defined in Section 2.5.6 of [RFC
|
|
58
|
+
// 4291](https://tools.ietf.org/html/rfc4291)). Thus, the host part parameter
|
|
59
|
+
// must be exactly 8 bytes.
|
|
60
60
|
|
|
61
61
|
private func setIPv6LinkLocalAddressHostPart(of address: sockaddr_in6, to hostPart: [UInt8]) -> sockaddr_in6 {
|
|
62
62
|
precondition(hostPart.count == 8)
|
|
@@ -67,16 +67,16 @@ class LocalNetworkManager {
|
|
|
67
67
|
return result
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
// Returns whether the supplied IPv6 address is link-local.
|
|
71
|
+
//
|
|
72
|
+
// Link-local address have the fe:c0/10 prefix.
|
|
73
73
|
|
|
74
74
|
private func isIPv6AddressLinkLocal(_ address: sockaddr_in6) -> Bool {
|
|
75
75
|
address.sin6_addr.__u6_addr.__u6_addr8.0 == 0xFE
|
|
76
76
|
&& (address.sin6_addr.__u6_addr.__u6_addr8.1 & 0xC0) == 0x80
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
// Returns the IPv6 address of every broadcast-capable interface.
|
|
80
80
|
|
|
81
81
|
private func ipv6AddressesOfBroadcastCapableInterfaces() -> [sockaddr_in6] {
|
|
82
82
|
var addrList: UnsafeMutablePointer<ifaddrs>?
|