feat: adding ringers and more audio boilerplate
This commit is contained in:
parent
cbfabdd0a7
commit
40d9386a81
|
@ -92,13 +92,13 @@ class WebRtcTestsActivity: PassphraseRequiredActionBarActivity(), PeerConnection
|
|||
|
||||
private val peerConnection by lazy {
|
||||
// TODO: in a lokinet world, ice servers shouldn't be needed as .loki addresses should suffice to p2p
|
||||
val turn = PeerConnection.IceServer.builder("turn:freyr.getsession.org:5349").setUsername("webrtc").setPassword("webrtc").createIceServer()
|
||||
// val stun = PeerConnection.IceServer.builder("stun:freyr.getsession.org").createIceServer()
|
||||
val iceServers = mutableListOf(turn)
|
||||
val stun = PeerConnection.IceServer.builder("stun:freyr.getsession.org:5349").setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK).createIceServer()
|
||||
val turn = PeerConnection.IceServer.builder("turn:freyr.getsession.org:5349").setUsername("webrtc").setPassword("webrtc").setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK).createIceServer()
|
||||
val iceServers = mutableListOf(turn, stun)
|
||||
val rtcConfig = PeerConnection.RTCConfiguration(iceServers).apply {
|
||||
this.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED
|
||||
this.candidateNetworkPolicy = PeerConnection.CandidateNetworkPolicy.ALL
|
||||
this.iceTransportsType = PeerConnection.IceTransportsType.RELAY
|
||||
// this.iceTransportsType = PeerConnection.IceTransportsType.RELAY
|
||||
}
|
||||
rtcConfig.keyType = PeerConnection.KeyType.ECDSA
|
||||
connectionFactory.createPeerConnection(rtcConfig, this)!!
|
||||
|
|
|
@ -8,11 +8,12 @@ import androidx.core.content.ContextCompat
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.thoughtcrime.securesms.webrtc.AudioManagerCommand
|
||||
import org.thoughtcrime.securesms.webrtc.CallManager
|
||||
import org.thoughtcrime.securesms.webrtc.RTCAudioManager
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class WebRtcCallService: Service() {
|
||||
class WebRtcCallService: Service(), RTCAudioManager.EventListener {
|
||||
|
||||
@Inject lateinit var callManager: CallManager
|
||||
|
||||
|
@ -63,9 +64,24 @@ class WebRtcCallService: Service() {
|
|||
.putExtra(EXTRA_ENABLED, register)
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
// create audio manager
|
||||
// reset call notification
|
||||
// register uncaught exception handler
|
||||
// register network receiver
|
||||
// telephony listen to call state
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// unregister exception handler
|
||||
// shutdown audiomanager
|
||||
// unregister network receiver
|
||||
// unregister power button
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.thoughtcrime.securesms.webrtc
|
||||
|
||||
enum class AudioEvent {
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package org.thoughtcrime.securesms.webrtc
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
|
||||
class RTCAudioManager(context: Context, deviceChangeListener: (currentDevice: AudioDevice?, availableDevices: Collection<AudioDevice>)->Unit) {
|
||||
|
||||
enum class AudioDevice {
|
||||
SPEAKER_PHONE, WIRED_HEADSET, EARPIECE, NONE
|
||||
}
|
||||
|
||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.thoughtcrime.securesms.webrtc
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.thoughtcrime.securesms.webrtc.audio.IncomingRinger
|
||||
|
||||
class RTCAudioManager(context: Context, deviceChangeListener: (currentDevice: AudioDevice?, availableDevices: Collection<AudioDevice>)->Unit) {
|
||||
|
||||
enum class AudioDevice {
|
||||
SPEAKER_PHONE, WIRED_HEADSET, EARPIECE, NONE
|
||||
}
|
||||
|
||||
private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
private val incomingRinger = IncomingRinger(context)
|
||||
|
||||
private val stateChannel = Channel<AudioEvent>()
|
||||
|
||||
interface EventListener {
|
||||
fun onAudioDeviceChanged(activeDevice: AudioDevice, devices: Set<AudioDevice>)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package org.thoughtcrime.securesms.webrtc.audio
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import android.media.RingtoneManager
|
||||
import android.os.Vibrator
|
||||
import org.session.libsignal.utilities.Log
|
||||
|
||||
class IncomingRinger(private val context: Context) {
|
||||
companion object {
|
||||
const val TAG = "IncomingRinger"
|
||||
val PATTERN = longArrayOf(0L, 1000L, 1000L)
|
||||
}
|
||||
|
||||
private val vibrator: Vibrator? = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?
|
||||
var mediaPlayer: MediaPlayer? = null
|
||||
|
||||
fun start(vibrate: Boolean) {
|
||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
mediaPlayer?.release()
|
||||
mediaPlayer = createMediaPlayer()
|
||||
val ringerMode = audioManager.ringerMode
|
||||
|
||||
if (shouldVibrate(mediaPlayer, ringerMode, vibrate)) {
|
||||
Log.i(TAG,"Starting vibration")
|
||||
vibrator?.vibrate(PATTERN, 1)
|
||||
} else {
|
||||
Log.i(TAG,"Skipping vibration")
|
||||
}
|
||||
|
||||
mediaPlayer?.let { player ->
|
||||
if (ringerMode == AudioManager.RINGER_MODE_NORMAL) {
|
||||
try {
|
||||
if (!player.isPlaying) {
|
||||
player.prepare()
|
||||
player.start()
|
||||
Log.i(TAG,"Playing ringtone")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG,"Failed to start mediaPlayer", e)
|
||||
}
|
||||
}
|
||||
} ?: run {
|
||||
Log.w(TAG,"Not ringing, mediaPlayer: ${mediaPlayer?.let{"available"}}, mode: $ringerMode")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
mediaPlayer?.release()
|
||||
mediaPlayer = null
|
||||
vibrator?.cancel()
|
||||
}
|
||||
|
||||
private fun shouldVibrate(player: MediaPlayer?, ringerMode: Int, vibrate: Boolean): Boolean {
|
||||
player ?: return true
|
||||
|
||||
if (vibrator == null || !vibrator.hasVibrator()) return false
|
||||
|
||||
return if (vibrate) ringerMode != AudioManager.RINGER_MODE_SILENT
|
||||
else ringerMode == AudioManager.RINGER_MODE_VIBRATE
|
||||
}
|
||||
|
||||
fun createMediaPlayer(): MediaPlayer? {
|
||||
try {
|
||||
val defaultRingtone = try {
|
||||
RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to get default system ringtone", e)
|
||||
null
|
||||
} ?: return null
|
||||
|
||||
try {
|
||||
val mediaPlayer = MediaPlayer()
|
||||
mediaPlayer.setDataSource(context, defaultRingtone)
|
||||
return mediaPlayer
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Failed to create player with ringtone the normal way", e)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG,"Failed to create mediaPlayer")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue