Upgrade ExoPlayer to 2.18 (#126)
* Upgrade ExoPlayer to 2.18 * Change the position polling from every 2 to every 5 sec * Make internalMediaItems non-nullable * Clean up mpv track names * Reduce explayer ffmpeg extension size by not including all decoders Removed decoders vorbis, opus, flac, pcm_mulaw, pcm_alaw, mp3, aac because these are already supported by Android. * Clean up preferredLanguage preferences
This commit is contained in:
parent
6f0d5a13a8
commit
bcdada538d
7 changed files with 70 additions and 197 deletions
|
@ -25,7 +25,7 @@ Home | Library | Movie | Season | Episode
|
|||
- ExoPlayer
|
||||
- Video codecs: H.263, H.264, H.265, VP8, VP9, AV1
|
||||
- Support depends on Android device
|
||||
- Audio codecs: Vorbis, Opus, FLAC, ALAC, PCM µ-law, PCM A-law, MP1, MP2, MP3, AMR-NB, AMR-WB, AAC, AC-3, E-AC-3, DTS, DTS-HD, TrueHD
|
||||
- Audio codecs: Vorbis, Opus, FLAC, ALAC, PCM, MP3, AMR-NB, AMR-WB, AAC, AC-3, E-AC-3, DTS, DTS-HD, TrueHD
|
||||
- Support provided by ExoPlayer FFmpeg extension
|
||||
- Subtitle codecs: SRT, VTT, SSA/ASS, PGSSUB
|
||||
- SSA/ASS has limited styling support see [this issue](https://github.com/google/ExoPlayer/issues/8435)
|
||||
|
|
|
@ -109,7 +109,7 @@ dependencies {
|
|||
kapt("com.google.dagger:hilt-compiler:$hiltVersion")
|
||||
|
||||
// ExoPlayer
|
||||
val exoplayerVersion = "2.17.1"
|
||||
val exoplayerVersion = "2.18.0"
|
||||
implementation("com.google.android.exoplayer:exoplayer-core:$exoplayerVersion")
|
||||
implementation("com.google.android.exoplayer:exoplayer-ui:$exoplayerVersion")
|
||||
implementation(files("libs/extension-ffmpeg-release.aar"))
|
||||
|
|
Binary file not shown.
|
@ -103,8 +103,10 @@ class PlayerActivity : BasePlayerActivity() {
|
|||
if (audioRenderer == null) return@setOnClickListener
|
||||
|
||||
val trackSelectionDialogBuilder = TrackSelectionDialogBuilder(
|
||||
this, resources.getString(R.string.select_audio_track),
|
||||
viewModel.trackSelector, audioRenderer
|
||||
this,
|
||||
resources.getString(R.string.select_audio_track),
|
||||
viewModel.player,
|
||||
C.TRACK_TYPE_AUDIO
|
||||
)
|
||||
val trackSelectionDialog = trackSelectionDialogBuilder.build()
|
||||
trackSelectionDialog.show()
|
||||
|
@ -134,8 +136,10 @@ class PlayerActivity : BasePlayerActivity() {
|
|||
if (subtitleRenderer == null) return@setOnClickListener
|
||||
|
||||
val trackSelectionDialogBuilder = TrackSelectionDialogBuilder(
|
||||
this, resources.getString(R.string.select_subtile_track),
|
||||
viewModel.trackSelector, subtitleRenderer
|
||||
this,
|
||||
resources.getString(R.string.select_subtile_track),
|
||||
viewModel.player,
|
||||
C.TRACK_TYPE_TEXT
|
||||
)
|
||||
trackSelectionDialogBuilder.setShowDisableOption(true)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.os.Bundle
|
|||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.mpv.MPVPlayer
|
||||
import dev.jdtech.jellyfin.mpv.TrackType
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
||||
import java.lang.IllegalStateException
|
||||
|
@ -14,21 +15,13 @@ class TrackSelectionDialogFragment(
|
|||
private val viewModel: PlayerActivityViewModel
|
||||
) : DialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val trackNames: List<String>
|
||||
when (type) {
|
||||
TrackType.AUDIO -> {
|
||||
trackNames = viewModel.currentAudioTracks.map { track ->
|
||||
val nameParts: MutableList<String> = mutableListOf()
|
||||
if (track.title.isNotEmpty()) nameParts.add(track.title)
|
||||
if (track.lang.isNotEmpty()) nameParts.add(track.lang)
|
||||
if (track.codec.isNotEmpty()) nameParts.add(track.codec)
|
||||
nameParts.joinToString(separator = " - ")
|
||||
}
|
||||
return activity?.let { activity ->
|
||||
val builder = MaterialAlertDialogBuilder(activity)
|
||||
builder.setTitle(getString(R.string.select_audio_track))
|
||||
.setSingleChoiceItems(
|
||||
trackNames.toTypedArray(),
|
||||
getTrackNames(viewModel.currentAudioTracks),
|
||||
viewModel.currentAudioTracks.indexOfFirst { it.selected }) { dialog, which ->
|
||||
viewModel.switchToTrack(
|
||||
TrackType.AUDIO,
|
||||
|
@ -40,18 +33,11 @@ class TrackSelectionDialogFragment(
|
|||
} ?: throw IllegalStateException("Activity cannot be null")
|
||||
}
|
||||
TrackType.SUBTITLE -> {
|
||||
trackNames = viewModel.currentSubtitleTracks.map { track ->
|
||||
val nameParts: MutableList<String> = mutableListOf()
|
||||
if (track.title.isNotEmpty()) nameParts.add(track.title)
|
||||
if (track.lang.isNotEmpty()) nameParts.add(track.lang)
|
||||
if (track.codec.isNotEmpty()) nameParts.add(track.codec)
|
||||
nameParts.joinToString(separator = " - ")
|
||||
}
|
||||
return activity?.let { activity ->
|
||||
val builder = MaterialAlertDialogBuilder(activity)
|
||||
builder.setTitle(getString(R.string.select_subtile_track))
|
||||
.setSingleChoiceItems(
|
||||
trackNames.toTypedArray(),
|
||||
getTrackNames(viewModel.currentSubtitleTracks),
|
||||
viewModel.currentSubtitleTracks.indexOfFirst { if (viewModel.disableSubtitle) it.ffIndex == -1 else it.selected }) { dialog, which ->
|
||||
viewModel.switchToTrack(
|
||||
TrackType.SUBTITLE,
|
||||
|
@ -67,4 +53,14 @@ class TrackSelectionDialogFragment(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTrackNames(tracks: List<MPVPlayer.Companion.Track>): Array<String> {
|
||||
return tracks.map { track ->
|
||||
val nameParts: MutableList<String> = mutableListOf()
|
||||
if (track.title.isNotEmpty()) nameParts.add(track.title)
|
||||
if (track.lang.isNotEmpty()) nameParts.add(track.lang)
|
||||
if (track.codec.isNotEmpty()) nameParts.add(track.codec)
|
||||
nameParts.joinToString(separator = " - ")
|
||||
}.toTypedArray()
|
||||
}
|
||||
}
|
|
@ -17,14 +17,10 @@ import androidx.core.content.getSystemService
|
|||
import com.google.android.exoplayer2.*
|
||||
import com.google.android.exoplayer2.Player.Commands
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||
import com.google.android.exoplayer2.source.MediaSource
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
||||
import com.google.android.exoplayer2.source.TrackGroup
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray
|
||||
import com.google.android.exoplayer2.text.Cue
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
|
||||
import com.google.android.exoplayer2.text.CueGroup
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters
|
||||
import com.google.android.exoplayer2.upstream.DataSource
|
||||
import com.google.android.exoplayer2.util.*
|
||||
import com.google.android.exoplayer2.video.VideoSize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
@ -153,7 +149,7 @@ class MPVPlayer(
|
|||
CopyOnWriteArraySet<Player.Listener>()
|
||||
|
||||
// Internal state.
|
||||
private var internalMediaItems: List<MediaItem>? = null
|
||||
private var internalMediaItems: List<MediaItem> = emptyList()
|
||||
|
||||
@Player.State
|
||||
private var playbackState: Int = Player.STATE_IDLE
|
||||
|
@ -161,7 +157,7 @@ class MPVPlayer(
|
|||
|
||||
@Player.RepeatMode
|
||||
private val repeatMode: Int = REPEAT_MODE_OFF
|
||||
private var tracksInfo: TracksInfo = TracksInfo.EMPTY
|
||||
private var tracks: Tracks = Tracks.EMPTY
|
||||
private var playbackParameters: PlaybackParameters = PlaybackParameters.DEFAULT
|
||||
|
||||
// MPV Custom
|
||||
|
@ -170,7 +166,7 @@ class MPVPlayer(
|
|||
private var currentPositionMs: Long? = null
|
||||
private var currentDurationMs: Long? = null
|
||||
private var currentCacheDurationMs: Long? = null
|
||||
var currentTracks: List<Track> = emptyList()
|
||||
var currentMpvTracks: List<Track> = emptyList()
|
||||
private var initialCommands = mutableListOf<Array<String>>()
|
||||
private var initialSeekTo: Long = 0L
|
||||
|
||||
|
@ -183,18 +179,18 @@ class MPVPlayer(
|
|||
handler.post {
|
||||
when (property) {
|
||||
"track-list" -> {
|
||||
val (tracks, newTracksInfo) = getMPVTracks(value)
|
||||
tracks.forEach { Log.i("mpv", "${it.ffIndex} ${it.type} ${it.codec}") }
|
||||
currentTracks = tracks
|
||||
val (mpvTracks, newTracks) = getMPVTracks(value)
|
||||
mpvTracks.forEach { Log.i("mpv", "${it.ffIndex} ${it.type} ${it.codec}") }
|
||||
currentMpvTracks = mpvTracks
|
||||
if (isPlayerReady) {
|
||||
if (newTracksInfo != tracksInfo) {
|
||||
tracksInfo = newTracksInfo
|
||||
if (newTracks != tracks) {
|
||||
tracks = newTracks
|
||||
listeners.sendEvent(Player.EVENT_TRACKS_CHANGED) { listener ->
|
||||
listener.onTracksInfoChanged(currentTracksInfo)
|
||||
listener.onTracksChanged(currentTracks)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tracksInfo = newTracksInfo
|
||||
tracks = newTracks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +202,7 @@ class MPVPlayer(
|
|||
when (property) {
|
||||
"eof-reached" -> {
|
||||
if (value && isPlayerReady) {
|
||||
if (currentIndex < (internalMediaItems?.size ?: 0)) {
|
||||
if (currentIndex < (internalMediaItems.size)) {
|
||||
currentIndex += 1
|
||||
prepareMediaItem(currentIndex)
|
||||
play()
|
||||
|
@ -299,7 +295,7 @@ class MPVPlayer(
|
|||
if (!isPlayerReady) {
|
||||
isPlayerReady = true
|
||||
listeners.sendEvent(Player.EVENT_TRACKS_CHANGED) { listener ->
|
||||
listener.onTracksInfoChanged(currentTracksInfo)
|
||||
listener.onTracksChanged(currentTracks)
|
||||
}
|
||||
seekTo(C.TIME_UNSET)
|
||||
if (playWhenReady) {
|
||||
|
@ -372,8 +368,8 @@ class MPVPlayer(
|
|||
index: Int
|
||||
): Boolean {
|
||||
if (index != C.INDEX_UNSET) {
|
||||
Log.i("mpv", "${currentTracks.size}")
|
||||
currentTracks.firstOrNull {
|
||||
Log.i("mpv", "${currentMpvTracks.size}")
|
||||
currentMpvTracks.firstOrNull {
|
||||
it.type == trackType && (if (isExternal) it.title else "${it.ffIndex}") == "$index"
|
||||
}.let { track ->
|
||||
if (track != null) {
|
||||
|
@ -386,7 +382,7 @@ class MPVPlayer(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (currentTracks.indexOfFirst { it.type == trackType && it.selected } != C.INDEX_UNSET) {
|
||||
if (currentMpvTracks.indexOfFirst { it.type == trackType && it.selected } != C.INDEX_UNSET) {
|
||||
MPVLib.setPropertyString(trackType, "no")
|
||||
}
|
||||
}
|
||||
|
@ -399,7 +395,7 @@ class MPVPlayer(
|
|||
* Returns the number of windows in the timeline.
|
||||
*/
|
||||
override fun getWindowCount(): Int {
|
||||
return internalMediaItems?.size ?: 0
|
||||
return internalMediaItems.size
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,7 +413,7 @@ class MPVPlayer(
|
|||
defaultPositionProjectionUs: Long
|
||||
): Window {
|
||||
val currentMediaItem =
|
||||
internalMediaItems?.get(windowIndex) ?: MediaItem.Builder().build()
|
||||
internalMediaItems.getOrNull(windowIndex) ?: MediaItem.Builder().build()
|
||||
return window.set(
|
||||
/* uid= */ windowIndex,
|
||||
/* mediaItem= */ currentMediaItem,
|
||||
|
@ -440,7 +436,7 @@ class MPVPlayer(
|
|||
* Returns the number of periods in the timeline.
|
||||
*/
|
||||
override fun getPeriodCount(): Int {
|
||||
return internalMediaItems?.size ?: 0
|
||||
return internalMediaItems.size
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -678,7 +674,7 @@ class MPVPlayer(
|
|||
currentPositionMs = null
|
||||
currentDurationMs = null
|
||||
currentCacheDurationMs = null
|
||||
tracksInfo = TracksInfo.EMPTY
|
||||
tracks = Tracks.EMPTY
|
||||
playbackParameters = PlaybackParameters.DEFAULT
|
||||
initialCommands.clear()
|
||||
//initialSeekTo = 0L
|
||||
|
@ -686,7 +682,7 @@ class MPVPlayer(
|
|||
|
||||
/** Prepares the player. */
|
||||
override fun prepare() {
|
||||
internalMediaItems?.forEach { mediaItem ->
|
||||
internalMediaItems.forEach { mediaItem ->
|
||||
MPVLib.command(
|
||||
arrayOf(
|
||||
"loadfile",
|
||||
|
@ -837,7 +833,7 @@ class MPVPlayer(
|
|||
}
|
||||
|
||||
private fun prepareMediaItem(index: Int) {
|
||||
internalMediaItems?.get(index)?.let { mediaItem ->
|
||||
internalMediaItems.getOrNull(index)?.let { mediaItem ->
|
||||
resetInternalState()
|
||||
mediaItem.localConfiguration?.subtitleConfigurations?.forEach { subtitle ->
|
||||
initialCommands.add(
|
||||
|
@ -926,33 +922,8 @@ class MPVPlayer(
|
|||
currentIndex = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available track groups.
|
||||
*
|
||||
* @see com.google.android.exoplayer2.Player.Listener.onTracksChanged
|
||||
*/
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getCurrentTrackGroups(): TrackGroupArray {
|
||||
return TrackGroupArray.EMPTY
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current track selections.
|
||||
*
|
||||
*
|
||||
* A concrete implementation may include null elements if it has a fixed number of renderer
|
||||
* components, wishes to report a TrackSelection for each of them, and has one or more renderer
|
||||
* components that is not assigned any selected tracks.
|
||||
*
|
||||
* @see com.google.android.exoplayer2.Player.Listener.onTracksChanged
|
||||
*/
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getCurrentTrackSelections(): TrackSelectionArray {
|
||||
return TrackSelectionArray()
|
||||
}
|
||||
|
||||
override fun getCurrentTracksInfo(): TracksInfo {
|
||||
return tracksInfo
|
||||
override fun getCurrentTracks(): Tracks {
|
||||
return tracks
|
||||
}
|
||||
|
||||
override fun getTrackSelectionParameters(): TrackSelectionParameters {
|
||||
|
@ -1203,7 +1174,7 @@ class MPVPlayer(
|
|||
}
|
||||
|
||||
/** Returns the current [Cues][Cue]. This list may be empty. */
|
||||
override fun getCurrentCues(): MutableList<Cue> {
|
||||
override fun getCurrentCues(): CueGroup {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
|
@ -1258,78 +1229,6 @@ class MPVPlayer(
|
|||
throw IllegalArgumentException("You should use global volume controls. Check out AUDIO_SERVICE.")
|
||||
}
|
||||
|
||||
/*private class CurrentTrackSelection(
|
||||
private val currentTrackGroup: TrackGroup,
|
||||
private val index: Int
|
||||
) : TrackSelection {
|
||||
/**
|
||||
* Returns an integer specifying the type of the selection, or [.TYPE_UNSET] if not
|
||||
* specified.
|
||||
*
|
||||
*
|
||||
* Track selection types are specific to individual applications, but should be defined
|
||||
* starting from [.TYPE_CUSTOM_BASE] to ensure they don't conflict with any types that may
|
||||
* be added to the library in the future.
|
||||
*/
|
||||
override fun getType(): Int {
|
||||
return TrackSelection.TYPE_UNSET
|
||||
}
|
||||
|
||||
/** Returns the [TrackGroup] to which the selected tracks belong. */
|
||||
override fun getTrackGroup(): TrackGroup {
|
||||
return currentTrackGroup
|
||||
}
|
||||
|
||||
/** Returns the number of tracks in the selection. */
|
||||
override fun length(): Int {
|
||||
return if (index != C.INDEX_UNSET) 1 else 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format of the track at a given index in the selection.
|
||||
*
|
||||
* @param index The index in the selection.
|
||||
* @return The format of the selected track.
|
||||
*/
|
||||
override fun getFormat(index: Int): Format {
|
||||
return currentTrackGroup.getFormat(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index in the track group of the track at a given index in the selection.
|
||||
*
|
||||
* @param index The index in the selection.
|
||||
* @return The index of the selected track.
|
||||
*/
|
||||
override fun getIndexInTrackGroup(index: Int): Int {
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index in the selection of the track with the specified format. The format is
|
||||
* located by identity so, for example, `selection.indexOf(selection.getFormat(index)) ==
|
||||
* index` even if multiple selected tracks have formats that contain the same values.
|
||||
*
|
||||
* @param format The format.
|
||||
* @return The index in the selection, or [C.INDEX_UNSET] if the track with the specified
|
||||
* format is not part of the selection.
|
||||
*/
|
||||
override fun indexOf(format: Format): Int {
|
||||
return currentTrackGroup.indexOf(format)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index in the selection of the track with the specified index in the track group.
|
||||
*
|
||||
* @param indexInTrackGroup The index in the track group.
|
||||
* @return The index in the selection, or [C.INDEX_UNSET] if the track with the specified
|
||||
* index is not part of the selection.
|
||||
*/
|
||||
override fun indexOf(indexInTrackGroup: Int): Int {
|
||||
return indexInTrackGroup
|
||||
}
|
||||
}*/
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Fraction to which audio volume is ducked on loss of audio focus
|
||||
|
@ -1449,10 +1348,10 @@ class MPVPlayer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getMPVTracks(trackList: String): Pair<List<Track>, TracksInfo> {
|
||||
val tracks = mutableListOf<Track>()
|
||||
var tracksInfo = TracksInfo.EMPTY
|
||||
val trackGroupInfos = mutableListOf<TracksInfo.TrackGroupInfo>()
|
||||
private fun getMPVTracks(trackList: String): Pair<List<Track>, Tracks> {
|
||||
val mpvTracks = mutableListOf<Track>()
|
||||
var tracks = Tracks.EMPTY
|
||||
val trackGroups = mutableListOf<Tracks.Group>()
|
||||
|
||||
val trackListVideo = mutableListOf<Format>()
|
||||
val trackListAudio = mutableListOf<Format>()
|
||||
|
@ -1475,7 +1374,7 @@ class MPVPlayer(
|
|||
width = null,
|
||||
height = null
|
||||
)
|
||||
tracks.add(emptyTrack)
|
||||
mpvTracks.add(emptyTrack)
|
||||
trackListText.add(emptyTrack.toFormat())
|
||||
val currentTrackList = JSONArray(trackList)
|
||||
for (index in 0 until currentTrackList.length()) {
|
||||
|
@ -1483,21 +1382,21 @@ class MPVPlayer(
|
|||
val currentFormat = currentTrack.toFormat()
|
||||
when (currentTrack.type) {
|
||||
TrackType.VIDEO -> {
|
||||
tracks.add(currentTrack)
|
||||
mpvTracks.add(currentTrack)
|
||||
trackListVideo.add(currentFormat)
|
||||
if (currentTrack.selected) {
|
||||
indexCurrentVideo = trackListVideo.indexOf(currentFormat)
|
||||
}
|
||||
}
|
||||
TrackType.AUDIO -> {
|
||||
tracks.add(currentTrack)
|
||||
mpvTracks.add(currentTrack)
|
||||
trackListAudio.add(currentFormat)
|
||||
if (currentTrack.selected) {
|
||||
indexCurrentAudio = trackListAudio.indexOf(currentFormat)
|
||||
}
|
||||
}
|
||||
TrackType.SUBTITLE -> {
|
||||
tracks.add(currentTrack)
|
||||
mpvTracks.add(currentTrack)
|
||||
trackListText.add(currentFormat)
|
||||
if (currentTrack.selected) {
|
||||
indexCurrentText = trackListText.indexOf(currentFormat)
|
||||
|
@ -1507,71 +1406,45 @@ class MPVPlayer(
|
|||
}
|
||||
}
|
||||
if (trackListText.size == 1 && trackListText[0].id == emptyTrack.id.toString()) {
|
||||
tracks.remove(emptyTrack)
|
||||
mpvTracks.remove(emptyTrack)
|
||||
trackListText.removeFirst()
|
||||
}
|
||||
if (trackListVideo.isNotEmpty()) {
|
||||
with(TrackGroup(*trackListVideo.toTypedArray())) {
|
||||
TracksInfo.TrackGroupInfo(
|
||||
Tracks.Group(
|
||||
this,
|
||||
true,
|
||||
intArrayOf(C.FORMAT_HANDLED),
|
||||
C.TRACK_TYPE_VIDEO,
|
||||
BooleanArray(this.length) { it == indexCurrentVideo }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (trackListAudio.isNotEmpty()) {
|
||||
with(TrackGroup(*trackListAudio.toTypedArray())) {
|
||||
TracksInfo.TrackGroupInfo(
|
||||
Tracks.Group(
|
||||
this,
|
||||
true,
|
||||
IntArray(this.length) { C.FORMAT_HANDLED },
|
||||
C.TRACK_TYPE_AUDIO,
|
||||
BooleanArray(this.length) { it == indexCurrentAudio }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (trackListText.isNotEmpty()) {
|
||||
with(TrackGroup(*trackListText.toTypedArray())) {
|
||||
TracksInfo.TrackGroupInfo(
|
||||
Tracks.Group(
|
||||
this,
|
||||
true,
|
||||
IntArray(this.length) { C.FORMAT_HANDLED },
|
||||
C.TRACK_TYPE_TEXT,
|
||||
BooleanArray(this.length) { it == indexCurrentText }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (trackGroupInfos.isNotEmpty()) {
|
||||
tracksInfo = TracksInfo(trackGroupInfos)
|
||||
if (trackGroups.isNotEmpty()) {
|
||||
tracks = Tracks(trackGroups)
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
}
|
||||
return Pair(tracks, tracksInfo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges multiple [subtitleSources] into a single [videoSource]
|
||||
*/
|
||||
fun mergeMediaSources(
|
||||
videoSource: MediaSource,
|
||||
subtitleSources: Array<MediaSource>,
|
||||
dataSource: DataSource.Factory
|
||||
): MediaSource {
|
||||
return when {
|
||||
subtitleSources.isEmpty() -> videoSource
|
||||
else -> {
|
||||
val subtitleConfigurations = mutableListOf<MediaItem.SubtitleConfiguration>()
|
||||
subtitleSources.forEach { subtitleSource ->
|
||||
subtitleSource.mediaItem.localConfiguration?.subtitleConfigurations?.forEach { subtitle ->
|
||||
subtitleConfigurations.add(subtitle)
|
||||
}
|
||||
}
|
||||
ProgressiveMediaSource.Factory(dataSource)
|
||||
.createMediaSource(
|
||||
videoSource.mediaItem.buildUpon()
|
||||
.setSubtitleConfigurations(subtitleConfigurations).build()
|
||||
)
|
||||
}
|
||||
}
|
||||
return Pair(mpvTracks, tracks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,8 +63,8 @@ constructor(
|
|||
|
||||
init {
|
||||
val useMpv = sp.getBoolean("mpv_player", false)
|
||||
val preferredAudioLanguage = sp.getString("audio_language", null) ?: ""
|
||||
val preferredSubtitleLanguage = sp.getString("subtitle_language", null) ?: ""
|
||||
val preferredAudioLanguage = sp.getString("audio_language", "")!!
|
||||
val preferredSubtitleLanguage = sp.getString("subtitle_language", "")!!
|
||||
|
||||
if (useMpv) {
|
||||
val preferredLanguages = mapOf(
|
||||
|
@ -180,7 +180,7 @@ constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
handler.postDelayed(this, 2000)
|
||||
handler.postDelayed(this, 5000)
|
||||
}
|
||||
}
|
||||
handler.post(runnable)
|
||||
|
@ -225,7 +225,7 @@ constructor(
|
|||
currentSubtitleTracks.clear()
|
||||
when (player) {
|
||||
is MPVPlayer -> {
|
||||
player.currentTracks.forEach {
|
||||
player.currentMpvTracks.forEach {
|
||||
when (it.type) {
|
||||
TrackType.AUDIO -> {
|
||||
currentAudioTracks.add(it)
|
||||
|
|
Loading…
Reference in a new issue