mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
Merge pull request #4849 from Bnyro/master
feat: option to set a different default resolution when not in fullscreen
This commit is contained in:
commit
38549dbdb8
@ -36,10 +36,10 @@ import com.github.libretube.enums.SbSkipOptions
|
||||
import com.github.libretube.extensions.updateParameters
|
||||
import com.github.libretube.obj.VideoStats
|
||||
import com.github.libretube.util.TextUtils
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.Locale
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.roundToInt
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
object PlayerHelper {
|
||||
private const val ACTION_MEDIA_CONTROL = "media_control"
|
||||
@ -324,13 +324,17 @@ object PlayerHelper {
|
||||
true
|
||||
)
|
||||
|
||||
fun getDefaultResolution(context: Context): String {
|
||||
val prefKey = if (NetworkHelper.isNetworkMetered(context)) {
|
||||
fun getDefaultResolution(context: Context, isFullscreen: Boolean): Int? {
|
||||
var prefKey = if (NetworkHelper.isNetworkMetered(context)) {
|
||||
PreferenceKeys.DEFAULT_RESOLUTION_MOBILE
|
||||
} else {
|
||||
PreferenceKeys.DEFAULT_RESOLUTION
|
||||
}
|
||||
if (!isFullscreen) prefKey += "_no_fullscreen"
|
||||
|
||||
return PreferenceHelper.getString(prefKey, "")
|
||||
.replace("p", "")
|
||||
.toIntOrNull()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -502,9 +506,9 @@ object PlayerHelper {
|
||||
if (currentPosition in segmentStart until segmentEnd) {
|
||||
if (sponsorBlockConfig[segment.category] == SbSkipOptions.AUTOMATIC ||
|
||||
(
|
||||
sponsorBlockConfig[segment.category] == SbSkipOptions.AUTOMATIC_ONCE &&
|
||||
!segment.skipped
|
||||
)
|
||||
sponsorBlockConfig[segment.category] == SbSkipOptions.AUTOMATIC_ONCE &&
|
||||
!segment.skipped
|
||||
)
|
||||
) {
|
||||
if (sponsorBlockNotifications) {
|
||||
runCatching {
|
||||
@ -516,9 +520,9 @@ object PlayerHelper {
|
||||
segment.skipped = true
|
||||
} else if (sponsorBlockConfig[segment.category] == SbSkipOptions.MANUAL ||
|
||||
(
|
||||
sponsorBlockConfig[segment.category] == SbSkipOptions.AUTOMATIC_ONCE &&
|
||||
segment.skipped
|
||||
)
|
||||
sponsorBlockConfig[segment.category] == SbSkipOptions.AUTOMATIC_ONCE &&
|
||||
segment.skipped
|
||||
)
|
||||
) {
|
||||
return segment
|
||||
}
|
||||
@ -543,9 +547,9 @@ object PlayerHelper {
|
||||
return chapters
|
||||
.filter {
|
||||
it.highlightDrawable == null ||
|
||||
// remove the video highlight if it's already longer ago than [ChapterSegment.HIGHLIGHT_LENGTH],
|
||||
// otherwise the SponsorBlock highlight would be shown from its starting point to the end
|
||||
(currentPositionSeconds - it.start) < ChapterSegment.HIGHLIGHT_LENGTH
|
||||
// remove the video highlight if it's already longer ago than [ChapterSegment.HIGHLIGHT_LENGTH],
|
||||
// otherwise the SponsorBlock highlight would be shown from its starting point to the end
|
||||
(currentPositionSeconds - it.start) < ChapterSegment.HIGHLIGHT_LENGTH
|
||||
}
|
||||
.sortedBy { it.start }
|
||||
.indexOfLast { currentPositionSeconds >= it.start }
|
||||
@ -701,9 +705,9 @@ object PlayerHelper {
|
||||
*/
|
||||
fun haveAudioTrackRoleFlagSet(@C.RoleFlags roleFlags: Int): Boolean {
|
||||
return isFlagSet(roleFlags, C.ROLE_FLAG_DESCRIBES_VIDEO) ||
|
||||
isFlagSet(roleFlags, C.ROLE_FLAG_DUB) ||
|
||||
isFlagSet(roleFlags, C.ROLE_FLAG_MAIN) ||
|
||||
isFlagSet(roleFlags, C.ROLE_FLAG_ALTERNATE)
|
||||
isFlagSet(roleFlags, C.ROLE_FLAG_DUB) ||
|
||||
isFlagSet(roleFlags, C.ROLE_FLAG_MAIN) ||
|
||||
isFlagSet(roleFlags, C.ROLE_FLAG_ALTERNATE)
|
||||
}
|
||||
|
||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||
@ -716,7 +720,8 @@ object PlayerHelper {
|
||||
val audioInfo = "${player.audioFormat?.codecs.orEmpty()} ${
|
||||
TextUtils.formatBitrate(player.audioFormat?.bitrate)
|
||||
}"
|
||||
val videoQuality = "${player.videoFormat?.width}x${player.videoFormat?.height} ${player.videoFormat?.frameRate?.toInt()}fps"
|
||||
val videoQuality =
|
||||
"${player.videoFormat?.width}x${player.videoFormat?.height} ${player.videoFormat?.frameRate?.toInt()}fps"
|
||||
return VideoStats(videoId, videoInfo, videoQuality, audioInfo)
|
||||
}
|
||||
}
|
||||
|
@ -159,33 +159,32 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
*/
|
||||
private lateinit var streams: Streams
|
||||
|
||||
/**
|
||||
* for the transition
|
||||
*/
|
||||
// progress state of the motion layout transition
|
||||
private var transitionStartId = 0
|
||||
private var transitionEndId = 0
|
||||
private var isTransitioning = true
|
||||
|
||||
/**
|
||||
* for the player
|
||||
*/
|
||||
// data and objects stored for the player
|
||||
private lateinit var exoPlayer: ExoPlayer
|
||||
private lateinit var trackSelector: DefaultTrackSelector
|
||||
private var currentSubtitle = Subtitle(code = PlayerHelper.defaultSubtitleCode)
|
||||
|
||||
// if null, it's been set to automatic
|
||||
private var fullscreenResolution: Int? = null
|
||||
|
||||
// the resolution to use when the video is not played in fullscreen
|
||||
// if null, use same quality as fullscreen
|
||||
private var noFullscreenResolution: Int? = null
|
||||
|
||||
private val cronetDataSourceFactory = CronetDataSource.Factory(
|
||||
CronetHelper.cronetEngine,
|
||||
Executors.newCachedThreadPool()
|
||||
)
|
||||
|
||||
/**
|
||||
* for the player notification
|
||||
*/
|
||||
// for the player notification
|
||||
private lateinit var nowPlayingNotification: NowPlayingNotification
|
||||
|
||||
/**
|
||||
* SponsorBlock
|
||||
*/
|
||||
// SponsorBlock
|
||||
private var segments = listOf<Segment>()
|
||||
private var sponsorBlockEnabled = PlayerHelper.sponsorBlockEnabled
|
||||
private var sponsorBlockConfig = PlayerHelper.getSponsorBlockCategories()
|
||||
@ -263,6 +262,9 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
1000,
|
||||
1000
|
||||
)
|
||||
|
||||
fullscreenResolution = PlayerHelper.getDefaultResolution(requireContext(), true)
|
||||
noFullscreenResolution = PlayerHelper.getDefaultResolution(requireContext(), false)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@ -541,6 +543,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
|
||||
updateFullscreenOrientation()
|
||||
viewModel.isFullscreen.value = true
|
||||
|
||||
updateResolutionOnFullscreenChange(true)
|
||||
}
|
||||
|
||||
@SuppressLint("SourceLockedOrientationActivity")
|
||||
@ -570,6 +574,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
}
|
||||
|
||||
viewModel.isFullscreen.value = false
|
||||
|
||||
updateResolutionOnFullscreenChange(false)
|
||||
}
|
||||
|
||||
private fun toggleDescription() {
|
||||
@ -1324,9 +1330,16 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateResolutionOnFullscreenChange(isFullscreen: Boolean) {
|
||||
if (!isFullscreen && noFullscreenResolution != null) {
|
||||
setPlayerResolution(noFullscreenResolution!!)
|
||||
} else {
|
||||
setPlayerResolution(fullscreenResolution ?: Int.MAX_VALUE)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setStreamSource() {
|
||||
val defaultResolution = PlayerHelper.getDefaultResolution(requireContext()).replace("p", "")
|
||||
if (defaultResolution.isNotEmpty()) setPlayerResolution(defaultResolution.toInt())
|
||||
updateResolutionOnFullscreenChange(viewModel.isFullscreen.value == true)
|
||||
|
||||
val (uri, mimeType) = when {
|
||||
// LBRY HLS
|
||||
@ -1503,7 +1516,15 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
if (currentQuality == it.resolution) "${it.name} ✓" else it.name
|
||||
}
|
||||
) { which ->
|
||||
setPlayerResolution(resolutions[which].resolution)
|
||||
val newResolution = resolutions[which].resolution
|
||||
setPlayerResolution(newResolution)
|
||||
|
||||
// save the selected resolution to update on fullscreen change
|
||||
if (noFullscreenResolution != null && viewModel.isFullscreen.value != true) {
|
||||
noFullscreenResolution = newResolution
|
||||
} else {
|
||||
fullscreenResolution = newResolution
|
||||
}
|
||||
}
|
||||
.show(childFragmentManager)
|
||||
}
|
||||
|
@ -177,6 +177,17 @@
|
||||
<item>240p</item>
|
||||
<item>144p</item>
|
||||
</string-array>
|
||||
<string-array name="defresNoPortrait">
|
||||
<item>@string/same_as_fullscreen</item>
|
||||
<item>2160p</item>
|
||||
<item>1440p</item>
|
||||
<item>1080p</item>
|
||||
<item>720p</item>
|
||||
<item>480p</item>
|
||||
<item>360p</item>
|
||||
<item>240p</item>
|
||||
<item>144p</item>
|
||||
</string-array>
|
||||
<string-array name="defresValue">
|
||||
<item />
|
||||
<item>2160p</item>
|
||||
|
@ -445,6 +445,9 @@
|
||||
<string name="uploader_name">Uploader name</string>
|
||||
<string name="duration_span">Duration: %1$s</string>
|
||||
<string name="remove_watched_videos">Remove watched videos</string>
|
||||
<string name="no_fullscreen_resolution">No-Fullscreen resolution</string>
|
||||
<string name="same_as_fullscreen">Same as fullscreen</string>
|
||||
|
||||
<!-- Backup & Restore Settings -->
|
||||
<string name="import_subscriptions_from">Import subscriptions from</string>
|
||||
<string name="export_subscriptions_to">Export subscriptions to</string>
|
||||
|
@ -13,6 +13,15 @@
|
||||
app:title="@string/defres"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:icon="@drawable/ic_fullscreen"
|
||||
app:defaultValue=""
|
||||
app:entries="@array/defresNoPortrait"
|
||||
app:entryValues="@array/defresValue"
|
||||
app:key="default_res_no_fullscreen"
|
||||
app:title="@string/no_fullscreen_resolution"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:icon="@drawable/ic_headphones"
|
||||
app:defaultValue="auto"
|
||||
@ -35,6 +44,15 @@
|
||||
app:title="@string/defres"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:icon="@drawable/ic_fullscreen"
|
||||
app:defaultValue=""
|
||||
app:entries="@array/defresNoPortrait"
|
||||
app:entryValues="@array/defresValue"
|
||||
app:key="default_res_mobile_no_fullscreen"
|
||||
app:title="@string/no_fullscreen_resolution"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:icon="@drawable/ic_headphones"
|
||||
app:defaultValue="auto"
|
||||
|
Loading…
Reference in New Issue
Block a user