mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 03:18:06 +00:00
Added very simple media player for audio files
This commit is contained in:
parent
fde0ca60a1
commit
22254b7846
9 changed files with 127 additions and 13 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue