react-native-audio-browser 0.2.0-next.4 → 0.2.0-next.5
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/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +11 -11
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +9 -5
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
- package/android/src/main/java/com/audiobrowser/player/Player.kt +19 -8
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +100 -56
- package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
- package/lib/commonjs/features/player/options.js +45 -15
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +13 -6
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/module/features/player/options.js +45 -15
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +13 -6
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/typescript/src/features/player/options.d.ts +84 -35
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +10 -3
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -1
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +5 -5
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +9 -9
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +5 -5
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +5 -5
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JOptions.hpp +5 -5
- package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
- package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +9 -9
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +36 -51
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +6 -6
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +6 -6
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
- package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
- package/nitrogen/generated/ios/swift/{Variant_NullType_NotificationButtonLayout.swift → Variant_NullType_RemoteButtonLayout.swift} +3 -3
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
- package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
- package/package.json +1 -1
- package/src/features/player/options.ts +95 -36
- package/src/features/player/setup.test.ts +12 -4
- package/src/features/player/setup.ts +13 -6
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
- package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
- package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
|
@@ -3,11 +3,11 @@ package com.audiobrowser.model
|
|
|
3
3
|
import com.margelo.nitro.audiobrowser.AndroidOptions
|
|
4
4
|
import com.margelo.nitro.audiobrowser.AppKilledPlaybackBehavior
|
|
5
5
|
import com.margelo.nitro.audiobrowser.NativeUpdateOptions
|
|
6
|
-
import com.margelo.nitro.audiobrowser.NotificationButtonLayout
|
|
7
6
|
import com.margelo.nitro.audiobrowser.Options
|
|
8
7
|
import com.margelo.nitro.audiobrowser.PlayerCapabilities
|
|
8
|
+
import com.margelo.nitro.audiobrowser.RemoteButtonLayout
|
|
9
9
|
import com.margelo.nitro.audiobrowser.Variant_NullType_Double
|
|
10
|
-
import com.margelo.nitro.audiobrowser.
|
|
10
|
+
import com.margelo.nitro.audiobrowser.Variant_NullType_RemoteButtonLayout
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Update options for the AudioBrowser that can be changed at runtime. These options control player
|
|
@@ -37,8 +37,8 @@ data class PlayerUpdateOptions(
|
|
|
37
37
|
playbackRate = null,
|
|
38
38
|
),
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
var
|
|
40
|
+
// Ordered button layout (null = derive from capabilities)
|
|
41
|
+
var remoteButtonLayout: RemoteButtonLayout? = null,
|
|
42
42
|
|
|
43
43
|
// Android-specific runtime options (all under android.* in JS)
|
|
44
44
|
var appKilledPlaybackBehavior: AppKilledPlaybackBehavior =
|
|
@@ -66,12 +66,12 @@ data class PlayerUpdateOptions(
|
|
|
66
66
|
// Update boolean options
|
|
67
67
|
androidOptions.skipSilence?.let { skipSilence = it }
|
|
68
68
|
|
|
69
|
-
// Handle
|
|
70
|
-
androidOptions.
|
|
71
|
-
|
|
69
|
+
// Handle remoteButtonLayout - variant allows distinguishing undefined from null
|
|
70
|
+
androidOptions.remoteButtonLayout?.let { variant ->
|
|
71
|
+
remoteButtonLayout =
|
|
72
72
|
when (variant) {
|
|
73
|
-
is
|
|
74
|
-
is
|
|
73
|
+
is Variant_NullType_RemoteButtonLayout.First -> null
|
|
74
|
+
is Variant_NullType_RemoteButtonLayout.Second -> variant.value
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -84,8 +84,8 @@ data class PlayerUpdateOptions(
|
|
|
84
84
|
AndroidOptions(
|
|
85
85
|
appKilledPlaybackBehavior = appKilledPlaybackBehavior,
|
|
86
86
|
skipSilence = skipSilence,
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
remoteButtonLayout =
|
|
88
|
+
remoteButtonLayout?.let { Variant_NullType_RemoteButtonLayout.create(it) },
|
|
89
89
|
),
|
|
90
90
|
forwardJumpInterval = forwardJumpInterval,
|
|
91
91
|
backwardJumpInterval = backwardJumpInterval,
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
package com.audiobrowser.player
|
|
2
2
|
|
|
3
|
-
import com.margelo.nitro.audiobrowser.NotificationButton
|
|
4
|
-
import com.margelo.nitro.audiobrowser.NotificationButtonLayout
|
|
5
3
|
import com.margelo.nitro.audiobrowser.PlayerCapabilities
|
|
4
|
+
import com.margelo.nitro.audiobrowser.RemoteButton
|
|
5
|
+
import com.margelo.nitro.audiobrowser.RemoteButtonLayout
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* The pure decision core for
|
|
9
|
-
* ([isEnabled]) and one derivation of the
|
|
10
|
-
* MediaSessionCommandManager's
|
|
11
|
-
* layout, notification commands/layout) all consume these decisions — previously each
|
|
8
|
+
* The pure decision core for Capabilities: one rule for whether a Capability is enabled
|
|
9
|
+
* ([isEnabled]) and one derivation of the button layout ([deriveButtonSlots]).
|
|
10
|
+
* MediaSessionCommandManager's Media3 assemblies all consume these decisions — previously each
|
|
12
11
|
* re-implemented them, and the copies had drifted.
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
|
-
/**
|
|
16
|
-
|
|
14
|
+
/**
|
|
15
|
+
* A control that a Capability gates. Mirrors the [PlayerCapabilities] flags Android acts on —
|
|
16
|
+
* `shuffleMode`, `repeatMode` and `playbackRate` exist on the struct but only drive CarPlay, so
|
|
17
|
+
* they have no entry here.
|
|
18
|
+
*/
|
|
19
|
+
enum class Capability {
|
|
17
20
|
PLAY_PAUSE,
|
|
18
21
|
STOP,
|
|
19
22
|
SEEK_TO,
|
|
@@ -25,95 +28,145 @@ enum class Control {
|
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
/**
|
|
28
|
-
* Whether a Capability
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
+
* Whether a Capability is enabled. Everything is enabled by default and only an explicit `false`
|
|
32
|
+
* disables — except FAVORITE, which is opt-in, and PLAY_PAUSE, which is one control on every
|
|
33
|
+
* surface and only goes away when both halves are disabled.
|
|
31
34
|
*/
|
|
32
|
-
fun PlayerCapabilities.isEnabled(
|
|
33
|
-
when (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
fun PlayerCapabilities.isEnabled(capability: Capability): Boolean =
|
|
36
|
+
when (capability) {
|
|
37
|
+
Capability.PLAY_PAUSE -> !(play == false && pause == false)
|
|
38
|
+
Capability.STOP -> stop != false
|
|
39
|
+
Capability.SEEK_TO -> seekTo != false
|
|
40
|
+
Capability.SKIP_TO_NEXT -> skipToNext != false
|
|
41
|
+
Capability.SKIP_TO_PREVIOUS -> skipToPrevious != false
|
|
42
|
+
Capability.JUMP_FORWARD -> jumpForward != false
|
|
43
|
+
Capability.JUMP_BACKWARD -> jumpBackward != false
|
|
44
|
+
Capability.FAVORITE -> favoriteEnabled
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The three positions Android actually offers, mapped to `CommandButton.SLOT_*` at Media3 assembly
|
|
49
|
+
* time. There is no secondary pair: every system surface flattens the layout to back, forward and
|
|
50
|
+
* overflow, so a fourth or fifth position would have nowhere to render.
|
|
51
|
+
*
|
|
52
|
+
* Media3 does define SLOT_BACK_SECONDARY and SLOT_FORWARD_SECONDARY, but `DisplayConstraints`
|
|
53
|
+
* defaults both to **0 buttons** — only a controller that opts in with `setMaxButtonsForSlot` shows
|
|
54
|
+
* them, which no system surface does.
|
|
55
|
+
*/
|
|
56
|
+
enum class ButtonSlot {
|
|
46
57
|
BACK,
|
|
47
58
|
FORWARD,
|
|
48
|
-
BACK_SECONDARY,
|
|
49
|
-
FORWARD_SECONDARY,
|
|
50
59
|
OVERFLOW,
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
data class SlottedButton(val button:
|
|
62
|
+
data class SlottedButton(val button: RemoteButton, val slot: ButtonSlot)
|
|
54
63
|
|
|
55
|
-
|
|
64
|
+
/** The Capability gating a button. */
|
|
65
|
+
private val RemoteButton.capability: Capability
|
|
56
66
|
get() =
|
|
57
67
|
when (this) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
RemoteButton.SKIP_TO_PREVIOUS -> Capability.SKIP_TO_PREVIOUS
|
|
69
|
+
RemoteButton.SKIP_TO_NEXT -> Capability.SKIP_TO_NEXT
|
|
70
|
+
RemoteButton.JUMP_BACKWARD -> Capability.JUMP_BACKWARD
|
|
71
|
+
RemoteButton.JUMP_FORWARD -> Capability.JUMP_FORWARD
|
|
72
|
+
RemoteButton.FAVORITE -> Capability.FAVORITE
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
/** Whether [button]'s gating Capability allows it. */
|
|
66
|
-
fun PlayerCapabilities.allows(button:
|
|
76
|
+
fun PlayerCapabilities.allows(button: RemoteButton): Boolean = isEnabled(button.capability)
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Whether two layouts describe the same arrangement.
|
|
80
|
+
*
|
|
81
|
+
* [RemoteButtonLayout] is a generated data class whose `overflow` is an `Array`, and Kotlin
|
|
82
|
+
* data-class equality compares arrays by *reference*. Plain `==` therefore reports "changed" for
|
|
83
|
+
* two identical layouts whenever overflow is set, because every options update carries a fresh
|
|
84
|
+
* array across the bridge — which would republish the layout to Android Auto on every unrelated
|
|
85
|
+
* `updateOptions` call.
|
|
86
|
+
*/
|
|
87
|
+
internal fun RemoteButtonLayout?.sameAs(other: RemoteButtonLayout?): Boolean =
|
|
88
|
+
if (this == null || other == null) {
|
|
89
|
+
this == null && other == null
|
|
90
|
+
} else {
|
|
91
|
+
back == other.back && forward == other.forward && overflow.contentEquals(other.overflow)
|
|
92
|
+
}
|
|
67
93
|
|
|
68
94
|
/**
|
|
69
|
-
* The single derivation of the
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
95
|
+
* The single derivation of the button layout.
|
|
96
|
+
*
|
|
97
|
+
* The two parameters answer different questions, and only one of them is authoritative:
|
|
98
|
+
* - [capabilities] — *may* this button exist? Admission.
|
|
99
|
+
* - [layout] — *where* does it go? Arrangement.
|
|
100
|
+
*
|
|
101
|
+
* **A layout can rearrange buttons but never add one.** Every entry is filtered through [allows]
|
|
102
|
+
* regardless of its position, so naming a button whose Capability is disabled does nothing —
|
|
103
|
+
* listing `FAVORITE` while `capabilities.favorite` is off leaves it off. This is the usual
|
|
104
|
+
* surprise, because JUMP_FORWARD and JUMP_BACKWARD default to disabled: a layout full of jump
|
|
105
|
+
* buttons silently produces none until those capabilities are turned on.
|
|
106
|
+
*
|
|
107
|
+
* With no [layout], [capabilities] does both jobs — it decides membership *and* infers positions:
|
|
108
|
+
* skip takes the primary positions, jump falls back into a primary position when its skip is
|
|
109
|
+
* disabled and otherwise sits in overflow, favorite in overflow.
|
|
110
|
+
*
|
|
111
|
+
* With a [layout], each field maps to its position — `back` to BACK, `forward` to FORWARD, every
|
|
112
|
+
* `overflow` entry to OVERFLOW in order — and disabled entries drop out. A dropped entry leaves its
|
|
113
|
+
* position empty rather than promoting anything into it: turning off one capability must not
|
|
114
|
+
* silently rearrange the row.
|
|
115
|
+
*
|
|
116
|
+
* A [layout] is all-or-nothing: every field is required, so it fully describes the arrangement and
|
|
117
|
+
* nothing is merged with the capability defaults. The bridge could not support a per-field merge
|
|
118
|
+
* anyway — Nitro maps both an omitted and a null enum field to Kotlin `null`, so native cannot tell
|
|
119
|
+
* "leave this empty" from "derive this one".
|
|
120
|
+
*
|
|
121
|
+
* [capabilities] has a second job outside this function: it also drives the player and session
|
|
122
|
+
* commands, which govern what a Bluetooth remote or headset can trigger. That is why placement is
|
|
123
|
+
* purely cosmetic here — a button left out of the layout disappears from every screen while still
|
|
124
|
+
* responding to a headset.
|
|
125
|
+
*
|
|
126
|
+
* @param capabilities What the player is allowed to do. Gates every button, in both modes.
|
|
127
|
+
* @param layout Explicit placement, or null to infer placement from [capabilities].
|
|
73
128
|
*/
|
|
74
|
-
fun
|
|
129
|
+
fun deriveButtonSlots(
|
|
75
130
|
capabilities: PlayerCapabilities,
|
|
76
|
-
layout:
|
|
131
|
+
layout: RemoteButtonLayout?,
|
|
77
132
|
): List<SlottedButton> {
|
|
78
133
|
if (layout != null) {
|
|
79
134
|
return buildList {
|
|
80
|
-
layout.back?.let { add(SlottedButton(it,
|
|
81
|
-
layout.forward?.let { add(SlottedButton(it,
|
|
82
|
-
layout.
|
|
83
|
-
layout.forwardSecondary?.let { add(SlottedButton(it, NotificationSlot.FORWARD_SECONDARY)) }
|
|
84
|
-
layout.overflow?.forEach { add(SlottedButton(it, NotificationSlot.OVERFLOW)) }
|
|
135
|
+
layout.back?.let { add(SlottedButton(it, ButtonSlot.BACK)) }
|
|
136
|
+
layout.forward?.let { add(SlottedButton(it, ButtonSlot.FORWARD)) }
|
|
137
|
+
layout.overflow.forEach { add(SlottedButton(it, ButtonSlot.OVERFLOW)) }
|
|
85
138
|
}
|
|
86
139
|
.filter { capabilities.allows(it.button) }
|
|
87
140
|
}
|
|
88
141
|
|
|
89
142
|
return buildList {
|
|
90
|
-
val skipPrevious = capabilities.isEnabled(
|
|
91
|
-
val skipNext = capabilities.isEnabled(
|
|
92
|
-
val jumpBackward = capabilities.isEnabled(
|
|
93
|
-
val jumpForward = capabilities.isEnabled(
|
|
143
|
+
val skipPrevious = capabilities.isEnabled(Capability.SKIP_TO_PREVIOUS)
|
|
144
|
+
val skipNext = capabilities.isEnabled(Capability.SKIP_TO_NEXT)
|
|
145
|
+
val jumpBackward = capabilities.isEnabled(Capability.JUMP_BACKWARD)
|
|
146
|
+
val jumpForward = capabilities.isEnabled(Capability.JUMP_FORWARD)
|
|
94
147
|
|
|
95
|
-
// Primary
|
|
148
|
+
// Primary positions: skip, with jump falling back when its skip is disabled.
|
|
96
149
|
if (skipPrevious) {
|
|
97
|
-
add(SlottedButton(
|
|
150
|
+
add(SlottedButton(RemoteButton.SKIP_TO_PREVIOUS, ButtonSlot.BACK))
|
|
98
151
|
} else if (jumpBackward) {
|
|
99
|
-
add(SlottedButton(
|
|
152
|
+
add(SlottedButton(RemoteButton.JUMP_BACKWARD, ButtonSlot.BACK))
|
|
100
153
|
}
|
|
101
154
|
if (skipNext) {
|
|
102
|
-
add(SlottedButton(
|
|
155
|
+
add(SlottedButton(RemoteButton.SKIP_TO_NEXT, ButtonSlot.FORWARD))
|
|
103
156
|
} else if (jumpForward) {
|
|
104
|
-
add(SlottedButton(
|
|
157
|
+
add(SlottedButton(RemoteButton.JUMP_FORWARD, ButtonSlot.FORWARD))
|
|
105
158
|
}
|
|
106
159
|
|
|
107
|
-
// Jump moves to
|
|
160
|
+
// Jump moves to overflow when skip holds the primary position.
|
|
108
161
|
if (skipPrevious && jumpBackward) {
|
|
109
|
-
add(SlottedButton(
|
|
162
|
+
add(SlottedButton(RemoteButton.JUMP_BACKWARD, ButtonSlot.OVERFLOW))
|
|
110
163
|
}
|
|
111
164
|
if (skipNext && jumpForward) {
|
|
112
|
-
add(SlottedButton(
|
|
165
|
+
add(SlottedButton(RemoteButton.JUMP_FORWARD, ButtonSlot.OVERFLOW))
|
|
113
166
|
}
|
|
114
167
|
|
|
115
|
-
if (capabilities.isEnabled(
|
|
116
|
-
add(SlottedButton(
|
|
168
|
+
if (capabilities.isEnabled(Capability.FAVORITE)) {
|
|
169
|
+
add(SlottedButton(RemoteButton.FAVORITE, ButtonSlot.OVERFLOW))
|
|
117
170
|
}
|
|
118
171
|
}
|
|
119
172
|
}
|
|
@@ -24,8 +24,8 @@ import com.margelo.nitro.audiobrowser.GateEvent
|
|
|
24
24
|
import com.margelo.nitro.audiobrowser.GateReason
|
|
25
25
|
import com.margelo.nitro.audiobrowser.MediaReference
|
|
26
26
|
import com.margelo.nitro.audiobrowser.NativeGateRequest
|
|
27
|
-
import com.margelo.nitro.audiobrowser.NotificationButtonLayout
|
|
28
27
|
import com.margelo.nitro.audiobrowser.PlayerCapabilities
|
|
28
|
+
import com.margelo.nitro.audiobrowser.RemoteButtonLayout
|
|
29
29
|
import com.margelo.nitro.audiobrowser.SearchParams
|
|
30
30
|
import com.margelo.nitro.audiobrowser.Track
|
|
31
31
|
import kotlinx.coroutines.CancellationException
|
|
@@ -160,16 +160,20 @@ class MediaSessionCallback(private val player: Player) :
|
|
|
160
160
|
fun updateMediaSession(
|
|
161
161
|
mediaSession: MediaSession,
|
|
162
162
|
capabilities: PlayerCapabilities,
|
|
163
|
-
|
|
163
|
+
remoteButtonLayout: RemoteButtonLayout?,
|
|
164
164
|
searchAvailable: Boolean,
|
|
165
|
+
forwardJumpInterval: Double,
|
|
166
|
+
backwardJumpInterval: Double,
|
|
165
167
|
) {
|
|
166
168
|
// Store as MediaLibrarySession for notifyChildrenChanged support
|
|
167
169
|
this.mediaLibrarySession = mediaSession as? MediaLibraryService.MediaLibrarySession
|
|
168
170
|
commandManager.updateMediaSession(
|
|
169
171
|
mediaSession,
|
|
170
172
|
capabilities,
|
|
171
|
-
|
|
173
|
+
remoteButtonLayout,
|
|
172
174
|
searchAvailable,
|
|
175
|
+
forwardJumpInterval,
|
|
176
|
+
backwardJumpInterval,
|
|
173
177
|
)
|
|
174
178
|
}
|
|
175
179
|
|
|
@@ -400,8 +404,8 @@ class MediaSessionCallback(private val player: Player) :
|
|
|
400
404
|
/**
|
|
401
405
|
* Converts tracks to MediaItems for browse delivery, routing http(s) artwork through the
|
|
402
406
|
* content:// provider so Android Auto can load it via the ArtworkContentProvider. Image-row
|
|
403
|
-
* tracks (a CarPlay-only rendering) are expanded into their items as regular grouped rows
|
|
404
|
-
*
|
|
407
|
+
* tracks (a CarPlay-only rendering) are expanded into their items as regular grouped rows first —
|
|
408
|
+
* see [TrackFactory.expandImageRows].
|
|
405
409
|
*/
|
|
406
410
|
private fun toMediaItems(tracks: List<Track>): List<MediaItem> {
|
|
407
411
|
val registry = player.browseArtworkRegistry
|