mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Add audio and video track support
This commit is contained in:
parent
67addd79a0
commit
ec3cdb60f2
8 changed files with 822 additions and 458 deletions
|
@ -212,6 +212,30 @@ class CS3IPlayer : IPlayer {
|
||||||
|
|
||||||
var currentSubtitles: SubtitleData? = null
|
var currentSubtitles: SubtitleData? = null
|
||||||
|
|
||||||
|
override fun setExoplayerVideoSize(width: Int, height: Int) {
|
||||||
|
exoPlayer?.trackSelectionParameters = exoPlayer?.trackSelectionParameters
|
||||||
|
?.buildUpon()
|
||||||
|
?.setMaxVideoSize(width, height)
|
||||||
|
?.build()
|
||||||
|
?: return
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setExoplayerAudioTrack(trackLanguage: String?) {
|
||||||
|
exoPlayer?.trackSelectionParameters = exoPlayer?.trackSelectionParameters
|
||||||
|
?.buildUpon()
|
||||||
|
?.setPreferredAudioLanguage(trackLanguage)
|
||||||
|
?.build()
|
||||||
|
?: return
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getExoplayerTracks(): ExoplayerTracks {
|
||||||
|
return ExoplayerTracks(
|
||||||
|
exoPlayer?.videoFormat,
|
||||||
|
exoPlayer?.audioFormat,
|
||||||
|
exoPlayer?.currentTracksInfo?.trackGroupInfos ?: emptyList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if the player should be reloaded
|
* @return True if the player should be reloaded
|
||||||
* */
|
* */
|
||||||
|
@ -465,6 +489,7 @@ class CS3IPlayer : IPlayer {
|
||||||
trackSelector.parameters = DefaultTrackSelector.ParametersBuilder(context)
|
trackSelector.parameters = DefaultTrackSelector.ParametersBuilder(context)
|
||||||
// .setRendererDisabled(C.TRACK_TYPE_VIDEO, true)
|
// .setRendererDisabled(C.TRACK_TYPE_VIDEO, true)
|
||||||
.setRendererDisabled(C.TRACK_TYPE_TEXT, true)
|
.setRendererDisabled(C.TRACK_TYPE_TEXT, true)
|
||||||
|
.setTunnelingEnabled(true)
|
||||||
.setDisabledTextTrackSelectionFlags(C.TRACK_TYPE_TEXT)
|
.setDisabledTextTrackSelectionFlags(C.TRACK_TYPE_TEXT)
|
||||||
.clearSelectionOverrides()
|
.clearSelectionOverrides()
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -176,6 +176,10 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
||||||
throw NotImplementedError()
|
throw NotImplementedError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun showTracksDialogue() {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
open fun openOnlineSubPicker(
|
open fun openOnlineSubPicker(
|
||||||
context: Context,
|
context: Context,
|
||||||
imdbId: Long?,
|
imdbId: Long?,
|
||||||
|
@ -1101,6 +1105,7 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
||||||
|
|
||||||
// if nothing has loaded these buttons should not be visible
|
// if nothing has loaded these buttons should not be visible
|
||||||
player_skip_episode?.isVisible = false
|
player_skip_episode?.isVisible = false
|
||||||
|
player_tracks_btt?.isVisible = false
|
||||||
player_skip_op?.isVisible = false
|
player_skip_op?.isVisible = false
|
||||||
shadow_overlay?.isVisible = false
|
shadow_overlay?.isVisible = false
|
||||||
|
|
||||||
|
@ -1296,6 +1301,10 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
||||||
showMirrorsDialogue()
|
showMirrorsDialogue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
player_tracks_btt?.setOnClickListener {
|
||||||
|
showTracksDialogue()
|
||||||
|
}
|
||||||
|
|
||||||
player_intro_play?.setOnClickListener {
|
player_intro_play?.setOnClickListener {
|
||||||
player_intro_play?.isGone = true
|
player_intro_play?.isGone = true
|
||||||
player.handleEvent(CSPlayerEvent.Play)
|
player.handleEvent(CSPlayerEvent.Play)
|
||||||
|
|
|
@ -18,6 +18,11 @@ import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.google.android.exoplayer2.C.TRACK_TYPE_AUDIO
|
||||||
|
import com.google.android.exoplayer2.C.TRACK_TYPE_VIDEO
|
||||||
|
import com.google.android.exoplayer2.Format
|
||||||
|
import com.google.android.exoplayer2.Format.NO_VALUE
|
||||||
|
import com.google.android.exoplayer2.TracksInfo
|
||||||
import com.google.android.exoplayer2.util.MimeTypes
|
import com.google.android.exoplayer2.util.MimeTypes
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
|
@ -53,6 +58,8 @@ import kotlinx.android.synthetic.main.dialog_online_subtitles.cancel_btt
|
||||||
import kotlinx.android.synthetic.main.fragment_player.*
|
import kotlinx.android.synthetic.main.fragment_player.*
|
||||||
import kotlinx.android.synthetic.main.player_custom_layout.*
|
import kotlinx.android.synthetic.main.player_custom_layout.*
|
||||||
import kotlinx.android.synthetic.main.player_select_source_and_subs.*
|
import kotlinx.android.synthetic.main.player_select_source_and_subs.*
|
||||||
|
import kotlinx.android.synthetic.main.player_select_source_and_subs.subtitles_click_settings
|
||||||
|
import kotlinx.android.synthetic.main.player_select_tracks.*
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
class GeneratorPlayer : FullScreenPlayer() {
|
class GeneratorPlayer : FullScreenPlayer() {
|
||||||
|
@ -106,6 +113,12 @@ class GeneratorPlayer : FullScreenPlayer() {
|
||||||
|
|
||||||
override fun embeddedSubtitlesFetched(subtitles: List<SubtitleData>) {
|
override fun embeddedSubtitlesFetched(subtitles: List<SubtitleData>) {
|
||||||
viewModel.addSubtitles(subtitles.toSet())
|
viewModel.addSubtitles(subtitles.toSet())
|
||||||
|
|
||||||
|
val tracks = player.getExoplayerTracks().allTracks
|
||||||
|
val videoTracks = tracks.filter { it.trackType == TRACK_TYPE_VIDEO }.getFormats().size
|
||||||
|
val audioTracks = tracks.filter { it.trackType == TRACK_TYPE_AUDIO }.getFormats().size
|
||||||
|
|
||||||
|
player_tracks_btt?.isVisible = videoTracks > 1 || audioTracks > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun noSubtitles(): Boolean {
|
private fun noSubtitles(): Boolean {
|
||||||
|
@ -476,6 +489,8 @@ class GeneratorPlayer : FullScreenPlayer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectSourceDialog: AlertDialog? = null
|
var selectSourceDialog: AlertDialog? = null
|
||||||
|
// var selectTracksDialog: AlertDialog? = null
|
||||||
|
|
||||||
override fun showMirrorsDialogue() {
|
override fun showMirrorsDialogue() {
|
||||||
try {
|
try {
|
||||||
currentSelectedSubtitles = player.getCurrentPreferredSubtitle()
|
currentSelectedSubtitles = player.getCurrentPreferredSubtitle()
|
||||||
|
@ -667,6 +682,139 @@ class GeneratorPlayer : FullScreenPlayer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all supported formats in a list
|
||||||
|
* */
|
||||||
|
private fun List<TracksInfo.TrackGroupInfo>.getFormats(): List<Format> {
|
||||||
|
return this.map {
|
||||||
|
(0 until it.trackGroup.length).mapNotNull { i ->
|
||||||
|
if (it.isSupported)
|
||||||
|
it.trackGroup.getFormat(i) // to it.isSelected
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
}.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showTracksDialogue() {
|
||||||
|
try {
|
||||||
|
//println("CURRENT SELECTED :$currentSelectedSubtitles of $currentSubs")
|
||||||
|
context?.let { ctx ->
|
||||||
|
val tracks = player.getExoplayerTracks()
|
||||||
|
|
||||||
|
val isPlaying = player.getIsPlaying()
|
||||||
|
player.handleEvent(CSPlayerEvent.Pause)
|
||||||
|
|
||||||
|
val currentVideoTracks = tracks.allTracks.filter {
|
||||||
|
it.trackType == TRACK_TYPE_VIDEO
|
||||||
|
}.getFormats().sortedBy {
|
||||||
|
-it.height
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentAudioTracks = tracks.allTracks.filter {
|
||||||
|
it.trackType == TRACK_TYPE_AUDIO
|
||||||
|
}.getFormats()
|
||||||
|
|
||||||
|
val trackBuilder = AlertDialog.Builder(ctx, R.style.AlertDialogCustomBlack)
|
||||||
|
.setView(R.layout.player_select_tracks)
|
||||||
|
|
||||||
|
val tracksDialog = trackBuilder.create()
|
||||||
|
|
||||||
|
// selectTracksDialog = tracksDialog
|
||||||
|
|
||||||
|
tracksDialog.show()
|
||||||
|
val videosList = tracksDialog.video_tracks_list
|
||||||
|
val audioList = tracksDialog.auto_tracks_list
|
||||||
|
|
||||||
|
tracksDialog.video_tracks_holder.isVisible = currentVideoTracks.size > 1
|
||||||
|
tracksDialog.audio_tracks_holder.isVisible = currentAudioTracks.size > 1
|
||||||
|
|
||||||
|
fun dismiss() {
|
||||||
|
if (isPlaying) {
|
||||||
|
player.handleEvent(CSPlayerEvent.Play)
|
||||||
|
}
|
||||||
|
activity?.hideSystemUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
val videosArrayAdapter =
|
||||||
|
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||||
|
|
||||||
|
videosArrayAdapter.addAll(currentVideoTracks.mapIndexed { index, format ->
|
||||||
|
format.label
|
||||||
|
?: (if (format.height == NO_VALUE || format.width == NO_VALUE) index else "${format.width}x${format.height}").toString()
|
||||||
|
})
|
||||||
|
|
||||||
|
videosList.choiceMode = AbsListView.CHOICE_MODE_SINGLE
|
||||||
|
videosList.adapter = videosArrayAdapter
|
||||||
|
|
||||||
|
// Sometimes the data is not the same because some data gets resolved at different stages i think
|
||||||
|
var videoIndex = currentVideoTracks.indexOf(tracks.currentVideoFormat).takeIf {
|
||||||
|
it != -1
|
||||||
|
} ?: currentVideoTracks.indexOfFirst {
|
||||||
|
tracks.currentVideoFormat?.id == it.id
|
||||||
|
}
|
||||||
|
|
||||||
|
videosList.setSelection(videoIndex)
|
||||||
|
videosList.setItemChecked(videoIndex, true)
|
||||||
|
|
||||||
|
videosList.setOnItemClickListener { _, _, which, _ ->
|
||||||
|
videoIndex = which
|
||||||
|
videosList.setItemChecked(which, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
tracksDialog.setOnDismissListener {
|
||||||
|
dismiss()
|
||||||
|
// selectTracksDialog = null
|
||||||
|
}
|
||||||
|
|
||||||
|
var audioIndexStart = currentAudioTracks.indexOf(tracks.currentAudioFormat).takeIf {
|
||||||
|
it != -1
|
||||||
|
} ?: currentVideoTracks.indexOfFirst {
|
||||||
|
tracks.currentAudioFormat?.id == it.id
|
||||||
|
}
|
||||||
|
|
||||||
|
val audioArrayAdapter =
|
||||||
|
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||||
|
// audioArrayAdapter.add(ctx.getString(R.string.no_subtitles))
|
||||||
|
audioArrayAdapter.addAll(currentAudioTracks.mapIndexed { index, format ->
|
||||||
|
format.label ?: format.language?.let { fromTwoLettersToLanguage(it) } ?: index.toString()
|
||||||
|
})
|
||||||
|
|
||||||
|
audioList.adapter = audioArrayAdapter
|
||||||
|
audioList.choiceMode = AbsListView.CHOICE_MODE_SINGLE
|
||||||
|
|
||||||
|
audioList.setSelection(audioIndexStart)
|
||||||
|
audioList.setItemChecked(audioIndexStart, true)
|
||||||
|
|
||||||
|
audioList.setOnItemClickListener { _, _, which, _ ->
|
||||||
|
audioIndexStart = which
|
||||||
|
audioList.setItemChecked(which, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
tracksDialog.cancel_btt?.setOnClickListener {
|
||||||
|
tracksDialog.dismissSafe(activity)
|
||||||
|
}
|
||||||
|
|
||||||
|
tracksDialog.apply_btt?.setOnClickListener {
|
||||||
|
player.setExoplayerAudioTrack(
|
||||||
|
currentAudioTracks.getOrNull(audioIndexStart)?.language
|
||||||
|
)
|
||||||
|
|
||||||
|
val currentVideo = currentVideoTracks.getOrNull(videoIndex)
|
||||||
|
val width = currentVideo?.width ?: NO_VALUE
|
||||||
|
val height = currentVideo?.height ?: NO_VALUE
|
||||||
|
if (width != NO_VALUE && height != NO_VALUE) {
|
||||||
|
player.setExoplayerVideoSize(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
tracksDialog.dismissSafe(activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun playerError(exception: Exception) {
|
override fun playerError(exception: Exception) {
|
||||||
Log.i(TAG, "playerError = $currentSelectedLink")
|
Log.i(TAG, "playerError = $currentSelectedLink")
|
||||||
super.playerError(exception)
|
super.playerError(exception)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.lagradost.cloudstream3.ui.player
|
package com.lagradost.cloudstream3.ui.player
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.google.android.exoplayer2.Format
|
||||||
|
import com.google.android.exoplayer2.TracksInfo
|
||||||
import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle
|
import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorUri
|
import com.lagradost.cloudstream3.utils.ExtractorUri
|
||||||
|
@ -46,7 +48,13 @@ enum class CSPlayerLoading {
|
||||||
//IsDone,
|
//IsDone,
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvalidFileException(msg : String) : Exception(msg)
|
data class ExoplayerTracks(
|
||||||
|
val currentVideoFormat: Format?,
|
||||||
|
val currentAudioFormat: Format?,
|
||||||
|
val allTracks: List<TracksInfo.TrackGroupInfo>
|
||||||
|
)
|
||||||
|
|
||||||
|
class InvalidFileException(msg: String) : Exception(msg)
|
||||||
|
|
||||||
//http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
|
//http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
|
||||||
const val STATE_RESUME_WINDOW = "resumeWindow"
|
const val STATE_RESUME_WINDOW = "resumeWindow"
|
||||||
|
@ -73,8 +81,8 @@ interface IPlayer {
|
||||||
fun seekTime(time: Long)
|
fun seekTime(time: Long)
|
||||||
fun seekTo(time: Long)
|
fun seekTo(time: Long)
|
||||||
|
|
||||||
fun getSubtitleOffset() : Long // in ms
|
fun getSubtitleOffset(): Long // in ms
|
||||||
fun setSubtitleOffset(offset : Long) // in ms
|
fun setSubtitleOffset(offset: Long) // in ms
|
||||||
|
|
||||||
fun initCallbacks(
|
fun initCallbacks(
|
||||||
playerUpdated: (Any?) -> Unit, // attach player to view
|
playerUpdated: (Any?) -> Unit, // attach player to view
|
||||||
|
@ -89,6 +97,7 @@ interface IPlayer {
|
||||||
subtitlesUpdates: (() -> Unit)? = null, // callback from player to inform that subtitles have updated in some way
|
subtitlesUpdates: (() -> Unit)? = null, // callback from player to inform that subtitles have updated in some way
|
||||||
embeddedSubtitlesFetched: ((List<SubtitleData>) -> Unit)? = null, // callback from player to give all embedded subtitles
|
embeddedSubtitlesFetched: ((List<SubtitleData>) -> Unit)? = null, // callback from player to give all embedded subtitles
|
||||||
)
|
)
|
||||||
|
|
||||||
fun releaseCallbacks()
|
fun releaseCallbacks()
|
||||||
|
|
||||||
fun updateSubtitleStyle(style: SaveCaptionStyle)
|
fun updateSubtitleStyle(style: SaveCaptionStyle)
|
||||||
|
@ -100,16 +109,16 @@ interface IPlayer {
|
||||||
link: ExtractorLink? = null,
|
link: ExtractorLink? = null,
|
||||||
data: ExtractorUri? = null,
|
data: ExtractorUri? = null,
|
||||||
startPosition: Long? = null,
|
startPosition: Long? = null,
|
||||||
subtitles : Set<SubtitleData>,
|
subtitles: Set<SubtitleData>,
|
||||||
subtitle : SubtitleData?,
|
subtitle: SubtitleData?,
|
||||||
autoPlay : Boolean? = true
|
autoPlay: Boolean? = true
|
||||||
)
|
)
|
||||||
|
|
||||||
fun reloadPlayer(context: Context)
|
fun reloadPlayer(context: Context)
|
||||||
|
|
||||||
fun setActiveSubtitles(subtitles : Set<SubtitleData>)
|
fun setActiveSubtitles(subtitles: Set<SubtitleData>)
|
||||||
fun setPreferredSubtitles(subtitle : SubtitleData?) : Boolean // returns true if the player requires a reload, null for nothing
|
fun setPreferredSubtitles(subtitle: SubtitleData?): Boolean // returns true if the player requires a reload, null for nothing
|
||||||
fun getCurrentPreferredSubtitle() : SubtitleData?
|
fun getCurrentPreferredSubtitle(): SubtitleData?
|
||||||
|
|
||||||
fun handleEvent(event: CSPlayerEvent)
|
fun handleEvent(event: CSPlayerEvent)
|
||||||
|
|
||||||
|
@ -120,5 +129,13 @@ interface IPlayer {
|
||||||
fun release()
|
fun release()
|
||||||
|
|
||||||
/** Get if player is actually used */
|
/** Get if player is actually used */
|
||||||
fun isActive() : Boolean
|
fun isActive(): Boolean
|
||||||
|
|
||||||
|
fun getExoplayerTracks(): ExoplayerTracks
|
||||||
|
|
||||||
|
/** If no parameters are set it'll default to no set size */
|
||||||
|
fun setExoplayerVideoSize(width: Int = Int.MAX_VALUE, height: Int = Int.MAX_VALUE)
|
||||||
|
|
||||||
|
/** If no trackLanguage is set it'll default to first track */
|
||||||
|
fun setExoplayerAudioTrack(trackLanguage: String?)
|
||||||
}
|
}
|
|
@ -75,6 +75,8 @@ open class ResultTrailerPlayer : com.lagradost.cloudstream3.ui.player.FullScreen
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showMirrorsDialogue() {}
|
override fun showMirrorsDialogue() {}
|
||||||
|
override fun showTracksDialogue() {}
|
||||||
|
|
||||||
override fun openOnlineSubPicker(context: Context, imdbId: Long?, dismissCallback: () -> Unit) {}
|
override fun openOnlineSubPicker(context: Context, imdbId: Long?, dismissCallback: () -> Unit) {}
|
||||||
|
|
||||||
override fun subtitlesChanged() {}
|
override fun subtitlesChanged() {}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
148
app/src/main/res/layout/player_select_tracks.xml
Normal file
148
app/src/main/res/layout/player_select_tracks.xml
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@null"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="60dp"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/video_tracks_holder"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:text="@string/video_tracks"
|
||||||
|
android:textColor="?attr/textColor"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:requiresFadingEdge="vertical"
|
||||||
|
android:id="@+id/video_tracks_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:background="?attr/primaryBlackBackground"
|
||||||
|
android:nextFocusLeft="@id/sort_subtitles"
|
||||||
|
android:nextFocusRight="@id/apply_btt"
|
||||||
|
tools:listitem="@layout/sort_bottom_single_choice" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/audio_tracks_holder"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- android:id="@+id/subs_settings" android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:id="@+id/subtitles_click_settings"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:text="@string/audio_tracks"
|
||||||
|
android:textColor="?attr/textColor"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<!-- <TextView-->
|
||||||
|
<!-- android:textSize="15sp"-->
|
||||||
|
<!-- android:id="@+id/subtitles_encoding_format"-->
|
||||||
|
<!-- android:textColor="?attr/textColor"-->
|
||||||
|
<!-- android:layout_gravity="center"-->
|
||||||
|
<!-- android:gravity="center"-->
|
||||||
|
<!-- tools:text="Thai (TIS 620-2533/ISO 8859-11)"-->
|
||||||
|
<!-- android:layout_width="wrap_content"-->
|
||||||
|
<!-- android:layout_height="wrap_content" />-->
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="25dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
|
||||||
|
android:contentDescription="@string/home_change_provider_img_des"
|
||||||
|
android:src="@drawable/ic_outline_settings_24"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:requiresFadingEdge="vertical"
|
||||||
|
android:id="@+id/auto_tracks_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:background="?attr/primaryBlackBackground"
|
||||||
|
android:nextFocusLeft="@id/sort_providers"
|
||||||
|
android:nextFocusRight="@id/cancel_btt"
|
||||||
|
tools:listfooter="@layout/sort_bottom_footer_add_choice"
|
||||||
|
tools:listitem="@layout/sort_bottom_single_choice" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/apply_btt_holder"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:gravity="bottom|end"
|
||||||
|
android:layout_marginTop="-60dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
style="@style/WhiteButton"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:text="@string/sort_apply"
|
||||||
|
android:id="@+id/apply_btt"
|
||||||
|
android:layout_width="wrap_content" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
style="@style/BlackButton"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:text="@string/sort_cancel"
|
||||||
|
android:id="@+id/cancel_btt"
|
||||||
|
android:layout_width="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
|
@ -607,4 +607,7 @@
|
||||||
|
|
||||||
<string name="download_all_plugins_from_repo">Download all plugins from this repository?</string>
|
<string name="download_all_plugins_from_repo">Download all plugins from this repository?</string>
|
||||||
<string name="single_plugin_disabled" formatted="true">%s (Disabled)</string>
|
<string name="single_plugin_disabled" formatted="true">%s (Disabled)</string>
|
||||||
|
<string name="tracks">Tracks</string>
|
||||||
|
<string name="audio_tracks">Audio tracks</string>
|
||||||
|
<string name="video_tracks">Video tracks</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue