diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 200317bc..95c1d5a7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,12 @@ android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/account" > + + GetStringUTFChars(env, jAcc, 0); + struct account *acc = (struct account *) strtoul(native_acc, NULL, 10); + (*env)->ReleaseStringUTFChars(env, jAcc, native_acc); + const char *codecs = (*env)->GetStringUTFChars(env, jCodecs, 0); + int res = account_set_video_codecs(acc, codecs); + (*env)->ReleaseStringUTFChars(env, jCodecs, codecs); + return res; +} + JNIEXPORT jint JNICALL Java_com_tutpro_baresip_AccountKt_account_1regint(JNIEnv *env, jobject thiz, jstring javaAcc) { const char *native_acc = (*env)->GetStringUTFChars(env, javaAcc, 0); @@ -1460,6 +1472,33 @@ Java_com_tutpro_baresip_Api_audio_1codecs(JNIEnv *env, jobject thiz) return (*env)->NewStringUTF(env, codec_buf); } +JNIEXPORT jstring JNICALL +Java_com_tutpro_baresip_Api_video_1codecs(JNIEnv *env, jobject thiz) +{ + struct list *vidcodecl = baresip_vidcodecl(); + struct le *le; + char codec_buf[256]; + char *start = &(codec_buf[0]); + unsigned int left = sizeof codec_buf; + int len; + for (le = list_head(vidcodecl); le != NULL; le = le->next) { + const struct vidcodec *vc = le->data; + if (start == &(codec_buf[0])) + len = re_snprintf(start, left, "%s", vc->name); + else + len = re_snprintf(start, left, ",%s", vc->name); + if (len == -1) { + LOGE("failed to print codec to buffer\n"); + codec_buf[0] = '\0'; + return (*env)->NewStringUTF(env, codec_buf); + } + start = start + len; + left = left - len; + } + *start = '\0'; + return (*env)->NewStringUTF(env, codec_buf); +} + JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_contact_1add(JNIEnv *env, jobject thiz, jstring javaContact) { struct pl pl_addr; diff --git a/app/src/main/kotlin/com/tutpro/baresip/Account.kt b/app/src/main/kotlin/com/tutpro/baresip/Account.kt index 261c6f9d..a68c4593 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Account.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Account.kt @@ -15,6 +15,7 @@ class Account(val accp: String) { var mediaNat = account_medianat(accp) var stunServer = "" var audioCodec = ArrayList() + var videoCodec = ArrayList() var regint = account_regint(accp) var mediaEnc = account_mediaenc(accp) var preferIPv6Media = false @@ -247,6 +248,7 @@ external fun account_set_mediaenc(acc: String, mediaenc: String): Int external fun account_medianat(acc: String): String external fun account_set_medianat(acc: String, medianat: String): Int external fun account_set_audio_codecs(acc: String, codecs: String): Int +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_extra(acc: String): String diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt index 55c40b3b..704539e7 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt @@ -37,7 +37,6 @@ class AccountActivity : AppCompatActivity() { internal lateinit var vmUri: EditText internal lateinit var defaultCheck: CheckBox - private var newCodecs = ArrayList() private var save = false private var uaIndex= -1 @@ -83,39 +82,6 @@ class AccountActivity : AppCompatActivity() { regCheck = findViewById(R.id.Register) as CheckBox regCheck.isChecked = acc.regint > 0 - val audioCodecs = ArrayList(Api.audio_codecs().split(",")) - newCodecs.addAll(acc.audioCodec) - while (newCodecs.size < audioCodecs.size) newCodecs.add("-") - val layout = findViewById(R.id.CodecSpinners) as LinearLayout - val spinnerList = Array(audioCodecs.size, {_ -> ArrayList()}) - for (i in audioCodecs.indices) { - val spinner = Spinner(applicationContext) - spinner.id = i + 100 - spinner.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) - layout.addView(spinner) - if (acc.audioCodec.size > i) { - val codec = acc.audioCodec[i] - spinnerList[i].add(codec) - spinnerList[i].add("-") - for (c in audioCodecs) if (c != codec) spinnerList[i].add(c) - } else { - spinnerList[i].addAll(audioCodecs) - spinnerList[i].add(0, "-") - } - val codecSpinner = findViewById(spinner.id) as Spinner - val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, - spinnerList[i]) - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - codecSpinner.adapter = adapter - codecSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { - newCodecs.set(parent.id - 100, parent.selectedItem.toString()) - } - override fun onNothingSelected(parent: AdapterView<*>) { - } - } - } - mediaNat = acc.mediaNat val mediaNatSpinner = findViewById(R.id.mediaNatSpinner) as Spinner val mediaNatKeys = arrayListOf("stun", "ice", "") @@ -379,18 +345,6 @@ class AccountActivity : AppCompatActivity() { } } - val ac = ArrayList(LinkedHashSet(newCodecs.filter { it != "-" } as ArrayList)) - if (ac != acc.audioCodec) { - val acList = Utils.implode(ac, ",") - if (account_set_audio_codecs(acc.accp, acList) == 0) { - Log.d("Baresip", "New audio codecs '$acList'") - acc.audioCodec = ac - save = true - } else { - Log.e("Baresip", "Setting of audio codecs '$acList' failed") - } - } - if (mediaEnc != acc.mediaEnc) { if (account_set_mediaenc(acc.accp, mediaEnc) == 0) { acc.mediaEnc = account_mediaenc(acc.accp) @@ -506,8 +460,12 @@ class AccountActivity : AppCompatActivity() { getString(R.string.register_help)) } findViewById(R.id.AudioCodecsTitle) as TextView -> { - Utils.alertView(this, getString(R.string.audio_codecs), - getString(R.string.audio_codecs_help)) + val i = Intent(this, CodecsActivity::class.java) + val b = Bundle() + b.putString("aor", aor) + b.putString("media", "audio") + i.putExtras(b) + startActivity(i) } findViewById(R.id.MediaNatTitle) as TextView -> { Utils.alertView(this, getString(R.string.media_nat), diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt index 72f7fa6b..062a6e5c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt @@ -186,7 +186,6 @@ class AccountsActivity : AppCompatActivity() { count++ } Utils.putFileContents(BaresipService.filesPath + "/accounts", accounts.toByteArray()) - Log.d("Baresip", "Saved $count account(s) to '${BaresipService.filesPath}/accounts'") // Log.d("Baresip", "Saved accounts '${accounts}' to '${BaresipService.filesPath}/accounts'") } diff --git a/app/src/main/kotlin/com/tutpro/baresip/Api.kt b/app/src/main/kotlin/com/tutpro/baresip/Api.kt index bf6d1204..e097fec8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Api.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Api.kt @@ -9,6 +9,7 @@ object Api { val VIDMODE_ON = 1 external fun audio_codecs(): String + external fun video_codecs(): String external fun uag_current_set(uap: String) external fun uag_reset_transp(reg: Boolean, reinvite: Boolean) external fun ua_account(ua: String): String diff --git a/app/src/main/kotlin/com/tutpro/baresip/CodecsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/CodecsActivity.kt new file mode 100644 index 00000000..4b17d219 --- /dev/null +++ b/app/src/main/kotlin/com/tutpro/baresip/CodecsActivity.kt @@ -0,0 +1,180 @@ +package com.tutpro.baresip + +import android.app.Activity +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity + +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.widget.* +import android.widget.LinearLayout.LayoutParams + +class CodecsActivity : AppCompatActivity() { + + private lateinit var acc: Account + private lateinit var ua: UserAgent + private var aor = "" + private var newCodecs = ArrayList() + private var media = "" + + override fun onCreate(savedInstanceState: Bundle?) { + + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_codecs) + + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + aor = intent.getStringExtra("aor")!! + media = intent.getStringExtra("media")!! + + Utils.addActivity("codecs,$aor,$media") + + ua = UserAgent.ofAor(aor)!! + acc = ua.account + + val codecs: ArrayList + + val title = findViewById(R.id.CodecsTitle) as TextView + + if (media == "audio") { + title.text = getString(R.string.audio_codecs) + codecs = ArrayList(Api.audio_codecs().split(",")) + newCodecs.addAll(acc.audioCodec) + } else { + title.text = getString(R.string.video_codecs) + codecs = ArrayList(Api.video_codecs().split(",")) + newCodecs.addAll(acc.videoCodec) + } + + while (newCodecs.size < codecs.size) newCodecs.add("-") + + val layout = findViewById(R.id.SpinnerTable) as TableLayout + val spinnerList = Array(codecs.size, {_ -> ArrayList()}) + for (i in codecs.indices) { + val spinner = Spinner(applicationContext) + spinner.id = i + 100 + spinner.layoutParams = TableRow.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT) + spinner.layoutParams.height = 75 + layout.addView(spinner) + if (acc.audioCodec.size > i) { + val codec = acc.audioCodec[i] + spinnerList[i].add(codec) + spinnerList[i].add("-") + for (c in codecs) if (c != codec) spinnerList[i].add(c) + } else { + spinnerList[i].addAll(codecs) + spinnerList[i].add(0, "-") + } + val codecSpinner = findViewById(spinner.id) as Spinner + val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, + spinnerList[i]) + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + codecSpinner.adapter = adapter + codecSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { + newCodecs.set(parent.id - 100, parent.selectedItem.toString()) + } + override fun onNothingSelected(parent: AdapterView<*>) { + } + } + } + + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + + super.onCreateOptionsMenu(menu) + val inflater = menuInflater + inflater.inflate(R.menu.check_icon, menu) + return true + + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + + if (BaresipService.activities.indexOf("codecs,$aor,$media") == -1) + return true + + when (item.itemId) { + + R.id.checkIcon -> { + + var save = false + val mc = ArrayList(LinkedHashSet(newCodecs.filter { it != "-" } as ArrayList)) + val mcList = Utils.implode(mc, ",") + + if (media == "audio") + if (mc != acc.audioCodec) { + if (account_set_audio_codecs(acc.accp, mcList) == 0) { + Log.d("Baresip", "New audio codecs '$mcList'") + acc.audioCodec = mc + save = true + } else { + Log.e("Baresip", "Setting of audio codecs '$mcList' failed") + } + } + + if (media == "video") + if (mc != acc.videoCodec) { + if (account_set_video_codecs(acc.accp, mcList) == 0) { + Log.d("Baresip", "New video codecs '$mcList'") + acc.audioCodec = mc + save = true + } else { + Log.e("Baresip", "Setting of video codecs '$mcList' failed") + } + } + + if (save) { + AccountsActivity.saveAccounts() + if (Api.ua_update_account(ua.uap) != 0) + Log.e("Baresip", "Failed to update UA ${ua.uap} with AoR $aor") + } + + if ((acc.regint > 0) && !((acc.authUser != "") && (acc.authPass == ""))) + Api.ua_register(ua.uap) + + BaresipService.activities.remove("codecs,$aor,$media") + finish() + return true + } + + android.R.id.home -> { + onBackPressed() + return true + } + + } + + return super.onOptionsItemSelected(item) + + } + + override fun onBackPressed() { + BaresipService.activities.remove("codecs,$aor,$media") + finish() + super.onBackPressed() + } + + override fun onPause() { + MainActivity.activityAor = aor + super.onPause() + } + + fun onClick(v: View) { + when (v) { + findViewById(R.id.CodecsTitle) as TextView -> { + if (media == "audio") + Utils.alertView(this, getString(R.string.audio_codecs), + getString(R.string.audio_codecs_help)) + else + Utils.alertView(this, getString(R.string.video_codecs), + getString(R.string.video_codecs_help)) + } + } + } + +} diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index 6740a256..b156e96f 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -1391,6 +1391,14 @@ class MainActivity : AppCompatActivity() { i.putExtras(b) startActivityForResult(i, ACCOUNT_CODE) } + "codecs" -> { + val i = Intent(this, CodecsActivity::class.java) + val b = Bundle() + b.putString("aor", activity[1]) + b.putString("media", activity[2]) + i.putExtras(b) + startActivity(i) + } "about" -> { val i = Intent(this, AboutActivity::class.java) startActivityForResult(i, ABOUT_CODE) @@ -1482,7 +1490,6 @@ class MainActivity : AppCompatActivity() { const val BACKUP_PERMISSION_REQUEST_CODE = 1 const val RESTORE_PERMISSION_REQUEST_CODE = 2 const val RECORD_PERMISSION_REQUEST_CODE = 3 - const val RESTART_REQUEST_CODE = 4 } diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index 43f6ad80..737440e3 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -146,25 +146,19 @@ android:id="@+id/AudioCodecsTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:paddingTop="10dp" android:textSize="18sp" + android:textStyle="bold" android:textColor="@android:color/black" android:onClick="onClick" android:text="@string/audio_codecs" > - - - + + + + + + + + + diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 295356b3..19913749 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -75,7 +75,10 @@ Äänen koodausmenetelmät Luettelo käytössä olevista äänen - koodausmenetelmistä prioriteettijärjestyksessä. + koodausmenetelmistä prioriteettijärjestyksessä + Videon koodausmenetelmät + Luettelo käytössä olevista videon + koodausmenetelmistä prioriteettijärjestyksessä Media NAT hallinta Valitsee media NAT hallintaprotokollan (vapaaehtoinen). Vaihtoehtoja ovat STUN (Session Traversal Utilities diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 388fcf78..30132605 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -71,6 +71,8 @@ Audio Codecs List of supported audio codecs in priority order. + Video Codecs + List of supported video codecs in priority order. Media NAT Traversal Selects media NAT traversal protocol (if any). Possible choices are STUN (Session Traversal Utilities for NAT, RFC 5389) and ICE (Interactive Connectivity @@ -312,4 +314,4 @@ You are not able to place or answer calls without Microphone permission. Account %1$s Authentication Password Show Password - \ No newline at end of file +