From 2fee9e59f64bf8a75330b7e627c26489b88ad1b3 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Sat, 14 Sep 2024 11:53:39 +0200 Subject: [PATCH] add yt test video --- .../net/newpipe/newplayer/MediaRepository.kt | 10 ++- .../java/net/newpipe/newplayer/NewPlayer.kt | 2 +- .../net/newpipe/newplayer/NewPlayerImpl.kt | 4 +- .../newplayer/model/VideoPlayerUIState.kt | 2 +- .../model/VideoPlayerViewModelImpl.kt | 8 +- .../streamselect/StreamSelectTopBar.kt | 2 +- .../newplayer/utils/MediaSourceBuilder.kt | 75 +++++++++++++++++++ test-app/src/main/res/values/test_streams.xml | 15 +++- 8 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt diff --git a/new-player/src/main/java/net/newpipe/newplayer/MediaRepository.kt b/new-player/src/main/java/net/newpipe/newplayer/MediaRepository.kt index 45da3e3..758f39d 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/MediaRepository.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/MediaRepository.kt @@ -38,7 +38,13 @@ data class StreamVariant( val streamType: StreamType, val language: String?, val streamVariantIdentifier: String -) +) { + override fun equals(other: Any?) = + other is StreamVariant + && other.streamType == streamType + && other.language == language + && other.streamVariantIdentifier == streamVariantIdentifier +} data class RepoMetaInfo( val canHandleTimestampedLinks: Boolean, @@ -52,7 +58,7 @@ data class Stream( interface MediaRepository { - fun getRepoInfo() : RepoMetaInfo + fun getRepoInfo(): RepoMetaInfo suspend fun getMetaInfo(item: String): MediaMetadata diff --git a/new-player/src/main/java/net/newpipe/newplayer/NewPlayer.kt b/new-player/src/main/java/net/newpipe/newplayer/NewPlayer.kt index 52addf7..5d1c263 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/NewPlayer.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/NewPlayer.kt @@ -37,7 +37,7 @@ enum class PlayMode { } enum class RepeatMode { - DONT_REPEAT, + DO_NOT_REPEAT, REPEAT_ALL, REPEAT_ONE } diff --git a/new-player/src/main/java/net/newpipe/newplayer/NewPlayerImpl.kt b/new-player/src/main/java/net/newpipe/newplayer/NewPlayerImpl.kt index 86611f0..aef380f 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/NewPlayerImpl.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/NewPlayerImpl.kt @@ -100,14 +100,14 @@ class NewPlayerImpl( override var repeatMode: RepeatMode get() = when (exoPlayer.value?.repeatMode) { - Player.REPEAT_MODE_OFF -> RepeatMode.DONT_REPEAT + Player.REPEAT_MODE_OFF -> RepeatMode.DO_NOT_REPEAT Player.REPEAT_MODE_ALL -> RepeatMode.REPEAT_ALL Player.REPEAT_MODE_ONE -> RepeatMode.REPEAT_ONE else -> throw NewPlayerException("Unknown Repeatmode option returned by ExoPlayer: ${exoPlayer.value?.repeatMode}") } set(value) { when (value) { - RepeatMode.DONT_REPEAT -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_OFF + RepeatMode.DO_NOT_REPEAT -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_OFF RepeatMode.REPEAT_ALL -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_ALL RepeatMode.REPEAT_ONE -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_ONE } diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt index 42ba523..7ba239e 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt @@ -96,7 +96,7 @@ data class VideoPlayerUIState( playList = emptyList(), chapters = emptyList(), shuffleEnabled = false, - repeatMode = RepeatMode.DONT_REPEAT, + repeatMode = RepeatMode.DO_NOT_REPEAT, playListDurationInS = 0, currentlyPlaying = null, currentPlaylistItemIndex = 0 diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt index ad0e35a..d75a30b 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt @@ -415,6 +415,10 @@ class VideoPlayerViewModelImpl @Inject constructor( } override fun finishFastSeek() { + if (mutableUiState.value.uiMode.controllerUiVisible) { + resetHideUiDelayedJob() + } + val fastSeekAmount = mutableUiState.value.fastSeekSeconds if (fastSeekAmount != 0) { Log.d(TAG, "$fastSeekAmount") @@ -513,9 +517,9 @@ class VideoPlayerViewModelImpl @Inject constructor( override fun cycleRepeatMode() { newPlayer?.let { it.repeatMode = when (it.repeatMode) { - RepeatMode.DONT_REPEAT -> RepeatMode.REPEAT_ALL + RepeatMode.DO_NOT_REPEAT -> RepeatMode.REPEAT_ALL RepeatMode.REPEAT_ALL -> RepeatMode.REPEAT_ONE - RepeatMode.REPEAT_ONE -> RepeatMode.DONT_REPEAT + RepeatMode.REPEAT_ONE -> RepeatMode.DO_NOT_REPEAT } } } diff --git a/new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/streamselect/StreamSelectTopBar.kt b/new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/streamselect/StreamSelectTopBar.kt index 93d2a4b..c9ae24b 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/streamselect/StreamSelectTopBar.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/streamselect/StreamSelectTopBar.kt @@ -81,7 +81,7 @@ fun StreamSelectTopBar( onClick = viewModel::cycleRepeatMode ) { when (uiState.repeatMode) { - RepeatMode.DONT_REPEAT -> Icon( + RepeatMode.DO_NOT_REPEAT -> Icon( imageVector = Icons.Filled.Repeat, contentDescription = stringResource(R.string.repeat_mode_no_repeat) ) diff --git a/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt b/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt new file mode 100644 index 0000000..23632dd --- /dev/null +++ b/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt @@ -0,0 +1,75 @@ +package net.newpipe.newplayer.utils + +import androidx.annotation.OptIn +import androidx.media3.common.MediaItem +import androidx.media3.common.Tracks +import androidx.media3.common.util.UnstableApi +import androidx.media3.datasource.HttpDataSource +import androidx.media3.exoplayer.dash.DashMediaSource +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory +import androidx.media3.exoplayer.source.MediaSource +import androidx.media3.exoplayer.source.MergingMediaSource +import androidx.media3.exoplayer.source.ProgressiveMediaSource +import kotlinx.coroutines.flow.MutableSharedFlow +import net.newpipe.newplayer.MediaRepository +import net.newpipe.newplayer.StreamType +import net.newpipe.newplayer.StreamVariant +import kotlin.random.Random + +class MediaSourceBuilder( + private val repository: MediaRepository, + private val uniqueIdToIdLookup: HashMap, + private val mutableErrorFlow: MutableSharedFlow, + private val httpDataSourceFactory: HttpDataSource.Factory +) { + suspend fun buildMediaSource(item: String) { + val availableStreamVariants = repository.getAvailableStreamVariants(item) + + + val tracks: Tracks? = null + MergingMediaSource + + } + + @OptIn(UnstableApi::class) + private suspend + fun toMediaItem(item: String, streamVariant: StreamVariant): MediaItem { + val dataStream = repository.getStream(item, streamVariant) + + val uniqueId = Random.nextLong() + uniqueIdToIdLookup[uniqueId] = item + val mediaItemBuilder = MediaItem.Builder() + .setMediaId(uniqueId.toString()) + .setUri(dataStream.streamUri) + + if (dataStream.mimeType != null) { + mediaItemBuilder.setMimeType(dataStream.mimeType) + } + + return mediaItemBuilder.build() + } + + @OptIn(UnstableApi::class) + private fun toMediaSource(mediaItem: MediaItem, streamVariant: StreamVariant) = + if (streamVariant.streamType == StreamType.DYNAMIC) + DashMediaSource.Factory(httpDataSourceFactory) + .createMediaSource(mediaItem) + else + ProgressiveMediaSource.Factory(httpDataSourceFactory) + .createMediaSource(mediaItem) + + + private suspend fun + addMetadata(mediaItem: MediaItem, item: String): MediaItem { + val mediaItemBuilder = mediaItem.buildUpon() + + try { + val metadata = repository.getMetaInfo(item) + mediaItemBuilder.setMediaMetadata(metadata) + } catch (e: Exception) { + mutableErrorFlow.emit(e) + } + + return mediaItemBuilder.build() + } +} \ No newline at end of file diff --git a/test-app/src/main/res/values/test_streams.xml b/test-app/src/main/res/values/test_streams.xml index d3548e8..5866be7 100644 --- a/test-app/src/main/res/values/test_streams.xml +++ b/test-app/src/main/res/values/test_streams.xml @@ -44,7 +44,7 @@ 23 - https://media.ccc.de/v/36c3-10694-intel_management_engine_deep_dive + https://media.ccc.de/v/36c3-10694-intel_management_engine_deep_dive https://ftp.fau.de/cdn.media.ccc.de/congress/2019/h264-hd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_hd.mp4 https://ftp.fau.de/cdn.media.ccc.de/congress/2019/h264-sd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_sd.mp4 https://ftp.fau.de/cdn.media.ccc.de/congress/2019/webm-hd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_webm-hd.webm @@ -64,4 +64,17 @@ https://cdn.media.ccc.de/congress/2019/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive.en.srt 3607 + + + + https://cloud.newpipe-ev.de/files/link/public/RyuyJKSUEzsHtwB + https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/fullhd.mp4 + https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/hd.mp4 + https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/sd.mp4 + https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/english.m4a + https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/spanish.m4a + Some YT Test video + A Channel on YT + 254 +