mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-05-06 21:33:09 +00:00
Added ringtone player next to picker
This commit is contained in:
parent
2a1b2bf7ac
commit
429553a6df
6 changed files with 152 additions and 2 deletions
|
|
@ -21,6 +21,7 @@ package org.linphone.ui.main.settings.viewmodel
|
|||
|
||||
import android.os.Vibrator
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.io.File
|
||||
|
|
@ -28,8 +29,11 @@ import java.util.Locale
|
|||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.core.Player
|
||||
import org.linphone.core.PlayerListener
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.AudioRouteUtils
|
||||
|
||||
class SettingsViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
|
|
@ -49,6 +53,7 @@ class SettingsViewModel @UiThread constructor() : ViewModel() {
|
|||
val availableRingtonesPaths = arrayListOf<String>()
|
||||
val availableRingtonesNames = arrayListOf<String>()
|
||||
val selectedRingtone = MutableLiveData<String>()
|
||||
val isRingtonePlaying = MutableLiveData<Boolean>()
|
||||
val vibrateDuringIncomingCall = MutableLiveData<Boolean>()
|
||||
val autoRecordCalls = MutableLiveData<Boolean>()
|
||||
|
||||
|
|
@ -59,6 +64,15 @@ class SettingsViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val isVibrationAvailable = MutableLiveData<Boolean>()
|
||||
|
||||
// Other
|
||||
|
||||
private lateinit var ringtonePlayer: Player
|
||||
|
||||
private val playerListener = PlayerListener {
|
||||
Log.i("[$TAG] End of ringtone reached")
|
||||
stopRingtonePlayer()
|
||||
}
|
||||
|
||||
init {
|
||||
expandCalls.value = false
|
||||
expandNetwork.value = false
|
||||
|
|
@ -86,6 +100,18 @@ class SettingsViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
coreContext.postOnCoreThread {
|
||||
if (::ringtonePlayer.isInitialized) {
|
||||
stopRingtonePlayer()
|
||||
ringtonePlayer.removeListener(playerListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleEchoCanceller() {
|
||||
val newValue = echoCancellerEnabled.value == false
|
||||
|
|
@ -140,6 +166,40 @@ class SettingsViewModel @UiThread constructor() : ViewModel() {
|
|||
fun setRingtone(ringtone: String) {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.ring = ringtone
|
||||
|
||||
if (::ringtonePlayer.isInitialized) {
|
||||
if (ringtonePlayer.state == Player.State.Playing) {
|
||||
stopRingtonePlayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun playPauseRingtone() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (!::ringtonePlayer.isInitialized) {
|
||||
val playbackDevice = AudioRouteUtils.getAudioPlaybackDeviceIdForCallRecordingOrVoiceMessage()
|
||||
val player = core.createLocalPlayer(playbackDevice, null, null)
|
||||
ringtonePlayer = player ?: return@postOnCoreThread
|
||||
ringtonePlayer.addListener(playerListener)
|
||||
}
|
||||
|
||||
if (ringtonePlayer.state == Player.State.Playing) {
|
||||
stopRingtonePlayer()
|
||||
} else {
|
||||
val path = core.ring.orEmpty()
|
||||
// TODO FIXME: play device default ringtone if selected
|
||||
if (ringtonePlayer.open(path) == 0) {
|
||||
if (ringtonePlayer.start() == 0) {
|
||||
isRingtonePlaying.postValue(true)
|
||||
} else {
|
||||
Log.e("$TAG Failed to play ringtone [$path]")
|
||||
}
|
||||
} else {
|
||||
Log.e("$TAG Failed to open ringtone [$path]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,4 +265,15 @@ class SettingsViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun stopRingtonePlayer() {
|
||||
if (::ringtonePlayer.isInitialized && ringtonePlayer.state != Player.State.Closed) {
|
||||
Log.i("$TAG Stopping ringtone player")
|
||||
ringtonePlayer.pause()
|
||||
ringtonePlayer.seek(0)
|
||||
ringtonePlayer.close()
|
||||
isRingtonePlaying.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,5 +160,38 @@ class AudioRouteUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getAudioPlaybackDeviceIdForCallRecordingOrVoiceMessage(): String? {
|
||||
// In case no headphones/headset/hearing aid/bluetooth is connected, use speaker sound card to play recordings, otherwise use earpiece
|
||||
// If none are available, default one will be used
|
||||
var headphonesCard: String? = null
|
||||
var bluetoothCard: String? = null
|
||||
var speakerCard: String? = null
|
||||
var earpieceCard: String? = null
|
||||
for (device in coreContext.core.audioDevices) {
|
||||
if (device.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||
when (device.type) {
|
||||
AudioDevice.Type.Headphones, AudioDevice.Type.Headset -> {
|
||||
headphonesCard = device.id
|
||||
}
|
||||
AudioDevice.Type.Bluetooth, AudioDevice.Type.HearingAid -> {
|
||||
bluetoothCard = device.id
|
||||
}
|
||||
AudioDevice.Type.Speaker -> {
|
||||
speakerCard = device.id
|
||||
}
|
||||
AudioDevice.Type.Earpiece -> {
|
||||
earpieceCard = device.id
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.i(
|
||||
"$TAG Found headset/headphones/hearingAid sound card [$headphonesCard], bluetooth sound card [$bluetoothCard], speaker sound card [$speakerCard] and earpiece sound card [$earpieceCard]"
|
||||
)
|
||||
return headphonesCard ?: bluetoothCard ?: speakerCard ?: earpieceCard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
9
app/src/main/res/drawable/pause.xml
Normal file
9
app/src/main/res/drawable/pause.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M200,32L160,32a16,16 0,0 0,-16 16L144,208a16,16 0,0 0,16 16h40a16,16 0,0 0,16 -16L216,48A16,16 0,0 0,200 32ZM200,208L160,208L160,48h40ZM96,32L56,32A16,16 0,0 0,40 48L40,208a16,16 0,0 0,16 16L96,224a16,16 0,0 0,16 -16L112,48A16,16 0,0 0,96 32ZM96,208L56,208L56,48L96,48Z"
|
||||
android:fillColor="#4e6074"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/play.xml
Normal file
9
app/src/main/res/drawable/play.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M232.4,114.49 L88.32,26.35a16,16 0,0 0,-16.2 -0.3A15.86,15.86 0,0 0,64 39.87V216.13A15.94,15.94 0,0 0,80 232a16.07,16.07 0,0 0,8.36 -2.35L232.4,141.51a15.81,15.81 0,0 0,0 -27ZM80,215.94V40l143.83,88Z"
|
||||
android:fillColor="#4e6074"/>
|
||||
</vector>
|
||||
|
|
@ -296,7 +296,7 @@
|
|||
android:ellipsize="end"
|
||||
app:layout_constraintTop_toBottomOf="@id/auto_accept_video_switch"
|
||||
app:layout_constraintStart_toStartOf="@id/calls_background"
|
||||
app:layout_constraintEnd_toEndOf="@id/calls_background"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/device_ringtone_player"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
style="@style/material_switch_style"
|
||||
|
|
@ -304,12 +304,13 @@
|
|||
android:visibility="@{viewModel.expandCalls ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/device_ringtone_title"
|
||||
app:layout_constraintStart_toStartOf="@id/device_ringtone_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/device_ringtone_title" />
|
||||
app:layout_constraintEnd_toStartOf="@id/device_ringtone_player" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/device_ringtone_spinner_caret"
|
||||
|
|
@ -322,6 +323,31 @@
|
|||
app:layout_constraintBottom_toBottomOf="@id/device_ringtone_spinner"
|
||||
app:layout_constraintEnd_toEndOf="@id/device_ringtone_spinner"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/tertiary_button_label_style"
|
||||
android:id="@+id/device_ringtone_player"
|
||||
android:onClick="@{() -> viewModel.playPauseRingtone()}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="17dp"
|
||||
android:background="@drawable/tertiary_button_background"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:gravity="center"
|
||||
android:text="@{viewModel.isRingtonePlaying ? @string/settings_calls_pause_ringtone_label : @string/settings_calls_play_ringtone_label, default=@string/settings_calls_play_ringtone_label}"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:drawableStart="@{viewModel.isRingtonePlaying ? @drawable/pause : @drawable/play, default=@drawable/play}"
|
||||
android:drawableTint="@color/tertiary_button_label_color"
|
||||
android:drawablePadding="8dp"
|
||||
android:visibility="@{viewModel.expandCalls ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintStart_toEndOf="@id/device_ringtone_spinner"
|
||||
app:layout_constraintEnd_toEndOf="@id/calls_background"
|
||||
app:layout_constraintTop_toTopOf="@id/device_ringtone_spinner"
|
||||
app:layout_constraintBottom_toBottomOf="@id/device_ringtone_spinner"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/settings_title_style"
|
||||
android:onClick="@{() -> viewModel.toggleVibrateOnIncomingCalls()}"
|
||||
|
|
|
|||
|
|
@ -187,6 +187,8 @@
|
|||
<string name="settings_calls_auto_accept_video_subtitle">Always accept video calls</string>
|
||||
<string name="settings_calls_ringtones_title">Choose your ringtone:</string>
|
||||
<string name="settings_calls_use_device_ringtone_label">Use this device\'s ringtone</string>
|
||||
<string name="settings_calls_play_ringtone_label">Play</string>
|
||||
<string name="settings_calls_pause_ringtone_label">Pause</string>
|
||||
<string name="settings_calls_vibrate_while_ringing_title">Vibrate while incoming call is ringing</string>
|
||||
<string name="settings_calls_auto_record_title">Automatically start recording calls</string>
|
||||
<string name="settings_network_title">Network</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue