diff --git a/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt b/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt index e1e822ff0..958cac154 100644 --- a/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt +++ b/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt @@ -135,7 +135,7 @@ class AudioPlayerActivity : BaseTvActivity() { override fun onProgressChanged(sb: SeekBar, progress: Int, fromUser: Boolean) { if (fromUser) { - model.time = progress.toLong() + model.setTime(progress.toLong()) } } } @@ -273,9 +273,9 @@ class AudioPlayerActivity : BaseTvActivity() { } private fun seek(delta: Int) { - val time = model.time.toInt() + delta + val time = model.getTime().toInt() + delta if (time < 0 || time > model.length) return - model.time = time.toLong() + model.setTime(time.toLong()) } fun onClick(v: View) { diff --git a/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt b/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt index c397995de..ad1e0b39c 100644 --- a/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt +++ b/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt @@ -229,7 +229,7 @@ internal class MediaSessionCallback(private val playbackService: PlaybackService override fun onPlayFromUri(uri: Uri?, extras: Bundle?) = playbackService.loadUri(uri) override fun onPlayFromSearch(query: String?, extras: Bundle?) { - playbackService.mediaSession.setPlaybackState(PlaybackStateCompat.Builder().setState(PlaybackStateCompat.STATE_CONNECTING, playbackService.time, 1.0f).build()) + playbackService.mediaSession.setPlaybackState(PlaybackStateCompat.Builder().setState(PlaybackStateCompat.STATE_CONNECTING, playbackService.getTime(), 1.0f).build()) playbackService.lifecycleScope.launch(Dispatchers.IO) { if (!isActive) return@launch playbackService.awaitMedialibraryStarted() @@ -273,11 +273,11 @@ internal class MediaSessionCallback(private val playbackService: PlaybackService override fun onSkipToPrevious() = playbackService.previous(false) - override fun onSeekTo(pos: Long) = playbackService.seek(if (pos < 0) playbackService.time + pos else pos, fromUser = true) + override fun onSeekTo(pos: Long) = playbackService.seek(if (pos < 0) playbackService.getTime() + pos else pos, fromUser = true) - override fun onFastForward() = playbackService.seek((playbackService.time + TEN_SECONDS).coerceAtMost(playbackService.length), fromUser = true) + override fun onFastForward() = playbackService.seek((playbackService.getTime() + TEN_SECONDS).coerceAtMost(playbackService.length), fromUser = true) - override fun onRewind() = playbackService.seek((playbackService.time - TEN_SECONDS).coerceAtLeast(0), fromUser = true) + override fun onRewind() = playbackService.seek((playbackService.getTime() - TEN_SECONDS).coerceAtLeast(0), fromUser = true) override fun onSkipToQueueItem(id: Long) = playbackService.playIndexOrLoadLastPlaylist(id.toInt()) } \ No newline at end of file diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt index d4707e45f..1be183dc8 100644 --- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt +++ b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt @@ -176,7 +176,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { if (BuildConfig.DEBUG) Log.i(TAG, "MediaPlayer.Event.Playing") executeUpdate() publishState() - lastTime = time + lastTime = getTime() audioFocusHelper.changeAudioFocus(true) if (!wakeLock.isHeld) wakeLock.acquire() showNotification() @@ -198,8 +198,8 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { } MediaPlayer.Event.PositionChanged -> { if (length == 0L) position = (NO_LENGTH_PROGRESS_MAX.toLong() * event.positionChanged).toLong() - if (time < 1000L && time < lastTime) publishState() - lastTime = time + if (getTime() < 1000L && getTime() < lastTime) publishState() + lastTime = getTime() if (widget != 0) updateWidgetPosition(event.positionChanged) } MediaPlayer.Event.ESAdded -> if (event.esChangedType == IMedia.Track.Type.Video && (playlistManager.videoBackground || !playlistManager.switchToVideo())) { @@ -384,15 +384,6 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { return tracks.toList() } - var time: Long - @MainThread - get() = playlistManager.player.getCurrentTime() - @MainThread - set(time) { - playlistManager.player.setTime(time) - publishState(time) - } - val length: Long @MainThread get() = playlistManager.player.getLength() @@ -711,6 +702,12 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { playlistManager.isHardware = true } + fun setTime(time:Long, fast:Boolean = false) { + playlistManager.player.setTime(time, fast) + } + + fun getTime() = playlistManager.player.getCurrentTime() + fun onMediaPlayerEvent(event: MediaPlayer.Event) = mediaPlayerListener.onEvent(event) fun onPlaybackStopped(systemExit: Boolean) { @@ -951,7 +948,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { val pscb = PlaybackStateCompat.Builder() var actions = PLAYBACK_BASE_ACTIONS val hasMedia = playlistManager.hasCurrentMedia() - var time = position ?: time + var time = position ?: getTime() var state = PlayerController.playbackState when (state) { PlaybackStateCompat.STATE_PLAYING -> actions = actions or (PlaybackStateCompat.ACTION_PAUSE or PlaybackStateCompat.ACTION_STOP) @@ -1294,7 +1291,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { /* HACK: flush when activating a video track. This will force an * I-Frame to be displayed right away. */ if (isSeekable) { - val time = time + val time = getTime() if (time > 0) seek(time) } @@ -1418,8 +1415,8 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { @MainThread @JvmOverloads - fun seek(time: Long, length: Double = this.length.toDouble(), fromUser: Boolean = false) { - if (length > 0.0) this.time = time else setPosition((time.toFloat() / NO_LENGTH_PROGRESS_MAX.toFloat())) + fun seek(time: Long, length: Double = this.length.toDouble(), fromUser: Boolean = false, fast:Boolean = false) { + if (length > 0.0) this.setTime(time, fast) else setPosition((time.toFloat() / NO_LENGTH_PROGRESS_MAX.toFloat())) if (fromUser) { publishState(time) } diff --git a/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt b/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt index 3dd0b454a..0107910f3 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt @@ -109,6 +109,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay lateinit var abRepeatAddMarker: Button private var audioPlayProgressMode:Boolean = false private var lastEndsAt = -1L + private var isDragging = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -369,7 +370,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay val displayTime = if (showRemainingTime) Tools.millisToString(progress.time - progress.length) else progress.timeText binding.headerTime.text = displayTime binding.time.text = displayTime - binding.timeline.progress = progress.time.toInt() + if (!isDragging) binding.timeline.progress = progress.time.toInt() binding.progressBar.progress = progress.time.toInt() } @@ -432,18 +433,18 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay fun onRewind10(view: View) { playlistModel.service ?.let { service -> - var position = service.time - 10000 + var position = service.getTime() - 10000 if (position < 0) position = 0 if (position > service.length) position = service.length service.seek(position, service.length.toDouble(), true) - if (service.playlistManager.player.lastPosition == 0.0f && service.time > 0) + if (service.playlistManager.player.lastPosition == 0.0f && service.getTime() > 0) UiTools.snacker(requireActivity(), getString(R.string.unseekable_stream)) } } fun onForward10(view: View) { playlistModel.service ?.let { service -> - var position = service.time + 10000 + var position = service.getTime() + 10000 if (position < 0) position = 0 if (position > service.length) position = service.length service.seek(position, service.length.toDouble(), true) @@ -624,7 +625,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay override fun onTouch(v: View, event: MotionEvent): Boolean { when (event.action) { MotionEvent.ACTION_DOWN -> { - possibleSeek = playlistModel.time.toInt() + possibleSeek = playlistModel.getTime().toInt() previewingSeek = true vibrated = false length = playlistModel.length @@ -636,7 +637,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay handler.removeCallbacks(seekRunnable) previewingSeek = false if (event.eventTime - event.downTime >= 1000L) { - playlistModel.time = possibleSeek.toLong().coerceAtLeast(0L).coerceAtMost(playlistModel.length) + playlistModel.setTime(possibleSeek.toLong().coerceAtLeast(0L).coerceAtMost(playlistModel.length)) v.isPressed = false return true } @@ -669,13 +670,18 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay private var timelineListener: OnSeekBarChangeListener = object : OnSeekBarChangeListener { - override fun onStopTrackingTouch(seekBar: SeekBar) {} + override fun onStopTrackingTouch(seekBar: SeekBar) { + playlistModel.setTime(seekBar.progress.toLong()) + isDragging = false + } - override fun onStartTrackingTouch(seekBar: SeekBar) {} + override fun onStartTrackingTouch(seekBar: SeekBar) { + isDragging = true + } override fun onProgressChanged(sb: SeekBar, progress: Int, fromUser: Boolean) { if (fromUser) { - playlistModel.time = progress.toLong() + playlistModel.setTime(progress.toLong(), true) binding.time.text = Tools.millisToString(if (showRemainingTime) progress - playlistModel.length else progress.toLong()) binding.headerTime.text = Tools.millisToString(progress.toLong()) } diff --git a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/JumpToTimeDialog.kt b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/JumpToTimeDialog.kt index 11ba36e83..6f084a62d 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/JumpToTimeDialog.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/JumpToTimeDialog.kt @@ -38,7 +38,7 @@ class JumpToTimeDialog : PickTimeFragment() { val minutes = if (minutes != "") java.lang.Long.parseLong(minutes) * MINUTES_IN_MICROS else 0L val seconds = if (seconds != "") java.lang.Long.parseLong(seconds) * SECONDS_IN_MICROS else 0L val newTime = (hours + minutes + seconds) / 1000L //Time in ms - playbackService.time = newTime + playbackService.setTime(newTime) playbackService.playlistManager.player.updateProgress(newTime) dismiss() } diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/BookmarkListDelegate.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/BookmarkListDelegate.kt index dd58723a6..0142c6654 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/BookmarkListDelegate.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/BookmarkListDelegate.kt @@ -155,7 +155,7 @@ class BookmarkListDelegate(val activity: FragmentActivity, val service: Playback } override fun onBookmarkClick(position: Int, item: Bookmark) { - service.time = item.time + service.setTime(item.time) } fun setProgressHeight(y: Float) { diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/PopupManager.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/PopupManager.kt index 1e19a2a42..7e06f4312 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/video/PopupManager.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/video/PopupManager.kt @@ -229,7 +229,7 @@ class PopupManager constructor(private val service: PlaybackService) : PlaybackS } private fun stopPlayback() { - var time = service.time + var time = service.getTime() if (time != -1L) { // remove saved position if in the last 5 seconds // else, go back 2 seconds, to compensate loading time diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt index df1cb4f76..243dfec78 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt @@ -55,7 +55,6 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.BaseContextWrappingDelegate import androidx.appcompat.widget.PopupMenu -import androidx.appcompat.widget.ViewStubCompat import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.Guideline @@ -268,11 +267,12 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback, override fun onStopTrackingTouch(seekBar: SeekBar) { isDragging = false overlayDelegate.showOverlay(true) + seek(seekBar.progress.toLong(), fromUser = true, fast = false) } override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { if (!isFinishing && fromUser && service?.isSeekable == true) { - seek(progress.toLong(), fromUser) + seek(progress.toLong(), fromUser, isDragging) if (service?.length != 0L) overlayDelegate.showInfo(Tools.millisToString(progress.toLong()), 1000) } if (fromUser) { @@ -298,7 +298,7 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback, */ val time: Long get() { - var time = service?.time ?: 0L + var time = service?.getTime() ?: 0L if (forcedTime != -1L && lastTime != -1L) { if (lastTime > forcedTime) { if (time in (forcedTime + 1)..lastTime || time > lastTime) { @@ -1595,11 +1595,15 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback, service?.let { seek(position, it.length, fromUser) } } - internal fun seek(position: Long, length: Long, fromUser: Boolean = false) { + fun seek(position: Long, fromUser: Boolean = false, fast:Boolean = false) { + service?.let { seek(position, it.length, fromUser, fast) } + } + + internal fun seek(position: Long, length: Long, fromUser: Boolean = false, fast:Boolean = false) { service?.let { service -> forcedTime = position - lastTime = service.time - service.seek(position, length.toDouble(), fromUser) + lastTime = service.getTime() + service.seek(position, length.toDouble(), fromUser, fast) service.playlistManager.player.updateProgress(position) } } diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerOverlayDelegate.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerOverlayDelegate.kt index fd6eb8ce1..60edc63da 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerOverlayDelegate.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerOverlayDelegate.kt @@ -155,7 +155,7 @@ class VideoPlayerOverlayDelegate (private val player: VideoPlayerActivity) { } VideoTracksDialog.TrackType.VIDEO -> { player.service?.let { service -> - player.seek(service.time) + player.seek(service.getTime()) service.setVideoTrack(trackID) runIO { val mw = player.medialibrary.findMedia(service.currentMediaWrapper) diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoTouchDelegate.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoTouchDelegate.kt index f9bd0425e..f4e8bb15f 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoTouchDelegate.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoTouchDelegate.kt @@ -317,7 +317,7 @@ class VideoTouchDelegate(private val player: VideoPlayerActivity, touchAction = TOUCH_SEEK val length = player.service!!.length - val time = player.service!!.time + val time = player.service!!.getTime() // Size of the jump, 10 minutes max (600000), with a bi-cubic progression, for a 8cm gesture var jump = (sign(gesturesize) * (600000 * (gesturesize / 8).toDouble().pow(4.0) + 3000) / coef).toInt() @@ -455,9 +455,9 @@ class VideoTouchDelegate(private val player: VideoPlayerActivity, nbTimesTaped++ lastSeekWasForward = seekForward - if (service.time > 0 && service.time < service.length) sb.append(if (nbTimesTaped == -1) (delta / 1000f).toInt() else (nbTimesTaped * (delta / 1000f).toInt())) + if (service.getTime() > 0 && service.getTime() < service.length) sb.append(if (nbTimesTaped == -1) (delta / 1000f).toInt() else (nbTimesTaped * (delta / 1000f).toInt())) .append("s ") - sb.append("(").append(Tools.millisToString(service.time)) + sb.append("(").append(Tools.millisToString(service.getTime())) .append(')') val container = if (seekForward) player.rightContainer else player.leftContainer diff --git a/application/vlc-android/src/org/videolan/vlc/media/PlayerController.kt b/application/vlc-android/src/org/videolan/vlc/media/PlayerController.kt index 514da9c5e..797f18403 100644 --- a/application/vlc-android/src/org/videolan/vlc/media/PlayerController.kt +++ b/application/vlc-android/src/org/videolan/vlc/media/PlayerController.kt @@ -109,16 +109,12 @@ class PlayerController(val context: Context) : IVLCVout.Callback, MediaPlayer.Ev release(mp) } - fun seek(time: Long, length: Double = getLength().toDouble()) { - if (length > 0.0) setTime(time) else setPosition((time / NO_LENGTH_PROGRESS_MAX).toFloat()) - } - fun setPosition(position: Float) { if (seekable && mediaplayer.hasMedia() && !mediaplayer.isReleased) mediaplayer.position = position } - fun setTime(time: Long) { - if (seekable && mediaplayer.hasMedia() && !mediaplayer.isReleased) mediaplayer.time = time + fun setTime(time: Long, fast:Boolean = false) { + if (seekable && mediaplayer.hasMedia() && !mediaplayer.isReleased) mediaplayer.setTime(time, fast) } fun isPlaying() = playbackState == PlaybackStateCompat.STATE_PLAYING diff --git a/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt b/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt index 32123a881..80ca2f152 100644 --- a/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt +++ b/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt @@ -908,7 +908,7 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList } MediaPlayer.Event.TimeChanged -> { abRepeat.value?.let { - if (it.stop != -1L && player.getCurrentTime() > it.stop) player.seek(it.start) + if (it.stop != -1L && player.getCurrentTime() > it.stop) player.setTime(it.start) } if (player.getCurrentTime() % 10 == 0L) savePosition() } diff --git a/application/vlc-android/src/org/videolan/vlc/viewmodels/BookmarkModel.kt b/application/vlc-android/src/org/videolan/vlc/viewmodels/BookmarkModel.kt index a589773c6..5b8558a4f 100644 --- a/application/vlc-android/src/org/videolan/vlc/viewmodels/BookmarkModel.kt +++ b/application/vlc-android/src/org/videolan/vlc/viewmodels/BookmarkModel.kt @@ -113,7 +113,7 @@ class BookmarkModel : ViewModel(), PlaybackService.Callback { service?.currentMediaWrapper?.let { viewModelScope.launch { withContext(Dispatchers.IO) { - val bookmark = it.addBookmark(service!!.time) + val bookmark = it.addBookmark(service!!.getTime()) bookmark?.setName(context.getString(R.string.bookmark_name, it.bookmarks.size.toString())) } refresh() diff --git a/application/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt b/application/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt index 53152979c..ea8e7bb3a 100644 --- a/application/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt +++ b/application/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt @@ -154,12 +154,6 @@ class PlaylistModel : ViewModel(), PlaybackService.Callback by EmptyPBSCallback } else false } ?: false - var time - get() = service?.time ?: 0L - set(value) { - service?.time = value - } - val length : Long get() = service?.length ?: 0L @@ -192,6 +186,12 @@ class PlaylistModel : ViewModel(), PlaybackService.Callback by EmptyPBSCallback fun shuffle() = service?.shuffle() + fun getTime() = service?.getTime() ?: 0L + + fun setTime(time:Long, fast:Boolean = false) { + service?.setTime(time, fast) + } + fun load(medialist: List, position: Int) = service?.load(medialist, position) suspend fun switchToVideo() : Boolean {