diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt index 37a6524b..edb2b381 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt @@ -465,6 +465,8 @@ class VideoDetailView : ConstraintLayout { nextVideo(); }; _player.onDatasourceError.subscribe(::onDataSourceError); + _player.onNext.subscribe { nextVideo(true) }; + _player.onPrevious.subscribe { previousVideo(true) }; _minimize_controls_play.setOnClickListener { handlePlay(); }; _minimize_controls_pause.setOnClickListener { handlePause(); }; @@ -542,7 +544,7 @@ class VideoDetailView : ConstraintLayout { MediaControlReceiver.onPlayReceived.subscribe(this) { handlePlay() }; MediaControlReceiver.onPauseReceived.subscribe(this) { handlePause() }; MediaControlReceiver.onNextReceived.subscribe(this) { nextVideo(true) }; - MediaControlReceiver.onPreviousReceived.subscribe(this) { prevVideo() }; + MediaControlReceiver.onPreviousReceived.subscribe(this) { previousVideo(true) }; MediaControlReceiver.onCloseReceived.subscribe(this) { Logger.i(TAG, "MediaControlReceiver.onCloseReceived") onClose.emit() @@ -1532,25 +1534,63 @@ class VideoDetailView : ConstraintLayout { _slideUpOverlay = _overlay_quality_selector; } - fun prevVideo() { - Logger.i(TAG, "prevVideo") - val next = StatePlayer.instance.prevQueueItem(_player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9); - if(next != null) { - setVideoOverview(next); + private fun getPreviousVideo(withoutRemoval: Boolean, forceLoop: Boolean = false): IPlatformVideo? { + if (!StatePlayer.instance.hasQueue) { + if (forceLoop) { + return StatePlayer.instance.currentVideo + } else { + return null + } } + + val shouldNotRemove = _player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9 + var previous = StatePlayer.instance.prevQueueItem(withoutRemoval || shouldNotRemove); + if(previous == null && forceLoop) + previous = StatePlayer.instance.getQueue().last(); + return previous; + } + + private fun getNextVideo(withoutRemoval: Boolean, forceLoop: Boolean = false): IPlatformVideo? { + if (!StatePlayer.instance.hasQueue) { + if (forceLoop) { + return StatePlayer.instance.currentVideo + } else { + return null + } + } + + val shouldNotRemove = _player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9 + var next = StatePlayer.instance.nextQueueItem(withoutRemoval || shouldNotRemove); + if(next == null && forceLoop) + next = StatePlayer.instance.restartQueue(); + return next; + } + + fun previousVideo(forceLoop: Boolean = false): Boolean { + Logger.i(TAG, "previousVideo") + + val previous = getPreviousVideo(false, forceLoop); + if(previous != null) { + setVideoOverview(previous); + return true; + } else { + StatePlayer.instance.setCurrentlyPlaying(null); + } + + return false; } fun nextVideo(forceLoop: Boolean = false): Boolean { Logger.i(TAG, "nextVideo") - var next = StatePlayer.instance.nextQueueItem(_player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9); - if(next == null && forceLoop) - next = StatePlayer.instance.restartQueue(); + + val next = getNextVideo(false, forceLoop); if(next != null) { setVideoOverview(next); return true; - } - else + } else { StatePlayer.instance.setCurrentlyPlaying(null); + } + return false; } @@ -1690,6 +1730,10 @@ class VideoDetailView : ConstraintLayout { private fun updateQueueState() { _upNext.update(); + /*_player.updateNextPrevious( + getPreviousVideo(withoutRemoval = true, forceLoop = true) != null, + getNextVideo(withoutRemoval = true, forceLoop = true) != null + )*/ } //Handlers diff --git a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayer.kt b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayer.kt index 3b1c9430..cdd35dcc 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayer.kt +++ b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayer.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.res.Resources import android.graphics.Color import android.graphics.drawable.Drawable -import android.os.Handler import android.util.AttributeSet import android.util.Log import android.util.TypedValue @@ -17,7 +16,6 @@ import android.widget.RelativeLayout import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.setMargins -import androidx.lifecycle.LifecycleOwner import com.futo.platformplayer.* import com.futo.platformplayer.api.media.models.chapters.IChapter import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource @@ -72,6 +70,8 @@ class FutoVideoPlayer : FutoVideoPlayerBase { private val _control_play: ImageButton; private val _control_chapter: TextView; private val _time_bar: TimeBar; + private val _buttonPrevious: ImageButton; + private val _buttonNext: ImageButton; private val _control_fullscreen_fullscreen: ImageButton; private val _control_videosettings_fullscreen: ImageButton; @@ -82,6 +82,8 @@ class FutoVideoPlayer : FutoVideoPlayerBase { private val _time_bar_fullscreen: TimeBar; private val _overlay_brightness: FrameLayout; private val _control_chapter_fullscreen: TextView; + private val _buttonPrevious_fullscreen: ImageButton; + private val _buttonNext_fullscreen: ImageButton; private val _title_fullscreen: TextView; private val _author_fullscreen: TextView; @@ -110,6 +112,8 @@ class FutoVideoPlayer : FutoVideoPlayerBase { val onToggleFullScreen = Event1(); val onSourceChanged = Event3(); val onSourceEnded = Event0(); + val onPrevious = Event0(); + val onNext = Event0(); val onChapterChanged = Event2(); @@ -132,6 +136,8 @@ class FutoVideoPlayer : FutoVideoPlayerBase { _control_play = videoControls.findViewById(com.google.android.exoplayer2.ui.R.id.exo_play); _time_bar = videoControls.findViewById(com.google.android.exoplayer2.ui.R.id.exo_progress); _control_chapter = videoControls.findViewById(R.id.text_chapter_current); + _buttonNext = videoControls.findViewById(R.id.button_next); + _buttonPrevious = videoControls.findViewById(R.id.button_previous); _videoControls_fullscreen = findViewById(R.id.video_player_controller_fullscreen); _control_fullscreen_fullscreen = _videoControls_fullscreen.findViewById(R.id.exo_fullscreen); @@ -142,11 +148,18 @@ class FutoVideoPlayer : FutoVideoPlayerBase { _control_play_fullscreen = videoControls.findViewById(com.google.android.exoplayer2.ui.R.id.exo_play); _control_chapter_fullscreen = _videoControls_fullscreen.findViewById(R.id.text_chapter_current); _time_bar_fullscreen = _videoControls_fullscreen.findViewById(com.google.android.exoplayer2.ui.R.id.exo_progress); + _buttonPrevious_fullscreen = _videoControls_fullscreen.findViewById(R.id.button_previous); + _buttonNext_fullscreen = _videoControls_fullscreen.findViewById(R.id.button_next); val castVisibility = if (Settings.instance.casting.enabled) View.VISIBLE else View.GONE _control_cast.visibility = castVisibility _control_cast_fullscreen.visibility = castVisibility + _buttonPrevious.setOnClickListener { onPrevious.emit() }; + _buttonNext.setOnClickListener { onNext.emit() }; + _buttonPrevious_fullscreen.setOnClickListener { onPrevious.emit() }; + _buttonNext_fullscreen.setOnClickListener { onNext.emit() }; + _overlay_brightness = findViewById(R.id.overlay_brightness); _title_fullscreen = _videoControls_fullscreen.findViewById(R.id.exo_title); @@ -278,6 +291,11 @@ class FutoVideoPlayer : FutoVideoPlayerBase { } } + /*fun updateNextPrevious(hasNext: Boolean, hasPrevious: Boolean) { + _buttonNext.visibility = if (hasNext) View.VISIBLE else View.GONE + _buttonPrevious.visibility = if (hasPrevious) View.VISIBLE else View.GONE + }*/ + private val _currentChapterUpdateInterval: Long = 1000L / Settings.instance.playback.getChapterUpdateFrames(); private var _currentChapterUpdateLastPos = 0L; private val _currentChapterUpdateExecuter = Executors.newSingleThreadScheduledExecutor(); diff --git a/app/src/main/res/drawable/ic_skip_next.xml b/app/src/main/res/drawable/ic_skip_next.xml new file mode 100644 index 00000000..ba5057f6 --- /dev/null +++ b/app/src/main/res/drawable/ic_skip_next.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_skip_previous.xml b/app/src/main/res/drawable/ic_skip_previous.xml new file mode 100644 index 00000000..a4a0b659 --- /dev/null +++ b/app/src/main/res/drawable/ic_skip_previous.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/video_player_ui.xml b/app/src/main/res/layout/video_player_ui.xml index 7a318f12..00651c7e 100644 --- a/app/src/main/res/layout/video_player_ui.xml +++ b/app/src/main/res/layout/video_player_ui.xml @@ -56,28 +56,60 @@ + android:layout_marginRight="40dp" + android:padding="5dp" + app:srcCompat="@drawable/ic_skip_previous" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintRight_toLeftOf="@id/layout_play_pause" + app:layout_constraintBottom_toBottomOf="parent" /> + + + + + + + + android:scaleType="centerCrop" + android:padding="5dp" + android:layout_marginLeft="40dp" + app:srcCompat="@drawable/ic_skip_next" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintLeft_toRightOf="@id/layout_play_pause" + app:layout_constraintBottom_toBottomOf="parent" /> + + + app:layout_constraintRight_toRightOf="parent"> + + + + + + app:layout_constraintLeft_toRightOf="@id/layout_play_pause" + app:layout_constraintBottom_toBottomOf="parent" />