Added very simple media player for audio files

This commit is contained in:
Sylvain Berfini 2024-05-06 14:34:41 +02:00
parent fde0ca60a1
commit 22254b7846
9 changed files with 127 additions and 13 deletions

View file

@ -38,6 +38,7 @@ class FileModel @AnyThread constructor(
val file: String,
val fileName: String,
val fileSize: Long,
val fileCreationTimestamp: Long,
private val isEncrypted: Boolean,
val isWaitingToBeDownloaded: Boolean = false,
private val onClicked: ((model: FileModel) -> Unit)? = null

View file

@ -370,9 +370,16 @@ class MessageModel @WorkerThread constructor(
)
val fileSize = content.fileSize.toLong()
val timestamp = -1L // TODO FIXME: use content.creationTimestamp
when (content.type) {
"image", "video" -> {
val fileModel = FileModel(path, name, fileSize, isFileEncrypted) { model ->
val fileModel = FileModel(
path,
name,
fileSize,
timestamp,
isFileEncrypted
) { model ->
onContentClicked?.invoke(model.file)
}
filesPath.add(fileModel)
@ -380,7 +387,13 @@ class MessageModel @WorkerThread constructor(
displayableContentFound = true
}
else -> {
val fileModel = FileModel(path, name, fileSize, isFileEncrypted) { model ->
val fileModel = FileModel(
path,
name,
fileSize,
timestamp,
isFileEncrypted
) { model ->
onContentClicked?.invoke(model.file)
}
filesPath.add(fileModel)
@ -398,14 +411,29 @@ class MessageModel @WorkerThread constructor(
allFilesDownloaded = false
filesContentCount += 1
val name = content.name ?: ""
val timestamp = -1L // TODO FIXME: use content.creationTimestamp
if (name.isNotEmpty()) {
val fileModel = if (isOutgoing && chatMessage.isFileTransferInProgress) {
val path = content.filePath ?: ""
FileModel(path, name, content.fileSize.toLong(), isFileEncrypted, false) { model ->
FileModel(
path,
name,
content.fileSize.toLong(),
timestamp,
isFileEncrypted,
false
) { model ->
onContentClicked?.invoke(model.file)
}
} else {
FileModel(name, name, content.fileSize.toLong(), isFileEncrypted, true) { model ->
FileModel(
name,
name,
content.fileSize.toLong(),
timestamp,
isFileEncrypted,
true
) { model ->
downloadContent(model, content)
}
}

View file

@ -72,8 +72,9 @@ class ConversationDocumentsListViewModel @UiThread constructor() : AbstractConve
}
val name = documentContent.name.orEmpty()
val size = documentContent.size.toLong()
val timestamp = -1L // TODO FIXME: use documentContent.creationTimestamp
if (path.isNotEmpty() && name.isNotEmpty()) {
val model = FileModel(path, name, size, isEncrypted) {
val model = FileModel(path, name, size, timestamp, isEncrypted) {
openDocumentEvent.postValue(Event(it))
}
list.add(model)

View file

@ -76,8 +76,9 @@ class ConversationMediaListViewModel @UiThread constructor() : AbstractConversat
}
val name = mediaContent.name.orEmpty()
val size = mediaContent.size.toLong()
val timestamp = -1L // TODO FIXME: use mediaContent.creationTimestamp
if (path.isNotEmpty() && name.isNotEmpty()) {
val model = FileModel(path, name, size, isEncrypted) {
val model = FileModel(path, name, size, timestamp, isEncrypted) {
openMediaEvent.postValue(Event(it))
}
list.add(model)

View file

@ -324,7 +324,8 @@ class SendMessageInConversationViewModel @UiThread constructor() : ViewModel() {
list.addAll(attachments.value.orEmpty())
val fileName = FileUtils.getNameFromFilePath(file)
val model = FileModel(file, fileName, 0, isEncrypted = false) { model ->
val timestamp = System.currentTimeMillis() / 1000
val model = FileModel(file, fileName, 0, timestamp, isEncrypted = false) { model ->
removeAttachment(model.file)
}

View file

@ -77,12 +77,7 @@ class MediaViewerFragment : GenericFragment() {
viewModel.isVideo.observe(viewLifecycleOwner) { isVideo ->
if (isVideo) {
Log.i("$TAG Creating video player for file [$path]")
binding.videoPlayer.setVideoPath(path)
binding.videoPlayer.setOnCompletionListener {
Log.i("$TAG End of file reached")
viewModel.isVideoPlaying.value = false
}
initVideoPlayer(path)
}
}
@ -124,6 +119,11 @@ class MediaViewerFragment : GenericFragment() {
viewModel.isVideoPlaying.value = false
}
if (viewModel.isAudioPlaying.value == true) {
Log.i("$TAG Paused, stopping audio player")
viewModel.pauseAudio()
}
super.onPause()
}
@ -132,4 +132,13 @@ class MediaViewerFragment : GenericFragment() {
super.onDestroyView()
}
private fun initVideoPlayer(path: String) {
Log.i("$TAG Creating video player for file [$path]")
binding.videoPlayer.setVideoPath(path)
binding.videoPlayer.setOnCompletionListener {
Log.i("$TAG End of file reached")
viewModel.isVideoPlaying.value = false
}
}
}

View file

@ -19,6 +19,8 @@
*/
package org.linphone.ui.main.file_media_viewer.viewmodel
import android.media.AudioAttributes
import android.media.MediaPlayer
import androidx.annotation.UiThread
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@ -45,12 +47,24 @@ class MediaViewModel @UiThread constructor() : ViewModel() {
val isAudio = MutableLiveData<Boolean>()
val isAudioPlaying = MutableLiveData<Boolean>()
val toggleVideoPlayPauseEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
private lateinit var filePath: String
private lateinit var mediaPlayer: MediaPlayer
override fun onCleared() {
if (::mediaPlayer.isInitialized) {
mediaPlayer.release()
}
super.onCleared()
}
@UiThread
fun loadFile(file: String) {
filePath = file
@ -73,6 +87,8 @@ class MediaViewModel @UiThread constructor() : ViewModel() {
FileUtils.MimeType.Audio -> {
Log.i("$TAG File [$file] seems to be an audio file")
isAudio.value = true
initMediaPlayer()
}
else -> { }
}
@ -89,4 +105,45 @@ class MediaViewModel @UiThread constructor() : ViewModel() {
isVideoPlaying.value = playVideo
toggleVideoPlayPauseEvent.value = Event(playVideo)
}
@UiThread
fun playPauseAudio() {
if (::mediaPlayer.isInitialized) {
if (mediaPlayer.isPlaying) {
mediaPlayer.pause()
isAudioPlaying.value = false
} else {
mediaPlayer.start()
isAudioPlaying.value = true
}
}
}
@UiThread
fun pauseAudio() {
if (::mediaPlayer.isInitialized) {
mediaPlayer.pause()
}
}
@UiThread
private fun initMediaPlayer() {
isAudioPlaying.value = false
mediaPlayer = MediaPlayer().apply {
setAudioAttributes(
AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).setUsage(
AudioAttributes.USAGE_MEDIA
).build()
)
setDataSource(filePath)
setOnCompletionListener {
Log.i("$TAG Media player reached the end of file")
isAudioPlaying.postValue(false)
}
prepare()
start()
isAudioPlaying.value = true
}
Log.i("$TAG Media player for file [$filePath] created")
}
}

View file

@ -16,6 +16,21 @@
android:layout_height="match_parent"
android:background="@color/black">
<ImageView
android:id="@+id/play_pause_audio_playback"
android:onClick="@{() -> viewModel.playPauseAudio()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:contentDescription="@string/content_description_play_pause_video_playback"
android:src="@{viewModel.isAudioPlaying ? @drawable/pause_fill : @drawable/play_fill, default=@drawable/play_fill}"
android:visibility="@{viewModel.isAudio ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:tint="@color/white"/>
<VideoView
android:id="@+id/video_player"
android:layout_width="0dp"

View file

@ -719,6 +719,7 @@
<string name="content_description_conference_participant_muted">Participant is muted</string>
<string name="content_description_conference_participant_speaking">Participant is speaking</string>
<string name="content_description_add_participants">Add participants</string>
<string name="content_description_play_pause_audio_playback">Plays/pauses the audio playback</string>
<string name="content_description_play_pause_video_playback">Plays/pauses the video playback</string>
<string name="content_description_share_file">Share file</string>
<string name="content_description_save_file">Save file</string>