Skip to content

Commit caaa095

Browse files
committed
feat: smoother, frictionless transition between audio and video mode
1 parent b3e4a24 commit caaa095

14 files changed

Lines changed: 75 additions & 63 deletions

app/src/main/java/com/github/libretube/constants/IntentData.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object IntentData {
1414
const val timeStamp = "timeStamp"
1515
const val playlistType = "playlistType"
1616
const val downloading = "downloading"
17-
const val openAudioPlayer = "openAudioPlayer"
17+
const val maximizePlayer = "openAudioPlayer"
1818
const val fragmentToOpen = "fragmentToOpen"
1919
const val comment = "comment"
2020
const val minimizeByDefault = "minimizeByDefault"
@@ -60,4 +60,5 @@ object IntentData {
6060
const val alreadyStarted = "alreadyStarted"
6161
const val showUpcoming = "showUpcoming"
6262
const val customInstance = "customInstance"
63+
const val audioOnly = "audioOnly"
6364
}

app/src/main/java/com/github/libretube/enums/PlayerCommand.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ enum class PlayerCommand {
99
SET_SUBTITLE,
1010
SET_SB_AUTO_SKIP_ENABLED,
1111
PLAY_VIDEO_BY_ID,
12-
SET_AUTOPLAY_COUNTDOWN_ENABLED
12+
SET_AUTOPLAY_COUNTDOWN_ENABLED,
13+
TOGGLE_AUDIO_ONLY_MODE
1314
}

app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import com.github.libretube.services.AbstractPlayerService
1818
import com.github.libretube.services.OfflinePlayerService
1919
import com.github.libretube.services.OnlinePlayerService
2020
import com.github.libretube.services.VideoOfflinePlayerService
21-
import com.github.libretube.services.VideoOnlinePlayerService
2221
import com.github.libretube.ui.activities.MainActivity
2322
import com.github.libretube.ui.activities.NoInternetActivity
2423
import com.github.libretube.ui.fragments.DownloadTab
@@ -56,7 +55,7 @@ object BackgroundHelper {
5655
startMediaService(
5756
context,
5857
OnlinePlayerService::class.java,
59-
bundleOf(IntentData.playerData to playerData)
58+
bundleOf(IntentData.playerData to playerData, IntentData.audioOnly to true)
6059
)
6160
}
6261

@@ -67,8 +66,7 @@ object BackgroundHelper {
6766
arrayOf(
6867
OnlinePlayerService::class.java,
6968
OfflinePlayerService::class.java,
70-
VideoOfflinePlayerService::class.java,
71-
VideoOnlinePlayerService::class.java
69+
VideoOfflinePlayerService::class.java
7270
).forEach {
7371
val intent = Intent(context, it)
7472
context.stopService(intent)
@@ -117,7 +115,6 @@ object BackgroundHelper {
117115
context: Context,
118116
serviceClass: Class<*>,
119117
arguments: Bundle = Bundle.EMPTY,
120-
sendStartCommand: Boolean = true,
121118
onController: (MediaController) -> Unit = {}
122119
) {
123120
val sessionToken =
@@ -127,7 +124,7 @@ object BackgroundHelper {
127124
MediaController.Builder(context, sessionToken).buildAsync()
128125
controllerFuture.addListener({
129126
val controller = controllerFuture.get()
130-
if (sendStartCommand) controller.sendCustomCommand(
127+
if (!arguments.isEmpty) controller.sendCustomCommand(
131128
AbstractPlayerService.startServiceCommand,
132129
arguments
133130
)

app/src/main/java/com/github/libretube/helpers/NavigationHelper.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ object NavigationHelper {
5959
channelId: String? = null,
6060
keepQueue: Boolean = false,
6161
timestamp: Long = 0,
62+
alreadyStarted: Boolean = false,
6263
forceVideo: Boolean = false
6364
) {
6465
if (videoUrlOrId == null) return
@@ -85,7 +86,10 @@ object NavigationHelper {
8586

8687
val playerData =
8788
PlayerData(videoUrlOrId.toID(), playlistId, channelId, keepQueue, timestamp)
88-
val bundle = bundleOf(IntentData.playerData to playerData)
89+
val bundle = bundleOf(
90+
IntentData.playerData to playerData,
91+
IntentData.alreadyStarted to alreadyStarted
92+
)
8993
activity.supportFragmentManager.commitNow {
9094
replace<PlayerFragment>(R.id.container, args = bundle)
9195
}

app/src/main/java/com/github/libretube/services/AbstractPlayerService.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import androidx.media3.common.ForwardingPlayer
1515
import androidx.media3.common.MediaMetadata
1616
import androidx.media3.common.PlaybackException
1717
import androidx.media3.common.Player
18+
import androidx.media3.common.util.Log
1819
import androidx.media3.common.util.UnstableApi
1920
import androidx.media3.exoplayer.ExoPlayer
2021
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
@@ -118,6 +119,13 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
118119
onServiceCreated(args)
119120
notificationProvider?.intentActivity = getIntentActivity()
120121

122+
if (isAudioOnlyPlayer) {
123+
trackSelector?.updateParameters {
124+
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, true)
125+
}
126+
}
127+
128+
Log.e("custom start", "custom start")
121129
if (::videoId.isInitialized) startPlayback()
122130
}
123131
}
@@ -179,6 +187,13 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
179187
args.containsKey(PlayerCommand.PLAY_VIDEO_BY_ID.name) -> {
180188
navigateVideo(args.getString(PlayerCommand.PLAY_VIDEO_BY_ID.name) ?: return)
181189
}
190+
191+
args.containsKey(PlayerCommand.TOGGLE_AUDIO_ONLY_MODE.name) -> {
192+
isAudioOnlyPlayer = args.getBoolean(PlayerCommand.TOGGLE_AUDIO_ONLY_MODE.name)
193+
trackSelector?.updateParameters {
194+
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, isAudioOnlyPlayer)
195+
}
196+
}
182197
}
183198
}
184199

@@ -233,7 +248,8 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
233248
}
234249

235250
abstract val isOfflinePlayer: Boolean
236-
abstract val isAudioOnlyPlayer: Boolean
251+
abstract var isAudioOnlyPlayer: Boolean
252+
open val maximizePlayer: Boolean = true
237253

238254
val watchPositionsEnabled get() =
239255
(PlayerHelper.watchPositionsAudio && isAudioOnlyPlayer) || (PlayerHelper.watchPositionsVideo && !isAudioOnlyPlayer)
@@ -246,7 +262,6 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
246262

247263
notificationProvider = NowPlayingNotification(
248264
this,
249-
backgroundOnly = isAudioOnlyPlayer,
250265
offlinePlayer = isOfflinePlayer,
251266
)
252267
setMediaNotificationProvider(notificationProvider!!)
@@ -293,12 +308,6 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
293308
val trackSelector = DefaultTrackSelector(this)
294309
this.trackSelector = trackSelector
295310

296-
if (isAudioOnlyPlayer) {
297-
trackSelector.updateParameters {
298-
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, true)
299-
}
300-
}
301-
302311
val player = PlayerHelper.createPlayer(this, trackSelector, true)
303312
// prevent android from putting LibreTube to sleep when locked
304313
player.setWakeMode(if (isOfflinePlayer) C.WAKE_MODE_LOCAL else C.WAKE_MODE_NETWORK)

app/src/main/java/com/github/libretube/services/OfflinePlayerService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import kotlin.io.path.exists
3333
@OptIn(UnstableApi::class)
3434
open class OfflinePlayerService : AbstractPlayerService() {
3535
override val isOfflinePlayer: Boolean = true
36-
override val isAudioOnlyPlayer: Boolean = true
36+
override var isAudioOnlyPlayer: Boolean = true
3737
private var noInternetService: Boolean = false
3838

3939
private var downloadWithItems: DownloadWithItems? = null

app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.media3.common.MediaItem
88
import androidx.media3.common.MediaItem.SubtitleConfiguration
99
import androidx.media3.common.MimeTypes
1010
import androidx.media3.common.Player
11+
import androidx.media3.common.util.Log
1112
import androidx.media3.datasource.DefaultDataSource
1213
import androidx.media3.exoplayer.hls.HlsMediaSource
1314
import com.github.libretube.R
@@ -45,7 +46,7 @@ import java.io.IOException
4546
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
4647
open class OnlinePlayerService : AbstractPlayerService() {
4748
override val isOfflinePlayer: Boolean = false
48-
override val isAudioOnlyPlayer: Boolean = true
49+
override var isAudioOnlyPlayer: Boolean = false
4950

5051
// PlaylistId/ChannelId for autoplay
5152
private var playlistId: String? = null
@@ -100,6 +101,7 @@ open class OnlinePlayerService : AbstractPlayerService() {
100101
stopSelf()
101102
return
102103
}
104+
isAudioOnlyPlayer = args.getBoolean(IntentData.audioOnly)
103105

104106
// get the intent arguments
105107
setVideoId(playerData.videoId)
@@ -115,6 +117,8 @@ open class OnlinePlayerService : AbstractPlayerService() {
115117
override suspend fun startPlayback() {
116118
super.startPlayback()
117119

120+
Log.e("start", "playback")
121+
118122
val timestampMs = startTimestampSeconds?.times(1000) ?: 0L
119123
startTimestampSeconds = null
120124

@@ -196,6 +200,8 @@ open class OnlinePlayerService : AbstractPlayerService() {
196200
this.streams = null
197201
this.sponsorBlockSegments = emptyList()
198202

203+
Log.e("play next", "play next")
204+
199205
scope.launch {
200206
startPlayback()
201207
}

app/src/main/java/com/github/libretube/services/VideoOfflinePlayerService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import kotlin.io.path.exists
1919

2020
@OptIn(UnstableApi::class)
2121
class VideoOfflinePlayerService: OfflinePlayerService() {
22-
override val isAudioOnlyPlayer = false
22+
override var isAudioOnlyPlayer = false
2323

2424
override fun setMediaItem(downloadWithItems: DownloadWithItems) {
2525
val downloadFiles = downloadWithItems.downloadItems.filter { it.path.exists() }

app/src/main/java/com/github/libretube/services/VideoOnlinePlayerService.kt

Lines changed: 0 additions & 9 deletions
This file was deleted.

app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,12 @@ class MainActivity : BaseActivity() {
433433
startActivity(nIntent)
434434
}
435435

436-
if (intent?.getBooleanExtra(IntentData.openAudioPlayer, false) == true) {
436+
if (intent?.getBooleanExtra(IntentData.maximizePlayer, false) == true) {
437+
// attempt to open the current player fragment first before creating a new one
438+
// TODO: handle this differently
439+
if (runOnPlayerFragment { binding.playerMotionLayout.transitionToStart(); true }) return
440+
if (runOnAudioPlayerFragment { binding.playerMotionLayout.transitionToStart(); true }) return
441+
437442
val offlinePlayer = intent!!.getBooleanExtra(IntentData.offlinePlayer, false)
438443
NavigationHelper.openAudioPlayerFragment(this, offlinePlayer = offlinePlayer)
439444
return

0 commit comments

Comments
 (0)