Skip to content

Commit

Permalink
新增弹幕设置
Browse files Browse the repository at this point in the history
  • Loading branch information
aaa1115910 committed Dec 16, 2023
1 parent 1bd0b2b commit 86caf3c
Show file tree
Hide file tree
Showing 7 changed files with 539 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.movableContentOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -91,7 +90,9 @@ import dev.aaa1115910.bv.mobile.viewmodel.MobileVideoPlayerViewModel
import dev.aaa1115910.bv.player.mobile.component.BvPlayer
import dev.aaa1115910.bv.player.mobile.util.LocalMobileVideoPlayerData
import dev.aaa1115910.bv.player.mobile.util.MobileVideoPlayerData
import dev.aaa1115910.bv.util.Prefs
import dev.aaa1115910.bv.util.formatPubTimeString
import dev.aaa1115910.bv.util.swapList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel
Expand Down Expand Up @@ -164,7 +165,7 @@ fun VideoPlayerScreen(
}
}

val bvPlayerContent = remember {
/*val bvPlayerContent = remember {
// TODO movableContentOf here doesn't avoid Media from recreating its surface view when
// screen rotation changed. Seems like a bug of Compose.
// see: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1654734644676989
Expand All @@ -184,10 +185,10 @@ fun VideoPlayerScreen(
//(context as Activity).requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
},
onBack = { (context as Activity).finish() },
onChangeResolution = {}
onChangeResolution = {},
)
}
}
}*/

Scaffold { innerPadding ->
Row(
Expand All @@ -205,7 +206,12 @@ fun VideoPlayerScreen(
CompositionLocalProvider(
LocalMobileVideoPlayerData provides MobileVideoPlayerData(
currentResolutionCode = playerViewModel.currentQuality,
availableResolutionMap = playerViewModel.availableQuality
availableResolutionMap = playerViewModel.availableQuality,
enabledDanmaku = playerViewModel.currentDanmakuEnabled,
currentDanmakuTypes = playerViewModel.currentDanmakuTypes,
currentDanmakuScale = playerViewModel.currentDanmakuScale,
currentDanmakuOpacity = playerViewModel.currentDanmakuOpacity,
currentDanmakuArea = playerViewModel.currentDanmakuArea
)
) {
BvPlayer(
Expand All @@ -230,6 +236,25 @@ fun VideoPlayerScreen(
playerViewModel.currentQuality = code
playerViewModel.playQuality(code)
}
},
onToggleDanmaku = { enabled ->
playerViewModel.currentDanmakuEnabled = enabled
Prefs.defaultDanmakuEnabled = enabled
},
onEnabledDanmakuTypesChange = { types ->
playerViewModel.currentDanmakuTypes.swapList(types)
},
onDanmakuOpacityChange = { opacity ->
playerViewModel.currentDanmakuOpacity = opacity
Prefs.defaultDanmakuOpacity = opacity
},
onDanmakuScaleChange = { scale ->
playerViewModel.currentDanmakuScale = scale
Prefs.defaultDanmakuScale = scale
},
onDanmakuAreaChange = { area ->
playerViewModel.currentDanmakuArea = area
Prefs.defaultDanmakuArea = area
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ import dev.aaa1115910.biliapi.repositories.VideoDetailRepository
import dev.aaa1115910.biliapi.repositories.VideoPlayRepository
import dev.aaa1115910.bilisubtitle.entity.SubtitleItem
import dev.aaa1115910.bv.BVApp
import dev.aaa1115910.bv.component.controllers2.DanmakuType
import dev.aaa1115910.bv.entity.Audio
import dev.aaa1115910.bv.entity.Resolution
import dev.aaa1115910.bv.entity.VideoCodec
import dev.aaa1115910.bv.player.mobile.component.DanmakuType
import dev.aaa1115910.bv.player.mobile.component.playUrl
import dev.aaa1115910.bv.util.Prefs
import dev.aaa1115910.bv.util.fException
Expand Down Expand Up @@ -81,7 +81,14 @@ class MobileVideoPlayerViewModel(
var currentDanmakuOpacity by mutableStateOf(Prefs.defaultDanmakuOpacity)
var currentDanmakuEnabled by mutableStateOf(Prefs.defaultDanmakuEnabled)
val currentDanmakuTypes = mutableStateListOf<DanmakuType>().apply {
addAll(Prefs.defaultDanmakuTypes)
addAll(Prefs.defaultDanmakuTypes.map {
when (it) {
dev.aaa1115910.bv.component.controllers2.DanmakuType.All -> DanmakuType.All
dev.aaa1115910.bv.component.controllers2.DanmakuType.Rolling -> DanmakuType.Rolling
dev.aaa1115910.bv.component.controllers2.DanmakuType.Top -> DanmakuType.Top
dev.aaa1115910.bv.component.controllers2.DanmakuType.Bottom -> DanmakuType.Bottom
}
})
}
var currentDanmakuArea by mutableStateOf(Prefs.defaultDanmakuArea)
var currentSubtitleId by mutableStateOf(-1L)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.aaa1115910.bv.player.mobile.component

import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
Expand All @@ -9,8 +10,13 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import com.kuaishou.akdanmaku.DanmakuConfig
import com.kuaishou.akdanmaku.data.DanmakuItemData
import com.kuaishou.akdanmaku.ecs.component.filter.TypeFilter
import com.kuaishou.akdanmaku.ext.RETAINER_BILIBILI
import com.kuaishou.akdanmaku.ui.DanmakuPlayer
import dev.aaa1115910.bv.player.mobile.component.controller.BvPlayerController
import dev.aaa1115910.bv.player.mobile.util.LocalMobileVideoPlayerData
Expand All @@ -24,12 +30,21 @@ fun BvPlayer(
onExitFullScreen: () -> Unit,
onBack: () -> Unit,
onChangeResolution: (Int) -> Unit,
onToggleDanmaku: (Boolean) -> Unit,
onEnabledDanmakuTypesChange: (List<DanmakuType>) -> Unit,
onDanmakuOpacityChange: (Float) -> Unit,
onDanmakuScaleChange: (Float) -> Unit,
onDanmakuAreaChange: (Float) -> Unit,
videoPlayer: ExoPlayer,
danmakuPlayer: DanmakuPlayer
) {
val mobileVideoPlayerData = LocalMobileVideoPlayerData.current
var isPlaying by rememberSaveable { mutableStateOf(false) }

var enabledDanmaku by rememberSaveable { mutableStateOf(mobileVideoPlayerData.enabledDanmaku) }
val typeFilter by remember { mutableStateOf(TypeFilter()) }
var danmakuConfig by remember { mutableStateOf(DanmakuConfig()) }

var currentTime by remember { mutableStateOf(0L) }
var totalTime by remember { mutableStateOf(0L) }
var currentSeekPosition by remember { mutableStateOf(0f) }
Expand All @@ -42,6 +57,55 @@ fun BvPlayer(
bufferedSeekPosition = videoPlayer.bufferedPercentage / 100f
}

val updateEnabledDanmakuTypeFilter: (List<DanmakuType>) -> Unit = { danmakuTypes ->
typeFilter.clear()
if (!danmakuTypes.contains(DanmakuType.All)) {
val types = DanmakuType.entries.toMutableList()
types.remove(DanmakuType.All)
types.removeAll(danmakuTypes)
val filterTypes = types.mapNotNull {
when (it) {
DanmakuType.Rolling -> DanmakuItemData.DANMAKU_MODE_ROLLING
DanmakuType.Top -> DanmakuItemData.DANMAKU_MODE_CENTER_TOP
DanmakuType.Bottom -> DanmakuItemData.DANMAKU_MODE_CENTER_BOTTOM
else -> null
}
}
filterTypes.forEach { typeFilter.addFilterItem(it) }
}
}

val initDanmakuConfig: () -> Unit = {
updateEnabledDanmakuTypeFilter(mobileVideoPlayerData.currentDanmakuTypes)
danmakuConfig = danmakuConfig.copy(
retainerPolicy = RETAINER_BILIBILI,
textSizeScale = mobileVideoPlayerData.currentDanmakuScale,
dataFilter = listOf(typeFilter)
)
danmakuConfig.updateFilter()
danmakuPlayer.updateConfig(danmakuConfig)
}

val updateDanmakuConfigTypeFilter: () -> Unit = {
updateEnabledDanmakuTypeFilter(mobileVideoPlayerData.currentDanmakuTypes)
danmakuConfig.updateFilter()
danmakuPlayer.updateConfig(danmakuConfig)
}

val toggleDanmakuEnabled: (Boolean) -> Unit = { enabled ->
updateEnabledDanmakuTypeFilter(if (enabled) mobileVideoPlayerData.currentDanmakuTypes else listOf())
danmakuConfig.updateFilter()
danmakuPlayer.updateConfig(danmakuConfig)
}

val updateDanmakuConfig: () -> Unit = {
danmakuConfig = danmakuConfig.copy(
retainerPolicy = RETAINER_BILIBILI,
textSizeScale = mobileVideoPlayerData.currentDanmakuScale,
)
danmakuPlayer.updateConfig(danmakuConfig)
}

LaunchedEffect(Unit) {
while (true) {
updatePosition()
Expand All @@ -63,6 +127,7 @@ fun BvPlayer(
override fun onPlaybackStateChanged(playbackState: Int) {
when (playbackState) {
Player.STATE_READY -> {
initDanmakuConfig()
danmakuPlayer.seekTo(videoPlayer.currentPosition)
if (!isPlaying) danmakuPlayer.pause()
}
Expand Down Expand Up @@ -95,18 +160,45 @@ fun BvPlayer(
currentResolutionCode = mobileVideoPlayerData.currentResolutionCode,
currentSpeed = mobileVideoPlayerData.currentSpeed,
availableResolutionMap = mobileVideoPlayerData.availableResolutionMap,
enabledDanmaku = enabledDanmaku,
enabledDanmakuTypes = mobileVideoPlayerData.currentDanmakuTypes,
danmakuOpacity = mobileVideoPlayerData.currentDanmakuOpacity,
danmakuScale = mobileVideoPlayerData.currentDanmakuScale,
danmakuArea = mobileVideoPlayerData.currentDanmakuArea,
onEnterFullScreen = onEnterFullScreen,
onExitFullScreen = onExitFullScreen,
onBack = onBack,
onPlay = { videoPlayer.play() },
onPause = { videoPlayer.pause() },
onSeekToPosition = videoPlayer::seekTo,
onChangeResolution = onChangeResolution,
onChangeSpeed = videoPlayer::setPlaybackSpeed
onChangeSpeed = videoPlayer::setPlaybackSpeed,
onToggleDanmaku = {
enabledDanmaku = !enabledDanmaku
toggleDanmakuEnabled(enabledDanmaku)
onToggleDanmaku(enabledDanmaku)
},
onEnabledDanmakuTypesChange = { enabledDanmakuTypes ->
onEnabledDanmakuTypesChange(enabledDanmakuTypes)
updateDanmakuConfigTypeFilter()
},
onDanmakuOpacityChange = onDanmakuOpacityChange,
onDanmakuScaleChange = { scale ->
onDanmakuScaleChange(scale)
updateDanmakuConfig()
},
onDanmakuAreaChange = onDanmakuAreaChange
) {
Media3VideoPlayer(videoPlayer = videoPlayer)
AkDanmakuPlayer(
modifier = Modifier
.alpha(mobileVideoPlayerData.currentDanmakuOpacity)
.fillMaxHeight(mobileVideoPlayerData.currentDanmakuArea),
danmakuPlayer = danmakuPlayer
)
}
}

enum class DanmakuType {
All, Top, Rolling, Bottom;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import dev.aaa1115910.bv.player.mobile.component.DanmakuType
import dev.aaa1115910.bv.player.mobile.component.controller.menu.DanmakuMenuController
import dev.aaa1115910.bv.player.mobile.component.controller.menu.ResolutionMenuController
import dev.aaa1115910.bv.player.mobile.component.controller.menu.SpeedMenuController
import kotlin.math.absoluteValue
Expand All @@ -39,6 +41,11 @@ fun BvPlayerController(
currentResolutionCode: Int,
availableResolutionMap: Map<Int, String>,
currentSpeed: Float,
enabledDanmaku: Boolean,
enabledDanmakuTypes: List<DanmakuType>,
danmakuOpacity: Float,
danmakuScale: Float,
danmakuArea: Float,
onEnterFullScreen: () -> Unit,
onExitFullScreen: () -> Unit,
onBack: () -> Unit,
Expand All @@ -47,13 +54,19 @@ fun BvPlayerController(
onSeekToPosition: (Long) -> Unit,
onChangeResolution: (Int) -> Unit,
onChangeSpeed: (Float) -> Unit,
onToggleDanmaku: (Boolean) -> Unit,
onEnabledDanmakuTypesChange: (List<DanmakuType>) -> Unit,
onDanmakuOpacityChange: (Float) -> Unit,
onDanmakuScaleChange: (Float) -> Unit,
onDanmakuAreaChange: (Float) -> Unit,
content: @Composable () -> Unit
) {
val context = LocalContext.current
var showBaseUi by remember { mutableStateOf(false) }

var showResolutionController by remember { mutableStateOf(false) }
var showSpeedController by remember { mutableStateOf(false) }
var showDanmakuController by remember { mutableStateOf(false) }

//在手势触发的事件中,直接读取 isPlaying currentTime 参数都只会读取到错误的值,原因未知
var isPlaying2 by remember { mutableStateOf(isPlaying) }
Expand Down Expand Up @@ -228,6 +241,7 @@ fun BvPlayerController(
bufferedSeekPosition = bufferedSeekPosition,
currentResolutionName = availableResolutionMap[currentResolutionCode]
?: "Unknown",
enabledDanmaku = enabledDanmaku,
onPlay = onPlay,
onPause = onPause,
onExitFullScreen = onExitFullScreen,
Expand All @@ -239,6 +253,11 @@ fun BvPlayerController(
onShowSpeedController = {
showBaseUi = false
showSpeedController = true
},
onToggleDanmaku = onToggleDanmaku,
onShowDanmakuController = {
showBaseUi = false
showDanmakuController = true
}
)
} else {
Expand Down Expand Up @@ -277,6 +296,19 @@ fun BvPlayerController(
showSpeedController = false
}
)

DanmakuMenuController(
show = showDanmakuController,
onHideController = { showDanmakuController = false },
enabledDanmakuTypes = enabledDanmakuTypes,
danmakuOpacity = danmakuOpacity,
danmakuScale = danmakuScale,
danmakuArea = danmakuArea,
onEnabledDanmakuTypesChange = onEnabledDanmakuTypesChange,
onDanmakuOpacityChange = onDanmakuOpacityChange,
onDanmakuScaleChange = onDanmakuScaleChange,
onDanmakuAreaChange = onDanmakuAreaChange
)
}
}

Expand Down
Loading

0 comments on commit 86caf3c

Please sign in to comment.