mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
[Audio Mode] Share, playback and queue controls
This commit is contained in:
parent
a5c3132916
commit
7ffe3a6ed9
@ -65,7 +65,7 @@ class BackgroundMode : Service() {
|
|||||||
/**
|
/**
|
||||||
* The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro)
|
* The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro)
|
||||||
*/
|
*/
|
||||||
private var player: ExoPlayer? = null
|
var player: ExoPlayer? = null
|
||||||
private var playWhenReadyPlayer = true
|
private var playWhenReadyPlayer = true
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,10 +15,14 @@ import android.view.ViewGroup
|
|||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
||||||
|
import com.github.libretube.enums.ShareObjectType
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.obj.ShareData
|
||||||
import com.github.libretube.services.BackgroundMode
|
import com.github.libretube.services.BackgroundMode
|
||||||
import com.github.libretube.ui.activities.MainActivity
|
import com.github.libretube.ui.activities.MainActivity
|
||||||
import com.github.libretube.ui.base.BaseFragment
|
import com.github.libretube.ui.base.BaseFragment
|
||||||
|
import com.github.libretube.ui.dialogs.ShareDialog
|
||||||
|
import com.github.libretube.ui.sheets.PlaybackOptionsSheet
|
||||||
import com.github.libretube.ui.sheets.PlayingQueueSheet
|
import com.github.libretube.ui.sheets.PlayingQueueSheet
|
||||||
import com.github.libretube.util.ImageHelper
|
import com.github.libretube.util.ImageHelper
|
||||||
import com.github.libretube.util.NavigationHelper
|
import com.github.libretube.util.NavigationHelper
|
||||||
@ -32,7 +36,7 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
private var handler = Handler(Looper.getMainLooper())
|
private var handler = Handler(Looper.getMainLooper())
|
||||||
private var isPaused: Boolean = false
|
private var isPaused: Boolean = false
|
||||||
|
|
||||||
private lateinit var playerService: BackgroundMode
|
private var playerService: BackgroundMode? = null
|
||||||
|
|
||||||
/** Defines callbacks for service binding, passed to bindService() */
|
/** Defines callbacks for service binding, passed to bindService() */
|
||||||
private val connection = object : ServiceConnection {
|
private val connection = object : ServiceConnection {
|
||||||
@ -86,16 +90,31 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
PlayingQueue.onQueueItemSelected(currentIndex + 1)
|
PlayingQueue.onQueueItemSelected(currentIndex + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.thumbnail.setOnClickListener {
|
binding.openQueue.setOnClickListener {
|
||||||
PlayingQueueSheet().show(childFragmentManager)
|
PlayingQueueSheet().show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.playbackOptions.setOnClickListener {
|
||||||
|
playerService?.player?.let {
|
||||||
|
PlaybackOptionsSheet(it)
|
||||||
|
.show(childFragmentManager)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.share.setOnClickListener {
|
||||||
|
val currentVideo = PlayingQueue.getCurrent() ?: return@setOnClickListener
|
||||||
|
ShareDialog(
|
||||||
|
id = currentVideo.url!!.toID(),
|
||||||
|
shareObjectType = ShareObjectType.VIDEO,
|
||||||
|
shareData = ShareData(currentVideo = currentVideo.title)
|
||||||
|
).show(childFragmentManager, null)
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for track changes due to autoplay or the notification
|
// Listen for track changes due to autoplay or the notification
|
||||||
PlayingQueue.addOnTrackChangedListener(onTrackChangeListener)
|
PlayingQueue.addOnTrackChangedListener(onTrackChangeListener)
|
||||||
|
|
||||||
binding.playPause.setOnClickListener {
|
binding.playPause.setOnClickListener {
|
||||||
if (!this::playerService.isInitialized) return@setOnClickListener
|
if (isPaused) playerService?.play() else playerService?.pause()
|
||||||
if (isPaused) playerService.play() else playerService.pause()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the stream info into the UI
|
// load the stream info into the UI
|
||||||
@ -121,10 +140,8 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeSeekBar() {
|
private fun initializeSeekBar() {
|
||||||
if (!this::playerService.isInitialized) return
|
|
||||||
|
|
||||||
binding.timeBar.addOnChangeListener { _, value, fromUser ->
|
binding.timeBar.addOnChangeListener { _, value, fromUser ->
|
||||||
if (fromUser) playerService.seekToPosition(value.toLong() * 1000)
|
if (fromUser) playerService?.seekToPosition(value.toLong() * 1000)
|
||||||
}
|
}
|
||||||
updateSeekBar()
|
updateSeekBar()
|
||||||
}
|
}
|
||||||
@ -133,7 +150,7 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
* Update the position, duration and text views belonging to the seek bar
|
* Update the position, duration and text views belonging to the seek bar
|
||||||
*/
|
*/
|
||||||
private fun updateSeekBar() {
|
private fun updateSeekBar() {
|
||||||
val duration = playerService.getDuration()?.toFloat() ?: return
|
val duration = playerService?.getDuration()?.toFloat() ?: return
|
||||||
|
|
||||||
// when the video is not loaded yet, retry in 100 ms
|
// when the video is not loaded yet, retry in 100 ms
|
||||||
if (duration <= 0) {
|
if (duration <= 0) {
|
||||||
@ -142,7 +159,7 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the current position from the player service
|
// get the current position from the player service
|
||||||
val currentPosition = playerService.getCurrentPosition()?.toFloat() ?: 0f
|
val currentPosition = playerService?.getCurrentPosition()?.toFloat() ?: 0f
|
||||||
|
|
||||||
// set the text for the indicators
|
// set the text for the indicators
|
||||||
binding.duration.text = DateUtils.formatElapsedTime((duration / 1000).toLong())
|
binding.duration.text = DateUtils.formatElapsedTime((duration / 1000).toLong())
|
||||||
@ -161,7 +178,7 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleServiceConnection() {
|
private fun handleServiceConnection() {
|
||||||
playerService.onIsPlayingChanged = { isPlaying ->
|
playerService?.onIsPlayingChanged = { isPlaying ->
|
||||||
binding.playPause.setIconResource(
|
binding.playPause.setIconResource(
|
||||||
if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
|
if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
|
||||||
)
|
)
|
||||||
@ -172,7 +189,7 @@ class AudioPlayerFragment : BaseFragment() {
|
|||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
// unregister all listeners and the connected [playerService]
|
// unregister all listeners and the connected [playerService]
|
||||||
playerService.onIsPlayingChanged = null
|
playerService?.onIsPlayingChanged = null
|
||||||
activity?.unbindService(connection)
|
activity?.unbindService(connection)
|
||||||
PlayingQueue.removeOnTrackChangedListener(onTrackChangeListener)
|
PlayingQueue.removeOnTrackChangedListener(onTrackChangeListener)
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import com.github.libretube.util.PreferenceHelper
|
|||||||
import com.google.android.exoplayer2.ExoPlayer
|
import com.google.android.exoplayer2.ExoPlayer
|
||||||
import com.google.android.exoplayer2.PlaybackParameters
|
import com.google.android.exoplayer2.PlaybackParameters
|
||||||
|
|
||||||
class PlaybackSpeedSheet(
|
class PlaybackOptionsSheet(
|
||||||
private val player: ExoPlayer
|
private val player: ExoPlayer
|
||||||
) : ExpandedBottomSheet() {
|
) : ExpandedBottomSheet() {
|
||||||
private lateinit var binding: PlaybackBottomSheetBinding
|
private lateinit var binding: PlaybackBottomSheetBinding
|
@ -30,7 +30,7 @@ import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
|||||||
import com.github.libretube.ui.interfaces.PlayerOptions
|
import com.github.libretube.ui.interfaces.PlayerOptions
|
||||||
import com.github.libretube.ui.models.PlayerViewModel
|
import com.github.libretube.ui.models.PlayerViewModel
|
||||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||||
import com.github.libretube.ui.sheets.PlaybackSpeedSheet
|
import com.github.libretube.ui.sheets.PlaybackOptionsSheet
|
||||||
import com.github.libretube.util.AudioHelper
|
import com.github.libretube.util.AudioHelper
|
||||||
import com.github.libretube.util.BrightnessHelper
|
import com.github.libretube.util.BrightnessHelper
|
||||||
import com.github.libretube.util.PlayerGestureController
|
import com.github.libretube.util.PlayerGestureController
|
||||||
@ -531,7 +531,7 @@ internal class CustomExoPlayerView(
|
|||||||
|
|
||||||
override fun onPlaybackSpeedClicked() {
|
override fun onPlaybackSpeedClicked() {
|
||||||
player?.let {
|
player?.let {
|
||||||
PlaybackSpeedSheet(it as ExoPlayer).show(supportFragmentManager)
|
PlaybackOptionsSheet(it as ExoPlayer).show(supportFragmentManager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
app/src/main/res/drawable/ic_video.xml
Normal file
5
app/src/main/res/drawable/ic_video.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M21,3L3,3c-1.11,0 -2,0.89 -2,2v12c0,1.1 0.89,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.11 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12zM16,11l-7,4L9,7z"/>
|
||||||
|
</vector>
|
@ -47,8 +47,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:textSize="18sp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginTop="10dp" />
|
android:textSize="18sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -56,8 +56,8 @@
|
|||||||
android:id="@+id/time_bar"
|
android:id="@+id/time_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:labelBehavior="gone"
|
android:layout_marginHorizontal="20dp"
|
||||||
android:layout_marginHorizontal="20dp" />
|
app:labelBehavior="gone" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -69,14 +69,14 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start|center"
|
android:layout_gravity="start|center"
|
||||||
tools:text="00:00"/>
|
tools:text="00:00" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="end|center"
|
android:layout_gravity="end|center"
|
||||||
tools:text="10:15"/>
|
tools:text="10:15" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@ -84,7 +84,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginVertical="50dp">
|
android:layout_marginVertical="36dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/prev"
|
android:id="@+id/prev"
|
||||||
@ -118,4 +118,44 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
style="@style/Widget.Material3.CardView.Elevated"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
app:cardCornerRadius="18dp"
|
||||||
|
android:layout_marginBottom="30dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:padding="15dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/open_queue"
|
||||||
|
style="@style/AudioPlayerButton"
|
||||||
|
android:src="@drawable/ic_queue" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/playback_options"
|
||||||
|
style="@style/AudioPlayerButton"
|
||||||
|
android:layout_width="27dp"
|
||||||
|
android:layout_height="27dp"
|
||||||
|
android:src="@drawable/ic_speed" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/open_video"
|
||||||
|
style="@style/AudioPlayerButton"
|
||||||
|
android:src="@drawable/ic_video" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/share"
|
||||||
|
style="@style/AudioPlayerButton"
|
||||||
|
android:src="@drawable/ic_share" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -238,4 +238,12 @@
|
|||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="AudioPlayerButton">
|
||||||
|
<item name="android:layout_width">30dp</item>
|
||||||
|
<item name="android:layout_height">30dp</item>
|
||||||
|
<item name="android:background">?attr/selectableItemBackgroundBorderless</item>
|
||||||
|
<item name="android:layout_marginStart">10dp</item>
|
||||||
|
<item name="android:layout_marginEnd">10dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user