mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
Implemented FutoVideoPlayer loader.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.futo.platformplayer.views.video
|
package com.futo.platformplayer.views.video
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
@@ -44,8 +45,11 @@ import com.futo.platformplayer.logging.Logger
|
|||||||
import com.futo.platformplayer.states.StateApp
|
import com.futo.platformplayer.states.StateApp
|
||||||
import com.futo.platformplayer.states.StatePlayer
|
import com.futo.platformplayer.states.StatePlayer
|
||||||
import com.futo.platformplayer.views.behavior.GestureControlView
|
import com.futo.platformplayer.views.behavior.GestureControlView
|
||||||
|
import com.futo.platformplayer.views.others.ProgressBar
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
@@ -150,6 +154,11 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
|
|||||||
|
|
||||||
val onChapterClicked = Event1<IChapter>();
|
val onChapterClicked = Event1<IChapter>();
|
||||||
|
|
||||||
|
private val loaderOverlay: FrameLayout
|
||||||
|
private val loaderIndeterminate: android.widget.ProgressBar
|
||||||
|
private val loaderDeterminate: android.widget.ProgressBar
|
||||||
|
private var determinateAnimator: ValueAnimator? = null
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
constructor(context: Context, attrs: AttributeSet? = null) : super(PLAYER_STATE_NAME, context, attrs) {
|
constructor(context: Context, attrs: AttributeSet? = null) : super(PLAYER_STATE_NAME, context, attrs) {
|
||||||
LayoutInflater.from(context).inflate(R.layout.video_view, this, true);
|
LayoutInflater.from(context).inflate(R.layout.video_view, this, true);
|
||||||
@@ -190,6 +199,14 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
|
|||||||
_control_duration_fullscreen = _videoControls_fullscreen.findViewById(R.id.text_duration);
|
_control_duration_fullscreen = _videoControls_fullscreen.findViewById(R.id.text_duration);
|
||||||
_control_pause_fullscreen = _videoControls_fullscreen.findViewById(R.id.button_pause);
|
_control_pause_fullscreen = _videoControls_fullscreen.findViewById(R.id.button_pause);
|
||||||
|
|
||||||
|
loaderOverlay = findViewById(R.id.loader_overlay)
|
||||||
|
loaderIndeterminate = findViewById(R.id.loader_indeterminate)
|
||||||
|
loaderDeterminate = findViewById(R.id.loader_determinate)
|
||||||
|
|
||||||
|
loaderOverlay.visibility = View.GONE
|
||||||
|
loaderIndeterminate.visibility = View.GONE
|
||||||
|
loaderDeterminate.visibility = View.GONE
|
||||||
|
|
||||||
_control_chapter.setOnClickListener {
|
_control_chapter.setOnClickListener {
|
||||||
_currentChapter?.let {
|
_currentChapter?.let {
|
||||||
onChapterClicked.emit(it);
|
onChapterClicked.emit(it);
|
||||||
@@ -865,4 +882,35 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
|
|||||||
override fun onSurfaceSizeChanged(width: Int, height: Int) {
|
override fun onSurfaceSizeChanged(width: Int, height: Int) {
|
||||||
gestureControl.resetZoomPan()
|
gestureControl.resetZoomPan()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setLoading(isLoading: Boolean) {
|
||||||
|
determinateAnimator?.cancel()
|
||||||
|
if (isLoading) {
|
||||||
|
loaderOverlay.visibility = View.VISIBLE
|
||||||
|
loaderIndeterminate.visibility = View.VISIBLE
|
||||||
|
loaderDeterminate.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
loaderOverlay.visibility = View.GONE
|
||||||
|
loaderIndeterminate.visibility = View.GONE
|
||||||
|
loaderDeterminate.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setLoading(expectedDurationMs: Int) {
|
||||||
|
determinateAnimator?.cancel()
|
||||||
|
|
||||||
|
loaderOverlay.visibility = View.VISIBLE
|
||||||
|
loaderIndeterminate.visibility = View.GONE
|
||||||
|
loaderDeterminate.visibility = View.VISIBLE
|
||||||
|
loaderDeterminate.max = expectedDurationMs
|
||||||
|
loaderDeterminate.progress = 0
|
||||||
|
|
||||||
|
determinateAnimator = ValueAnimator.ofInt(0, expectedDurationMs).apply {
|
||||||
|
duration = expectedDurationMs.toLong()
|
||||||
|
addUpdateListener { anim ->
|
||||||
|
loaderDeterminate.progress = anim.animatedValue as Int
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,8 @@ import com.futo.platformplayer.views.video.datasources.JSHttpDataSource
|
|||||||
import getHttpDataSourceFactory
|
import getHttpDataSourceFactory
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
@@ -573,7 +575,17 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
val plugin = videoSource.getUnderlyingPlugin() ?: return@launch;
|
val plugin = videoSource.getUnderlyingPlugin() ?: return@launch;
|
||||||
startId = plugin.getUnderlyingPlugin()?.runtimeId ?: -1;
|
startId = plugin.getUnderlyingPlugin()?.runtimeId ?: -1;
|
||||||
val generatedDef = plugin.busy { videoSource.generateAsync(scope); };
|
val generatedDef = plugin.busy { videoSource.generateAsync(scope); };
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (generatedDef.estDuration >= 0) {
|
||||||
|
setLoading(generatedDef.estDuration)
|
||||||
|
} else {
|
||||||
|
setLoading(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
val generated = generatedDef.await();
|
val generated = generatedDef.await();
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
if (generated != null) {
|
if (generated != null) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
val dataSource = if(videoSource is JSSource && (videoSource.requiresCustomDatasource))
|
val dataSource = if(videoSource is JSSource && (videoSource.requiresCustomDatasource))
|
||||||
@@ -610,6 +622,10 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
}
|
}
|
||||||
catch(ex: Throwable) {
|
catch(ex: Throwable) {
|
||||||
Logger.e(TAG, "DashRaw generator failed", ex);
|
Logger.e(TAG, "DashRaw generator failed", ex);
|
||||||
|
} finally {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -702,7 +718,17 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
val plugin = audioSource.getUnderlyingPlugin() ?: return@launch;
|
val plugin = audioSource.getUnderlyingPlugin() ?: return@launch;
|
||||||
startId = audioSource.getUnderlyingPlugin()?.getUnderlyingPlugin()?.runtimeId ?: -1;
|
startId = audioSource.getUnderlyingPlugin()?.getUnderlyingPlugin()?.runtimeId ?: -1;
|
||||||
val generatedDef = plugin.busy { audioSource.generateAsync(scope); }
|
val generatedDef = plugin.busy { audioSource.generateAsync(scope); }
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (generatedDef.estDuration >= 0) {
|
||||||
|
setLoading(generatedDef.estDuration)
|
||||||
|
} else {
|
||||||
|
setLoading(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
val generated = generatedDef.await();
|
val generated = generatedDef.await();
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
if(generated != null) {
|
if(generated != null) {
|
||||||
val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource))
|
val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource))
|
||||||
audioSource.getHttpDataSourceFactory()
|
audioSource.getHttpDataSourceFactory()
|
||||||
@@ -729,6 +755,10 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
}
|
}
|
||||||
catch(ex: Throwable) {
|
catch(ex: Throwable) {
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -938,6 +968,9 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun setLoading(isLoading: Boolean) { }
|
||||||
|
protected open fun setLoading(expectedDurationMs: Int) { }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0";
|
val DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0";
|
||||||
|
|
||||||
|
|||||||
@@ -64,4 +64,36 @@
|
|||||||
app:controller_layout_id="@layout/video_player_ui_fullscreen"
|
app:controller_layout_id="@layout/video_player_ui_fullscreen"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/loader_overlay"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
|
android:background="@color/black"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loader_indeterminate"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loader_determinate"
|
||||||
|
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="false"
|
||||||
|
android:max="100"
|
||||||
|
android:progress="0"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Reference in New Issue
Block a user