Route audio to headset/headphones if available (replaces earpiece)
This commit is contained in:
parent
5d2621af03
commit
f78be7e306
4 changed files with 50 additions and 18 deletions
|
@ -39,6 +39,7 @@ This version is a full rewrite of the app in kotlin, using modern Android compon
|
||||||
|
|
||||||
- Call history view groups call from the same SIP URI (like linphone-iphone)
|
- Call history view groups call from the same SIP URI (like linphone-iphone)
|
||||||
- Reworked conference (using new linphone-sdk APIs)
|
- Reworked conference (using new linphone-sdk APIs)
|
||||||
|
- Route audio to headset / headphones / bluetooth device automatically when available
|
||||||
- Improved how Android native contacts are used
|
- Improved how Android native contacts are used
|
||||||
- Switched to material design for text input fields & switches
|
- Switched to material design for text input fields & switches
|
||||||
- Launcher shortcuts can be to either contacts or chat rooms
|
- Launcher shortcuts can be to either contacts or chat rooms
|
||||||
|
|
|
@ -195,9 +195,13 @@ class ControlsViewModel : ViewModel() {
|
||||||
val wasBluetoothPreviouslyAvailable = audioRoutesEnabled.value == true
|
val wasBluetoothPreviouslyAvailable = audioRoutesEnabled.value == true
|
||||||
updateAudioRoutesState()
|
updateAudioRoutesState()
|
||||||
|
|
||||||
if (!wasBluetoothPreviouslyAvailable && corePreferences.routeAudioToBluetoothIfAvailable) {
|
if (AudioRouteUtils.isHeadsetAudioRouteAvailable()) {
|
||||||
|
AudioRouteUtils.routeAudioToHeadset()
|
||||||
|
} else if (!wasBluetoothPreviouslyAvailable && corePreferences.routeAudioToBluetoothIfAvailable) {
|
||||||
// Only attempt to route audio to bluetooth automatically when bluetooth device is connected
|
// Only attempt to route audio to bluetooth automatically when bluetooth device is connected
|
||||||
AudioRouteUtils.routeAudioToBluetooth()
|
if (AudioRouteUtils.isBluetoothAudioRouteAvailable()) {
|
||||||
|
AudioRouteUtils.routeAudioToBluetooth()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +379,12 @@ class ControlsViewModel : ViewModel() {
|
||||||
|
|
||||||
fun forceEarpieceAudioRoute() {
|
fun forceEarpieceAudioRoute() {
|
||||||
somethingClickedEvent.value = Event(true)
|
somethingClickedEvent.value = Event(true)
|
||||||
AudioRouteUtils.routeAudioToEarpiece()
|
if (AudioRouteUtils.isHeadsetAudioRouteAvailable()) {
|
||||||
|
Log.i("[Call] Headset found, route audio to it instead of earpiece")
|
||||||
|
AudioRouteUtils.routeAudioToHeadset()
|
||||||
|
} else {
|
||||||
|
AudioRouteUtils.routeAudioToEarpiece()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forceSpeakerAudioRoute() {
|
fun forceSpeakerAudioRoute() {
|
||||||
|
|
|
@ -194,9 +194,14 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
} else if (state == Call.State.StreamsRunning) {
|
} else if (state == Call.State.StreamsRunning) {
|
||||||
// Do not automatically route audio to bluetooth after first call
|
// Do not automatically route audio to bluetooth after first call
|
||||||
if (core.callsNb == 1) {
|
if (core.callsNb == 1) {
|
||||||
// Only try to route bluetooth when the call is in StreamsRunning for the first time
|
// Only try to route bluetooth / headphone / headset when the call is in StreamsRunning for the first time
|
||||||
if (previousCallState == Call.State.Connected && corePreferences.routeAudioToBluetoothIfAvailable) {
|
if (previousCallState == Call.State.Connected) {
|
||||||
AudioRouteUtils.routeAudioToBluetooth(call)
|
Log.i("[Context] First call going into StreamsRunning state for the first time, trying to route audio to headset or bluetooth if available")
|
||||||
|
if (AudioRouteUtils.isHeadsetAudioRouteAvailable()) {
|
||||||
|
AudioRouteUtils.routeAudioToHeadset(call)
|
||||||
|
} else if (corePreferences.routeAudioToBluetoothIfAvailable && AudioRouteUtils.isBluetoothAudioRouteAvailable()) {
|
||||||
|
AudioRouteUtils.routeAudioToBluetooth(call)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,18 +68,36 @@ class AudioRouteUtils {
|
||||||
val currentCall = call ?: coreContext.core.currentCall ?: coreContext.core.calls[0]
|
val currentCall = call ?: coreContext.core.currentCall ?: coreContext.core.calls[0]
|
||||||
|
|
||||||
for (audioDevice in coreContext.core.audioDevices) {
|
for (audioDevice in coreContext.core.audioDevices) {
|
||||||
if (audioDevice.type == AudioDevice.Type.Bluetooth && audioDevice.hasCapability(
|
if (audioDevice.type == AudioDevice.Type.Bluetooth) {
|
||||||
AudioDevice.Capabilities.CapabilityPlay
|
if (audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||||
)
|
Log.i("[Audio Route Helper] Found bluetooth audio device [${audioDevice.deviceName}], routing audio to it")
|
||||||
) {
|
currentCall.outputAudioDevice = audioDevice
|
||||||
Log.i("[Audio Route Helper] Found bluetooth audio device [${audioDevice.deviceName}], routing audio to it")
|
return
|
||||||
currentCall.outputAudioDevice = audioDevice
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.e("[Audio Route Helper] Couldn't find bluetooth audio device")
|
Log.e("[Audio Route Helper] Couldn't find bluetooth audio device")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun routeAudioToHeadset(call: Call? = null) {
|
||||||
|
if (coreContext.core.callsNb == 0) {
|
||||||
|
Log.e("[Audio Route Helper] No call found, aborting headset 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.Headphones || audioDevice.type == AudioDevice.Type.Headset) {
|
||||||
|
if (audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||||
|
Log.i("[Audio Route Helper] Found headset audio device [${audioDevice.deviceName}], routing audio to it")
|
||||||
|
currentCall.outputAudioDevice = audioDevice
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.e("[Audio Route Helper] Couldn't find headset audio device")
|
||||||
|
}
|
||||||
|
|
||||||
fun isBluetoothAudioRouteCurrentlyUsed(call: Call? = null): Boolean {
|
fun isBluetoothAudioRouteCurrentlyUsed(call: Call? = null): Boolean {
|
||||||
if (coreContext.core.callsNb == 0) {
|
if (coreContext.core.callsNb == 0) {
|
||||||
Log.w("[Audio Route Helper] No call found, so bluetooth audio route isn't used")
|
Log.w("[Audio Route Helper] No call found, so bluetooth audio route isn't used")
|
||||||
|
@ -94,10 +112,8 @@ class AudioRouteUtils {
|
||||||
|
|
||||||
fun isBluetoothAudioRouteAvailable(): Boolean {
|
fun isBluetoothAudioRouteAvailable(): Boolean {
|
||||||
for (audioDevice in coreContext.core.audioDevices) {
|
for (audioDevice in coreContext.core.audioDevices) {
|
||||||
if (audioDevice.type == AudioDevice.Type.Bluetooth && audioDevice.hasCapability(
|
if (audioDevice.type == AudioDevice.Type.Bluetooth &&
|
||||||
AudioDevice.Capabilities.CapabilityPlay
|
audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||||
)
|
|
||||||
) {
|
|
||||||
Log.i("[Audio Route Helper] Found bluetooth audio device [${audioDevice.deviceName}]")
|
Log.i("[Audio Route Helper] Found bluetooth audio device [${audioDevice.deviceName}]")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -107,7 +123,8 @@ class AudioRouteUtils {
|
||||||
|
|
||||||
fun isHeadsetAudioRouteAvailable(): Boolean {
|
fun isHeadsetAudioRouteAvailable(): Boolean {
|
||||||
for (audioDevice in coreContext.core.audioDevices) {
|
for (audioDevice in coreContext.core.audioDevices) {
|
||||||
if (audioDevice.type == AudioDevice.Type.Headset || audioDevice.type == AudioDevice.Type.Headphones) {
|
if ((audioDevice.type == AudioDevice.Type.Headset || audioDevice.type == AudioDevice.Type.Headphones) &&
|
||||||
|
audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) {
|
||||||
Log.i("[Audio Route Helper] Found headset/headphones audio device [${audioDevice.deviceName}]")
|
Log.i("[Audio Route Helper] Found headset/headphones audio device [${audioDevice.deviceName}]")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue