Added initial support for attended call transfer
Use red colored spinner text when account has active call
This commit is contained in:
@ -1277,6 +1277,21 @@ Java_com_tutpro_baresip_Call_call_1has_1video(JNIEnv *env, jobject thiz, jlong c
|
||||
return call_has_video((struct call *)call) ? true : false;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_tutpro_baresip_Call_call_1replaces(JNIEnv *env, jobject thiz, jlong call)
|
||||
{
|
||||
return call_supported((struct call *)call, REPLACES) ? true : false;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_tutpro_baresip_Call_call_1replace_1transfer(JNIEnv *env, jobject thiz, jlong xferCall, jlong call)
|
||||
{
|
||||
re_thread_enter();
|
||||
int res = call_replace_transfer((struct call *)xferCall, (struct call *)call);
|
||||
re_thread_leave();
|
||||
return res == 0 ? true : false;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_Api_message_1send(JNIEnv *env, jobject thiz, jlong ua, jstring jPeer, jstring jMsg, jstring jTime)
|
||||
{
|
||||
|
||||
@ -838,13 +838,18 @@ class BaresipService: Service() {
|
||||
Log.d(TAG, "AoR $aor call $callp is closed")
|
||||
stopRinging()
|
||||
stopMediaPlayer()
|
||||
/* when (ev[2]) {
|
||||
"busy" ->
|
||||
playMedia(R.raw.busy, 1)
|
||||
"error" ->
|
||||
playMedia(R.raw.error, 1)
|
||||
} */
|
||||
call!!.remove()
|
||||
val newCall = call!!.newCall
|
||||
if (newCall != null) {
|
||||
newCall.onHoldCall = null
|
||||
call.newCall = null
|
||||
}
|
||||
val onHoldCall = call.onHoldCall
|
||||
if (onHoldCall != null) {
|
||||
onHoldCall.newCall = null
|
||||
onHoldCall.referTo = ""
|
||||
call.onHoldCall = null
|
||||
}
|
||||
call.remove()
|
||||
if (Call.calls().size == 0) {
|
||||
resetCallVolume()
|
||||
am.isSpeakerphoneOn = false
|
||||
@ -911,7 +916,7 @@ class BaresipService: Service() {
|
||||
return
|
||||
}
|
||||
val reason = ev[1].trim()
|
||||
if ((reason != "") && (Call.uaCalls(ua, "").size == 0)) {
|
||||
if ((reason != "") && (ua.calls().isEmpty())) {
|
||||
if (reason[0].isDigit())
|
||||
toast("${getString(R.string.call_failed)}: $reason")
|
||||
else
|
||||
|
||||
@ -8,6 +8,8 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
|
||||
var onhold = false
|
||||
var held = false
|
||||
var onHoldCall: Call? = null
|
||||
var newCall: Call? = null
|
||||
var rejected = false
|
||||
var security = 0
|
||||
var zid = ""
|
||||
@ -15,31 +17,39 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
var referTo = ""
|
||||
|
||||
fun add() {
|
||||
BaresipService.calls.add(this)
|
||||
BaresipService.calls.add(0, this)
|
||||
}
|
||||
|
||||
fun remove() {
|
||||
BaresipService.calls.remove(this)
|
||||
}
|
||||
|
||||
fun connect(uri: String): Int {
|
||||
return call_connect(callp, uri)
|
||||
fun connect(uri: String): Boolean {
|
||||
return call_connect(callp, uri) == 0
|
||||
}
|
||||
|
||||
fun hold(): Int {
|
||||
return call_hold(callp, true)
|
||||
fun hold(): Boolean {
|
||||
return call_hold(callp, true) == 0
|
||||
}
|
||||
|
||||
fun resume(): Int {
|
||||
return call_hold(callp, false)
|
||||
fun resume(): Boolean {
|
||||
return call_hold(callp, false) == 0
|
||||
}
|
||||
|
||||
fun transfer(uri: String): Int {
|
||||
fun transfer(uri: String): Boolean {
|
||||
val err = call_hold(callp, true)
|
||||
if (err != 0)
|
||||
return err
|
||||
return false
|
||||
referTo = uri
|
||||
return call_transfer(callp, uri)
|
||||
return call_transfer(callp, uri) == 0
|
||||
}
|
||||
|
||||
fun executeTransfer(): Boolean {
|
||||
return if (this.onHoldCall != null) {
|
||||
call_hold(callp, true)
|
||||
call_replace_transfer(this.onHoldCall!!.callp, callp)
|
||||
} else
|
||||
false
|
||||
}
|
||||
|
||||
fun sendDigit(digit: Char): Int {
|
||||
@ -54,7 +64,6 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
return call_duration(callp)
|
||||
}
|
||||
|
||||
|
||||
fun stats(stream: String): String {
|
||||
return call_stats(callp, stream)
|
||||
}
|
||||
@ -63,6 +72,10 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
return call_audio_codecs(callp)
|
||||
}
|
||||
|
||||
fun replaces(): Boolean {
|
||||
return call_replaces(callp)
|
||||
}
|
||||
|
||||
init {
|
||||
if (ua.account.mediaEnc != "") security = R.drawable.box_red
|
||||
}
|
||||
@ -78,6 +91,8 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
private external fun call_duration(callp: Long): Int
|
||||
private external fun call_stats(callp: Long, stream: String): String
|
||||
private external fun call_has_video(callp: Long): Boolean
|
||||
private external fun call_replaces(callp: Long): Boolean
|
||||
private external fun call_replace_transfer(xfer_callp: Long, callp: Long): Boolean
|
||||
|
||||
companion object {
|
||||
|
||||
@ -85,13 +100,6 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
return BaresipService.calls
|
||||
}
|
||||
|
||||
fun uaCalls(ua: UserAgent, dir: String): ArrayList<Call> {
|
||||
val result = ArrayList<Call>()
|
||||
for (c in BaresipService.calls)
|
||||
if ((c.ua == ua) && ((dir == "") || c.dir == dir)) result.add(c)
|
||||
return result
|
||||
}
|
||||
|
||||
fun ofCallp(callp: Long): Call? {
|
||||
for (c in BaresipService.calls)
|
||||
if (c.callp == callp) return c
|
||||
@ -104,12 +112,5 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
return null
|
||||
}
|
||||
|
||||
fun isStatus(status: String): Boolean {
|
||||
for (call in BaresipService.calls)
|
||||
if (call.status == status)
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.tutpro.baresip
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.app.KeyguardManager
|
||||
import android.app.NotificationManager
|
||||
import android.content.*
|
||||
@ -75,6 +76,7 @@ class MainActivity : AppCompatActivity() {
|
||||
private var speakerIcon: MenuItem? = null
|
||||
private lateinit var swipeRefresh: SwipeRefreshLayout
|
||||
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
|
||||
private var executeTransferDialog: androidx.appcompat.app.AlertDialog? = null
|
||||
|
||||
private lateinit var accountsRequest: ActivityResultLauncher<Intent>
|
||||
private lateinit var chatRequests: ActivityResultLauncher<Intent>
|
||||
@ -297,7 +299,8 @@ class MainActivity : AppCompatActivity() {
|
||||
setTitle(R.string.info)
|
||||
setMessage(getString(R.string.call_is_secure))
|
||||
setPositiveButton(getString(R.string.unverify)) { dialog, _ ->
|
||||
val calls = Call.uaCalls(UserAgent.uas()[aorSpinner.selectedItemPosition], "")
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val calls = ua.calls()
|
||||
if (calls.size > 0) {
|
||||
if (Api.cmd_exec("zrtp_unverify " + calls[0].zid) != 0) {
|
||||
Log.e(TAG, "Command 'zrtp_unverify ${calls[0].zid}' failed")
|
||||
@ -329,7 +332,7 @@ class MainActivity : AppCompatActivity() {
|
||||
hangupButton.setOnClickListener {
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val uaCalls = Call.uaCalls(ua, "")
|
||||
val uaCalls = ua.calls()
|
||||
if (uaCalls.size > 0) {
|
||||
val call = uaCalls[uaCalls.size - 1]
|
||||
val callp = call.callp
|
||||
@ -344,7 +347,7 @@ class MainActivity : AppCompatActivity() {
|
||||
answerButton.setOnClickListener {
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val callp = Call.uaCalls(ua, "in")[0].callp
|
||||
val callp = ua.calls("in")[0].callp
|
||||
Log.d(TAG, "AoR $aor answering call $callp from ${callUri.text}")
|
||||
answerButton.isEnabled = false
|
||||
rejectButton.isEnabled = false
|
||||
@ -359,7 +362,7 @@ class MainActivity : AppCompatActivity() {
|
||||
rejectButton.setOnClickListener {
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val call = Call.uaCalls(ua, "in")[0]
|
||||
val call = ua.calls("in")[0]
|
||||
val callp = call.callp
|
||||
Log.d(TAG, "AoR $aor rejecting call $callp from ${callUri.text}")
|
||||
answerButton.isEnabled = false
|
||||
@ -371,7 +374,7 @@ class MainActivity : AppCompatActivity() {
|
||||
holdButton.setOnClickListener {
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val call = Call.uaCalls(ua, "")[0]
|
||||
val call = ua.calls()[0]
|
||||
if (call.onhold) {
|
||||
Log.d(TAG, "AoR $aor resuming call ${call.callp} with ${callUri.text}")
|
||||
call.resume()
|
||||
@ -391,7 +394,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
infoButton.setOnClickListener {
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val calls = Call.uaCalls(ua, "")
|
||||
val calls = ua.calls()
|
||||
if (calls.size > 0) {
|
||||
val call = calls[0]
|
||||
val stats = call.stats("audio")
|
||||
@ -982,6 +985,7 @@ class MainActivity : AppCompatActivity() {
|
||||
"call incoming", "call outgoing" -> {
|
||||
val callp = params[1] as Long
|
||||
if (BaresipService.isMainVisible) {
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
if (aor != aorSpinner.tag)
|
||||
spinToAor(aor)
|
||||
showCall(ua, Call.ofCallp(callp))
|
||||
@ -1110,6 +1114,14 @@ class MainActivity : AppCompatActivity() {
|
||||
showCall(ua)
|
||||
}
|
||||
"call closed" -> {
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
val call = ua.currentCall()
|
||||
if (call != null) {
|
||||
call.resume()
|
||||
startCallTimer(call)
|
||||
} else {
|
||||
callTimer.stop()
|
||||
}
|
||||
if (aor == aorSpinner.tag) {
|
||||
callUri.inputType = InputType.TYPE_CLASS_TEXT +
|
||||
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
@ -1122,7 +1134,6 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
if (speakerIcon != null)
|
||||
speakerIcon!!.setIcon(R.drawable.speaker_off)
|
||||
callTimer.stop()
|
||||
if ((Build.VERSION.SDK_INT >= 22 && kgm.isDeviceLocked) ||
|
||||
(Build.VERSION.SDK_INT < 22 && kgm.isKeyguardLocked && kgm.isKeyguardSecure))
|
||||
Utils.setShowWhenLocked(this, false)
|
||||
@ -1371,14 +1382,18 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun makeTransfer(ua: UserAgent) {
|
||||
|
||||
val layout = LayoutInflater.from(this)
|
||||
.inflate(R.layout.call_transfer_dialog, findViewById(android.R.id.content),
|
||||
false)
|
||||
.inflate(R.layout.call_transfer_dialog, findViewById(android.R.id.content), false)
|
||||
val blind = layout.findViewById(R.id.blind) as CheckBox
|
||||
val attended = layout.findViewById(R.id.attended) as CheckBox
|
||||
|
||||
val transferUri = layout.findViewById(R.id.transferUri) as AutoCompleteTextView
|
||||
transferUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
Contact.contactNames()))
|
||||
transferUri.threshold = 2
|
||||
transferUri.requestFocus()
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
||||
with(builder) {
|
||||
setView(layout)
|
||||
@ -1398,8 +1413,19 @@ class MainActivity : AppCompatActivity() {
|
||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||
} else {
|
||||
if (Call.uaCalls(ua, "").size > 0) {
|
||||
Call.uaCalls(ua, "")[0].transfer(uri)
|
||||
val call = ua.currentCall()
|
||||
if (call != null) {
|
||||
if (attended.isChecked) {
|
||||
if (call.hold()) {
|
||||
call.referTo = uri
|
||||
call(ua, uri, call)
|
||||
}
|
||||
} else {
|
||||
if (!call.transfer(uri)) {
|
||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||
String.format(getString(R.string.transfer_failed)))
|
||||
}
|
||||
}
|
||||
showCall(ua)
|
||||
}
|
||||
}
|
||||
@ -1411,6 +1437,27 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
val alertDialog = builder.create()
|
||||
|
||||
val call = ua.currentCall() ?: return
|
||||
val blindOrAttended = layout.findViewById(R.id.blindOrAttended) as RelativeLayout
|
||||
if (call.replaces()) {
|
||||
blind.setOnClickListener {
|
||||
if (blind.isChecked) {
|
||||
attended.isChecked = false
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).text = getString(R.string.transfer)
|
||||
}
|
||||
}
|
||||
attended.setOnClickListener {
|
||||
if (attended.isChecked) {
|
||||
blind.isChecked = false
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).text = getString(R.string.call)
|
||||
}
|
||||
}
|
||||
blindOrAttended.visibility = View.VISIBLE
|
||||
} else {
|
||||
blindOrAttended.visibility = View.GONE
|
||||
}
|
||||
|
||||
// This needs to be done after dialog has been created and before it is shown
|
||||
alertDialog.window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
alertDialog.show()
|
||||
@ -1608,20 +1655,23 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
}
|
||||
|
||||
private fun call(ua: UserAgent, uri: String): Boolean {
|
||||
private fun call(ua: UserAgent, uri: String, onHoldCall: Call? = null): Boolean {
|
||||
if (ua.account.aor != aorSpinner.tag)
|
||||
spinToAor(ua.account.aor)
|
||||
val callp = Api.ua_call_alloc(ua.uap, 0L, Api.VIDMODE_OFF)
|
||||
return if (callp != 0L) {
|
||||
Log.d(TAG, "Adding outgoing call ${ua.uap}/$callp/$uri")
|
||||
val call = Call(callp, ua, uri, "out", "outgoing", Utils.dtmfWatcher(callp))
|
||||
call.onHoldCall = onHoldCall
|
||||
call.add()
|
||||
val err = call.connect(uri)
|
||||
if (err == 0) {
|
||||
if (onHoldCall != null)
|
||||
onHoldCall.newCall = call
|
||||
if (call.connect(uri)) {
|
||||
showCall(ua)
|
||||
true
|
||||
} else {
|
||||
Log.w(TAG, "call_connect $callp failed with error $err")
|
||||
showCall(ua)
|
||||
Log.w(TAG, "call_connect $callp failed")
|
||||
false
|
||||
}
|
||||
} else {
|
||||
@ -1637,13 +1687,12 @@ class MainActivity : AppCompatActivity() {
|
||||
val newCall = Call(newCallp, ua, uri, "out", "transferring",
|
||||
Utils.dtmfWatcher(newCallp))
|
||||
newCall.add()
|
||||
val err = newCall.connect(uri)
|
||||
if (err == 0) {
|
||||
if (newCall.connect(uri)) {
|
||||
if (ua.account.aor != aorSpinner.tag)
|
||||
spinToAor(ua.account.aor)
|
||||
showCall(ua)
|
||||
} else {
|
||||
Log.w(TAG, "call_connect $newCallp failed with error $err")
|
||||
Log.w(TAG, "call_connect $newCallp failed")
|
||||
call.notifySipfrag(500, "Call Error")
|
||||
}
|
||||
} else {
|
||||
@ -1712,6 +1761,7 @@ class MainActivity : AppCompatActivity() {
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
hangupButton.isEnabled = false
|
||||
} else {
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
callButton.visibility = View.INVISIBLE
|
||||
callButton.isEnabled = false
|
||||
hangupButton.visibility = View.VISIBLE
|
||||
@ -1728,7 +1778,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun showCall(ua: UserAgent, showCall: Call? = null) {
|
||||
if (Call.uaCalls(ua, "").size == 0) {
|
||||
val call = showCall ?: ua.currentCall()
|
||||
if (call == null) {
|
||||
swipeRefresh.isEnabled = true
|
||||
callTitle.text = getString(R.string.outgoing_call_to_dots)
|
||||
callTimer.visibility = View.INVISIBLE
|
||||
@ -1757,7 +1808,6 @@ class MainActivity : AppCompatActivity() {
|
||||
onHoldNotice.visibility = View.GONE
|
||||
} else {
|
||||
swipeRefresh.isEnabled = false
|
||||
val call = showCall ?: Call.uaCalls(ua, "")[0]
|
||||
callUri.isFocusable = false
|
||||
when (call.status) {
|
||||
"outgoing", "transferring", "answered" -> {
|
||||
@ -1813,9 +1863,26 @@ class MainActivity : AppCompatActivity() {
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
transferButton.isEnabled = true
|
||||
}
|
||||
callTimer.base = SystemClock.elapsedRealtime() - (call.duration() * 1000L)
|
||||
callTimer.stop()
|
||||
callTimer.start()
|
||||
if (call.onHoldCall != null) {
|
||||
val builder = MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
||||
with(builder) {
|
||||
setTitle(getString(R.string.execute_transfer))
|
||||
setPositiveButton(getText(R.string.yes)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
call.executeTransfer()
|
||||
}
|
||||
setNeutralButton(getText(R.string.no)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
Api.ua_hangup(ua.uap, call.callp, 0, "")
|
||||
}
|
||||
}
|
||||
executeTransferDialog = builder.create()
|
||||
executeTransferDialog!!.show()
|
||||
} else {
|
||||
executeTransferDialog?.dismiss()
|
||||
executeTransferDialog = null
|
||||
}
|
||||
startCallTimer(call)
|
||||
callTimer.visibility = View.VISIBLE
|
||||
if (ua.account.mediaEnc == "") {
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
@ -1981,13 +2048,19 @@ class MainActivity : AppCompatActivity() {
|
||||
private fun saveCallUri() {
|
||||
if (UserAgent.uas().isNotEmpty() && aorSpinner.selectedItemPosition >= 0) {
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
if (Call.uaCalls(ua, "").size == 0)
|
||||
if (ua.calls().isEmpty())
|
||||
ua.account.resumeUri = callUri.text.toString()
|
||||
else
|
||||
ua.account.resumeUri = ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCallTimer(call: Call) {
|
||||
callTimer.stop()
|
||||
callTimer.base = SystemClock.elapsedRealtime() - (call.duration() * 1000L)
|
||||
callTimer.start()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var accountRequest: ActivityResultLauncher<Intent>? = null
|
||||
|
||||
@ -7,10 +7,11 @@ import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat.getColor
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class UaSpinnerAdapter(cxt: Context, private val uas: ArrayList<UserAgent>,
|
||||
class UaSpinnerAdapter(private val cxt: Context, private val uas: ArrayList<UserAgent>,
|
||||
private val images: ArrayList<Int>) :
|
||||
ArrayAdapter<Int>(cxt, android.R.layout.simple_spinner_item, images) {
|
||||
|
||||
@ -43,8 +44,11 @@ class UaSpinnerAdapter(cxt: Context, private val uas: ArrayList<UserAgent>,
|
||||
viewHolder = rowView.tag as ViewHolder
|
||||
}
|
||||
|
||||
viewHolder.textView.text = uas[position].account.aor.split(":")[1]
|
||||
val ua = uas[position]
|
||||
viewHolder.textView.text = ua.account.aor.split(":")[1]
|
||||
viewHolder.textView.textSize = 17f
|
||||
if (ua.calls().isNotEmpty())
|
||||
viewHolder.textView.setTextColor(getColor(cxt, R.color.colorRed))
|
||||
viewHolder.imageView.setImageResource(images[position])
|
||||
|
||||
return rowView
|
||||
|
||||
@ -19,6 +19,20 @@ class UserAgent(val uap: Long) {
|
||||
BaresipService.status[BaresipService.uas.indexOf(this)] = status
|
||||
}
|
||||
|
||||
fun calls(dir: String = ""): ArrayList<Call> {
|
||||
val result = ArrayList<Call>()
|
||||
for (c in BaresipService.calls)
|
||||
if ((c.ua == this) && ((dir == "") || c.dir == dir)) result.add(c)
|
||||
return result
|
||||
}
|
||||
|
||||
fun currentCall(): Call? {
|
||||
for (c in BaresipService.calls)
|
||||
if (c.ua == this)
|
||||
return c
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun uas(): ArrayList<UserAgent> {
|
||||
|
||||
@ -123,6 +123,7 @@ object Utils {
|
||||
val params = uriParams(u)
|
||||
if (uri.startsWith("<") && (uri.endsWith(">")))
|
||||
u = uri.substring(1).substringBeforeLast(">")
|
||||
u = u.substringBefore("?")
|
||||
u = u.replace(":5060", "")
|
||||
u = u.replace(";transport=udp", "", true)
|
||||
if (u.split(":").size == 3 ||
|
||||
|
||||
@ -11,15 +11,67 @@
|
||||
android:paddingTop="?dialogPreferredPadding"
|
||||
android:paddingStart="?dialogPreferredPadding"
|
||||
android:paddingEnd="?dialogPreferredPadding"
|
||||
android:paddingBottom="8dp"
|
||||
android:textSize="20sp"
|
||||
android:text="@string/call_transfer"
|
||||
android:textColor="@color/colorPrimary" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/blindOrAttended"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="?dialogPreferredPadding"
|
||||
android:paddingEnd="?dialogPreferredPadding"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/blindTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/blind" >
|
||||
</TextView>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/blind"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/blindTitle"
|
||||
android:checked="true" >
|
||||
</CheckBox>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/attendedTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@id/attended"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/attended" >
|
||||
</TextView>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/attended"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:checked="false" >
|
||||
</CheckBox>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/transferDestination"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="?dialogPreferredPadding"
|
||||
android:paddingEnd="?dialogPreferredPadding"
|
||||
android:paddingStart="?dialogPreferredPadding"
|
||||
android:paddingBottom="12dp"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/transfer_destination"
|
||||
android:textColor="@color/colorStrong" />
|
||||
|
||||
@ -452,8 +452,11 @@
|
||||
<string name="call_is_on_hold">Puhelu on pidossa</string>
|
||||
<string name="mic">Mikrofoni päälle/pois</string>
|
||||
<string name="call_transfer">Puhelun siirto</string>
|
||||
<string name="blind">Sokeasti</string>
|
||||
<string name="attended">Osallistu</string>
|
||||
<string name="transfer_destination">Siirron kohde</string>
|
||||
<string name="transfer">Siirto</string>
|
||||
<string name="execute_transfer">Suorita siirto</string>
|
||||
<string name="transfer_failed">Siirto epäonnistui</string>
|
||||
<string name="dtmf">DTMF</string>
|
||||
<string name="call_info">Puhelutiedot</string>
|
||||
|
||||
@ -412,8 +412,11 @@
|
||||
<string name="call_is_on_hold">Call is on hold</string>
|
||||
<string name="mic">Microphone On/Off</string>
|
||||
<string name="call_transfer">Call Transfer</string>
|
||||
<string name="blind">Blind</string>
|
||||
<string name="attended">Attended</string>
|
||||
<string name="transfer_destination">Transfer destination</string>
|
||||
<string name="transfer">Transfer</string>
|
||||
<string name="execute_transfer">Execute Transfer</string>
|
||||
<string name="transfer_failed">Transfer Failed</string>
|
||||
<string name="dtmf">DTMF</string>
|
||||
<string name="call_info">Call Info</string>
|
||||
|
||||
Reference in New Issue
Block a user