diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index d0b74e61..fbc8754f 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -1062,6 +1062,42 @@ Java_com_tutpro_baresip_Api_account_1vm_1uri(JNIEnv *env, jobject thiz, jstring return (*env)->NewStringUTF(env, ""); } +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_account_1answermode(JNIEnv *env, jobject thiz, jstring jAcc) { + const char *native_acc = (*env)->GetStringUTFChars(env, jAcc, 0); + struct account *acc = (struct account *)strtoul(native_acc, NULL, 10); + (*env)->ReleaseStringUTFChars(env, jAcc, native_acc); + return account_answermode(acc); +} + +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_account_1set_1answermode(JNIEnv *env, jobject thiz, + jstring jAcc, jint jMode) { + const char *native_acc = (*env)->GetStringUTFChars(env, jAcc, 0); + struct account *acc = (struct account *)strtoul(native_acc, NULL, 10); + (*env)->ReleaseStringUTFChars(env, jAcc, native_acc); + const uint32_t mode = (uint32_t)jMode; + return account_set_answermode(acc, mode); +} + +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_account_1dtmfmode(JNIEnv *env, jobject thiz, jstring jAcc) { + const char *native_acc = (*env)->GetStringUTFChars(env, jAcc, 0); + struct account *acc = (struct account *)strtoul(native_acc, NULL, 10); + (*env)->ReleaseStringUTFChars(env, jAcc, native_acc); + return account_dtmfmode(acc); +} + +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_account_1set_1dtmfmode(JNIEnv *env, jobject thiz, + jstring jAcc, jint jMode) { + const char *native_acc = (*env)->GetStringUTFChars(env, jAcc, 0); + struct account *acc = (struct account *)strtoul(native_acc, NULL, 10); + (*env)->ReleaseStringUTFChars(env, jAcc, native_acc); + const uint32_t mode = (uint32_t)jMode; + return account_set_dtmfmode(acc, mode); +} + JNIEXPORT jstring JNICALL Java_com_tutpro_baresip_Api_account_1extra(JNIEnv *env, jobject thiz, jstring javaAcc) { diff --git a/app/src/main/kotlin/com/tutpro/baresip/Account.kt b/app/src/main/kotlin/com/tutpro/baresip/Account.kt index 0c106484..23544d88 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Account.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Account.kt @@ -21,7 +21,8 @@ class Account(val accp: String) { var regint = Api.account_regint(accp) var mediaEnc = Api.account_mediaenc(accp) var preferIPv6Media = false - var answerMode = "" + var dtmfMode = Api.account_dtmfmode(accp) + var answerMode = Api.account_answermode(accp) var vmUri = Api.account_vm_uri(accp) var vmNew = 0 var vmOld = 0 @@ -56,8 +57,6 @@ class Account(val accp: String) { val extra = Api.account_extra(accp) preferIPv6Media = Utils.paramValue(extra,"prefer_ipv6_media") == "yes" - answerMode = Utils.paramValue(extra,"answer_mode") - if (answerMode == "") answerMode = "manual" callHistory = Utils.paramValue(extra,"call_history") == "" } @@ -114,6 +113,9 @@ class Account(val accp: String) { else res = res + ";mwi=yes;vm_uri=\"$vmUri\"" + if (answerMode == Api.ANSWERMODE_AUTO) + res += ";answermode=auto" + res += ";ptime=20;regint=${regint};regq=0.5;pubint=0;call_transfer=yes" var extra = "" @@ -121,9 +123,6 @@ class Account(val accp: String) { if (!callHistory) extra += ";call_history=no" - if (answerMode == "auto") - extra += ";answer_mode=auto" - if (preferIPv6Media) extra += ";prefer_ipv6_media=yes" diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt index 259b539d..f27e41b4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt @@ -39,7 +39,9 @@ class AccountActivity : AppCompatActivity() { private lateinit var mediaEnc: String private lateinit var mediaEncSpinner: Spinner private lateinit var ipV6MediaCheck: CheckBox - private lateinit var answerMode: String + private var dtmfMode = Api.DTMFMODE_RTP_EVENT + private lateinit var dtmfModeSpinner: Spinner + private var answerMode = Api.ANSWERMODE_MANUAL private lateinit var answerModeSpinner: Spinner private lateinit var vmUri: EditText private lateinit var defaultCheck: CheckBox @@ -74,6 +76,7 @@ class AccountActivity : AppCompatActivity() { stunPass = binding.StunPass mediaEncSpinner = binding.mediaEncSpinner ipV6MediaCheck = binding.PreferIPv6Media + dtmfModeSpinner = binding.dtmfModeSpinner answerModeSpinner = binding.answerModeSpinner vmUri = binding.voicemailUri defaultCheck = binding.Default @@ -181,8 +184,29 @@ class AccountActivity : AppCompatActivity() { ipV6MediaCheck.isChecked = acc.preferIPv6Media + dtmfMode = acc.dtmfMode + val dtmfModeKeys = arrayListOf(Api.DTMFMODE_RTP_EVENT, Api.DTMFMODE_SIP_INFO) + val dtmfModeVals = arrayListOf(getString(R.string.dtmf_inband), getString(R.string.dtmf_info)) + keyIx = dtmfModeKeys.indexOf(acc.dtmfMode) + keyVal = dtmfModeVals.elementAt(keyIx) + dtmfModeKeys.removeAt(keyIx) + dtmfModeVals.removeAt(keyIx) + dtmfModeKeys.add(0, acc.dtmfMode) + dtmfModeVals.add(0, keyVal) + val dtmfModeAdapter = ArrayAdapter(this,android.R.layout.simple_spinner_item, + dtmfModeVals) + dtmfModeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + dtmfModeSpinner.adapter = dtmfModeAdapter + dtmfModeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { + dtmfMode = dtmfModeKeys[dtmfModeVals.indexOf(parent.selectedItem.toString())] + } + override fun onNothingSelected(parent: AdapterView<*>) { + } + } + answerMode = acc.answerMode - val answerModeKeys = arrayListOf("manual", "auto") + val answerModeKeys = arrayListOf(Api.ANSWERMODE_MANUAL, Api.ANSWERMODE_AUTO) val answerModeVals = arrayListOf(getString(R.string.manual), getString(R.string.auto)) keyIx = answerModeKeys.indexOf(acc.answerMode) keyVal = answerModeVals.elementAt(keyIx) @@ -436,10 +460,24 @@ class AccountActivity : AppCompatActivity() { save = true } + if (dtmfMode != acc.dtmfMode) { + if (Api.account_set_dtmfmode(acc.accp, dtmfMode) == 0) { + acc.dtmfMode = Api.account_dtmfmode(acc.accp) + Log.d(TAG, "New dtmfmode is ${acc.dtmfMode}") + save = true + } else { + Log.e(TAG, "Setting of dtmfmode $dtmfMode failed") + } + } + if (answerMode != acc.answerMode) { - acc.answerMode = answerMode - Log.d(TAG, "New answermode is ${acc.answerMode}") - save = true + if (Api.account_set_answermode(acc.accp, answerMode) == 0) { + acc.answerMode = Api.account_answermode(acc.accp) + Log.d(TAG, "New answermode is ${acc.answerMode}") + save = true + } else { + Log.e(TAG, "Setting of answermode $answerMode failed") + } } var tVmUri = vmUri.text.toString().trim() @@ -562,6 +600,10 @@ class AccountActivity : AppCompatActivity() { Utils.alertView(this, getString(R.string.prefer_ipv6_media), getString(R.string.prefer_ipv6_media_help)) } + binding.DtmfModeTitle -> { + Utils.alertView(this, getString(R.string.dtmf_mode), + getString(R.string.dtmf_mode_help)) + } binding.AnswerModeTitle -> { Utils.alertView(this, getString(R.string.answer_mode), getString(R.string.answer_mode_help)) @@ -649,9 +691,20 @@ class AccountActivity : AppCompatActivity() { acc.stunServer = text "prefer-ipv6-media" -> acc.preferIPv6Media = text == "yes" + "dtmf-mode" -> + if (text in arrayOf("rtp-event", "sip-info")) { + acc.dtmfMode = if (text == "rtp-event") + Api.DTMFMODE_RTP_EVENT + else + Api.DTMFMODE_SIP_INFO + } "answer-mode" -> - if (text in arrayOf("manual", "auto")) - acc.answerMode = text + if (text in arrayOf("manual", "auto")) { + acc.answerMode = if (text == "manual") + Api.ANSWERMODE_MANUAL + else + Api.ANSWERMODE_AUTO + } "voicemail-uri" -> if (text.isNotEmpty()) acc.vmUri = text diff --git a/app/src/main/kotlin/com/tutpro/baresip/Api.kt b/app/src/main/kotlin/com/tutpro/baresip/Api.kt index f251e55e..36da1793 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Api.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Api.kt @@ -7,6 +7,10 @@ object Api { const val AF_INET6 = 10 const val VIDMODE_OFF = 0 const val VIDMODE_ON = 1 + const val ANSWERMODE_MANUAL = 0 + const val ANSWERMODE_AUTO = 2 + const val DTMFMODE_RTP_EVENT = 0 + const val DTMFMODE_SIP_INFO = 1 external fun account_set_display_name(acc: String, dn: String): Int external fun account_display_name(acc: String): String @@ -36,6 +40,10 @@ object Api { external fun account_set_video_codecs(acc: String, codecs: String): Int external fun account_set_mwi(acc: String, value: String): Int external fun account_vm_uri(acc: String): String + external fun account_answermode(acc: String): Int + external fun account_set_answermode(acc: String, mode: Int): Int + external fun account_dtmfmode(acc: String): Int + external fun account_set_dtmfmode(acc: String, mode: Int): Int external fun account_extra(acc: String): String external fun account_debug(acc: String) diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 6a2c2854..28aed3bd 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -530,7 +530,7 @@ class BaresipService: Service() { Log.d(LOG_TAG, "Incoming call $uap/$callp/$peerUri") Call(callp, ua, peerUri, "in", "incoming", Utils.dtmfWatcher(callp)).add() - if (ua.account.answerMode == "manual") { + if (ua.account.answerMode == Api.ANSWERMODE_MANUAL) { if (Build.VERSION.SDK_INT >= 23) { Log.d(LOG_TAG, "CurrentInterruptionFilter ${nm.currentInterruptionFilter}") if (nm.currentInterruptionFilter <= NotificationManager.INTERRUPTION_FILTER_ALL) diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index b93f74af..18b14a24 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -277,6 +277,23 @@ + + + + + + + DTMF-moodi + Valitsee miten DTMF-merkit 0–9, #, * ja A-D lähetetään. + RTP-tapahtumina + SIP INFO-pyyntöinä Vastaustapa Valitsee tulevien puheluiden vastaustavan. Manuaalinen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c509134e..efabb6f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -166,6 +166,10 @@ Prefer IPv6 Media If checked, offer to use IPv6 media protocol (if available) when media protocol of peer cannot be automatically determined. + DTMF Mode + Selects how DTMF tones 0–9, #, *, and A-D are sent. + In-band RTP Events + SIP INFO Requests Answer Mode Selects how incoming calls are answered. Manual