diff --git a/video/app/src/main/AndroidManifest.xml b/video/app/src/main/AndroidManifest.xml index ad55630ca3..cde6d6b0b6 100644 --- a/video/app/src/main/AndroidManifest.xml +++ b/video/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - - @@ -16,7 +15,6 @@ @@ -24,6 +22,14 @@ + + \ No newline at end of file diff --git a/video/app/src/main/java/org/thoughtcrime/video/app/MainActivity.kt b/video/app/src/main/java/org/thoughtcrime/video/app/MainActivity.kt index 267299b1f7..909d767860 100644 --- a/video/app/src/main/java/org/thoughtcrime/video/app/MainActivity.kt +++ b/video/app/src/main/java/org/thoughtcrime/video/app/MainActivity.kt @@ -5,43 +5,36 @@ package org.thoughtcrime.video.app +import android.content.Intent +import android.content.pm.ActivityInfo +import android.content.pm.PackageManager +import android.content.pm.PackageManager.NameNotFoundException import android.os.Bundle import android.util.Log -import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.result.PickVisualMediaRequest -import androidx.activity.result.contract.ActivityResultContracts -import androidx.activity.viewModels -import androidx.annotation.OptIn +import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.viewinterop.AndroidView -import androidx.media3.common.util.UnstableApi -import androidx.media3.exoplayer.ExoPlayer -import androidx.media3.exoplayer.source.MediaSource -import androidx.media3.ui.PlayerView +import org.thoughtcrime.video.app.playback.PlaybackTestActivity +import org.thoughtcrime.video.app.transcode.TranscodeTestActivity +import org.thoughtcrime.video.app.ui.composables.LabeledButton import org.thoughtcrime.video.app.ui.theme.SignalTheme + /** * Main activity for this sample app. */ -class MainActivity : ComponentActivity() { - private val viewModel: MainScreenViewModel by viewModels() - private lateinit var exoPlayer: ExoPlayer +class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - viewModel.initialize(this) - exoPlayer = ExoPlayer.Builder(this).build() + val startPlaybackScreen = Intent(this, PlaybackTestActivity::class.java) + val startTranscodeScreen = Intent(this, TranscodeTestActivity::class.java) setContent { SignalTheme { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { @@ -49,70 +42,11 @@ class MainActivity : ComponentActivity() { verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - val videoUri = viewModel.selectedVideo - if (videoUri == null) { - LabeledButton("Select Video") { pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.VideoOnly)) } - } else { - LabeledButton("Play Video") { viewModel.updateMediaSource(this@MainActivity) } - LabeledButton("Play Video with slow download") { viewModel.updateMediaSourceTrickle(this@MainActivity) } - ExoVideoView(source = viewModel.mediaSource, exoPlayer = exoPlayer) - } + LabeledButton("Test Playback") { startActivity(startPlaybackScreen) } + LabeledButton("Test Transcode") { startActivity(startTranscodeScreen) } } } } } } - - override fun onPause() { - super.onPause() - exoPlayer.pause() - } - - override fun onDestroy() { - super.onDestroy() - viewModel.releaseCache() - exoPlayer.stop() - exoPlayer.release() - } - - /** - * This launches the system media picker and stores the resulting URI. - */ - private val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> - if (uri != null) { - Log.d("PhotoPicker", "Selected URI: $uri") - viewModel.selectedVideo = uri - viewModel.updateMediaSource(this) - } else { - Log.d("PhotoPicker", "No media selected") - } - } -} - -@Composable -fun LabeledButton(buttonLabel: String, modifier: Modifier = Modifier, onClick: () -> Unit) { - Button(onClick = onClick, modifier = modifier) { - Text(buttonLabel) - } -} - -@OptIn(UnstableApi::class) -@Composable -fun ExoVideoView(source: MediaSource, exoPlayer: ExoPlayer, modifier: Modifier = Modifier) { - exoPlayer.playWhenReady = false - exoPlayer.setMediaSource(source) - exoPlayer.prepare() - AndroidView(factory = { context -> - PlayerView(context).apply { - player = exoPlayer - } - }, modifier = modifier) -} - -@Preview(showBackground = true) -@Composable -fun GreetingPreview() { - SignalTheme { - LabeledButton("Preview Render") {} - } -} +} \ No newline at end of file diff --git a/video/app/src/main/java/org/thoughtcrime/video/app/playback/PlaybackTestActivity.kt b/video/app/src/main/java/org/thoughtcrime/video/app/playback/PlaybackTestActivity.kt new file mode 100644 index 0000000000..c88b739de3 --- /dev/null +++ b/video/app/src/main/java/org/thoughtcrime/video/app/playback/PlaybackTestActivity.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.video.app.playback + +import android.os.Bundle +import android.util.Log +import androidx.activity.compose.setContent +import androidx.activity.result.PickVisualMediaRequest +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels +import androidx.annotation.OptIn +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.viewinterop.AndroidView +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.source.MediaSource +import androidx.media3.ui.PlayerView +import org.thoughtcrime.video.app.ui.composables.LabeledButton +import org.thoughtcrime.video.app.ui.theme.SignalTheme + +class PlaybackTestActivity : AppCompatActivity() { + private val viewModel: PlaybackTestViewModel by viewModels() + private lateinit var exoPlayer: ExoPlayer + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewModel.initialize(this) + exoPlayer = ExoPlayer.Builder(this).build() + setContent { + SignalTheme { + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + val videoUri = viewModel.selectedVideo + if (videoUri == null) { + LabeledButton("Select Video") { pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.VideoOnly)) } + } else { + LabeledButton("Play Video") { viewModel.updateMediaSource(this@PlaybackTestActivity) } + LabeledButton("Play Video with slow download") { viewModel.updateMediaSourceTrickle(this@PlaybackTestActivity) } + ExoVideoView(source = viewModel.mediaSource, exoPlayer = exoPlayer) + } + } + } + } + } + } + + override fun onPause() { + super.onPause() + exoPlayer.pause() + } + + override fun onDestroy() { + super.onDestroy() + viewModel.releaseCache() + exoPlayer.stop() + exoPlayer.release() + } + + /** + * This launches the system media picker and stores the resulting URI. + */ + private val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> + if (uri != null) { + Log.d("PhotoPicker", "Selected URI: $uri") + viewModel.selectedVideo = uri + viewModel.updateMediaSource(this) + } else { + Log.d("PhotoPicker", "No media selected") + } + } +} + + +@OptIn(UnstableApi::class) +@Composable +fun ExoVideoView(source: MediaSource, exoPlayer: ExoPlayer, modifier: Modifier = Modifier) { + exoPlayer.playWhenReady = false + exoPlayer.setMediaSource(source) + exoPlayer.prepare() + AndroidView(factory = { context -> + PlayerView(context).apply { + player = exoPlayer + } + }, modifier = modifier) +} + +@Preview(showBackground = true) +@Composable +fun GreetingPreview() { + SignalTheme { + LabeledButton("Preview Render") {} + } +} \ No newline at end of file diff --git a/video/app/src/main/java/org/thoughtcrime/video/app/MainScreenViewModel.kt b/video/app/src/main/java/org/thoughtcrime/video/app/playback/PlaybackTestViewModel.kt similarity index 96% rename from video/app/src/main/java/org/thoughtcrime/video/app/MainScreenViewModel.kt rename to video/app/src/main/java/org/thoughtcrime/video/app/playback/PlaybackTestViewModel.kt index a91d6590e3..408ac35df0 100644 --- a/video/app/src/main/java/org/thoughtcrime/video/app/MainScreenViewModel.kt +++ b/video/app/src/main/java/org/thoughtcrime/video/app/playback/PlaybackTestViewModel.kt @@ -1,9 +1,9 @@ /* - * Copyright 2023 Signal Messenger, LLC + * Copyright 2024 Signal Messenger, LLC * SPDX-License-Identifier: AGPL-3.0-only */ -package org.thoughtcrime.video.app +package org.thoughtcrime.video.app.playback import android.content.Context import android.net.Uri @@ -28,7 +28,7 @@ import java.io.File * Main screen view model for the video sample app. */ @OptIn(UnstableApi::class) -class MainScreenViewModel : ViewModel() { +class PlaybackTestViewModel : ViewModel() { // Initialize an silent media source before the user selects a video. This is the closest I could find to an "empty" media source while still being nullsafe. private val value by lazy { val factory = SilenceMediaSource.Factory() diff --git a/video/app/src/main/java/org/thoughtcrime/video/app/SlowDataSource.kt b/video/app/src/main/java/org/thoughtcrime/video/app/playback/SlowDataSource.kt similarity index 95% rename from video/app/src/main/java/org/thoughtcrime/video/app/SlowDataSource.kt rename to video/app/src/main/java/org/thoughtcrime/video/app/playback/SlowDataSource.kt index 5406e1e156..887f6f8e4b 100644 --- a/video/app/src/main/java/org/thoughtcrime/video/app/SlowDataSource.kt +++ b/video/app/src/main/java/org/thoughtcrime/video/app/playback/SlowDataSource.kt @@ -1,9 +1,9 @@ /* - * Copyright 2023 Signal Messenger, LLC + * Copyright 2024 Signal Messenger, LLC * SPDX-License-Identifier: AGPL-3.0-only */ -package org.thoughtcrime.video.app +package org.thoughtcrime.video.app.playback import android.content.Context import android.net.Uri diff --git a/video/app/src/main/java/org/thoughtcrime/video/app/transcode/TranscodeTestActivity.kt b/video/app/src/main/java/org/thoughtcrime/video/app/transcode/TranscodeTestActivity.kt new file mode 100644 index 0000000000..d4416c562d --- /dev/null +++ b/video/app/src/main/java/org/thoughtcrime/video/app/transcode/TranscodeTestActivity.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.video.app.transcode + +import androidx.appcompat.app.AppCompatActivity + +class TranscodeTestActivity : AppCompatActivity() { +} \ No newline at end of file diff --git a/video/app/src/main/java/org/thoughtcrime/video/app/ui/composables/LabeledButton.kt b/video/app/src/main/java/org/thoughtcrime/video/app/ui/composables/LabeledButton.kt new file mode 100644 index 0000000000..f03647feef --- /dev/null +++ b/video/app/src/main/java/org/thoughtcrime/video/app/ui/composables/LabeledButton.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.video.app.ui.composables + +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun LabeledButton(buttonLabel: String, modifier: Modifier = Modifier, onClick: () -> Unit) { + Button(onClick = onClick, modifier = modifier) { + Text(buttonLabel) + } +} \ No newline at end of file diff --git a/video/app/src/main/res/values/strings.xml b/video/app/src/main/res/values/strings.xml index 06af607989..ffbef093bf 100644 --- a/video/app/src/main/res/values/strings.xml +++ b/video/app/src/main/res/values/strings.xml @@ -4,5 +4,5 @@ --> - Video Player + Video Framework Tester \ No newline at end of file diff --git a/video/app/src/main/res/values/themes.xml b/video/app/src/main/res/values/themes.xml index 35ed1d0bff..b51e9d97da 100644 --- a/video/app/src/main/res/values/themes.xml +++ b/video/app/src/main/res/values/themes.xml @@ -6,5 +6,5 @@ -