Trigger play/pause/resume/stop actions on VoiceRecorder

This commit is contained in:
Florian Renaud 2022-10-06 17:04:27 +02:00
parent fc58e25af4
commit a88a172f0f
9 changed files with 76 additions and 9 deletions

View File

@ -114,8 +114,13 @@ class AudioMessageHelper @Inject constructor(
* When entering in playback mode actually. * When entering in playback mode actually.
*/ */
fun pauseRecording() { fun pauseRecording() {
voiceRecorder.stopRecord() voiceRecorder.pauseRecord()
stopRecordingAmplitudes() pauseRecordingAmplitudes()
}
fun resumeRecording() {
voiceRecorder.resumeRecord()
resumeRecordingAmplitudes()
} }
fun deleteRecording() { fun deleteRecording() {
@ -221,6 +226,14 @@ class AudioMessageHelper @Inject constructor(
} }
} }
private fun pauseRecordingAmplitudes() {
amplitudeTicker?.pause()
}
private fun resumeRecordingAmplitudes() {
amplitudeTicker?.resume()
}
private fun stopRecordingAmplitudes() { private fun stopRecordingAmplitudes() {
amplitudeTicker?.stop() amplitudeTicker?.stop()
amplitudeTicker = null amplitudeTicker = null

View File

@ -32,7 +32,7 @@ abstract class AbstractVoiceRecorder(
) : VoiceRecorder { ) : VoiceRecorder {
private val outputDirectory: File by lazy { ensureAudioDirectory(context) } private val outputDirectory: File by lazy { ensureAudioDirectory(context) }
private var mediaRecorder: MediaRecorder? = null protected var mediaRecorder: MediaRecorder? = null
private var outputFile: File? = null private var outputFile: File? = null
abstract fun setOutputFormat(mediaRecorder: MediaRecorder) abstract fun setOutputFormat(mediaRecorder: MediaRecorder)
@ -79,8 +79,8 @@ abstract class AbstractVoiceRecorder(
} }
override fun stopRecord() { override fun stopRecord() {
// Can throw when the record is less than 1 second.
mediaRecorder?.let { mediaRecorder?.let {
// Can throw when the record is less than 1 second.
tryOrNull { it.stop() } tryOrNull { it.stop() }
it.reset() it.reset()
it.release() it.release()

View File

@ -34,6 +34,16 @@ interface VoiceRecorder {
*/ */
fun startRecord(roomId: String) fun startRecord(roomId: String)
/**
* Pause the recording.
*/
fun pauseRecord()
/**
* Resume the recording.
*/
fun resumeRecord()
/** /**
* Stop the recording. * Stop the recording.
*/ */

View File

@ -23,6 +23,7 @@ import android.media.MediaRecorder
import android.media.audiofx.AutomaticGainControl import android.media.audiofx.AutomaticGainControl
import android.media.audiofx.NoiseSuppressor import android.media.audiofx.NoiseSuppressor
import android.os.Build import android.os.Build
import android.widget.Toast
import io.element.android.opusencoder.OggOpusEncoder import io.element.android.opusencoder.OggOpusEncoder
import io.element.android.opusencoder.configuration.SampleRate import io.element.android.opusencoder.configuration.SampleRate
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -40,7 +41,7 @@ import kotlin.coroutines.CoroutineContext
* VoiceRecorder to be used on Android versions < [Build.VERSION_CODES.Q]. It uses libopus to record ogg files. * VoiceRecorder to be used on Android versions < [Build.VERSION_CODES.Q]. It uses libopus to record ogg files.
*/ */
class VoiceRecorderL( class VoiceRecorderL(
context: Context, private val context: Context,
coroutineContext: CoroutineContext, coroutineContext: CoroutineContext,
private val codec: OggOpusEncoder, private val codec: OggOpusEncoder,
) : VoiceRecorder { ) : VoiceRecorder {
@ -112,6 +113,14 @@ class VoiceRecorderL(
} }
} }
override fun pauseRecord() {
Toast.makeText(context, "Not implemented for this Android version", Toast.LENGTH_SHORT).show()
}
override fun resumeRecord() {
Toast.makeText(context, "Not implemented for this Android version", Toast.LENGTH_SHORT).show()
}
override fun stopRecord() { override fun stopRecord() {
val recorder = this.audioRecorder ?: return val recorder = this.audioRecorder ?: return
recordingJob?.cancel() recordingJob?.cancel()

View File

@ -20,12 +20,23 @@ import android.content.Context
import android.media.MediaRecorder import android.media.MediaRecorder
import android.os.Build import android.os.Build
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import org.matrix.android.sdk.api.extensions.tryOrNull
/** /**
* VoiceRecorder to be used on Android versions >= [Build.VERSION_CODES.Q]. It uses the native OPUS support on Android 10+. * VoiceRecorder to be used on Android versions >= [Build.VERSION_CODES.Q]. It uses the native OPUS support on Android 10+.
*/ */
@RequiresApi(Build.VERSION_CODES.Q) @RequiresApi(Build.VERSION_CODES.Q)
class VoiceRecorderQ(context: Context) : AbstractVoiceRecorder(context, "ogg") { class VoiceRecorderQ(context: Context) : AbstractVoiceRecorder(context, "ogg") {
override fun pauseRecord() {
// Can throw when the record is less than 1 second.
tryOrNull { mediaRecorder?.pause() }
}
override fun resumeRecord() {
mediaRecorder?.resume()
}
override fun setOutputFormat(mediaRecorder: MediaRecorder) { override fun setOutputFormat(mediaRecorder: MediaRecorder) {
// We can directly use OGG here // We can directly use OGG here
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.OGG) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.OGG)

View File

@ -16,6 +16,7 @@
package im.vector.app.features.voicebroadcast.usecase package im.vector.app.features.voicebroadcast.usecase
import im.vector.app.features.home.room.detail.composer.AudioMessageHelper
import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
@ -31,6 +32,7 @@ import javax.inject.Inject
class PauseVoiceBroadcastUseCase @Inject constructor( class PauseVoiceBroadcastUseCase @Inject constructor(
private val session: Session, private val session: Session,
private val audioMessageHelper: AudioMessageHelper,
) { ) {
suspend fun execute(roomId: String): Result<Unit> = runCatching { suspend fun execute(roomId: String): Result<Unit> = runCatching {
@ -60,6 +62,10 @@ class PauseVoiceBroadcastUseCase @Inject constructor(
).toContent(), ).toContent(),
) )
// TODO pause recording audio files pauseRecording()
}
private fun pauseRecording() {
audioMessageHelper.pauseRecording()
} }
} }

View File

@ -16,6 +16,7 @@
package im.vector.app.features.voicebroadcast.usecase package im.vector.app.features.voicebroadcast.usecase
import im.vector.app.features.home.room.detail.composer.AudioMessageHelper
import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
@ -31,6 +32,7 @@ import javax.inject.Inject
class ResumeVoiceBroadcastUseCase @Inject constructor( class ResumeVoiceBroadcastUseCase @Inject constructor(
private val session: Session, private val session: Session,
private val audioMessageHelper: AudioMessageHelper,
) { ) {
suspend fun execute(roomId: String): Result<Unit> = runCatching { suspend fun execute(roomId: String): Result<Unit> = runCatching {
@ -65,6 +67,10 @@ class ResumeVoiceBroadcastUseCase @Inject constructor(
).toContent(), ).toContent(),
) )
// TODO resume recording audio files resumeRecording()
}
private fun resumeRecording() {
audioMessageHelper.resumeRecording()
} }
} }

View File

@ -16,6 +16,7 @@
package im.vector.app.features.voicebroadcast.usecase package im.vector.app.features.voicebroadcast.usecase
import im.vector.app.features.home.room.detail.composer.AudioMessageHelper
import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
@ -30,6 +31,7 @@ import javax.inject.Inject
class StartVoiceBroadcastUseCase @Inject constructor( class StartVoiceBroadcastUseCase @Inject constructor(
private val session: Session, private val session: Session,
private val audioMessageHelper: AudioMessageHelper,
) { ) {
suspend fun execute(roomId: String): Result<Unit> = runCatching { suspend fun execute(roomId: String): Result<Unit> = runCatching {
@ -62,6 +64,10 @@ class StartVoiceBroadcastUseCase @Inject constructor(
).toContent() ).toContent()
) )
// TODO start recording audio files startRecording(room)
}
private fun startRecording(room: Room) {
audioMessageHelper.startRecording(room.roomId)
} }
} }

View File

@ -16,6 +16,7 @@
package im.vector.app.features.voicebroadcast.usecase package im.vector.app.features.voicebroadcast.usecase
import im.vector.app.features.home.room.detail.composer.AudioMessageHelper
import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
@ -31,6 +32,7 @@ import javax.inject.Inject
class StopVoiceBroadcastUseCase @Inject constructor( class StopVoiceBroadcastUseCase @Inject constructor(
private val session: Session, private val session: Session,
private val audioMessageHelper: AudioMessageHelper,
) { ) {
suspend fun execute(roomId: String): Result<Unit> = runCatching { suspend fun execute(roomId: String): Result<Unit> = runCatching {
@ -61,6 +63,10 @@ class StopVoiceBroadcastUseCase @Inject constructor(
).toContent(), ).toContent(),
) )
// TODO stop recording audio files stopRecording()
}
private fun stopRecording() {
audioMessageHelper.stopRecording()
} }
} }