Reworked audio route handling code and added auto switch to bluetooth if available and to speaker when video is enabled
This commit is contained in:
parent
704e7d84fa
commit
7172d7cf60
15 changed files with 186 additions and 66 deletions
|
@ -36,6 +36,7 @@ import org.linphone.compatibility.Compatibility
|
|||
import org.linphone.core.*
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.AudioRouteUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.PermissionHelper
|
||||
|
||||
|
@ -68,7 +69,7 @@ class ControlsViewModel : ViewModel() {
|
|||
|
||||
val optionsVisibility = MutableLiveData<Boolean>()
|
||||
|
||||
val audioRoutesVisibility = MutableLiveData<Boolean>()
|
||||
val audioRoutesSelected = MutableLiveData<Boolean>()
|
||||
|
||||
val audioRoutesEnabled = MutableLiveData<Boolean>()
|
||||
|
||||
|
@ -170,7 +171,9 @@ class ControlsViewModel : ViewModel() {
|
|||
state: Call.State,
|
||||
message: String
|
||||
) {
|
||||
if (state == Call.State.StreamsRunning) isVideoUpdateInProgress.value = false
|
||||
if (state == Call.State.StreamsRunning) {
|
||||
isVideoUpdateInProgress.value = false
|
||||
}
|
||||
|
||||
if (coreContext.isVideoCallOrConferenceActive() && !PermissionHelper.get().hasCameraPermission()) {
|
||||
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
|
||||
|
@ -186,9 +189,14 @@ class ControlsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
override fun onAudioDevicesListUpdated(core: Core) {
|
||||
if (core.callsNb == 0) return
|
||||
Log.i("[Call] Audio devices list updated")
|
||||
val wasBluetoothPreviouslyAvailable = audioRoutesEnabled.value == true
|
||||
updateAudioRoutesState()
|
||||
coreContext.routeAudioToBluetoothIfAvailable(core.currentCall ?: core.calls[0])
|
||||
|
||||
if (!wasBluetoothPreviouslyAvailable && corePreferences.routeAudioToBluetoothIfAvailable) {
|
||||
// Only attempt to route audio to bluetooth automatically when bluetooth device is connected
|
||||
AudioRouteUtils.routeAudioToBluetooth()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +210,7 @@ class ControlsViewModel : ViewModel() {
|
|||
|
||||
numpadVisibility.value = false
|
||||
optionsVisibility.value = false
|
||||
audioRoutesVisibility.value = false
|
||||
audioRoutesSelected.value = false
|
||||
|
||||
isRecording.value = currentCall?.isRecording
|
||||
isVideoUpdateInProgress.value = false
|
||||
|
@ -309,8 +317,8 @@ class ControlsViewModel : ViewModel() {
|
|||
|
||||
fun toggleRoutesMenu() {
|
||||
somethingClickedEvent.value = Event(true)
|
||||
audioRoutesVisibility.value = audioRoutesVisibility.value != true
|
||||
if (audioRoutesVisibility.value == true) {
|
||||
audioRoutesSelected.value = audioRoutesSelected.value != true
|
||||
if (audioRoutesSelected.value == true) {
|
||||
audioRoutesMenuAnimator.start()
|
||||
} else {
|
||||
audioRoutesMenuAnimator.reverse()
|
||||
|
@ -365,38 +373,17 @@ class ControlsViewModel : ViewModel() {
|
|||
|
||||
fun forceEarpieceAudioRoute() {
|
||||
somethingClickedEvent.value = Event(true)
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Earpiece) {
|
||||
Log.i("[Call] Found earpiece audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
coreContext.core.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.e("[Call] Couldn't find earpiece audio device")
|
||||
AudioRouteUtils.routeAudioToEarpiece()
|
||||
}
|
||||
|
||||
fun forceSpeakerAudioRoute() {
|
||||
somethingClickedEvent.value = Event(true)
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Speaker) {
|
||||
Log.i("[Call] Found speaker audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
coreContext.core.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.e("[Call] Couldn't find speaker audio device")
|
||||
AudioRouteUtils.routeAudioToSpeaker()
|
||||
}
|
||||
|
||||
fun forceBluetoothAudioRoute() {
|
||||
somethingClickedEvent.value = Event(true)
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if ((audioDevice.type == AudioDevice.Type.Bluetooth) && audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||
Log.i("[Call] Found bluetooth audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
coreContext.core.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.e("[Call] Couldn't find bluetooth audio device")
|
||||
AudioRouteUtils.routeAudioToBluetooth()
|
||||
}
|
||||
|
||||
private fun updateAudioRelated() {
|
||||
|
@ -425,21 +412,16 @@ class ControlsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
private fun updateAudioRoutesState() {
|
||||
var bluetoothDeviceAvailable = false
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Bluetooth) {
|
||||
bluetoothDeviceAvailable = true
|
||||
break
|
||||
}
|
||||
}
|
||||
val bluetoothDeviceAvailable = AudioRouteUtils.isBluetoothAudioRouteAvailable()
|
||||
audioRoutesEnabled.value = bluetoothDeviceAvailable
|
||||
if (!bluetoothDeviceAvailable) {
|
||||
audioRoutesVisibility.value = false
|
||||
audioRoutesSelected.value = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBluetoothHeadsetState() {
|
||||
val audioDevice = coreContext.core.outputAudioDevice
|
||||
if (coreContext.core.callsNb == 0) return
|
||||
val audioDevice = (coreContext.core.currentCall ?: coreContext.core.calls[0]).outputAudioDevice
|
||||
isBluetoothHeadsetSelected.value = audioDevice?.type == AudioDevice.Type.Bluetooth
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.linphone.activities.main.about
|
|||
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.utils.LogsUploadViewModel
|
||||
import org.linphone.activities.main.viewmodels.LogsUploadViewModel
|
||||
|
||||
class AboutViewModel : LogsUploadViewModel() {
|
||||
val appVersion: String = coreContext.appVersion
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.utils
|
||||
package org.linphone.activities.main.adapters
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
|
@ -33,6 +33,7 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.adapters.SelectionListAdapter
|
||||
import org.linphone.activities.main.chat.viewmodels.ChatMessageViewModel
|
||||
import org.linphone.activities.main.chat.viewmodels.EventViewModel
|
||||
import org.linphone.activities.main.chat.viewmodels.OnContentClickedListener
|
||||
|
@ -43,7 +44,6 @@ import org.linphone.core.EventLog
|
|||
import org.linphone.databinding.ChatEventListCellBinding
|
||||
import org.linphone.databinding.ChatMessageListCellBinding
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.SelectionListAdapter
|
||||
|
||||
class ChatMessagesListAdapter(
|
||||
selectionVM: ListTopBarViewModel,
|
||||
|
|
|
@ -27,12 +27,12 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.adapters.SelectionListAdapter
|
||||
import org.linphone.activities.main.chat.viewmodels.ChatRoomViewModel
|
||||
import org.linphone.activities.main.viewmodels.ListTopBarViewModel
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.databinding.ChatRoomListCellBinding
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.SelectionListAdapter
|
||||
|
||||
class ChatRoomsListAdapter(
|
||||
selectionVM: ListTopBarViewModel,
|
||||
|
|
|
@ -29,6 +29,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.adapters.SelectionListAdapter
|
||||
import org.linphone.activities.main.contact.viewmodels.ContactViewModel
|
||||
import org.linphone.activities.main.viewmodels.ListTopBarViewModel
|
||||
import org.linphone.contact.Contact
|
||||
|
@ -37,7 +38,6 @@ import org.linphone.databinding.GenericListHeaderBinding
|
|||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.HeaderAdapter
|
||||
import org.linphone.utils.SelectionListAdapter
|
||||
|
||||
class ContactsListAdapter(
|
||||
selectionVM: ListTopBarViewModel,
|
||||
|
|
|
@ -27,12 +27,12 @@ import androidx.lifecycle.MutableLiveData
|
|||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.activities.main.dialer.NumpadDigitListener
|
||||
import org.linphone.activities.main.viewmodels.LogsUploadViewModel
|
||||
import org.linphone.compatibility.Compatibility
|
||||
import org.linphone.core.*
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
import org.linphone.utils.LogsUploadViewModel
|
||||
|
||||
class DialerViewModel : LogsUploadViewModel() {
|
||||
val enteredUri = MutableLiveData<String>()
|
||||
|
|
|
@ -28,12 +28,12 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.LinphoneApplication
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.adapters.SelectionListAdapter
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.main.viewmodels.ListTopBarViewModel
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.SelectionListAdapter
|
||||
|
||||
/**
|
||||
* This fragment can be inherited by all fragments that will display a list
|
||||
|
|
|
@ -29,6 +29,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.adapters.SelectionListAdapter
|
||||
import org.linphone.activities.main.history.viewmodels.CallLogViewModel
|
||||
import org.linphone.activities.main.history.viewmodels.GroupedCallLogViewModel
|
||||
import org.linphone.activities.main.viewmodels.ListTopBarViewModel
|
||||
|
|
|
@ -30,6 +30,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.adapters.SelectionListAdapter
|
||||
import org.linphone.activities.main.recordings.viewmodels.RecordingViewModel
|
||||
import org.linphone.activities.main.viewmodels.ListTopBarViewModel
|
||||
import org.linphone.databinding.GenericListHeaderBinding
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.linphone.utils
|
||||
package org.linphone.activities.main.viewmodels
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.utils.Event
|
||||
|
||||
open class LogsUploadViewModel : ViewModel() {
|
||||
val uploadInProgress = MutableLiveData<Boolean>()
|
|
@ -47,6 +47,7 @@ import org.linphone.core.tools.Log
|
|||
import org.linphone.mediastream.Version
|
||||
import org.linphone.notifications.NotificationsManager
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.AudioRouteUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
|
@ -110,6 +111,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
private var overlayY = 0f
|
||||
private var callOverlay: View? = null
|
||||
private var isVibrating = false
|
||||
private var previousCallState = Call.State.Idle
|
||||
|
||||
private val listener: CoreListenerStub = object : CoreListenerStub() {
|
||||
override fun onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
||||
|
@ -169,8 +171,8 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
} else if (state == Call.State.OutgoingInit) {
|
||||
onOutgoingStarted()
|
||||
} else if (state == Call.State.OutgoingProgress) {
|
||||
if (core.callsNb == 1) {
|
||||
routeAudioToBluetoothIfAvailable(call)
|
||||
if (core.callsNb == 1 && corePreferences.routeAudioToBluetoothIfAvailable) {
|
||||
AudioRouteUtils.routeAudioToBluetooth(call)
|
||||
}
|
||||
} else if (state == Call.State.Connected) {
|
||||
if (isVibrating) {
|
||||
|
@ -180,11 +182,23 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
isVibrating = false
|
||||
}
|
||||
|
||||
if (call.dir == Call.Dir.Incoming && core.callsNb == 1) {
|
||||
routeAudioToBluetoothIfAvailable(call)
|
||||
onCallStarted()
|
||||
} else if (state == Call.State.StreamsRunning) {
|
||||
// Do not automatically route audio to bluetooth after first call
|
||||
if (core.callsNb == 1) {
|
||||
// Only try to route bluetooth when the call is in StreamsRunning for the first time
|
||||
if (previousCallState == Call.State.Connected && corePreferences.routeAudioToBluetoothIfAvailable) {
|
||||
AudioRouteUtils.routeAudioToBluetooth(call)
|
||||
}
|
||||
}
|
||||
|
||||
onCallStarted()
|
||||
if (corePreferences.routeAudioToSpeakerWhenVideoIsEnabled && call.currentParams.videoEnabled()) {
|
||||
// Do not turn speaker on when video is enabled if headset or bluetooth is used
|
||||
if (!AudioRouteUtils.isHeadsetAudioRouteAvailable() && !AudioRouteUtils.isBluetoothAudioRouteCurrentlyUsed(call)) {
|
||||
Log.i("[Context] Video enabled and no wired headset not bluetooth in use, routing audio to speaker")
|
||||
AudioRouteUtils.routeAudioToSpeaker(call)
|
||||
}
|
||||
}
|
||||
} else if (state == Call.State.End || state == Call.State.Error || state == Call.State.Released) {
|
||||
if (core.callsNb == 0) {
|
||||
if (isVibrating) {
|
||||
|
@ -215,6 +229,8 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
callErrorMessageResourceId.value = Event(id)
|
||||
}
|
||||
}
|
||||
|
||||
previousCallState = state
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,18 +565,6 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
}
|
||||
}
|
||||
|
||||
fun routeAudioToBluetoothIfAvailable(call: Call) {
|
||||
for (audioDevice in core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Bluetooth &&
|
||||
audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||
Log.i("[Context] Found bluetooth audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
call.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.w("[Context] Didn't find any bluetooth audio device, keeping default audio route")
|
||||
}
|
||||
|
||||
/* Start call related activities */
|
||||
|
||||
private fun onIncomingReceived() {
|
||||
|
|
|
@ -225,6 +225,19 @@ class CorePreferences constructor(private val context: Context) {
|
|||
config.setBool("app", "full_screen_call", value)
|
||||
}
|
||||
|
||||
var routeAudioToBluetoothIfAvailable: Boolean
|
||||
get() = config.getBool("app", "route_audio_to_bluetooth_if_available", true)
|
||||
set(value) {
|
||||
config.setBool("app", "route_audio_to_bluetooth_if_available", value)
|
||||
}
|
||||
|
||||
// This won't be done if bluetooth or wired headset is used
|
||||
var routeAudioToSpeakerWhenVideoIsEnabled: Boolean
|
||||
get() = config.getBool("app", "route_audio_to_speaker_when_video_enabled", true)
|
||||
set(value) {
|
||||
config.setBool("app", "route_audio_to_speaker_when_video_enabled", value)
|
||||
}
|
||||
|
||||
/* Assistant */
|
||||
|
||||
var firstStart: Boolean
|
||||
|
|
118
app/src/main/java/org/linphone/utils/AudioRouteUtils.kt
Normal file
118
app/src/main/java/org/linphone/utils/AudioRouteUtils.kt
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.utils
|
||||
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.AudioDevice
|
||||
import org.linphone.core.Call
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
class AudioRouteUtils {
|
||||
companion object {
|
||||
fun routeAudioToEarpiece(call: Call? = null) {
|
||||
if (coreContext.core.callsNb == 0) {
|
||||
Log.e("[Audio Route Helper] No call found, aborting earpiece audio route change")
|
||||
return
|
||||
}
|
||||
val currentCall = call ?: coreContext.core.currentCall ?: coreContext.core.calls[0]
|
||||
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Earpiece) {
|
||||
Log.i("[Audio Route Helper] Found earpiece audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
currentCall.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.e("[Audio Route Helper] Couldn't find earpiece audio device")
|
||||
}
|
||||
|
||||
fun routeAudioToSpeaker(call: Call? = null) {
|
||||
if (coreContext.core.callsNb == 0) {
|
||||
Log.e("[Audio Route Helper] No call found, aborting speaker audio route change")
|
||||
return
|
||||
}
|
||||
val currentCall = call ?: coreContext.core.currentCall ?: coreContext.core.calls[0]
|
||||
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Speaker) {
|
||||
Log.i("[Audio Route Helper] Found speaker audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
currentCall.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.e("[Audio Route Helper] Couldn't find speaker audio device")
|
||||
}
|
||||
|
||||
fun routeAudioToBluetooth(call: Call? = null) {
|
||||
if (coreContext.core.callsNb == 0) {
|
||||
Log.e("[Audio Route Helper] No call found, aborting bluetooth audio route change")
|
||||
return
|
||||
}
|
||||
val currentCall = call ?: coreContext.core.currentCall ?: coreContext.core.calls[0]
|
||||
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Bluetooth && audioDevice.hasCapability(
|
||||
AudioDevice.Capabilities.CapabilityPlay
|
||||
)
|
||||
) {
|
||||
Log.i("[Audio Route Helper] Found bluetooth audio device [${audioDevice.deviceName}], routing audio to it")
|
||||
currentCall.outputAudioDevice = audioDevice
|
||||
return
|
||||
}
|
||||
}
|
||||
Log.e("[Audio Route Helper] Couldn't find bluetooth audio device")
|
||||
}
|
||||
|
||||
fun isBluetoothAudioRouteCurrentlyUsed(call: Call? = null): Boolean {
|
||||
if (coreContext.core.callsNb == 0) {
|
||||
Log.w("[Audio Route Helper] No call found, so bluetooth audio route isn't used")
|
||||
return false
|
||||
}
|
||||
val currentCall = call ?: coreContext.core.currentCall ?: coreContext.core.calls[0]
|
||||
|
||||
val audioDevice = currentCall.outputAudioDevice
|
||||
Log.i("[Audio Route Helper] Audio device currently in use is [${audioDevice?.deviceName}]")
|
||||
return audioDevice?.type == AudioDevice.Type.Bluetooth
|
||||
}
|
||||
|
||||
fun isBluetoothAudioRouteAvailable(): Boolean {
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Bluetooth && audioDevice.hasCapability(
|
||||
AudioDevice.Capabilities.CapabilityPlay
|
||||
)
|
||||
) {
|
||||
Log.i("[Audio Route Helper] Found bluetooth audio device [${audioDevice.deviceName}]")
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun isHeadsetAudioRouteAvailable(): Boolean {
|
||||
for (audioDevice in coreContext.core.audioDevices) {
|
||||
if (audioDevice.type == AudioDevice.Type.Headset || audioDevice.type == AudioDevice.Type.Headphones) {
|
||||
Log.i("[Audio Route Helper] Found headset/headphones audio device [${audioDevice.deviceName}]")
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -144,7 +144,7 @@
|
|||
android:id="@+id/audio_routes"
|
||||
android:onClick="@{() -> viewModel.toggleRoutesMenu()}"
|
||||
android:visibility="@{viewModel.audioRoutesEnabled ? View.VISIBLE : View.INVISIBLE, default=invisible}"
|
||||
android:selected="@{viewModel.audioRoutesVisibility}"
|
||||
android:selected="@{viewModel.audioRoutesSelected}"
|
||||
android:contentDescription="@string/content_description_toggle_audio_menu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/call_button_size"
|
||||
|
|
Loading…
Reference in a new issue