Commit 931475eb authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Duncan McNamara
Browse files

Improve the ask resume setting by asking for each video

Fixes #1620
parent a643adf6
Pipeline #197422 passed with stage
in 20 minutes and 20 seconds
......@@ -499,7 +499,6 @@
<string name="playlist_name_hint">Playlist name</string>
<string name="go_to_chapter">Go to chapter…</string>
<string name="current_chapter">Chapter: %s</string>
<string name="resume_from_position">Resume from last position</string>
<string name="confirm_resume">Resume from last position?</string>
<string name="confirm_resume_title">Resume played videos</string>
<string name="tv_ui_title">Android TV interface</string>
......
<?xml version="1.0" encoding="utf-8"?>
<!--
~ *************************************************************************
~ dialog_video_resume.xml
~ **************************************************************************
~ Copyright © 2022 VLC authors and VideoLAN
~ Author: Nicolas POMEPUY
~ This program is free software; you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation; either version 2 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program; if not, write to the Free Software
~ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
~ ***************************************************************************
~
~
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/video_resume_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:fontFamily="sans-serif-medium"
android:text="@string/confirm_resume"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="@+id/video_resume_checkbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="Apply for all the play queue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/video_resume_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -45,11 +45,8 @@ import android.view.animation.Animation
import android.view.animation.AnimationSet
import android.view.animation.DecelerateInterpolator
import android.view.animation.RotateAnimation
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.*
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
......@@ -104,6 +101,8 @@ import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.helpers.hf.StoragePermissionsDelegate
import org.videolan.vlc.interfaces.IPlaybackSettingsController
import org.videolan.vlc.media.NO_LENGTH_PROGRESS_MAX
import org.videolan.vlc.media.VideoResumeStatus
import org.videolan.vlc.media.WaitConfirmation
import org.videolan.vlc.repository.ExternalSubRepository
import org.videolan.vlc.repository.SlaveRepository
import org.videolan.vlc.util.*
......@@ -730,6 +729,7 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
if (savedTime != -1L) settings.putSingle(VIDEO_RESUME_TIME, savedTime)
saveBrightness()
service?.playlistManager?.resetResumeStatus()
service?.removeCallback(this)
service = null
......@@ -1881,31 +1881,17 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
} else media = openedMedia
if (media != null) {
// in media library
if (askResume && !fromStart && positionInPlaylist <= 0 && media.time > 0) {
showConfirmResumeDialog()
return
}
lastAudioTrack = media.audioTrack
lastSpuTrack = media.spuTrack
} else if (!fromStart) {
// not in media library
if (askResume && startTime > 0L) {
showConfirmResumeDialog()
return
} else {
val rTime = settings.getLong(VIDEO_RESUME_TIME, -1L)
val lastUri = settings.getString(VIDEO_RESUME_URI, "")
if (rTime > 0 && service.currentMediaLocation == lastUri) {
if (askResume) {
showConfirmResumeDialog()
return
} else {
settings.putSingle(VIDEO_RESUME_TIME, -1L)
startTime = rTime
}
}
}
}
}
......@@ -2027,14 +2013,27 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
}
}
private fun showConfirmResumeDialog() {
private fun showConfirmResumeDialog(confirmation: WaitConfirmation) {
if (isFinishing) return
if (isInPictureInPictureMode) {
lifecycleScope.launch { service?.playlistManager?.playIndex(confirmation.index, confirmation.flags, forceResume = true) }
return
}
service?.pause()
/* Encountered Error, exit player with a message */
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.dialog_video_resume, null)
val resumeAllCheck = dialogView.findViewById<CheckBox>(R.id.video_resume_checkbox)
alertDialog = AlertDialog.Builder(this@VideoPlayerActivity)
.setMessage(R.string.confirm_resume)
.setPositiveButton(R.string.resume_from_position) { _, _ -> loadMedia(false) }
.setNegativeButton(R.string.play_from_start) { _, _ -> loadMedia(true) }
.setTitle(confirmation.title)
.setView(dialogView)
.setPositiveButton(R.string.resume) { _, _ ->
if (resumeAllCheck.isChecked) service?.playlistManager?.videoResumeStatus = VideoResumeStatus.ALWAYS
lifecycleScope.launch { service?.playlistManager?.playIndex(confirmation.index, confirmation.flags, forceResume = true) }
}
.setNegativeButton(R.string.no) { _, _ ->
if (resumeAllCheck.isChecked) service?.playlistManager?.videoResumeStatus = VideoResumeStatus.NEVER
lifecycleScope.launch { service?.playlistManager?.playIndex(confirmation.index, confirmation.flags, forceRestart = true) }
}
.create().apply {
setCancelable(false)
setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, _ ->
......@@ -2149,6 +2148,9 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
if (volSave > 100 && service.volume != volSave) service.setVolume(volSave)
}
service.addCallback(this)
service.playlistManager.waitForConfirmation.observe(this) {
if (it != null) showConfirmResumeDialog(it)
}
} else if (this.service != null) {
this.service?.removeCallback(this)
this.service = null
......
......@@ -76,9 +76,11 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
val abRepeatOn by lazy(LazyThreadSafetyMode.NONE) { MutableLiveData<Boolean>().apply { value = false } }
val videoStatsOn by lazy(LazyThreadSafetyMode.NONE) { MutableLiveData<Boolean>().apply { value = false } }
val delayValue by lazy(LazyThreadSafetyMode.NONE) { MutableLiveData<DelayValues>().apply { value = DelayValues() } }
val waitForConfirmation by lazy(LazyThreadSafetyMode.NONE) { MutableLiveData<WaitConfirmation?>().apply { value = null } }
private var lastPrevious = -1L
private val mediaFactory = FactoryManager.getFactory(IMediaFactory.factoryId) as IMediaFactory
lateinit var videoResumeStatus: VideoResumeStatus
fun hasCurrentMedia() = isValidPosition(currentIndex)
......@@ -93,6 +95,13 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
init {
repeating = settings.getInt(PLAYLIST_REPEAT_MODE_KEY, PlaybackStateCompat.REPEAT_MODE_NONE)
resetResumeStatus()
}
fun resetResumeStatus() {
val string = settings.getString(KEY_VIDEO_CONFIRM_RESUME, "0")
videoResumeStatus = if (string == "2") VideoResumeStatus.ASK else if (string == "0") VideoResumeStatus.ALWAYS else VideoResumeStatus.NEVER
waitForConfirmation.postValue(null)
}
/**
......@@ -350,7 +359,7 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
showAudioPlayer.value = PlayerController.playbackState != PlaybackStateCompat.STATE_STOPPED && (item !== null || !player.isVideoPlaying())
}
suspend fun playIndex(index: Int, flags: Int = 0) {
suspend fun playIndex(index: Int, flags: Int = 0, forceResume:Boolean = false, forceRestart:Boolean = false) {
videoBackground = videoBackground || (!player.isVideoPlaying() && player.canSwitchToVideo())
if (mediaList.size() == 0) {
Log.w(TAG, "Warning: empty media list, nothing to play !")
......@@ -385,7 +394,13 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
}
val title = mw.getMetaLong(MediaWrapper.META_TITLE)
if (title > 0) uri = "$uri#$title".toUri()
val start = getStartTime(mw)
val start = if (forceRestart || videoResumeStatus == VideoResumeStatus.NEVER) 0L else getStartTime(mw)
if (isVideoPlaying) {
if (!forceResume && videoResumeStatus == VideoResumeStatus.ASK && start > 0) {
waitForConfirmation.postValue(WaitConfirmation(mw.title, index, flags))
return
}
}
//todo restore position as well when we move to VLC 4.0
val media = mediaFactory.getFromUri(VLCInstance.getInstance(service), uri)
//fixme workaround to prevent the issue described in https://code.videolan.org/videolan/vlc-android/-/issues/2106
......@@ -1042,3 +1057,7 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
class ABRepeat(var start: Long = -1L, var stop: Long = -1L)
class DelayValues(var start: Long = -1L, var stop: Long = -1L)
class WaitConfirmation(val title: String, val index: Int, val flags: Int)
enum class VideoResumeStatus {
ALWAYS, ASK, NEVER
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment