Revert audio editor code
This commit is contained in:
parent
4b1c045676
commit
60eda663a3
13 changed files with 144 additions and 879 deletions
|
@ -100,7 +100,5 @@ dependencies {
|
||||||
implementation(libs.androidx.swiperefreshlayout)
|
implementation(libs.androidx.swiperefreshlayout)
|
||||||
implementation(libs.androidx.constraintlayout)
|
implementation(libs.androidx.constraintlayout)
|
||||||
implementation(libs.tandroidlame)
|
implementation(libs.tandroidlame)
|
||||||
//implementation(libs.bundles.audiotool)
|
|
||||||
//implementation(libs.bundles.amplituda)
|
|
||||||
implementation(libs.autofittextview)
|
implementation(libs.autofittextview)
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,8 +77,6 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".activities.EditRecordingActivity" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.SettingsActivity"
|
android:name=".activities.SettingsActivity"
|
||||||
android:configChanges="orientation"
|
android:configChanges="orientation"
|
||||||
|
|
|
@ -1,428 +0,0 @@
|
||||||
package com.simplemobiletools.voicerecorder.activities
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.media.AudioManager
|
|
||||||
import android.media.MediaPlayer
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.os.PowerManager
|
|
||||||
import android.provider.DocumentsContract
|
|
||||||
import android.widget.SeekBar
|
|
||||||
import androidx.core.view.children
|
|
||||||
import com.simplemobiletools.commons.extensions.*
|
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
|
||||||
import com.simplemobiletools.voicerecorder.R
|
|
||||||
import com.simplemobiletools.voicerecorder.databinding.ActivityEditRecordingBinding
|
|
||||||
import com.simplemobiletools.voicerecorder.extensions.getAllRecordings
|
|
||||||
import com.simplemobiletools.voicerecorder.helpers.getAudioFileContentUri
|
|
||||||
import com.simplemobiletools.voicerecorder.models.Recording
|
|
||||||
import java.io.File
|
|
||||||
import java.util.Timer
|
|
||||||
import java.util.TimerTask
|
|
||||||
|
|
||||||
class EditRecordingActivity : SimpleActivity() {
|
|
||||||
companion object {
|
|
||||||
const val RECORDING_ID = "recording_id"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var player: MediaPlayer? = null
|
|
||||||
private var progressTimer = Timer()
|
|
||||||
private lateinit var recording: Recording
|
|
||||||
private lateinit var currentRecording: Recording
|
|
||||||
private var progressStart: Float = 0f
|
|
||||||
|
|
||||||
private lateinit var binding: ActivityEditRecordingBinding
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
isMaterialActivity = true
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
binding = ActivityEditRecordingBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
setupOptionsMenu()
|
|
||||||
|
|
||||||
updateMaterialActivityViews(binding.mainCoordinator, binding.recordingVisualizer, useTransparentNavigation = false, useTopSearchMenu = false)
|
|
||||||
|
|
||||||
val recordingId = intent.getIntExtra(RECORDING_ID, -1)
|
|
||||||
if (recordingId == -1) {
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
recording = getAllRecordings().first { it.id == recordingId }
|
|
||||||
currentRecording = recording
|
|
||||||
// AudioTool.getInstance(this)
|
|
||||||
// .withAudio(File(recording.path))
|
|
||||||
// .cutAudio("00:00:00", "00:00:00.250") {}
|
|
||||||
// .saveCurrentTo(recording.path)
|
|
||||||
// .release()
|
|
||||||
|
|
||||||
// binding.recordingVisualizer.waveProgressColor = getProperPrimaryColor()
|
|
||||||
// binding.recordingVisualizer.setSampleFrom(recording.path)
|
|
||||||
binding.recordingVisualizer.chunkColor = getProperPrimaryColor()
|
|
||||||
binding.recordingVisualizer.recreate()
|
|
||||||
binding.recordingVisualizer.editListener = {
|
|
||||||
if (binding.recordingVisualizer.startPosition >= 0f) {
|
|
||||||
binding.settingsToolbar.menu.children.forEach { it.isVisible = true }
|
|
||||||
} else {
|
|
||||||
binding.settingsToolbar.menu.children.forEach { it.isVisible = false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateVisualization()
|
|
||||||
// android.media.MediaCodec.createByCodecName().createInputSurface()
|
|
||||||
// binding.recordingVisualizer.update()
|
|
||||||
|
|
||||||
initMediaPlayer()
|
|
||||||
playRecording(recording.path, recording.id, recording.title, recording.duration, false)
|
|
||||||
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setOnClickListener {
|
|
||||||
togglePlayPause()
|
|
||||||
}
|
|
||||||
setupColors()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateVisualization() {
|
|
||||||
/*Amplituda(this).apply {
|
|
||||||
try {
|
|
||||||
val uri = Uri.parse(currentRecording.path)
|
|
||||||
|
|
||||||
fun handleAmplitudes(amplitudaResult: AmplitudaResult<*>) {
|
|
||||||
binding.recordingVisualizer.recreate()
|
|
||||||
binding.recordingVisualizer.clearEditing()
|
|
||||||
binding.recordingVisualizer.putAmplitudes(amplitudaResult.amplitudesAsList())
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
DocumentsContract.isDocumentUri(this@EditRecordingActivity, uri) -> {
|
|
||||||
processAudio(contentResolver.openInputStream(uri)).get(AmplitudaSuccessListener {
|
|
||||||
handleAmplitudes(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
currentRecording.path.isEmpty() -> {
|
|
||||||
processAudio(contentResolver.openInputStream(getAudioFileContentUri(currentRecording.id.toLong()))).get(AmplitudaSuccessListener {
|
|
||||||
handleAmplitudes(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
processAudio(currentRecording.path).get(AmplitudaSuccessListener {
|
|
||||||
handleAmplitudes(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupColors() {
|
|
||||||
val properPrimaryColor = getProperPrimaryColor()
|
|
||||||
updateTextColors(binding.mainCoordinator)
|
|
||||||
|
|
||||||
val textColor = getProperTextColor()
|
|
||||||
arrayListOf(binding.playerControlsWrapper.previousBtn, binding.playerControlsWrapper.nextBtn).forEach {
|
|
||||||
it.applyColorFilter(textColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.background.applyColorFilter(properPrimaryColor)
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupOptionsMenu() {
|
|
||||||
binding.settingsToolbar.inflateMenu(R.menu.menu_edit)
|
|
||||||
// binding.settingsToolbar.toggleHideOnScroll(false)
|
|
||||||
// binding.settingsToolbar.setupMenu()
|
|
||||||
|
|
||||||
// binding.settingsToolbar.onSearchOpenListener = {
|
|
||||||
// if (binding.viewPager.currentItem == 0) {
|
|
||||||
// binding.viewPager.currentItem = 1
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// binding.settingsToolbar.onSearchTextChangedListener = { text ->
|
|
||||||
// getPagerAdapter()?.searchTextChanged(text)
|
|
||||||
// }
|
|
||||||
|
|
||||||
binding.settingsToolbar.menu.children.forEach { it.isVisible = false }
|
|
||||||
binding.settingsToolbar.setOnMenuItemClickListener { menuItem ->
|
|
||||||
when (menuItem.itemId) {
|
|
||||||
R.id.play -> {
|
|
||||||
val start = binding.recordingVisualizer.startPosition
|
|
||||||
val end = binding.recordingVisualizer.endPosition
|
|
||||||
|
|
||||||
val startMillis = start * currentRecording.duration
|
|
||||||
val durationMillis = (end - start) * currentRecording.duration
|
|
||||||
val startMillisPart = String.format("%.3f", startMillis - startMillis.toInt()).replace("0.", "")
|
|
||||||
val durationMillisPart = String.format("%.3f", durationMillis - durationMillis.toInt()).replace("0.", "")
|
|
||||||
val startFormatted = (startMillis.toInt()).getFormattedDuration(true) + ".$startMillisPart"
|
|
||||||
val durationFormatted = (durationMillis.toInt()).getFormattedDuration(true) + ".$durationMillisPart"
|
|
||||||
/*modifyAudioFile(currentRecording)
|
|
||||||
.cutAudio(startFormatted, durationFormatted) {
|
|
||||||
progressStart = binding.recordingVisualizer.startPosition
|
|
||||||
playRecording(it.path, null, it.name, durationMillis.toInt(), true)
|
|
||||||
}
|
|
||||||
.release()*/
|
|
||||||
// playRecording()
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.cut -> {
|
|
||||||
val start = binding.recordingVisualizer.startPosition
|
|
||||||
val end = binding.recordingVisualizer.endPosition
|
|
||||||
|
|
||||||
val startMillis = start * currentRecording.duration
|
|
||||||
val endMillis = end * currentRecording.duration
|
|
||||||
val realEnd = (1 - end) * currentRecording.duration
|
|
||||||
val startMillisPart = String.format("%.3f", startMillis - startMillis.toInt()).replace("0.", "")
|
|
||||||
val endMillisPart = String.format("%.3f", endMillis - endMillis.toInt()).replace("0.", "")
|
|
||||||
val realEndMillisPart = String.format("%.3f", realEnd - realEnd.toInt()).replace("0.", "")
|
|
||||||
val startFormatted = (startMillis.toInt()).getFormattedDuration(true) + ".$startMillisPart"
|
|
||||||
val endFormatted = (endMillis.toInt()).getFormattedDuration(true) + ".$endMillisPart"
|
|
||||||
val realEndFormatted = (realEnd.toInt()).getFormattedDuration(true) + ".$realEndMillisPart"
|
|
||||||
|
|
||||||
var leftPart: File? = null
|
|
||||||
var rightPart: File? = null
|
|
||||||
|
|
||||||
fun merge() {
|
|
||||||
if (leftPart != null && rightPart != null) {
|
|
||||||
ensureBackgroundThread {
|
|
||||||
val tempFile =
|
|
||||||
File.createTempFile("${currentRecording.title}.edit.", ".${currentRecording.title.getFilenameExtension()}", cacheDir)
|
|
||||||
/*AudioTool.getInstance(this)
|
|
||||||
.joinAudios(arrayOf(leftPart, rightPart), tempFile.path) {
|
|
||||||
runOnUiThread {
|
|
||||||
currentRecording = Recording(
|
|
||||||
-1,
|
|
||||||
it.name,
|
|
||||||
it.path,
|
|
||||||
it.lastModified().toInt(),
|
|
||||||
(startMillis + realEnd).toInt(),
|
|
||||||
it.getProperSize(false).toInt()
|
|
||||||
)
|
|
||||||
updateVisualization()
|
|
||||||
playRecording(currentRecording.path, currentRecording.id, currentRecording.title, currentRecording.duration, true)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*modifyAudioFile(currentRecording)
|
|
||||||
.cutAudio("00:00:00", startFormatted) {
|
|
||||||
leftPart = it
|
|
||||||
merge()
|
|
||||||
}
|
|
||||||
modifyAudioFile(currentRecording)
|
|
||||||
.cutAudio(endFormatted, realEndFormatted) {
|
|
||||||
rightPart = it
|
|
||||||
merge()
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
// R.id.save -> {
|
|
||||||
// binding.recordingVisualizer.clearEditing()
|
|
||||||
// currentRecording = recording
|
|
||||||
// playRecording(currentRecording.path, currentRecording.id, currentRecording.title, currentRecording.duration, true)
|
|
||||||
// }
|
|
||||||
R.id.clear -> {
|
|
||||||
progressStart = 0f
|
|
||||||
binding.recordingVisualizer.clearEditing()
|
|
||||||
playRecording(currentRecording.path, currentRecording.id, currentRecording.title, currentRecording.duration, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.reset -> {
|
|
||||||
progressStart = 0f
|
|
||||||
binding.recordingVisualizer.clearEditing()
|
|
||||||
currentRecording = recording
|
|
||||||
updateVisualization()
|
|
||||||
playRecording(currentRecording.path, currentRecording.id, currentRecording.title, currentRecording.duration, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> return@setOnMenuItemClickListener false
|
|
||||||
}
|
|
||||||
return@setOnMenuItemClickListener true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initMediaPlayer() {
|
|
||||||
player = MediaPlayer().apply {
|
|
||||||
setWakeMode(this@EditRecordingActivity, PowerManager.PARTIAL_WAKE_LOCK)
|
|
||||||
setAudioStreamType(AudioManager.STREAM_MUSIC)
|
|
||||||
|
|
||||||
setOnCompletionListener {
|
|
||||||
progressTimer.cancel()
|
|
||||||
binding.playerControlsWrapper.playerProgressbar.progress = binding.playerControlsWrapper.playerProgressbar.max
|
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.text = binding.playerControlsWrapper.playerProgressMax.text
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
|
||||||
}
|
|
||||||
|
|
||||||
setOnPreparedListener {
|
|
||||||
// setupProgressTimer()
|
|
||||||
// player?.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun playRecording(path: String, id: Int?, title: String?, duration: Int?, playOnPrepared: Boolean) {
|
|
||||||
resetProgress(title, duration)
|
|
||||||
// (binding.recordingsList.adapter as RecordingsAdapter).updateCurrentRecording(recording.id)
|
|
||||||
// playOnPreparation = playOnPrepared
|
|
||||||
|
|
||||||
player!!.apply {
|
|
||||||
reset()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val uri = Uri.parse(path)
|
|
||||||
when {
|
|
||||||
DocumentsContract.isDocumentUri(this@EditRecordingActivity, uri) -> {
|
|
||||||
setDataSource(this@EditRecordingActivity, uri)
|
|
||||||
}
|
|
||||||
|
|
||||||
path.isEmpty() -> {
|
|
||||||
setDataSource(this@EditRecordingActivity, getAudioFileContentUri(id?.toLong() ?: 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
setDataSource(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
prepareAsync()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
|
||||||
binding.playerControlsWrapper.playerProgressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
|
||||||
if (fromUser) {
|
|
||||||
player?.seekTo(progress * 1000)
|
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.text = progress.getFormattedDuration()
|
|
||||||
resumePlayback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartTrackingTouch(seekBar: SeekBar) {}
|
|
||||||
|
|
||||||
override fun onStopTrackingTouch(seekBar: SeekBar) {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupProgressTimer() {
|
|
||||||
progressTimer.cancel()
|
|
||||||
progressTimer = Timer()
|
|
||||||
progressTimer.scheduleAtFixedRate(getProgressUpdateTask(), 100, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getProgressUpdateTask() = object : TimerTask() {
|
|
||||||
override fun run() {
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
if (player != null) {
|
|
||||||
binding.recordingVisualizer.updateProgress(player!!.currentPosition.toFloat() / (currentRecording.duration * 1000) + progressStart)
|
|
||||||
val progress = Math.round(player!!.currentPosition / 1000.toDouble()).toInt()
|
|
||||||
updateCurrentProgress(progress)
|
|
||||||
binding.playerControlsWrapper.playerProgressbar.progress = progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateCurrentProgress(seconds: Int) {
|
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.text = seconds.getFormattedDuration()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resetProgress(title: String?, duration: Int?) {
|
|
||||||
updateCurrentProgress(0)
|
|
||||||
binding.playerControlsWrapper.playerProgressbar.progress = 0
|
|
||||||
binding.playerControlsWrapper.playerProgressbar.max = duration ?: 0
|
|
||||||
binding.playerControlsWrapper.playerTitle.text = title ?: ""
|
|
||||||
binding.playerControlsWrapper.playerProgressMax.text = (duration ?: 0).getFormattedDuration()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun togglePlayPause() {
|
|
||||||
if (getIsPlaying()) {
|
|
||||||
pausePlayback()
|
|
||||||
} else {
|
|
||||||
resumePlayback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun pausePlayback() {
|
|
||||||
player?.pause()
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
|
||||||
progressTimer.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resumePlayback() {
|
|
||||||
player?.start()
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(true))
|
|
||||||
setupProgressTimer()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getToggleButtonIcon(isPlaying: Boolean): Drawable {
|
|
||||||
val drawable = if (isPlaying) com.simplemobiletools.commons.R.drawable.ic_pause_vector else com.simplemobiletools.commons.R.drawable.ic_play_vector
|
|
||||||
return resources.getColoredDrawableWithColor(drawable, getProperPrimaryColor().getContrastColor())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun skip(forward: Boolean) {
|
|
||||||
// val curr = player?.currentPosition ?: return
|
|
||||||
// var newProgress = if (forward) curr + FAST_FORWARD_SKIP_MS else curr - FAST_FORWARD_SKIP_MS
|
|
||||||
// if (newProgress > player!!.duration) {
|
|
||||||
// newProgress = player!!.duration
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// player!!.seekTo(newProgress)
|
|
||||||
// resumePlayback()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getIsPlaying() = player?.isPlaying == true
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*private fun modifyAudioFile(recording: Recording): AudioTool {
|
|
||||||
return AudioTool.getInstance(this)
|
|
||||||
.withAudio(copyToTempFile(recording))
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private fun copyToTempFile(recording: Recording): File {
|
|
||||||
try {
|
|
||||||
val uri = Uri.parse(recording.path)
|
|
||||||
|
|
||||||
when {
|
|
||||||
DocumentsContract.isDocumentUri(this@EditRecordingActivity, uri) -> {
|
|
||||||
val tempFile = File.createTempFile(recording.title, ".${recording.title.getFilenameExtension()}", cacheDir)
|
|
||||||
contentResolver.openInputStream(uri)?.copyTo(tempFile.outputStream())
|
|
||||||
return tempFile
|
|
||||||
}
|
|
||||||
|
|
||||||
recording.path.isEmpty() -> {
|
|
||||||
val tempFile = File.createTempFile(recording.title, ".${recording.title.getFilenameExtension()}", cacheDir)
|
|
||||||
contentResolver.openInputStream(getAudioFileContentUri(recording.id.toLong()))?.copyTo(tempFile.outputStream())
|
|
||||||
return tempFile
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
return File(recording.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
return File(recording.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -280,13 +280,6 @@ class RecordingsAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*R.id.cab_edit -> {
|
|
||||||
Intent(activity, EditRecordingActivity::class.java).apply {
|
|
||||||
putExtra(EditRecordingActivity.RECORDING_ID, recordingId)
|
|
||||||
activity.startActivity(this)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
R.id.cab_delete -> {
|
R.id.cab_delete -> {
|
||||||
executeItemMenuOperation(recordingId, removeAfterCallback = false) {
|
executeItemMenuOperation(recordingId, removeAfterCallback = false) {
|
||||||
askConfirmDelete()
|
askConfirmDelete()
|
||||||
|
|
|
@ -84,23 +84,23 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
binding.playerControlsWrapper.playPauseBtn.setOnClickListener {
|
binding.playPauseBtn.setOnClickListener {
|
||||||
if (playedRecordingIDs.empty() || binding.playerControlsWrapper.playerProgressbar.max == 0) {
|
if (playedRecordingIDs.empty() || binding.playerProgressbar.max == 0) {
|
||||||
binding.playerControlsWrapper.nextBtn.callOnClick()
|
binding.nextBtn.callOnClick()
|
||||||
} else {
|
} else {
|
||||||
togglePlayPause()
|
togglePlayPause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.setOnClickListener {
|
binding.playerProgressCurrent.setOnClickListener {
|
||||||
skip(false)
|
skip(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.playerProgressMax.setOnClickListener {
|
binding.playerProgressMax.setOnClickListener {
|
||||||
skip(true)
|
skip(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.previousBtn.setOnClickListener {
|
binding.previousBtn.setOnClickListener {
|
||||||
if (playedRecordingIDs.isEmpty()) {
|
if (playedRecordingIDs.isEmpty()) {
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
@ -116,14 +116,14 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
playRecording(prevRecording, true)
|
playRecording(prevRecording, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.playerTitle.setOnLongClickListener {
|
binding.playerTitle.setOnLongClickListener {
|
||||||
if (binding.playerControlsWrapper.playerTitle.value.isNotEmpty()) {
|
if (binding.playerTitle.value.isNotEmpty()) {
|
||||||
context.copyToClipboard(binding.playerControlsWrapper.playerTitle.value)
|
context.copyToClipboard(binding.playerTitle.value)
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.nextBtn.setOnClickListener {
|
binding.nextBtn.setOnClickListener {
|
||||||
val adapter = getRecordingsAdapter()
|
val adapter = getRecordingsAdapter()
|
||||||
if (adapter == null || adapter.recordings.isEmpty()) {
|
if (adapter == null || adapter.recordings.isEmpty()) {
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
|
@ -193,9 +193,9 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
|
|
||||||
setOnCompletionListener {
|
setOnCompletionListener {
|
||||||
progressTimer.cancel()
|
progressTimer.cancel()
|
||||||
binding.playerControlsWrapper.playerProgressbar.progress = binding.playerControlsWrapper.playerProgressbar.max
|
binding.playerProgressbar.progress = binding.playerProgressbar.max
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.text = binding.playerControlsWrapper.playerProgressMax.text
|
binding.playerProgressCurrent.text = binding.playerProgressMax.text
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
setOnPreparedListener {
|
setOnPreparedListener {
|
||||||
|
@ -245,12 +245,12 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(playOnPreparation))
|
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(playOnPreparation))
|
||||||
binding.playerControlsWrapper.playerProgressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
binding.playerProgressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
if (fromUser && !playedRecordingIDs.isEmpty()) {
|
if (fromUser && !playedRecordingIDs.isEmpty()) {
|
||||||
player?.seekTo(progress * 1000)
|
player?.seekTo(progress * 1000)
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.text = progress.getFormattedDuration()
|
binding.playerProgressCurrent.text = progress.getFormattedDuration()
|
||||||
resumePlayback()
|
resumePlayback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,22 +273,22 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
val progress = Math.round(player!!.currentPosition / 1000.toDouble()).toInt()
|
val progress = Math.round(player!!.currentPosition / 1000.toDouble()).toInt()
|
||||||
updateCurrentProgress(progress)
|
updateCurrentProgress(progress)
|
||||||
binding.playerControlsWrapper.playerProgressbar.progress = progress
|
binding.playerProgressbar.progress = progress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCurrentProgress(seconds: Int) {
|
private fun updateCurrentProgress(seconds: Int) {
|
||||||
binding.playerControlsWrapper.playerProgressCurrent.text = seconds.getFormattedDuration()
|
binding.playerProgressCurrent.text = seconds.getFormattedDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetProgress(recording: Recording?) {
|
private fun resetProgress(recording: Recording?) {
|
||||||
updateCurrentProgress(0)
|
updateCurrentProgress(0)
|
||||||
binding.playerControlsWrapper.playerProgressbar.progress = 0
|
binding.playerProgressbar.progress = 0
|
||||||
binding.playerControlsWrapper.playerProgressbar.max = recording?.duration ?: 0
|
binding.playerProgressbar.max = recording?.duration ?: 0
|
||||||
binding.playerControlsWrapper.playerTitle.text = recording?.title ?: ""
|
binding.playerTitle.text = recording?.title ?: ""
|
||||||
binding.playerControlsWrapper.playerProgressMax.text = (recording?.duration ?: 0).getFormattedDuration()
|
binding.playerProgressMax.text = (recording?.duration ?: 0).getFormattedDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSearchTextChanged(text: String) {
|
fun onSearchTextChanged(text: String) {
|
||||||
|
@ -307,13 +307,13 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
|
|
||||||
private fun pausePlayback() {
|
private fun pausePlayback() {
|
||||||
player?.pause()
|
player?.pause()
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
||||||
progressTimer.cancel()
|
progressTimer.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resumePlayback() {
|
private fun resumePlayback() {
|
||||||
player?.start()
|
player?.start()
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(true))
|
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(true))
|
||||||
setupProgressTimer()
|
setupProgressTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,12 +352,12 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
|
||||||
context.updateTextColors(binding.playerHolder)
|
context.updateTextColors(binding.playerHolder)
|
||||||
|
|
||||||
val textColor = context.getProperTextColor()
|
val textColor = context.getProperTextColor()
|
||||||
arrayListOf(binding.playerControlsWrapper.previousBtn, binding.playerControlsWrapper.nextBtn).forEach {
|
arrayListOf(binding.previousBtn, binding.nextBtn).forEach {
|
||||||
it.applyColorFilter(textColor)
|
it.applyColorFilter(textColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerControlsWrapper.playPauseBtn.background.applyColorFilter(properPrimaryColor)
|
binding.playPauseBtn.background.applyColorFilter(properPrimaryColor)
|
||||||
binding.playerControlsWrapper.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun finishActMode() = getRecordingsAdapter()?.finishActMode()
|
fun finishActMode() = getRecordingsAdapter()?.finishActMode()
|
||||||
|
|
|
@ -1,188 +0,0 @@
|
||||||
package com.simplemobiletools.voicerecorder.views
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import com.simplemobiletools.commons.extensions.adjustAlpha
|
|
||||||
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
|
||||||
import com.simplemobiletools.commons.extensions.getProperTextColor
|
|
||||||
import com.simplemobiletools.commons.helpers.LOWER_ALPHA
|
|
||||||
import com.visualizer.amplitude.dp
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class AudioEditorView @JvmOverloads constructor(
|
|
||||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
|
||||||
) : View(context, attrs, defStyleAttr) {
|
|
||||||
private val chunkPaint = Paint()
|
|
||||||
private val highlightPaint = Paint()
|
|
||||||
private val progressPaint = Paint()
|
|
||||||
|
|
||||||
private var chunks = ArrayList<Float>()
|
|
||||||
private var topBottomPadding = 6.dp()
|
|
||||||
|
|
||||||
private var startX: Float = -1f
|
|
||||||
private var endX: Float = -1f
|
|
||||||
|
|
||||||
private var currentProgress: Float = 0f
|
|
||||||
|
|
||||||
private enum class Dragging {
|
|
||||||
START,
|
|
||||||
END,
|
|
||||||
NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
private var dragging = Dragging.NONE
|
|
||||||
|
|
||||||
var startPosition: Float = -1f
|
|
||||||
var endPosition: Float = -1f
|
|
||||||
|
|
||||||
var editListener: (() -> Unit)? = null
|
|
||||||
|
|
||||||
var chunkColor = Color.RED
|
|
||||||
set(value) {
|
|
||||||
chunkPaint.color = value
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
private var chunkWidth = 20.dp()
|
|
||||||
set(value) {
|
|
||||||
chunkPaint.strokeWidth = value
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
private var chunkSpace = 1.dp()
|
|
||||||
var chunkMinHeight = 3.dp() // recommended size > 10 dp
|
|
||||||
var chunkRoundedCorners = false
|
|
||||||
set(value) {
|
|
||||||
if (value) {
|
|
||||||
chunkPaint.strokeCap = Paint.Cap.ROUND
|
|
||||||
} else {
|
|
||||||
chunkPaint.strokeCap = Paint.Cap.BUTT
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
chunkPaint.strokeWidth = chunkWidth
|
|
||||||
chunkPaint.color = chunkColor
|
|
||||||
chunkRoundedCorners = false
|
|
||||||
highlightPaint.color = context.getProperPrimaryColor().adjustAlpha(LOWER_ALPHA)
|
|
||||||
progressPaint.color = context.getProperTextColor()
|
|
||||||
progressPaint.strokeWidth = 4.dp()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun recreate() {
|
|
||||||
chunks.clear()
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearEditing() {
|
|
||||||
startX = -1f
|
|
||||||
endX = -1f
|
|
||||||
startPosition = -1f
|
|
||||||
endPosition = -1f
|
|
||||||
editListener?.invoke()
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun putAmplitudes(amplitudes: List<Int>) {
|
|
||||||
val maxAmp = amplitudes.max()
|
|
||||||
chunkWidth = (1.0f / amplitudes.size) * (2.0f / 3)
|
|
||||||
chunkSpace = chunkWidth / 2
|
|
||||||
|
|
||||||
chunks.addAll(amplitudes.map { it.toFloat() / maxAmp })
|
|
||||||
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
|
||||||
super.onDraw(canvas)
|
|
||||||
if (chunkWidth < 1f) {
|
|
||||||
chunkWidth *= width
|
|
||||||
chunkSpace = chunkWidth / 2
|
|
||||||
}
|
|
||||||
val verticalCenter = height / 2
|
|
||||||
var x = chunkSpace
|
|
||||||
val maxHeight = height - (topBottomPadding * 2)
|
|
||||||
val verticalDrawScale = maxHeight - chunkMinHeight
|
|
||||||
if (verticalDrawScale == 0f) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
chunks.forEach {
|
|
||||||
val chunkHeight = it * verticalDrawScale + chunkMinHeight
|
|
||||||
val startY = verticalCenter - chunkHeight / 2
|
|
||||||
val stopY = verticalCenter + chunkHeight / 2
|
|
||||||
|
|
||||||
canvas.drawLine(x, startY, x, stopY, chunkPaint)
|
|
||||||
x += chunkWidth + chunkSpace
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startPosition >= 0f || startX >= 0f ) {
|
|
||||||
val start: Float
|
|
||||||
val end: Float
|
|
||||||
if (startX >= 0f) {
|
|
||||||
start = startX
|
|
||||||
end = endX
|
|
||||||
} else {
|
|
||||||
start = width * startPosition
|
|
||||||
end = width * endPosition
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.drawRect(start, 0f, end, height.toFloat(), highlightPaint)
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.drawLine(width * currentProgress, 0f, width * currentProgress, height.toFloat(), progressPaint)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
|
||||||
when (event?.actionMasked) {
|
|
||||||
MotionEvent.ACTION_DOWN -> {
|
|
||||||
if (abs(event.x - startPosition * width) < 50.0f) {
|
|
||||||
startX = event.x
|
|
||||||
endX = endPosition * width
|
|
||||||
dragging = Dragging.START
|
|
||||||
} else if (abs(event.x - endPosition * width) < 50.0f) {
|
|
||||||
endX = event.x
|
|
||||||
startX = startPosition * width
|
|
||||||
dragging = Dragging.END
|
|
||||||
} else {
|
|
||||||
startX = event.x
|
|
||||||
endX = event.x
|
|
||||||
dragging = Dragging.END
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
|
||||||
if (dragging == Dragging.START) {
|
|
||||||
startX = event.x
|
|
||||||
} else if (dragging == Dragging.END) {
|
|
||||||
endX = event.x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MotionEvent.ACTION_UP -> {
|
|
||||||
if (dragging == Dragging.START) {
|
|
||||||
startX = event.x
|
|
||||||
} else if (dragging == Dragging.END) {
|
|
||||||
endX = event.x
|
|
||||||
}
|
|
||||||
dragging = Dragging.NONE
|
|
||||||
startPosition = min(startX, endX) / width
|
|
||||||
endPosition = max(startX, endX) / width
|
|
||||||
startX = -1f
|
|
||||||
endX = -1f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
invalidate()
|
|
||||||
editListener?.invoke()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateProgress(progress: Float) {
|
|
||||||
currentProgress = progress
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M9.64,7.64c0.23,-0.5 0.36,-1.05 0.36,-1.64 0,-2.21 -1.79,-4 -4,-4S2,3.79 2,6s1.79,4 4,4c0.59,0 1.14,-0.13 1.64,-0.36L10,12l-2.36,2.36C7.14,14.13 6.59,14 6,14c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4c0,-0.59 -0.13,-1.14 -0.36,-1.64L12,14l7,7h3v-1L9.64,7.64zM6,8c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM6,20c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM12,12.5c-0.28,0 -0.5,-0.22 -0.5,-0.5s0.22,-0.5 0.5,-0.5 0.5,0.22 0.5,0.5 -0.22,0.5 -0.5,0.5zM19,3l-6,6 2,2 7,-7L22,3z"/>
|
|
||||||
</vector>
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/main_coordinator"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
|
||||||
android:id="@+id/settings_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:background="@color/color_primary"
|
|
||||||
app:title="@string/settings"
|
|
||||||
app:titleTextAppearance="@style/AppTheme.ActionBar.TitleTextStyle" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/content_wrapper"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="?attr/actionBarSize">
|
|
||||||
|
|
||||||
<com.simplemobiletools.voicerecorder.views.AudioEditorView
|
|
||||||
android:id="@+id/recording_visualizer"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/player_controls_wrapper"
|
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:layout_marginStart="@dimen/big_margin"
|
|
||||||
android:layout_marginEnd="@dimen/big_margin" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/player_controls_wrapper"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/recording_visualizer"
|
|
||||||
layout="@layout/layout_player_controls" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.simplemobiletools.voicerecorder.fragments.PlayerFragment xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.simplemobiletools.voicerecorder.fragments.PlayerFragment xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/player_holder"
|
android:id="@+id/player_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
@ -36,7 +37,120 @@
|
||||||
|
|
||||||
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
|
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
|
||||||
|
|
||||||
<include
|
<RelativeLayout
|
||||||
android:id="@+id/player_controls_wrapper"
|
android:id="@+id/player_controls_wrapper"
|
||||||
layout="@layout/layout_player_controls" />
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:ignore="HardcodedText">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/player_divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1px"
|
||||||
|
android:background="@color/divider_grey"
|
||||||
|
android:importantForAccessibility="no" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/player_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/medium_margin"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:padding="@dimen/activity_margin"
|
||||||
|
android:textSize="@dimen/big_text_size"
|
||||||
|
tools:text="Recording title" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/player_progress_current"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/player_controls"
|
||||||
|
android:layout_alignTop="@+id/player_progressbar"
|
||||||
|
android:layout_alignBottom="@+id/player_progressbar"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingStart="@dimen/normal_margin"
|
||||||
|
android:paddingEnd="@dimen/medium_margin"
|
||||||
|
android:text="00:00" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MySeekBar
|
||||||
|
android:id="@+id/player_progressbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/player_title"
|
||||||
|
android:layout_toStartOf="@+id/player_progress_max"
|
||||||
|
android:layout_toEndOf="@+id/player_progress_current"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:max="0"
|
||||||
|
android:paddingTop="@dimen/normal_margin"
|
||||||
|
android:paddingBottom="@dimen/normal_margin" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/player_progress_max"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@+id/player_progressbar"
|
||||||
|
android:layout_alignBottom="@+id/player_progressbar"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingStart="@dimen/medium_margin"
|
||||||
|
android:paddingEnd="@dimen/normal_margin"
|
||||||
|
android:text="00:00" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/player_controls"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/player_progressbar"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/previous_btn"
|
||||||
|
android:layout_width="@dimen/normal_icon_size"
|
||||||
|
android:layout_height="@dimen/normal_icon_size"
|
||||||
|
android:layout_alignTop="@+id/play_pause_btn"
|
||||||
|
android:layout_alignBottom="@+id/play_pause_btn"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toStartOf="@+id/play_pause_btn"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/previous"
|
||||||
|
android:padding="@dimen/medium_margin"
|
||||||
|
android:src="@drawable/ic_previous_vector" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/play_pause_btn"
|
||||||
|
android:layout_width="@dimen/toggle_recording_button_size"
|
||||||
|
android:layout_height="@dimen/toggle_recording_button_size"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginStart="@dimen/player_button_margin"
|
||||||
|
android:layout_marginEnd="@dimen/player_button_margin"
|
||||||
|
android:layout_marginBottom="@dimen/big_margin"
|
||||||
|
android:background="@drawable/circle_background"
|
||||||
|
android:contentDescription="@string/playpause"
|
||||||
|
android:padding="@dimen/activity_margin"
|
||||||
|
android:src="@drawable/ic_play_vector" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/next_btn"
|
||||||
|
android:layout_width="@dimen/normal_icon_size"
|
||||||
|
android:layout_height="@dimen/normal_icon_size"
|
||||||
|
android:layout_alignTop="@+id/play_pause_btn"
|
||||||
|
android:layout_alignBottom="@+id/play_pause_btn"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toEndOf="@+id/play_pause_btn"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/next"
|
||||||
|
android:padding="@dimen/medium_margin"
|
||||||
|
android:src="@drawable/ic_next_vector" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</RelativeLayout>
|
||||||
</com.simplemobiletools.voicerecorder.fragments.PlayerFragment>
|
</com.simplemobiletools.voicerecorder.fragments.PlayerFragment>
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/player_controls_wrapper"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
tools:ignore="HardcodedText"
|
|
||||||
tools:showIn="@layout/fragment_player">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/player_divider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1px"
|
|
||||||
android:background="@color/divider_grey"
|
|
||||||
android:importantForAccessibility="no" />
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyTextView
|
|
||||||
android:id="@+id/player_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/medium_margin"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:padding="@dimen/activity_margin"
|
|
||||||
android:textSize="@dimen/big_text_size"
|
|
||||||
tools:text="Recording title" />
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyTextView
|
|
||||||
android:id="@+id/player_progress_current"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/player_controls"
|
|
||||||
android:layout_alignTop="@+id/player_progressbar"
|
|
||||||
android:layout_alignBottom="@+id/player_progressbar"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:paddingStart="@dimen/normal_margin"
|
|
||||||
android:paddingEnd="@dimen/medium_margin"
|
|
||||||
android:text="00:00" />
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MySeekBar
|
|
||||||
android:id="@+id/player_progressbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/player_title"
|
|
||||||
android:layout_toStartOf="@+id/player_progress_max"
|
|
||||||
android:layout_toEndOf="@+id/player_progress_current"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:max="0"
|
|
||||||
android:paddingTop="@dimen/normal_margin"
|
|
||||||
android:paddingBottom="@dimen/normal_margin" />
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyTextView
|
|
||||||
android:id="@+id/player_progress_max"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignTop="@+id/player_progressbar"
|
|
||||||
android:layout_alignBottom="@+id/player_progressbar"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:paddingStart="@dimen/medium_margin"
|
|
||||||
android:paddingEnd="@dimen/normal_margin"
|
|
||||||
android:text="00:00" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/player_controls"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/player_progressbar"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/previous_btn"
|
|
||||||
android:layout_width="@dimen/normal_icon_size"
|
|
||||||
android:layout_height="@dimen/normal_icon_size"
|
|
||||||
android:layout_alignTop="@+id/play_pause_btn"
|
|
||||||
android:layout_alignBottom="@+id/play_pause_btn"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toStartOf="@+id/play_pause_btn"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/previous"
|
|
||||||
android:padding="@dimen/medium_margin"
|
|
||||||
android:src="@drawable/ic_previous_vector" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/play_pause_btn"
|
|
||||||
android:layout_width="@dimen/toggle_recording_button_size"
|
|
||||||
android:layout_height="@dimen/toggle_recording_button_size"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginStart="@dimen/player_button_margin"
|
|
||||||
android:layout_marginEnd="@dimen/player_button_margin"
|
|
||||||
android:layout_marginBottom="@dimen/big_margin"
|
|
||||||
android:background="@drawable/circle_background"
|
|
||||||
android:contentDescription="@string/playpause"
|
|
||||||
android:padding="@dimen/activity_margin"
|
|
||||||
android:src="@drawable/ic_play_vector" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/next_btn"
|
|
||||||
android:layout_width="@dimen/normal_icon_size"
|
|
||||||
android:layout_height="@dimen/normal_icon_size"
|
|
||||||
android:layout_alignTop="@+id/play_pause_btn"
|
|
||||||
android:layout_alignBottom="@+id/play_pause_btn"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toEndOf="@+id/play_pause_btn"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/next"
|
|
||||||
android:padding="@dimen/medium_margin"
|
|
||||||
android:src="@drawable/ic_next_vector" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
</RelativeLayout>
|
|
|
@ -18,12 +18,6 @@
|
||||||
android:icon="@drawable/ic_delete_vector"
|
android:icon="@drawable/ic_delete_vector"
|
||||||
android:showAsAction="always"
|
android:showAsAction="always"
|
||||||
android:title="@string/delete" />
|
android:title="@string/delete" />
|
||||||
<!--<item
|
|
||||||
android:id="@+id/cab_edit"
|
|
||||||
android:icon="@drawable/ic_edit_vector"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
android:title="@string/edit"
|
|
||||||
app:showAsAction="ifRoom" />-->
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/cab_open_with"
|
android:id="@+id/cab_open_with"
|
||||||
android:showAsAction="never"
|
android:showAsAction="never"
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:ignore="AlwaysShowAction">
|
|
||||||
<item
|
|
||||||
android:id="@+id/play"
|
|
||||||
android:icon="@drawable/ic_play_vector"
|
|
||||||
android:title="Play"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/cut"
|
|
||||||
android:icon="@drawable/ic_cut_vector"
|
|
||||||
android:title="Cut"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
<!-- <item-->
|
|
||||||
<!-- android:id="@+id/save"-->
|
|
||||||
<!-- android:icon="@drawable/ic_save_vector"-->
|
|
||||||
<!-- android:title="Save"-->
|
|
||||||
<!-- app:showAsAction="ifRoom" />-->
|
|
||||||
<item
|
|
||||||
android:id="@+id/reset"
|
|
||||||
android:icon="@drawable/ic_reset_vector"
|
|
||||||
android:title="Reset"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/clear"
|
|
||||||
android:icon="@drawable/ic_cross_vector"
|
|
||||||
android:title="Clear"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
</menu>
|
|
|
@ -15,11 +15,6 @@ room = "2.6.0-alpha02"
|
||||||
simple-commons = "8e7dd4508e"
|
simple-commons = "8e7dd4508e"
|
||||||
#AudioRecordView
|
#AudioRecordView
|
||||||
audiorecordview = "1.0.4"
|
audiorecordview = "1.0.4"
|
||||||
#AudioTool
|
|
||||||
#audiotool = "1.2.1"
|
|
||||||
#amplituda = "2.2.2"
|
|
||||||
#waveformseekbar = "5.0.1"
|
|
||||||
#mobileffmpeg = "4.4"
|
|
||||||
#TAndroidLame
|
#TAndroidLame
|
||||||
tandroidlame = "1.1"
|
tandroidlame = "1.1"
|
||||||
#AutofitTextView
|
#AutofitTextView
|
||||||
|
@ -29,7 +24,7 @@ gradlePlugins-agp = "8.1.1"
|
||||||
#build
|
#build
|
||||||
app-build-compileSDKVersion = "34"
|
app-build-compileSDKVersion = "34"
|
||||||
app-build-targetSDK = "34"
|
app-build-targetSDK = "34"
|
||||||
app-build-minimumSDK = "24"
|
app-build-minimumSDK = "23"
|
||||||
app-build-javaVersion = "VERSION_17"
|
app-build-javaVersion = "VERSION_17"
|
||||||
app-build-kotlinJVMTarget = "17"
|
app-build-kotlinJVMTarget = "17"
|
||||||
#versioning
|
#versioning
|
||||||
|
@ -51,11 +46,6 @@ simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons",
|
||||||
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
|
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
|
||||||
#AudioRecordView
|
#AudioRecordView
|
||||||
audiorecordview = { module = "com.github.Armen101:AudioRecordView", version.ref = "audiorecordview" }
|
audiorecordview = { module = "com.github.Armen101:AudioRecordView", version.ref = "audiorecordview" }
|
||||||
#AudioTool
|
|
||||||
#audiotool = { module = "com.github.lincollincol:AudioTool", version.ref = "audiotool" }
|
|
||||||
#amplituda = { module = "com.github.lincollincol:amplituda", version.ref = "amplituda" }
|
|
||||||
#mobileffmpeg = { module = "com.arthenica:mobile-ffmpeg-full", version.ref = "mobileffmpeg" }
|
|
||||||
#waveformseekbar = { module = "com.github.massoudss:waveformSeekBar", version.ref = "waveformseekbar" }
|
|
||||||
#TAndroidLame
|
#TAndroidLame
|
||||||
tandroidlame = { module = "com.github.naman14:TAndroidLame", version.ref = "tandroidlame" }
|
tandroidlame = { module = "com.github.naman14:TAndroidLame", version.ref = "tandroidlame" }
|
||||||
#AutofitTextView
|
#AutofitTextView
|
||||||
|
@ -65,14 +55,6 @@ room = [
|
||||||
"androidx-room-ktx",
|
"androidx-room-ktx",
|
||||||
"androidx-room-runtime",
|
"androidx-room-runtime",
|
||||||
]
|
]
|
||||||
#audiotool = [
|
|
||||||
# "audiotool",
|
|
||||||
# "mobileffmpeg",
|
|
||||||
#]
|
|
||||||
#amplituda = [
|
|
||||||
# "amplituda",
|
|
||||||
# "waveformseekbar",
|
|
||||||
#]
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
|
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
|
||||||
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
|
Loading…
Reference in a new issue