added support for incoming call transfer requests (REFER requests)
This commit is contained in:
+2
-2
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId = 'com.tutpro.baresip'
|
applicationId = 'com.tutpro.baresip'
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode = 26
|
versionCode = 27
|
||||||
versionName = '3.0.5'
|
versionName = '3.1.0'
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
cFlags '-DHAVE_INTTYPES_H'
|
cFlags '-DHAVE_INTTYPES_H'
|
||||||
|
|||||||
+92
-27
@@ -131,6 +131,9 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev,
|
|||||||
else
|
else
|
||||||
re_snprintf(event_buf, sizeof event_buf, "%s", "unknown menc event");
|
re_snprintf(event_buf, sizeof event_buf, "%s", "unknown menc event");
|
||||||
break;
|
break;
|
||||||
|
case UA_EVENT_CALL_TRANSFER:
|
||||||
|
re_snprintf(event_buf, sizeof event_buf, "call transfer,%s", prm);
|
||||||
|
break;
|
||||||
case UA_EVENT_CALL_CLOSED:
|
case UA_EVENT_CALL_CLOSED:
|
||||||
play = mem_deref(play);
|
play = mem_deref(play);
|
||||||
if (call_scode(call)) {
|
if (call_scode(call)) {
|
||||||
@@ -881,6 +884,31 @@ Java_com_tutpro_baresip_MainActivity_ua_1connect(JNIEnv *env, jobject thiz,
|
|||||||
return (*env)->NewStringUTF(env, call_buf);
|
return (*env)->NewStringUTF(env, call_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_com_tutpro_baresip_MainActivity_ua_1call_1alloc(JNIEnv *env, jobject thiz,
|
||||||
|
jstring javaUA, jstring javaXCall) {
|
||||||
|
struct call *xcall, *call = NULL;
|
||||||
|
struct ua *ua;
|
||||||
|
int err;
|
||||||
|
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||||
|
const char *native_xcall = (*env)->GetStringUTFChars(env, javaXCall, 0);
|
||||||
|
char call_buf[64];
|
||||||
|
LOGD("allocating new call for ua %s xcall %s\n", native_ua, native_xcall);
|
||||||
|
ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||||
|
xcall = (struct call *)strtoul(native_xcall, NULL, 10);
|
||||||
|
re_thread_enter();
|
||||||
|
err = ua_call_alloc(&call, ua, VIDMODE_OFF, NULL, xcall, call_localuri(xcall), true);
|
||||||
|
if (err) {
|
||||||
|
LOGW("call allocation for ua %s failed with error %d\n", native_ua, err);
|
||||||
|
call_buf[0] = '\0';
|
||||||
|
} else {
|
||||||
|
sprintf(call_buf, "%lu", (unsigned long)call);
|
||||||
|
}
|
||||||
|
re_thread_leave();
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaXCall, native_xcall);
|
||||||
|
return (*env)->NewStringUTF(env, call_buf);
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_tutpro_baresip_MainActivity_ua_1answer(JNIEnv *env, jobject thiz,
|
Java_com_tutpro_baresip_MainActivity_ua_1answer(JNIEnv *env, jobject thiz,
|
||||||
@@ -900,28 +928,45 @@ Java_com_tutpro_baresip_MainActivity_ua_1answer(JNIEnv *env, jobject thiz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_tutpro_baresip_MainActivity_ua_1hold_1answer(JNIEnv *env, jobject thiz,
|
Java_com_tutpro_baresip_MainActivity_call_1connect(JNIEnv *env, jobject thiz, jstring javaCall,
|
||||||
jstring javaUA, jstring javaCall) {
|
jstring javaPeer) {
|
||||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
|
||||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||||
int ret;
|
const char *native_peer = (*env)->GetStringUTFChars(env, javaPeer, 0);
|
||||||
LOGD("answering call %s/%s\n", native_ua, native_call);
|
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||||
struct ua *ua = (struct ua *) strtoul(native_ua, NULL, 10);
|
LOGD("connecting call %s to %s\n", native_call, native_peer);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
|
||||||
struct call *call;
|
|
||||||
if (strlen(native_call) > 0)
|
|
||||||
call = (struct call *) strtoul(native_call, NULL, 10);
|
|
||||||
else
|
|
||||||
call = NULL;
|
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
|
||||||
play = mem_deref(play);
|
|
||||||
audio_set_source(call_audio(ua_call(uag_current())), NULL, NULL);
|
|
||||||
re_thread_enter();
|
re_thread_enter();
|
||||||
call_hold(ua_call(uag_current()), true);
|
struct pl pl;
|
||||||
ua_answer(ua, call);
|
pl_set_str(&pl, native_peer);
|
||||||
ret = ua_hold_answer(ua, call);
|
int err = call_connect(call, &pl);
|
||||||
re_thread_leave();
|
re_thread_leave();
|
||||||
return ret;
|
if (err) LOGW("call_connect error: %d\n", err);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaPeer, native_peer);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_tutpro_baresip_MainActivity_call_1start_1audio(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||||
|
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||||
|
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||||
|
LOGD("starting audio of call %s\n", native_call);
|
||||||
|
re_thread_enter();
|
||||||
|
audio_start(call_audio(call));
|
||||||
|
re_thread_leave();
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_tutpro_baresip_MainActivity_call_1stop_1audio(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||||
|
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||||
|
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||||
|
LOGD("stopping audio of call %s\n", native_call);
|
||||||
|
re_thread_enter();
|
||||||
|
audio_stop(call_audio(call));
|
||||||
|
re_thread_leave();
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
@@ -932,27 +977,26 @@ Java_com_tutpro_baresip_MainActivity_call_1hold(JNIEnv *env, jobject thiz,
|
|||||||
int ret;
|
int ret;
|
||||||
LOGD("holding call %s\n", native_call);
|
LOGD("holding call %s\n", native_call);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
struct audio *au = call_audio(call);
|
|
||||||
audio_set_hold(au, true);
|
|
||||||
audio_set_source(au, NULL, NULL);
|
|
||||||
re_thread_enter();
|
re_thread_enter();
|
||||||
|
struct audio *au = call_audio(call);
|
||||||
|
//audio_set_hold(au, true);
|
||||||
|
// audio_set_source(au, NULL, NULL);
|
||||||
ret = call_hold(call, true);
|
ret = call_hold(call, true);
|
||||||
re_thread_leave();
|
re_thread_leave();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_tutpro_baresip_MainActivity_call_1unhold(JNIEnv *env, jobject thiz,
|
Java_com_tutpro_baresip_MainActivity_call_1unhold(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||||
jstring javaCall) {
|
|
||||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||||
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
||||||
int ret;
|
int ret;
|
||||||
LOGD("unholding call %s\n", native_call);
|
LOGD("unholding call %s\n", native_call);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
struct audio *au = call_audio(call);
|
|
||||||
audio_set_hold(au, false);
|
|
||||||
audio_set_source(au, "opensles", "nil");
|
|
||||||
re_thread_enter();
|
re_thread_enter();
|
||||||
|
struct audio *au = call_audio(call);
|
||||||
|
// audio_set_hold(au, false);
|
||||||
|
// audio_set_source(au, "opensles", "nil");
|
||||||
ret = call_hold(call, false);
|
ret = call_hold(call, false);
|
||||||
re_thread_leave();
|
re_thread_leave();
|
||||||
return ret;
|
return ret;
|
||||||
@@ -988,8 +1032,10 @@ Java_com_tutpro_baresip_MainActivity_call_1send_1digit(JNIEnv *env, jobject thiz
|
|||||||
const uint16_t native_digit = digit;
|
const uint16_t native_digit = digit;
|
||||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||||
LOGD("sending DTMF digit '%c' to call %s\n", (char)native_digit, native_call);
|
LOGD("sending DTMF digit '%c' to call %s\n", (char)native_digit, native_call);
|
||||||
|
re_thread_enter();
|
||||||
int res = call_send_digit(call, (char)native_digit);
|
int res = call_send_digit(call, (char)native_digit);
|
||||||
if (!res) res = call_send_digit(call, KEYCODE_REL);
|
if (!res) res = call_send_digit(call, KEYCODE_REL);
|
||||||
|
re_thread_leave();
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1005,7 +1051,9 @@ Java_com_tutpro_baresip_MessageActivity_message_1send(JNIEnv *env, jobject thiz,
|
|||||||
const char *native_time = (*env)->GetStringUTFChars(env, javaTime, 0);
|
const char *native_time = (*env)->GetStringUTFChars(env, javaTime, 0);
|
||||||
LOGD("sending message from ua %s to %s at %s\n", native_ua, native_peer, native_time);
|
LOGD("sending message from ua %s to %s at %s\n", native_ua, native_peer, native_time);
|
||||||
ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||||
|
re_thread_enter();
|
||||||
int err = message_send(ua, native_peer, native_msg, send_resp_handler, (void *)native_time);
|
int err = message_send(ua, native_peer, native_msg, send_resp_handler, (void *)native_time);
|
||||||
|
re_thread_leave();
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGW("message_send failed with error %d\n", err);
|
LOGW("message_send failed with error %d\n", err);
|
||||||
}
|
}
|
||||||
@@ -1015,6 +1063,23 @@ Java_com_tutpro_baresip_MessageActivity_message_1send(JNIEnv *env, jobject thiz,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_tutpro_baresip_MainActivity_call_1notify_1sipfrag(JNIEnv *env, jobject thiz,
|
||||||
|
jstring javaCall, jint code, jstring reason) {
|
||||||
|
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||||
|
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||||
|
const uint16_t native_code = code;
|
||||||
|
const char *native_reason = (*env)->GetStringUTFChars(env, reason, 0);
|
||||||
|
LOGD("notifying call %s/%s\n", native_call, native_reason);
|
||||||
|
re_thread_enter();
|
||||||
|
(void)call_notify_sipfrag(call, native_code, native_reason);
|
||||||
|
re_thread_leave();
|
||||||
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, reason, native_reason);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_tutpro_baresip_ContactsActivity_00024Companion_contacts_1remove(JNIEnv *env, jobject thiz) {
|
Java_com_tutpro_baresip_ContactsActivity_00024Companion_contacts_1remove(JNIEnv *env, jobject thiz) {
|
||||||
struct le *le;
|
struct le *le;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class Account(val accp: String) {
|
|||||||
else
|
else
|
||||||
res = res + ";vm_uri=\"$vmUri\""
|
res = res + ";vm_uri=\"$vmUri\""
|
||||||
|
|
||||||
res = res + ";ptime=20;regint=${regint};regq=0.5;pubint=0;answermode=manual;call_transfer=no"
|
res = res + ";ptime=20;regint=${regint};regq=0.5;pubint=0;answermode=manual;call_transfer=yes"
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,80 +121,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val ua = uas[position]
|
val ua = uas[position]
|
||||||
Log.d("Baresip", "Setting $aor current")
|
Log.d("Baresip", "Setting $aor current")
|
||||||
uag_current_set(uas[position].uap)
|
uag_current_set(uas[position].uap)
|
||||||
val callsOut = Call.uaCalls(calls, ua, "out")
|
showCall(ua)
|
||||||
val callsIn = Call.uaCalls(calls, ua, "in")
|
|
||||||
if ((callsOut.size == 0) && (callsIn.size == 0)) {
|
|
||||||
callTitle.text = "Outgoing call to ..."
|
|
||||||
callUri.text.clear()
|
|
||||||
callUri.hint = "Callee"
|
|
||||||
securityButton.visibility = View.INVISIBLE
|
|
||||||
callButton.visibility = View.VISIBLE
|
|
||||||
hangupButton.visibility = View.INVISIBLE
|
|
||||||
answerButton.visibility = View.INVISIBLE
|
|
||||||
rejectButton.visibility = View.INVISIBLE
|
|
||||||
dtmf.visibility = View.INVISIBLE
|
|
||||||
} else {
|
|
||||||
val call: Call
|
|
||||||
if (callsOut.size > 0) {
|
|
||||||
callTitle.text = "Outgoing call to ..."
|
|
||||||
call = callsOut[0]
|
|
||||||
} else {
|
|
||||||
callTitle.text = "Incoming call from ..."
|
|
||||||
call = callsIn[0]
|
|
||||||
}
|
|
||||||
callUri.setText(call.peerURI)
|
|
||||||
when (call.status) {
|
|
||||||
"outgoing" -> {
|
|
||||||
securityButton.visibility = View.INVISIBLE
|
|
||||||
callButton.visibility = View.INVISIBLE
|
|
||||||
hangupButton.visibility = View.VISIBLE
|
|
||||||
answerButton.visibility = View.INVISIBLE
|
|
||||||
rejectButton.visibility = View.INVISIBLE
|
|
||||||
holdButton.visibility = View.INVISIBLE
|
|
||||||
dtmf.visibility = View.INVISIBLE
|
|
||||||
}
|
|
||||||
"incoming" -> {
|
|
||||||
securityButton.visibility = View.INVISIBLE
|
|
||||||
callButton.visibility = View.INVISIBLE
|
|
||||||
hangupButton.visibility = View.INVISIBLE
|
|
||||||
answerButton.visibility = View.VISIBLE
|
|
||||||
answerButton.isEnabled = true
|
|
||||||
rejectButton.visibility = View.VISIBLE
|
|
||||||
rejectButton.isEnabled = true
|
|
||||||
holdButton.visibility = View.INVISIBLE
|
|
||||||
dtmf.visibility = View.INVISIBLE
|
|
||||||
if (answerCall == call.callp) {
|
|
||||||
answerCall = ""
|
|
||||||
answerButton.performClick()
|
|
||||||
}
|
|
||||||
if (rejectCall == call.callp) {
|
|
||||||
rejectCall = ""
|
|
||||||
rejectButton.performClick()
|
|
||||||
moveTaskToBack(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"connected" -> {
|
|
||||||
securityButton.setImageResource(call.security)
|
|
||||||
setSecurityButtonTag(securityButton, call.security)
|
|
||||||
if ((acc.mediaenc == "zrtp") || (acc.mediaenc == "dtls_srtpf"))
|
|
||||||
securityButton.visibility = View.VISIBLE
|
|
||||||
else
|
|
||||||
securityButton.visibility = View.INVISIBLE
|
|
||||||
callButton.visibility = View.INVISIBLE
|
|
||||||
hangupButton.visibility = View.VISIBLE
|
|
||||||
answerButton.visibility = View.INVISIBLE
|
|
||||||
rejectButton.visibility = View.INVISIBLE
|
|
||||||
if (call.onhold) {
|
|
||||||
holdButton.setImageResource(R.drawable.play)
|
|
||||||
} else {
|
|
||||||
holdButton.setImageResource(R.drawable.pause)
|
|
||||||
}
|
|
||||||
holdButton.visibility = View.VISIBLE
|
|
||||||
dtmf.visibility = View.VISIBLE
|
|
||||||
dtmf.requestFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acc.vmUri != "") {
|
if (acc.vmUri != "") {
|
||||||
if (acc.vmNew > 0)
|
if (acc.vmNew > 0)
|
||||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||||
@@ -305,10 +232,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
hangupButton.setOnClickListener {
|
hangupButton.setOnClickListener {
|
||||||
val ua = uas[aorSpinner.selectedItemPosition]
|
val ua = uas[aorSpinner.selectedItemPosition]
|
||||||
val aor = ua.account.aor
|
val aor = ua.account.aor
|
||||||
val callp = Call.uaCalls(calls, ua,"")[0].callp
|
val uaCalls = Call.uaCalls(calls, ua, "")
|
||||||
Log.d("Baresip", "AoR $aor hanging up call $callp with ${callUri.text}")
|
if (uaCalls.size > 0) {
|
||||||
hangupButton.isEnabled = false
|
val callp = uaCalls[uaCalls.size - 1].callp
|
||||||
ua_hangup(ua.uap, callp, 0, "")
|
Log.d("Baresip", "AoR $aor hanging up call $callp with ${callUri.text}")
|
||||||
|
hangupButton.isEnabled = false
|
||||||
|
ua_hangup(ua.uap, callp, 0, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
answerButton.setOnClickListener {
|
answerButton.setOnClickListener {
|
||||||
@@ -521,6 +451,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
call.onhold = false
|
call.onhold = false
|
||||||
call.security = R.drawable.box_red
|
call.security = R.drawable.box_red
|
||||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||||
|
if (call.dir == "in")
|
||||||
|
callTitle.text = "Incoming call from ..."
|
||||||
|
else
|
||||||
|
callTitle.text = "Outgoing call to ..."
|
||||||
if (acc.mediaenc == "") {
|
if (acc.mediaenc == "") {
|
||||||
securityButton.visibility = View.INVISIBLE
|
securityButton.visibility = View.INVISIBLE
|
||||||
} else {
|
} else {
|
||||||
@@ -619,6 +553,29 @@ class MainActivity : AppCompatActivity() {
|
|||||||
securityButton.visibility = View.VISIBLE
|
securityButton.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"call transfer" -> {
|
||||||
|
val callp = params[1]
|
||||||
|
val call = Call.find(calls, callp)
|
||||||
|
if (call == null) {
|
||||||
|
Log.e("Baresip", "Call $callp to be transfered is not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val transferDialog = AlertDialog.Builder(this)
|
||||||
|
transferDialog.setMessage("Do you want to transfer this call to ${ev[1]}?")
|
||||||
|
transferDialog.setPositiveButton("Yes") { dialog, _ ->
|
||||||
|
if (call in calls)
|
||||||
|
transfer(ua, call, ev[1])
|
||||||
|
else
|
||||||
|
call(ua, ev[1])
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
transferDialog.setNegativeButton("No") { dialog, _ ->
|
||||||
|
if (call in calls)
|
||||||
|
call_notify_sipfrag(callp, 603, "Decline")
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
transferDialog.create().show()
|
||||||
|
}
|
||||||
"call closed" -> {
|
"call closed" -> {
|
||||||
val callp = params[1]
|
val callp = params[1]
|
||||||
val call = Call.find(calls, callp)
|
val call = Call.find(calls, callp)
|
||||||
@@ -629,20 +586,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Log.d("Baresip", "Removing call ${uap}/${callp}/" + call.peerURI)
|
Log.d("Baresip", "Removing call ${uap}/${callp}/" + call.peerURI)
|
||||||
stopRinging()
|
stopRinging()
|
||||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||||
callTitle.text = "Outgoing call to ..."
|
|
||||||
callUri.setText("")
|
|
||||||
callUri.hint = "Callee"
|
|
||||||
securityButton.visibility = View.INVISIBLE
|
|
||||||
callButton.visibility = View.VISIBLE
|
|
||||||
hangupButton.visibility = View.INVISIBLE
|
|
||||||
answerButton.visibility = View.INVISIBLE
|
|
||||||
rejectButton.visibility = View.INVISIBLE
|
|
||||||
holdButton.visibility = View.INVISIBLE
|
|
||||||
dtmf.visibility = View.INVISIBLE
|
|
||||||
imm.hideSoftInputFromWindow(dtmf.windowToken, 0)
|
|
||||||
dtmf.removeTextChangedListener(call.dtmfWatcher)
|
dtmf.removeTextChangedListener(call.dtmfWatcher)
|
||||||
}
|
}
|
||||||
calls.remove(call)
|
calls.remove(call)
|
||||||
|
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||||
|
showCall(ua)
|
||||||
|
}
|
||||||
if (!call.hasHistory) {
|
if (!call.hasHistory) {
|
||||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||||
CallHistory.aorRemoveHistory(history, aor)
|
CallHistory.aorRemoveHistory(history, aor)
|
||||||
@@ -654,7 +603,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
callsButton.setImageResource(R.drawable.calls_missed)
|
callsButton.setImageResource(R.drawable.calls_missed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (calls.size == 0) am.mode = AudioManager.MODE_NORMAL
|
if (calls.size == 0) {
|
||||||
|
am.mode = AudioManager.MODE_NORMAL
|
||||||
|
} else {
|
||||||
|
val uaCalls = Call.uaCalls(calls, ua, "")
|
||||||
|
if (uaCalls.size > 0) call_start_audio(uaCalls[uaCalls.size - 1].callp)
|
||||||
|
}
|
||||||
if (am.isSpeakerphoneOn) {
|
if (am.isSpeakerphoneOn) {
|
||||||
am.isSpeakerphoneOn = false
|
am.isSpeakerphoneOn = false
|
||||||
val speakerIcon = findViewById(R.id.speakerIcon) as ActionMenuItemView
|
val speakerIcon = findViewById(R.id.speakerIcon) as ActionMenuItemView
|
||||||
@@ -977,6 +931,29 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun transfer(ua: UserAgent, call: Call, uri: String) {
|
||||||
|
val newCallp = ua_call_alloc(ua.uap, call.callp)
|
||||||
|
if (newCallp != "") {
|
||||||
|
Log.d("Baresip", "Adding outgoing call ${ua.uap}/$newCallp/$uri")
|
||||||
|
val newCall = Call(newCallp, ua, uri, "out", "transferring",
|
||||||
|
dtmfWatcher(newCallp))
|
||||||
|
calls.add(newCall)
|
||||||
|
call_stop_audio(call.callp)
|
||||||
|
call_start_audio(newCallp)
|
||||||
|
val err = call_connect(newCallp, uri)
|
||||||
|
if (err == 0) {
|
||||||
|
if (ua == uas[aorSpinner.selectedItemPosition]) showCall(ua)
|
||||||
|
} else {
|
||||||
|
call_start_audio(call.callp)
|
||||||
|
Log.w("Baresip", "call_connect $newCallp failed with error $err")
|
||||||
|
call_notify_sipfrag(call.callp, 500, "Call Error")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w("Baresip", "ua_call_alloc ${ua.uap}/${call.callp} failed")
|
||||||
|
call_notify_sipfrag(call.callp, 500, "Call Error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun dtmfWatcher(callp: String): TextWatcher {
|
private fun dtmfWatcher(callp: String): TextWatcher {
|
||||||
return object : TextWatcher {
|
return object : TextWatcher {
|
||||||
override fun beforeTextChanged(sequence: CharSequence, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(sequence: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
@@ -1010,6 +987,88 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showCall(ua: UserAgent) {
|
||||||
|
if (Call.uaCalls(calls, ua, "").size == 0) {
|
||||||
|
callTitle.text = "Outgoing call to ..."
|
||||||
|
callUri.text.clear()
|
||||||
|
callUri.hint = "Callee"
|
||||||
|
securityButton.visibility = View.INVISIBLE
|
||||||
|
callButton.visibility = View.VISIBLE
|
||||||
|
hangupButton.visibility = View.INVISIBLE
|
||||||
|
answerButton.visibility = View.INVISIBLE
|
||||||
|
rejectButton.visibility = View.INVISIBLE
|
||||||
|
holdButton.visibility = View.INVISIBLE
|
||||||
|
dtmf.visibility = View.INVISIBLE
|
||||||
|
} else {
|
||||||
|
val callsOut = Call.uaCalls(calls, ua, "out")
|
||||||
|
val callsIn = Call.uaCalls(calls, ua, "in")
|
||||||
|
val call: Call
|
||||||
|
if (callsOut.size > 0) {
|
||||||
|
call = callsOut[callsOut.size - 1]
|
||||||
|
if (call.status == "transferring")
|
||||||
|
callTitle.text = "Transferring call to ..."
|
||||||
|
else
|
||||||
|
callTitle.text = "Outgoing call to ..."
|
||||||
|
} else {
|
||||||
|
callTitle.text = "Incoming call from ..."
|
||||||
|
call = callsIn[callsIn.size - 1]
|
||||||
|
}
|
||||||
|
callUri.setText(call.peerURI)
|
||||||
|
when (call.status) {
|
||||||
|
"outgoing", "transferring" -> {
|
||||||
|
securityButton.visibility = View.INVISIBLE
|
||||||
|
callButton.visibility = View.INVISIBLE
|
||||||
|
hangupButton.visibility = View.VISIBLE
|
||||||
|
answerButton.visibility = View.INVISIBLE
|
||||||
|
rejectButton.visibility = View.INVISIBLE
|
||||||
|
holdButton.visibility = View.INVISIBLE
|
||||||
|
dtmf.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
"incoming" -> {
|
||||||
|
securityButton.visibility = View.INVISIBLE
|
||||||
|
callButton.visibility = View.INVISIBLE
|
||||||
|
hangupButton.visibility = View.INVISIBLE
|
||||||
|
answerButton.visibility = View.VISIBLE
|
||||||
|
answerButton.isEnabled = true
|
||||||
|
rejectButton.visibility = View.VISIBLE
|
||||||
|
rejectButton.isEnabled = true
|
||||||
|
holdButton.visibility = View.INVISIBLE
|
||||||
|
dtmf.visibility = View.INVISIBLE
|
||||||
|
if (answerCall == call.callp) {
|
||||||
|
answerCall = ""
|
||||||
|
answerButton.performClick()
|
||||||
|
}
|
||||||
|
if (rejectCall == call.callp) {
|
||||||
|
rejectCall = ""
|
||||||
|
rejectButton.performClick()
|
||||||
|
moveTaskToBack(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"connected" -> {
|
||||||
|
securityButton.setImageResource(call.security)
|
||||||
|
setSecurityButtonTag(securityButton, call.security)
|
||||||
|
if ((ua.account.mediaenc == "zrtp") || (ua.account.mediaenc == "dtls_srtpf"))
|
||||||
|
securityButton.visibility = View.VISIBLE
|
||||||
|
else
|
||||||
|
securityButton.visibility = View.INVISIBLE
|
||||||
|
callButton.visibility = View.INVISIBLE
|
||||||
|
hangupButton.visibility = View.VISIBLE
|
||||||
|
hangupButton.isEnabled = true
|
||||||
|
answerButton.visibility = View.INVISIBLE
|
||||||
|
rejectButton.visibility = View.INVISIBLE
|
||||||
|
if (call.onhold) {
|
||||||
|
holdButton.setImageResource(R.drawable.play)
|
||||||
|
} else {
|
||||||
|
holdButton.setImageResource(R.drawable.pause)
|
||||||
|
}
|
||||||
|
holdButton.visibility = View.VISIBLE
|
||||||
|
dtmf.visibility = View.VISIBLE
|
||||||
|
dtmf.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun requestAudioFocus(stream: Int) {
|
private fun requestAudioFocus(stream: Int) {
|
||||||
if (!audioFocused) {
|
if (!audioFocused) {
|
||||||
val res = am.requestAudioFocus(null, stream, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
val res = am.requestAudioFocus(null, stream, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
||||||
@@ -1047,12 +1106,16 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
external fun uag_current_set(uap: String)
|
external fun uag_current_set(uap: String)
|
||||||
external fun ua_connect(uap: String, peer_uri: String): String
|
external fun ua_connect(uap: String, peer_uri: String): String
|
||||||
|
external fun ua_call_alloc(uap: String, xcallp: String): String
|
||||||
external fun ua_answer(uap: String, callp: String)
|
external fun ua_answer(uap: String, callp: String)
|
||||||
external fun ua_hold_answer(uap: String, callp: String): Int
|
|
||||||
external fun ua_hangup(uap: String, callp: String, code: Int, reason: String)
|
external fun ua_hangup(uap: String, callp: String, code: Int, reason: String)
|
||||||
external fun call_hold(callp: String): Int
|
external fun call_hold(callp: String): Int
|
||||||
external fun call_unhold(callp: String): Int
|
external fun call_unhold(callp: String): Int
|
||||||
external fun call_send_digit(callp: String, digit: Char): Int
|
external fun call_send_digit(callp: String, digit: Char): Int
|
||||||
|
external fun call_connect(callp: String, peer_uri: String): Int
|
||||||
|
external fun call_notify_sipfrag(callp: String, code: Int, reason: String)
|
||||||
|
external fun call_start_audio(callp: String)
|
||||||
|
external fun call_stop_audio(callp: String)
|
||||||
external fun reload_config(): Int
|
external fun reload_config(): Int
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
Reference in New Issue
Block a user