diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt index 5f6ef921..11b8c940 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt @@ -212,6 +212,30 @@ class CS3IPlayer : IPlayer { 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 * */ @@ -465,6 +489,7 @@ class CS3IPlayer : IPlayer { trackSelector.parameters = DefaultTrackSelector.ParametersBuilder(context) // .setRendererDisabled(C.TRACK_TYPE_VIDEO, true) .setRendererDisabled(C.TRACK_TYPE_TEXT, true) + .setTunnelingEnabled(true) .setDisabledTextTrackSelectionFlags(C.TRACK_TYPE_TEXT) .clearSelectionOverrides() .build() diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt index 2ddef9a4..19f2b25b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt @@ -176,6 +176,10 @@ open class FullScreenPlayer : AbstractPlayerFragment() { throw NotImplementedError() } + open fun showTracksDialogue() { + throw NotImplementedError() + } + open fun openOnlineSubPicker( context: Context, imdbId: Long?, @@ -1101,6 +1105,7 @@ open class FullScreenPlayer : AbstractPlayerFragment() { // if nothing has loaded these buttons should not be visible player_skip_episode?.isVisible = false + player_tracks_btt?.isVisible = false player_skip_op?.isVisible = false shadow_overlay?.isVisible = false @@ -1296,6 +1301,10 @@ open class FullScreenPlayer : AbstractPlayerFragment() { showMirrorsDialogue() } + player_tracks_btt?.setOnClickListener { + showTracksDialogue() + } + player_intro_play?.setOnClickListener { player_intro_play?.isGone = true player.handleEvent(CSPlayerEvent.Play) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index 3e6e24cb..ef6bea6b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -18,6 +18,11 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider 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.hippo.unifile.UniFile 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.player_custom_layout.* 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 class GeneratorPlayer : FullScreenPlayer() { @@ -106,6 +113,12 @@ class GeneratorPlayer : FullScreenPlayer() { override fun embeddedSubtitlesFetched(subtitles: List) { 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 { @@ -476,6 +489,8 @@ class GeneratorPlayer : FullScreenPlayer() { } var selectSourceDialog: AlertDialog? = null +// var selectTracksDialog: AlertDialog? = null + override fun showMirrorsDialogue() { try { currentSelectedSubtitles = player.getCurrentPreferredSubtitle() @@ -667,6 +682,139 @@ class GeneratorPlayer : FullScreenPlayer() { } } + /** + * Gets all supported formats in a list + * */ + private fun List.getFormats(): List { + 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(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(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) { Log.i(TAG, "playerError = $currentSelectedLink") super.playerError(exception) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt index 8561a0f4..42980455 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt @@ -1,6 +1,8 @@ package com.lagradost.cloudstream3.ui.player 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.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorUri @@ -46,7 +48,13 @@ enum class CSPlayerLoading { //IsDone, } -class InvalidFileException(msg : String) : Exception(msg) +data class ExoplayerTracks( + val currentVideoFormat: Format?, + val currentAudioFormat: Format?, + val allTracks: List +) + +class InvalidFileException(msg: String) : Exception(msg) //http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 const val STATE_RESUME_WINDOW = "resumeWindow" @@ -73,8 +81,8 @@ interface IPlayer { fun seekTime(time: Long) fun seekTo(time: Long) - fun getSubtitleOffset() : Long // in ms - fun setSubtitleOffset(offset : Long) // in ms + fun getSubtitleOffset(): Long // in ms + fun setSubtitleOffset(offset: Long) // in ms fun initCallbacks( 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 embeddedSubtitlesFetched: ((List) -> Unit)? = null, // callback from player to give all embedded subtitles ) + fun releaseCallbacks() fun updateSubtitleStyle(style: SaveCaptionStyle) @@ -100,16 +109,16 @@ interface IPlayer { link: ExtractorLink? = null, data: ExtractorUri? = null, startPosition: Long? = null, - subtitles : Set, - subtitle : SubtitleData?, - autoPlay : Boolean? = true + subtitles: Set, + subtitle: SubtitleData?, + autoPlay: Boolean? = true ) fun reloadPlayer(context: Context) - fun setActiveSubtitles(subtitles : Set) - fun setPreferredSubtitles(subtitle : SubtitleData?) : Boolean // returns true if the player requires a reload, null for nothing - fun getCurrentPreferredSubtitle() : SubtitleData? + fun setActiveSubtitles(subtitles: Set) + fun setPreferredSubtitles(subtitle: SubtitleData?): Boolean // returns true if the player requires a reload, null for nothing + fun getCurrentPreferredSubtitle(): SubtitleData? fun handleEvent(event: CSPlayerEvent) @@ -120,5 +129,13 @@ interface IPlayer { fun release() /** 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?) } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultTrailerPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultTrailerPlayer.kt index db0a7e16..a3556964 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultTrailerPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultTrailerPlayer.kt @@ -75,6 +75,8 @@ open class ResultTrailerPlayer : com.lagradost.cloudstream3.ui.player.FullScreen } override fun showMirrorsDialogue() {} + override fun showTracksDialogue() {} + override fun openOnlineSubPicker(context: Context, imdbId: Long?, dismissCallback: () -> Unit) {} override fun subtitlesChanged() {} diff --git a/app/src/main/res/layout/player_custom_layout.xml b/app/src/main/res/layout/player_custom_layout.xml index 5e10e471..9bbded4e 100644 --- a/app/src/main/res/layout/player_custom_layout.xml +++ b/app/src/main/res/layout/player_custom_layout.xml @@ -1,23 +1,23 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/player_holder" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:screenOrientation="landscape" + tools:orientation="vertical"> + android:id="@+id/subtitle_holder" + android:layout_width="match_parent" + android:layout_height="match_parent"> + android:id="@+id/shadow_overlay" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/black_overlay" /> + android:id="@+id/player_time_menu" + android:layout_width="match_parent" + android:layout_height="200dp" + android:orientation="horizontal" + app:layout_constraintBottom_toTopOf="@+id/player_center_menu" + app:layout_constraintTop_toBottomOf="@+id/topMenuRight"> + android:id="@+id/player_time_text" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:shadowColor="@android:color/black" + android:shadowRadius="10.0" + android:textColor="@android:color/white" + android:textSize="30sp" + tools:text="+100" /> + android:id="@+id/player_episode_filler_holder" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_margin="20dp"> + android:id="@+id/player_episode_filler" + style="@style/SmallBlackButton" + android:text="@string/filler" /> + + - + android:layout_height="wrap_content" + android:layout_marginStart="80dp" + android:layout_marginTop="35dp" + android:layout_marginEnd="80dp" + android:gravity="center" + android:textColor="@color/white" + android:textStyle="bold" + android:visibility="visible" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="Hello world" /> - - + android:id="@+id/player_video_title_rez" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="80dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="80dp" + android:gravity="center" + android:textColor="@color/white" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/player_video_title" + tools:text="1920x1080" /> @@ -138,30 +138,30 @@ app:layout_constraintTop_toTopOf="parent" />--> + android:id="@+id/player_go_back_holder" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="5dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + android:layout_width="30dp" + android:layout_height="30dp" + android:layout_gravity="center" + android:contentDescription="@string/go_back_img_des" + android:src="@drawable/ic_baseline_arrow_back_24" + app:tint="@android:color/white" /> + android:id="@+id/player_go_back" + android:layout_width="70dp" + android:layout_height="70dp" + android:layout_gravity="center" + android:background="@drawable/video_tap_button_always_white" + android:clickable="true" + android:contentDescription="@string/go_back_img_des" + android:focusable="true" /> @@ -169,362 +169,374 @@ + android:indeterminate="true" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:visibility="visible" /> + android:id="@+id/player_pause_play_holder_holder" + android:layout_width="100dp" + android:layout_height="100dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent"> + android:id="@+id/player_pause_play_holder" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:ignore="uselessParent"> + android:src="@drawable/netflix_pause" + app:tint="@color/white" + tools:ignore="ContentDescription" /> + android:id="@+id/player_center_menu" + android:layout_width="match_parent" + android:layout_height="100dp" + android:layout_gravity="center" + android:gravity="center" + android:layoutDirection="ltr" + android:orientation="horizontal" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent"> + android:id="@+id/player_rew_holder" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|start" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toLeftOf="@id/player_ffwd_holder" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_percent="0.5"> + android:textStyle="bold" + tools:text="10" /> + android:background="@drawable/video_tap_button_skip" + android:nextFocusLeft="@id/exo_rew" + android:nextFocusUp="@id/player_go_back" + android:nextFocusDown="@id/player_lock" + android:padding="10dp" + android:scaleType="fitCenter" + android:scaleX="-1" + android:src="@drawable/netflix_skip_forward" + android:tintMode="src_in" + app:tint="@color/white" + tools:ignore="ContentDescription" /> + android:id="@+id/player_ffwd_holder" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toRightOf="@id/player_rew_holder" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_percent="0.5"> + android:id="@+id/exo_ffwd_text" + android:layout_width="200dp" + android:layout_height="40dp" + android:layout_gravity="center" + android:gravity="center" + android:textColor="@color/white" + android:textSize="19sp" + android:textStyle="bold" + tools:text="10" /> + android:background="@drawable/video_tap_button_skip" + android:nextFocusRight="@id/exo_rew" + android:nextFocusUp="@id/player_go_back" + android:nextFocusDown="@id/player_lock" + android:padding="10dp" + android:scaleType="fitCenter" + android:src="@drawable/netflix_skip_forward" + android:tintMode="src_in" + app:tint="@color/white" + tools:ignore="ContentDescription" /> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:layout_marginBottom="20dp" + android:gravity="center" + android:orientation="horizontal" + android:paddingTop="4dp" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent"> + android:id="@id/exo_prev" + style="@style/ExoMediaButton.Previous" + android:tintMode="src_in" + app:tint="?attr/colorPrimaryDark" + tools:ignore="ContentDescription" /> + android:id="@id/exo_repeat_toggle" + style="@style/ExoMediaButton" + android:tintMode="src_in" + app:tint="?attr/colorPrimaryDark" + tools:ignore="ContentDescription" /> + android:id="@id/exo_next" + style="@style/ExoMediaButton.Next" + android:tintMode="src_in" + app:tint="?attr/colorPrimaryDark" + tools:ignore="ContentDescription" /> + android:id="@id/exo_vr" + style="@style/ExoMediaButton.VR" + android:tintMode="src_in" + app:tint="?attr/colorPrimaryDark" + tools:ignore="ContentDescription" /> + android:id="@id/exo_play" + android:layout_width="0dp" + android:layout_height="0dp" + android:tintMode="src_in" + app:tint="?attr/colorPrimaryDark" + tools:ignore="ContentDescription" /> + android:id="@id/exo_pause" + android:layout_width="0dp" + android:layout_height="0dp" + android:tintMode="src_in" + app:tint="?attr/colorPrimaryDark" + tools:ignore="ContentDescription" /> + android:id="@+id/bottom_player_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="10dp" + android:gravity="center_vertical" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent"> + android:id="@+id/player_video_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layoutDirection="ltr" + android:orientation="horizontal"> + android:id="@id/exo_position" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginStart="20dp" + android:gravity="end" + android:includeFontPadding="false" + android:minWidth="50dp" + android:paddingLeft="4dp" + android:paddingRight="4dp" + android:textColor="@android:color/white" + android:textSize="14sp" + android:textStyle="normal" + tools:text="15:30" /> + app:scrubber_color="?attr/colorPrimary" + app:scrubber_dragged_size="26dp" + app:scrubber_enabled_size="24dp" + app:unplayed_color="@color/videoProgress" /> + android:id="@id/exo_duration" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginEnd="20dp" + android:includeFontPadding="false" + android:minWidth="50dp" + android:paddingLeft="4dp" + android:paddingRight="4dp" + android:textColor="@android:color/white" + android:textSize="14sp" + android:textStyle="normal" + tools:text="23:20" /> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"> + android:layout_width="wrap_content" + android:layout_height="60dp" + android:gravity="center" + android:orientation="horizontal" + android:paddingTop="10dp" + android:paddingBottom="10dp"> + app:iconSize="30dp" /> + android:id="@+id/player_lock_holder" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="horizontal"> + android:nextFocusRight="@id/player_speed_btt" + android:text="@string/video_aspect_ratio_resize" + app:icon="@drawable/ic_baseline_aspect_ratio_24" /> + android:nextFocusRight="@id/player_subtitle_offset_btt" + app:icon="@drawable/ic_baseline_speed_24" + tools:text="Speed" /> + android:visibility="gone" + app:icon="@drawable/ic_outline_subtitles_24" + tools:visibility="visible" /> - android:nextFocusRight="@id/player_skip_op" - android:text="@string/video_source" - app:icon="@drawable/ic_baseline_playlist_play_24" /> + android:nextFocusLeft="@id/player_sources_btt" + android:nextFocusRight="@id/player_skip_op" + android:text="@string/tracks" + app:icon="@drawable/ic_baseline_playlist_play_24" /> + android:nextFocusRight="@id/player_skip_episode" + android:text="@string/video_skip_op" + app:icon="@drawable/ic_baseline_fast_forward_24" /> + + @@ -532,66 +544,66 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layoutDirection="ltr" + android:orientation="horizontal"> + android:id="@+id/player_progressbar_left_holder" + android:layout_width="100dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:gravity="start" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toLeftOf="@+id/centerMenuView" + app:layout_constraintTop_toTopOf="parent" + tools:alpha="1" + tools:visibility="visible"> + android:id="@+id/player_progressbar_left_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_marginBottom="220dp" + android:src="@drawable/ic_baseline_volume_up_24" + app:tint="@android:color/white" + tools:ignore="ContentDescription"> + android:id="@+id/player_progressbar_left" + style="@android:style/Widget.Material.ProgressBar.Horizontal" + android:layout_width="4dp" + android:layout_height="150dp" + android:layout_centerInParent="true" + android:layout_gravity="end|center_vertical" + android:layout_marginStart="40dp" + android:indeterminate="false" + android:max="100" + android:progress="100" + android:progressDrawable="@drawable/progress_drawable_vertical" + tools:progress="30" /> + android:id="@+id/player_progressbar_right_holder" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:gravity="right" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toRightOf="@+id/centerMenuView" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:alpha="1" + tools:ignore="RtlHardcoded" + tools:visibility="visible"> + android:id="@+id/player_progressbar_right" + style="@android:style/Widget.Material.ProgressBar.Horizontal" + android:layout_width="4dp" + android:layout_height="150dp" + android:layout_centerInParent="true" + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="40dp" + android:indeterminate="false" + android:max="100" + android:progress="100" + android:progressDrawable="@drawable/progress_drawable_vertical" /> - + + + + + + + --> diff --git a/app/src/main/res/layout/player_select_tracks.xml b/app/src/main/res/layout/player_select_tracks.xml new file mode 100644 index 00000000..d32e1b4e --- /dev/null +++ b/app/src/main/res/layout/player_select_tracks.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1b47b180..3a25427c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -607,4 +607,7 @@ Download all plugins from this repository? %s (Disabled) + Tracks + Audio tracks + Video tracks